more xpcshell unifications
[guerillascript.git] / includes / basic.js
blob8fa65598a99d797234e619b6311b1c014a1547b4
1 /*
2 * Copyright 2015 Ketmar Dark <ketmar@ketmar.no-ip.org>
3 * Portions copyright 2010, Erik Vold
4 * Contributors: See contributors list in install.rdf and CREDITS
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * Note that this license applies only to the Greasemonkey extension source
14 * files, not to the user scripts which it runs. User scripts are licensed
15 * separately by their authors.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
25 * The above copyright notice and this permission notice shall be included in all
26 * copies or substantial portions of the Software.
28 // WARNING! there is no `require` yet!
29 const {utils:Cu, classes:Cc, interfaces:Ci, results:Cr} = Components;
30 Cu.import("resource://gre/modules/Services.jsm", this);
33 ////////////////////////////////////////////////////////////////////////////////
34 const isXPCShell = false;
35 let srvPrefs = Services.prefs;
38 ////////////////////////////////////////////////////////////////////////////////
39 // error console log
40 function logError () {
41 if (arguments.length) {
42 let s = "";
43 for (let idx = 0; idx < arguments.length; ++idx) s += ""+arguments[idx];
44 Cu.reportError(s);
48 function logException (msg, e) {
49 if (e) {
50 Cu.reportError(""+msg+" ERROR: "+e.name+": "+e.message+" : "+e.lineNumber)
51 if (e.stack) Cu.reportError(e.stack);
52 Cu.reportError(e);
53 } else {
54 Cu.reportError(""+msg);
58 // https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIConsoleService#logStringMessage() - wstring / wide string
59 (function (global) {
60 const conService = global.Cc["@mozilla.org/consoleservice;1"].getService(global.Ci.nsIConsoleService);
61 global.conlog = function () {
62 if (arguments.length) {
63 let le = ("guerillaOptions" in global ? global["guerillaOptions"].logEnabled : true);
64 if (le) {
65 let s = "";
66 for (let idx = 0; idx < arguments.length; ++idx) s += ""+arguments[idx];
67 conService.logStringMessage(s);
71 })(this);
74 ////////////////////////////////////////////////////////////////////////////////
75 // include
76 (function (global) {
77 let myUrl = global.__SCRIPT_URI_SPEC__;
78 let scp = {};
79 global.Cu.import("resource://gre/modules/Services.jsm", scp);
81 global.include = function (name) {
82 if (name.indexOf("/") >= 0 || name.length == 0) { global.logError("invalid include name: '"+name+"'"); throw new Error("invalid include name: '"+name+"'"); }
83 if (!(/.\.js$/.test(name))) name += ".js";
84 let uri = scp.Services.io.newURI(myUrl+"/../includes/"+name, null, null);
85 try {
86 scp.Services.scriptloader.loadSubScript(uri.spec, global);
87 } catch (e) {
88 global.logException("INCLUDE", e);
89 throw e;
92 })(this);
95 ////////////////////////////////////////////////////////////////////////////////
96 // addExport, require
97 (function (global) {
98 let myUrl = global.__SCRIPT_URI_SPEC__;
99 let scp = {};
100 const Cu = global.Cu;
101 Cu.import("resource://gre/modules/Services.jsm", scp);
103 let loc = null;
104 global.getLocale = function () {
105 if (loc === null) loc = global.Cc["@mozilla.org/chrome/chrome-registry;1"].getService(global.Ci.nsIXULChromeRegistry).getSelectedLocale("global");
106 return loc;
109 // list of symbols exported to modules
110 let exportList = {};
112 function addExport (name, fn) {
113 if (typeof(name) != "string" || name.length == 0) throw new Error("invalid export name");
114 if (typeof(fn) === "undefined") {
115 // only one operand, this must be function name
116 exportList[name] = name;
117 } else if (typeof(fn) === null) {
118 // remove export
119 delete exportList[name];
120 } else {
121 exportList[name] = fn;
124 global.addExport = addExport;
126 function fillExports (scope) {
127 for (let name in exportList) {
128 if (typeof(name) == "string" && name.length > 0) {
129 let exp = exportList[name];
130 if (typeof(exp) === "string") {
131 if (!(exp in global)) continue;
132 //global.conlog("fillExports: indirect: '"+exp+"'");
133 exp = global[exp];
135 scope[name] = exp;
140 addExport("Cu");
141 addExport("Cc");
142 addExport("Ci");
143 addExport("Cr");
144 addExport("Services");
145 addExport("srvPrefs");
147 addExport("logException");
148 addExport("logError");
149 addExport("conlog");
151 // imports a commonjs style javascript file with loadSubScrpt
152 let modules = {}; // list of loaded modules
154 global.require = function (name) {
155 if (name.indexOf("/") >= 0 || name.length == 0) { global.logError("invalid module name: '"+name+"'"); throw new Error("invalid module name: '"+name+"'"); }
156 if (!(/.\.js$/.test(name))) name += ".js";
157 if (modules[name]) return modules[name];
158 // functions available to modules
159 let scope = {};
160 fillExports(scope);
161 //scope.global = global; // just in case
162 // uses(name[, name]...);
163 scope.uses = function () {
164 if (arguments.length != 1) {
165 for (let idx = 0; idx < arguments.length; ++idx) Cu.import(arguments[idx], scope);
166 return null;
167 } else {
168 return Cu.import(arguments[0], scope);
171 scope.exports = {};
172 try {
173 let uri = scp.Services.io.newURI(myUrl+"/../modules/"+name, null, null);
174 scp.Services.scriptloader.loadSubScript(uri.spec, scope);
175 } catch (e) {
176 global.logException("REQUIRE", e);
177 throw e;
179 modules[name] = scope.exports;
180 return scope.exports;
183 addExport("getLocale");
184 addExport("addExport");
185 addExport("require");
187 global.alert = function (str) {
188 let ps = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
189 ps.alert(null, "Guerilla", ""+str);
191 addExport("alert");
193 let dirSvcProps = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
195 // get profile directory
196 global.getProfileDir = function () {
197 return dirSvcProps.get("ProfD", Ci.nsIFile);
199 addExport("getProfileDir");
201 global.hitch = function (obj, method) {
202 if (obj && method && typeof(method) == "string") {
203 if (!obj[method]) throw new Error("method ["+method+"] doesn't exist in object ["+obj+"]");
204 method = obj[method];
205 } else if (typeof(method) == "function") {
206 obj = obj||{};
207 } else {
208 throw new Error("invalid arguments to hitch()");
210 let stargs = Array.prototype.splice.call(arguments, 2, arguments.length);
211 return function() {
212 // make a copy of stargs (don't modify it because it gets reused for every invocation)
213 let args = Array.prototype.slice.call(stargs);
214 // add all the new arguments
215 Array.prototype.push.apply(args, arguments);
216 // invoke the original function with the correct this obj and the combined list of static and dynamic arguments
217 return method.apply(obj, args);
220 addExport("hitch");
222 global.fileReadText = function (file, charset) {
223 if (typeof(charset) !== "string") charset = "UTF-8";
224 charset = charset||"UTF-8";
225 let inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
226 inputStream.init(file, -1, -1, null);
227 let scInputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
228 scInputStream.init(inputStream);
229 let output = scInputStream.read(-1);
230 scInputStream.close();
231 inputStream.close();
232 let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
233 converter.charset = charset;
234 let res = converter.ConvertToUnicode(output);
235 if (typeof(res) != "string") throw new Error("invalid file '"+file.path+"'");
236 // fuck BOM
237 if (charset == "UTF-8" && res.length >= 3 && res.substr(0, 3) == "\u00EF\u00BB\u00BF") res = res.substr(3);
238 return res;
240 addExport("fileReadText");
241 })(this);