1 /* coded by Ketmar // Invisible Vector (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
10 ////////////////////////////////////////////////////////////////////////////////
11 let K8_GuerillaScriptObject = (function () {
12 const myUrl = (function (spc) {
13 let esp = spc.lastIndexOf("/");
14 return spc.substr(0, esp+1);
15 })(__SCRIPT_URI_SPEC__);
17 const {utils:Cu, classes:Cc, interfaces:Ci, results:Cr} = Components;
19 const sysPrincipal = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
20 let gsbox = new Cu.Sandbox(/*window*/sysPrincipal, {
21 sandboxName: "GuerillaScript Internal Sandbox",
22 wantComponents: false,
24 wantXHRConstructor: true,
27 Cu.import("resource://gre/modules/Services.jsm", gsbox);
29 // add some common API
30 Object.defineProperty(gsbox, "isXPCShell", {get: function () false});
32 // `tieto` API: ties method to object, so it always has correct `this`
33 // you may specify additional arguments that will be always there
34 function tieto (obj, method) {
36 if (typeof(obj) === "undefined") throw new Error("object or `null` expected");
37 if (obj !== null && typeof(obj) !== "object") throw new Error("object or `null` expected");
38 switch (typeof(method)) {
40 if (!obj) throw new Error("can't take method by name from `null` object");
41 if (!(method in obj)) throw new Error("method '"+method+"' doesn't exist in object '"+obj+"'");
43 if (typeof(mt) !== "function") throw new Error("method '"+method+"' isn't a function in object '"+obj+"'");
50 throw new Error("`method` should be function or method name");
53 let rest = Array.prototype.splice.call(arguments, 2, arguments.length);
56 try { throw new Error("!"); } catch (e) {
57 //print("TIETO!\n"+e.stack);
58 stk = e.stack.split("\n")[1];
63 // `rest` is reused for each invocation, so copy it, and append new arguments to copy
64 let args = Array.prototype.slice.call(rest);
65 Array.prototype.push.apply(args, arguments);
66 return mt.apply(me, args);
69 const sb_tieto = tieto(gsbox, tieto);
70 Object.defineProperty(gsbox, "tieto", {get: function () sb_tieto});
72 const sb_Components = tieto(gsbox, function (c) c, Components);
73 const sb_Cu = tieto(gsbox, function (cu) cu, Cu);
74 const sb_Cc = tieto(gsbox, function (cc) cc, Cc);
75 const sb_Ci = tieto(gsbox, function (ci) ci, Ci);
76 const sb_Cr = tieto(gsbox, function (cr) cr, Cr);
78 Object.defineProperty(gsbox, "Components", {get: function () sb_Components()});
79 Object.defineProperty(gsbox, "Cu", {get: function () sb_Cu()});
80 Object.defineProperty(gsbox, "Cc", {get: function () sb_Cc()});
81 Object.defineProperty(gsbox, "Ci", {get: function () sb_Ci()});
82 Object.defineProperty(gsbox, "Cr", {get: function () sb_Cr()});
84 // console log functions
85 const oldlogerr = (typeof(conlog) == "function" ? logError : null);
86 function logErr (str) {
87 if (oldlogerr) oldlogerr(str); else Cu.reportError(str);
89 const sb_logError = tieto(gsbox, function (logErrMsg) {
90 if (arguments.length) {
92 for (let idx = 0; idx < arguments.length; ++idx) s += ""+arguments[idx];
96 Object.defineProperty(gsbox, "logError", {get: function () sb_logError});
98 const sb_logException = tieto(gsbox, function (logErrMsg) {
99 if (e instanceof this.Error) {
100 logErrMsg(""+msg+" ERROR: "+e.name+": "+e.message+" : "+e.lineNumber)
101 if (e.stack) logErrMsg(e.stack);
107 Object.defineProperty(gsbox, "logException", {get: function () sb_logException});
109 //let conlogEnabled = true;
110 //Object.defineProperty(gsbox, "conlogEnabled", {get: tieto(this, function () this.conlogEnabled)});
112 // https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIConsoleService#logStringMessage() - wstring / wide string
113 const conService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
114 const oldconlog = (typeof(conlog) == "function" ? conlog : null);
115 function logStr (str) {
116 if (oldconlog) oldconlog(str); else conService.logStringMessage(str);
119 const sb_conlog = tieto(gsbox, function (logStrMsg) {
120 if (arguments.length > 1) {
121 let le = ("guerillaOptions" in this ? this["guerillaOptions"].logEnabled : true);
124 for (let idx = 1; idx < arguments.length; ++idx) s += ""+arguments[idx];
128 Object.defineProperty(gsbox, "conlog", {get: function () sb_conlog});
130 const sb_print = tieto(gsbox, function (logStrMsg) {
131 if (arguments.length > 1) {
132 let le = ("guerillaOptions" in this ? this["guerillaOptions"].logEnabled : true);
135 let wasPrint = false;
136 for (let idx = 1; idx < arguments.length; ++idx) {
137 let t = ""+arguments[idx];
140 logStrMsg(s.substr(1));
143 Object.defineProperty(gsbox, "print", {get: function () sb_print});
146 //const scLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
147 const newURI = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newURI;
148 //const newFileURI = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newFileURI;
149 const loadSubScript = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader).loadSubScript;
151 // include("incname")
152 const sb_include = tieto(gsbox, function (scriptSpec, newURI, loadSubScript, reportError, name) {
153 if (name.length == 0) throw new Error("invalid include name: '"+name+"'");
154 if (!(/.\.js$/.test(name))) name += ".js";
156 let uri = newURI(scriptSpec+name, null, null);
157 loadSubScript(uri.spec, gsbox, "UTF-8");
159 reportError("INCLUDE ERROR: "+e.name+": "+e.message+" : "+e.lineNumber+"\n"+e.stack);
163 }, myUrl+"includes/", newURI, loadSubScript, Cu.reportError);
164 Object.defineProperty(gsbox, "include", {get: function () sb_include});
167 let modules = {}; // list of loaded modules
169 // require("modname")
170 const sb_require = tieto(gsbox, function (scriptSpec, newURI, loadSubScript, reportError, import_, modules, name) {
171 if (name.length == 0) throw new Error("invalid include name: '"+name+"'");
172 if (!(/.\.js$/.test(name))) name += ".js";
173 if (name in modules) return modules[name];
175 let scope = Object.create(gsbox);
176 // uses(name[, name]...);
177 let sc_uses = tieto(gsbox, function (scope, import_) {
178 if (arguments.length > 3) {
179 for (let idx = 2; idx < arguments.length; ++idx) import_(arguments[idx], scope);
181 } else if (arguments.length == 3) {
182 return import_(arguments[2], scope);
185 Object.defineProperty(scope, "uses", {get: function () sc_uses});
187 scope.exportsGlobal = {};
189 for (let k in gsbox) {
191 if (k !== "__exposedProps__" && !(k in scope) && Object.prototype.hasOwnProperty.call(gsbox, k)) {
192 print(" EXPORT: k=["+k+"]");
193 try { scope[k] = gsbox[k]; } catch (e) {}
198 let uri = newURI(scriptSpec+name, null, null);
199 loadSubScript(uri.spec, scope, "UTF-8");
201 reportError("REQUIRE ERROR: "+e.name+": "+e.message+" : "+e.lineNumber+"\n"+e.stack);
205 modules[name] = scope.exports;
206 if (typeof(scope.exportsGlobal) === "object") {
207 for (let k in scope.exportsGlobal) {
208 if (k !== "__exposedProps__" && Object.prototype.hasOwnProperty.call(scope.exportsGlobal, k)) {
209 try { gsbox[k] = scope.exportsGlobal[k]; } catch (e) {}
213 return scope.exports;
214 }, myUrl+"modules/", newURI, loadSubScript, Cu.reportError, Cu.import, modules);
215 Object.defineProperty(gsbox, "require", {get: function () sb_require});
218 const promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
220 const sb_alert = tieto(gsbox, function (promptSvc, msg) {
221 promptSvc.alert(null, "Guerilla", ""+msg);
223 Object.defineProperty(gsbox, "alert", {get: function () sb_alert});
226 let startupHooks = [], shutdownHooks = [];
228 function runHooks (list, rev, data, reason) {
229 let idx = (rev ? list.length : -1);
232 if (--idx < 0) break;
234 if (++idx >= list.length) break;
238 //conService.logStringMessage("running hook: '"+h.name+"'");
239 h.cback(data, reason);
241 Cu.reportError("HOOK ERROR: "+e.name+": "+e.message+" : "+e.lineNumber+"\n"+e.stack);
247 function addHook (hooks, name, cback) {
248 if (typeof(cback) === "undefined") {
249 // register*Hook(hookfn)
253 if (typeof(name) === "undefined") throw new Error("name or `null` expected");
254 if (!name) name = "";
255 if (typeof(name) !== "string") throw new Error("name or `null` expected");
256 if (typeof(cback) !== "function") throw new Error("function expected");
257 hooks.push({name:name, cback:cback});
260 const sb_rsth = tieto(gsbox, addHook, startupHooks);
261 const sb_rsuh = tieto(gsbox, addHook, shutdownHooks);
263 // registerStartupHook(name, hookfn)
264 Object.defineProperty(gsbox, "registerStartupHook", {get: function () sb_rsth});
265 // registerShutdownHook(name, hookfn)
266 Object.defineProperty(gsbox, "registerShutdownHook", {get: function () sb_rsuh});
268 // now load main file
269 gsbox.include("../main.js"); //HACK!
273 onInstall: function (data, reason) {},
274 onUnistall: function (data, reason) {},
275 onStartup: function (data, reason) { runHooks(startupHooks, false, data, reason); },
276 onShutdown: function (data, reason) { runHooks(shutdownHooks, true, data, reason); },
282 ////////////////////////////////////////////////////////////////////////////////
283 // ADDON_INSTALL, ADDON_UPGRADE, or ADDON_DOWNGRADE
284 function install (data, reason) { K8_GuerillaScriptObject.onInstall(data, reason); }
286 // ADDON_UNINSTALL, ADDON_UPGRADE, or ADDON_DOWNGRADE
287 function uninstall (data, reason) { K8_GuerillaScriptObject.onUnistall(data, reason); }
289 // APP_STARTUP, ADDON_ENABLE, ADDON_INSTALL, ADDON_UPGRADE, or ADDON_DOWNGRADE
290 function startup (data, reason) { K8_GuerillaScriptObject.onStartup(data, reason); }
292 // APP_SHUTDOWN, ADDON_DISABLE, ADDON_UNINSTALL, ADDON_UPGRADE, or ADDON_DOWNGRADE
293 function shutdown (data, reason) { K8_GuerillaScriptObject.onShutdown(data, reason); }