// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2008-2014 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("util", {
exports: ["DOM", "$", "FailedAssertion", "Math", "NS", "Point", "Util", "XBL", "XHTML", "XUL", "util"],
- require: ["dom", "services"]
-}, this);
+ require: ["dom", "promises", "services"]
+});
+
+lazyRequire("overlay", ["overlay"]);
+lazyRequire("storage", ["File", "storage"]);
+lazyRequire("template", ["template"]);
+
+var Magic = Class("Magic", {
+ init: function init(str) {
+ this.str = str;
+ },
+
+ get message() this.str,
-this.lazyRequire("overlay", ["overlay"]);
+ toString: function () this.str
+});
var FailedAssertion = Class("FailedAssertion", ErrorBase, {
init: function init(message, level, noTrace) {
}
var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), {
- init: function () {
+ Magic: Magic,
+
+ init: function init() {
this.Array = array;
this.addObserver(this);
},
activeWindow: deprecated("overlay.activeWindow", { get: function activeWindow() overlay.activeWindow }),
- overlayObject: deprecated("overlay.overlayObject", { get: function overlayObject() overlay.closure.overlayObject }),
- overlayWindow: deprecated("overlay.overlayWindow", { get: function overlayWindow() overlay.closure.overlayWindow }),
+ overlayObject: deprecated("overlay.overlayObject", { get: function overlayObject() overlay.bound.overlayObject }),
+ overlayWindow: deprecated("overlay.overlayWindow", { get: function overlayWindow() overlay.bound.overlayWindow }),
compileMatcher: deprecated("DOM.compileMatcher", { get: function compileMatcher() DOM.compileMatcher }),
computedStyle: deprecated("DOM#style", function computedStyle(elem) DOM(elem).style),
readFromClipboard: deprecated("dactyl.clipboardRead", function readFromClipboard() util.dactyl.clipboardRead(false)),
chromePackages: deprecated("config.chromePackages", { get: function chromePackages() config.chromePackages }),
- haveGecko: deprecated("config.haveGecko", { get: function haveGecko() config.closure.haveGecko }),
+ haveGecko: deprecated("config.haveGecko", { get: function haveGecko() config.bound.haveGecko }),
OS: deprecated("config.OS", { get: function OS() config.OS }),
dactyl: update(function dactyl(obj) {
var global = Class.objectGlobal(obj);
return {
- __noSuchMethod__: function (meth, args) {
+ __noSuchMethod__: function __noSuchMethod__(meth, args) {
let win = overlay.activeWindow;
var dactyl = global && global.dactyl || win && win.dactyl;
}
};
}, {
- __noSuchMethod__: function () this().__noSuchMethod__.apply(null, arguments)
+ __noSuchMethod__: function __noSuchMethod__() this().__noSuchMethod__.apply(null, arguments)
}),
/**
let cleanup = ["dactyl-cleanup-modules", "quit-application"];
function register(meth) {
- for (let target in Set(cleanup.concat(Object.keys(obj.observers))))
+ for (let target of RealSet(cleanup.concat(Object.keys(obj.observers))))
try {
services.observer[meth](obj, target, true);
}
}
});
- obj.observe.unregister = function () register("removeObserver");
+ obj.observe.unregister = () => register("removeObserver");
register("addObserver");
}, { dump: dump, Error: Error }),
* @param {string} message The message to present to the
* user on failure.
*/
- assert: function (condition, message, quiet) {
+ assert: function assert(condition, message, quiet) {
if (!condition)
throw FailedAssertion(message, 1, quiet === undefined ? true : quiet);
return condition;
* @param {string} name The name to mangle.
* @returns {string} The mangled name.
*/
- camelCase: function camelCase(name) String.replace(name, /-(.)/g, function (m, m1) m1.toUpperCase()),
+ camelCase: function camelCase(name) String.replace(name, /-(.)/g,
+ (m, m1) => m1.toUpperCase()),
/**
* Capitalizes the first character of the given string.
function frame() update(
function _frame(obj)
- _frame === stack.top || _frame.valid(obj) ?
- _frame.elements.map(function (e) callable(e) ? e(obj) : e).join("") : "",
+ _frame === stack.top || _frame.valid(obj)
+ ? _frame.elements.map(e => callable(e) ? e(obj) : e)
+ .join("")
+ : "",
{
elements: [],
seen: {},
- valid: function (obj) this.elements.every(function (e) !e.test || e.test(obj))
+ valid: function valid(obj) this.elements.every(e => !e.test || e.test(obj))
});
let end = 0;
char = char.toLowerCase();
stack.top.elements.push(update(
- function (obj) obj[char] != null ? quote(obj, char) : "",
- { test: function (obj) obj[char] != null }));
+ function (obj) obj[char] != null ? quote(obj, char)
+ : "",
+ { test: function test(obj) obj[char] != null }));
for (let elem in array.iterValues(stack))
elem.seen[char] = true;
let unknown = util.identity;
if (!keepUnknown)
- unknown = function () "";
+ unknown = () => "";
function frame() update(
function _frame(obj)
- _frame === stack.top || _frame.valid(obj) ?
- _frame.elements.map(function (e) callable(e) ? e(obj) : e).join("") : "",
+ _frame === stack.top || _frame.valid(obj)
+ ? _frame.elements.map(e => callable(e) ? e(obj) : e)
+ .join("")
+ : "",
{
elements: [],
- seen: {},
- valid: function (obj) this.elements.every(function (e) !e.test || e.test(obj))
+ seen: RealSet(),
+ valid: function valid(obj) this.elements.every(e => (!e.test || e.test(obj)))
});
let defaults = { lt: "<", gt: ">" };
- let re = util.regexp(<![CDATA[
+ let re = util.regexp(literal(/*
([^]*?) // 1
(?:
(<\{) | // 2
(< ((?:[a-z]-)?[a-z-]+?) (?:\[([0-9]+)\])? >) | // 3 4 5
(\}>) // 6
)
- ]]>, "gixy");
+ */), "gixy");
macro = String(macro);
let end = 0;
for (let match in re.iterate(macro)) {
}
else if (close) {
stack.pop();
- util.assert(stack.length, /*L*/"Unmatched %] in macro");
+ util.assert(stack.length, /*L*/"Unmatched }> in macro");
}
else {
let [, flags, name] = /^((?:[a-z]-)*)(.*)/.exec(macro);
- flags = Set(flags);
+ flags = RealSet(flags);
let quote = util.identity;
- if (flags.q)
+ if (flags.has("q"))
quote = function quote(obj) typeof obj === "number" ? obj : String.quote(obj);
- if (flags.e)
+ if (flags.has("e"))
quote = function quote(obj) "";
- if (Set.has(defaults, name))
+ if (hasOwnProperty(defaults, name))
stack.top.elements.push(quote(defaults[name]));
else {
let index = idx;
if (idx) {
idx = Number(idx) - 1;
stack.top.elements.push(update(
- function (obj) obj[name] != null && idx in obj[name] ? quote(obj[name][idx])
- : Set.has(obj, name) ? "" : unknown(full),
+ obj => obj[name] != null && idx in obj[name] ? quote(obj[name][idx])
+ : hasOwnProperty(obj, name) ? "" : unknown(full),
{
- test: function (obj) obj[name] != null && idx in obj[name]
- && obj[name][idx] !== false
- && (!flags.e || obj[name][idx] != "")
+ test: function test(obj) obj[name] != null && idx in obj[name]
+ && obj[name][idx] !== false
+ && (!flags.e || obj[name][idx] != "")
}));
}
else {
stack.top.elements.push(update(
- function (obj) obj[name] != null ? quote(obj[name])
- : Set.has(obj, name) ? "" : unknown(full),
+ obj => obj[name] != null ? quote(obj[name])
+ : hasOwnProperty(obj, name) ? "" : unknown(full),
{
- test: function (obj) obj[name] != null
- && obj[name] !== false
- && (!flags.e || obj[name] != "")
+ test: function test(obj) obj[name] != null
+ && obj[name] !== false
+ && (!flags.e || obj[name] != "")
}));
}
for (let elem in array.iterValues(stack))
- elem.seen[name] = true;
+ elem.seen.add(name);
}
}
}
acc.push(vals);
if (acc.length == pattern.length)
- this.res.push(acc.join(""))
+ this.res.push(acc.join(""));
else
for (let val in values(vals))
this.rec(acc.concat(val));
return obj.res;
}
- if (pattern.indexOf("{") == -1)
+ if (!pattern.contains("{"))
return [pattern];
let res = [];
fn(match);
}
res.push(pattern.substr(end));
- return res.map(function (s) util.dequote(s, dequote));
- }
+ return res.map(s => util.dequote(s, dequote));
+ };
let patterns = [];
let substrings = split(pattern, /((?:[^\\{]|\\.)*)\{((?:[^\\}]|\\.)*)\}/gy,
else
for (let [, pattern] in Iterator(patterns[acc.length]))
rec(acc.concat(pattern));
- }
+ };
rec([]);
return res;
}
- catch (e if e.message && ~e.message.indexOf("res is undefined")) {
+ catch (e if e.message && e.message.contains("res is undefined")) {
// prefs.safeSet() would be reset on :rehash
prefs.set("javascript.options.methodjit.chrome", false);
util.dactyl.warn(_(UTF8("error.damnYouJägermonkey")));
}
},
+ /**
+ * Briefly delay the execution of the passed function.
+ *
+ * @param {function} callback The function to delay.
+ */
+ delay: function delay(callback) {
+ let { mainThread } = services.threading;
+ mainThread.dispatch(callback,
+ mainThread.DISPATCH_NORMAL);
+ },
+
/**
* Removes certain backslash-quoted characters while leaving other
* backslash-quoting sequences untouched.
* @returns {string}
*/
dequote: function dequote(pattern, chars)
- pattern.replace(/\\(.)/, function (m0, m1) chars.indexOf(m1) >= 0 ? m1 : m0),
+ pattern.replace(/\\(.)/, (m0, m1) => chars.contains(m1) ? m1 : m0),
/**
* Returns the nsIDocShell for the given window.
* @param {string} stack The stack trace from an Error.
* @returns {[string]} The stack frames.
*/
- stackLines: function (stack) {
+ stackLines: function stackLines(stack) {
let lines = [];
let match, re = /([^]*?)@([^@\n]*)(?:\n|$)/g;
while (match = re.exec(stack))
* @param {string} msg The trace message.
* @param {number} frames The number of frames to print.
*/
- dumpStack: function dumpStack(msg, frames) {
+ dumpStack: function dumpStack(msg="Stack", frames=null) {
let stack = util.stackLines(Error().stack);
stack = stack.slice(1, 1 + (frames || stack.length)).join("\n").replace(/^/gm, " ");
- util.dump((arguments.length == 0 ? "Stack" : msg) + "\n" + stack + "\n");
+ util.dump(msg + "\n" + stack + "\n");
},
/**
[hours, minutes] = div(minutes, 60);
[days, hours] = div(hours, 24);
if (days)
- return /*L*/days + " days " + hours + " hours"
+ return /*L*/days + " days " + hours + " hours";
if (hours)
return /*L*/hours + "h " + minutes + "m";
if (minutes)
* @param {string} url
* @returns {string|null}
*/
- getHost: function (url) {
+ getHost: function getHost(url) {
try {
return util.createURI(url).host;
}
*
* @returns {XMLHttpRequest}
*/
- httpGet: function httpGet(url, callback, self) {
- let params = callback;
- if (!isObject(params))
- params = { callback: params && function () callback.apply(self, arguments) };
+ httpGet: function httpGet(url, params={}, self) {
+ if (callable(params))
+ // Deprecated.
+ params = { callback: params.bind(self) };
try {
let xmlhttp = services.Xmlhttp();
- xmlhttp.mozBackgroundRequest = Set.has(params, "background") ? params.background : true;
+ xmlhttp.mozBackgroundRequest = hasOwnProperty(params, "background") ? params.background : true;
let async = params.callback || params.onload || params.onerror;
if (async) {
- xmlhttp.addEventListener("load", function handler(event) { util.trapErrors(params.onload || params.callback, params, xmlhttp, event) }, false);
- xmlhttp.addEventListener("error", function handler(event) { util.trapErrors(params.onerror || params.callback, params, xmlhttp, event) }, false);
+ xmlhttp.addEventListener("load", event => { util.trapErrors(params.onload || params.callback, params, xmlhttp, event); }, false);
+ xmlhttp.addEventListener("error", event => { util.trapErrors(params.onerror || params.callback, params, xmlhttp, event); }, false);
}
-
if (isObject(params.params)) {
let data = [encodeURIComponent(k) + "=" + encodeURIComponent(v)
for ([k, v] in iter(params.params))];
}
},
+ /**
+ * Like #httpGet, but returns a promise rather than accepting
+ * callbacks.
+ *
+ * @param {string} url The URL to fetch.
+ * @param {object} params Parameter object, as in #httpGet.
+ */
+ fetchUrl: promises.withCallbacks(function fetchUrl([accept, reject, deferred], url, params) {
+ params = update({}, params);
+ params.onload = accept;
+ params.onerror = reject;
+
+ let req = this.httpGet(url, params);
+ promises.oncancel(deferred, req.cancel);
+ }),
+
/**
* The identity function.
*
* @param {Object} r2
* @returns {Object}
*/
- intersection: function (r1, r2) ({
+ intersection: function intersection(r1, r2) ({
get width() this.right - this.left,
get height() this.bottom - this.top,
left: Math.max(r1.left, r2.left),
* top-level window and sub-frames thereof.
*/
iterDocuments: function iterDocuments(types) {
- types = types ? types.map(function (s) "type" + util.capitalize(s))
+ types = types ? types.map(s => "type" + util.capitalize(s))
: ["typeChrome", "typeContent"];
let windows = services.windowMediator.getXULWindowEnumerator(null);
while (windows.hasMoreElements()) {
let window = windows.getNext().QueryInterface(Ci.nsIXULWindow);
- for each (let type in types) {
+ for (let type of types) {
let docShells = window.docShell.getDocShellEnumerator(Ci.nsIDocShellTreeItem[type],
Ci.nsIDocShell.ENUMERATE_FORWARDS);
while (docShells.hasMoreElements())
let (viewer = docShells.getNext().QueryInterface(Ci.nsIDocShell).contentViewer) {
if (viewer)
yield viewer.DOMDocument;
- }
+ };
}
}
},
// ripped from Firefox; modified
- unsafeURI: Class.Memoize(function () util.regexp(String.replace(<![CDATA[
+ unsafeURI: Class.Memoize(() => util.regexp(String.replace(literal(/*
[
\s
// Invisible characters (bug 452979)
// Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6)
U200E U200F U202A U202B U202C U202D U202E
]
- ]]>, /U/g, "\\u"),
+ */), /U/g, "\\u"),
"gx")),
losslessDecodeURI: function losslessDecodeURI(url) {
return url.split("%25").map(function (url) {
* for *obj*.
*/
makeDTD: let (map = { "'": "'", '"': """, "%": "%", "&": "&", "<": "<", ">": ">" })
- function makeDTD(obj) iter(obj)
- .map(function ([k, v]) ["<!ENTITY ", k, " '", String.replace(v == null ? "null" : typeof v == "xml" ? v.toXMLString() : v,
- typeof v == "xml" ? /['%]/g : /['"%&<>]/g,
- function (m) map[m]),
- "'>"].join(""))
- .join("\n"),
+ function makeDTD(obj) {
+ function escape(val) {
+ let isDOM = DOM.isJSONXML(val);
+ return String.replace(val == null ? "null" :
+ isDOM ? DOM.toXML(val)
+ : val,
+ isDOM ? /['%]/g
+ : /['"%&<>]/g,
+ m => map[m]);
+ }
+
+ return iter(obj).map(([k, v]) =>
+ ["<!ENTITY ", k, " '", escape(v), "'>"].join(""))
+ .join("\n");
+ },
/**
* Converts a URI string into a URI object.
* @returns {string}
*/
objectToString: function objectToString(object, color) {
- // Use E4X literals so html is automatically quoted
- // only when it's asked for. No one wants to see <
- // on their console or :map :foo in their buffer
- // when they expect :map <C-f> :foo.
- XML.prettyPrinting = false;
- XML.ignoreWhitespace = false;
-
if (object == null)
return object + "\n";
catch (e) {
obj = Object.prototype.toString.call(obj);
}
- obj = template.highlightFilter(util.clip(obj, 150), "\n", !color ? function () "^J" : function () <span highlight="NonText">^J</span>);
- let string = <><span highlight="Title Object">{obj}</span>::
</>;
+
+ if (color) {
+ obj = template.highlightFilter(util.clip(obj, 150), "\n",
+ () => ["span", { highlight: "NonText" },
+ "^J"]);
+
+ var head = ["span", { highlight: "Title Object" }, obj, "::\n"];
+ }
+ else
+ head = util.clip(obj, 150).replace(/\n/g, "^J") + "::\n";
let keys = [];
// window.content often does not want to be queried with "var i in object"
try {
let hasValue = !("__iterator__" in object || isinstance(object, ["Generator", "Iterator"]));
+
if (object.dactyl && object.modules && object.modules.modules == object.modules) {
object = Iterator(object);
hasValue = false;
}
+
let keyIter = object;
- if ("__iterator__" in object && !callable(object.__iterator__))
- keyIter = keys(object)
+ if (iter.iteratorProp in object) {
+ keyIter = (k for (k of object));
+ hasValue = false;
+ }
+ else if ("__iterator__" in object && !callable(object.__iterator__))
+ keyIter = keys(object);
for (let i in keyIter) {
- let value = <![CDATA[<no value>]]>;
+ let value = Magic("<no value>");
try {
value = object[i];
}
catch (e) {}
+
if (!hasValue) {
if (isArray(i) && i.length == 2)
[i, value] = i;
}
}
- value = template.highlight(value, true, 150, !color);
- let key = <span highlight="Key">{i}</span>;
+ let key = i;
if (!isNaN(i))
i = parseInt(i);
else if (/^[A-Z_]+$/.test(i))
i = "";
- keys.push([i, <>{noVal ? value : <>{key}: {value}</>}
</>]);
+
+ if (color)
+ value = template.highlight(value, true, 150, !color);
+ else if (value instanceof Magic)
+ value = String(value);
+ else
+ value = util.clip(String(value).replace(/\n/g, "^J"), 150);
+
+ if (noVal)
+ var val = value;
+ else if (color)
+ val = [["span", { highlight: "Key" }, key], ": ", value];
+ else
+ val = key + ": " + value;
+
+ keys.push([i, val]);
}
}
catch (e) {
return a[0] - b[0];
return String.localeCompare(a[0], b[0]);
}
- string += template.map(keys.sort(compare), function (f) f[1]);
- return color ? <div style="white-space: pre-wrap;">{string}</div> : [s for each (s in string)].join("");
+
+ let vals = template.map(keys.sort(compare), f => f[1],
+ "\n");
+
+ if (color) {
+ return ["div", { style: "white-space: pre-wrap" }, head, vals];
+ }
+ return head + vals.join("");
+ },
+
+ prettifyJSON: function prettifyJSON(data, indent, invalidOK) {
+ const INDENT = indent || " ";
+
+ function rec(data, level, seen) {
+ if (isObject(data)) {
+ seen = RealSet(seen);
+ if (seen.add(data))
+ throw Error("Recursive object passed");
+ }
+
+ let prefix = level + INDENT;
+
+ if (data === undefined)
+ data = null;
+
+ if (~["boolean", "number"].indexOf(typeof data) || data === null)
+ res.push(String(data));
+ else if (isinstance(data, ["String", _]))
+ res.push(JSON.stringify(String(data)));
+ else if (isArray(data)) {
+ if (data.length == 0)
+ res.push("[]");
+ else {
+ res.push("[\n");
+ for (let [i, val] in Iterator(data)) {
+ if (i)
+ res.push(",\n");
+ res.push(prefix);
+ rec(val, prefix, seen);
+ }
+ res.push("\n", level, "]");
+ }
+ }
+ else if (isObject(data)) {
+ res.push("{\n");
+
+ let i = 0;
+ for (let [key, val] in Iterator(data)) {
+ if (i++)
+ res.push(",\n");
+ res.push(prefix, JSON.stringify(key), ": ");
+ rec(val, prefix, seen);
+ }
+ if (i > 0)
+ res.push("\n", level, "}");
+ else
+ res[res.length - 1] = "{}";
+ }
+ else if (invalidOK)
+ res.push({}.toString.call(data));
+ else
+ throw Error("Invalid JSON object");
+ }
+
+ let res = [];
+ rec(data, "", RealSet());
+ return res.join("");
},
observers: {
- "dactyl-cleanup-modules": function (subject, reason) {
+ "dactyl-cleanup-modules": function cleanupModules(subject, reason) {
defineModule.loadLog.push("dactyl: util: observe: dactyl-cleanup-modules " + reason);
for (let module in values(defineModule.modules))
util.dump("cleanup: " + module.constructor.className);
util.trapErrors(module.cleanup, module, reason);
}
-
- JSMLoader.cleanup();
-
- if (!this.rehashing)
- services.observer.addObserver(this, "dactyl-rehash", true);
- },
- "dactyl-rehash": function () {
- services.observer.removeObserver(this, "dactyl-rehash");
-
- defineModule.loadLog.push("dactyl: util: observe: dactyl-rehash");
- if (!this.rehashing)
- for (let module in values(defineModule.modules)) {
- defineModule.loadLog.push("dactyl: util: init(" + module + ")");
- if (module.reinit)
- module.reinit();
- else
- module.init();
- }
- },
- "dactyl-purge": function () {
- this.rehashing = 1;
- },
+ }
},
/**
*
* This is similar to Perl's extended regular expression format.
*
- * @param {string|XML} expr The expression to compile into a RegExp.
+ * @param {string} expr The expression to compile into a RegExp.
* @param {string} flags Flags to apply to the new RegExp.
* @param {object} tokens The tokens to substitute. @optional
* @returns {RegExp} A custom regexp object.
// Replace replacement <tokens>.
if (tokens)
- expr = String.replace(expr, /(\(?P)?<(\w+)>/g, function (m, n1, n2) !n1 && Set.has(tokens, n2) ? tokens[n2].dactylSource || tokens[n2].source || tokens[n2] : m);
+ expr = String.replace(expr, /(\(?P)?<(\w+)>/g,
+ (m, n1, n2) => !n1 && hasOwnProperty(tokens, n2) ? tokens[n2].dactylSource
+ || tokens[n2].source
+ || tokens[n2]
+ : m);
// Strip comments and white space.
if (/x/.test(flags))
- expr = String.replace(expr, /(\\.)|\/\/[^\n]*|\/\*[^]*?\*\/|\s+/gm, function (m, m1) m1 || "");
+ expr = String.replace(expr, /(\\.)|\/\/[^\n]*|\/\*[^]*?\*\/|\s+/gm,
+ (m, m1) => m1 || "");
// Replace (?P<named> parameters)
if (/\(\?P</.test(expr)) {
}
let res = update(RegExp(expr, flags.replace("x", "")), {
- closure: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "closure")),
+ bound: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "bound")),
+ closure: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "bound")),
dactylPropertyNames: ["exec", "match", "test", "toSource", "toString", "global", "ignoreCase", "lastIndex", "multiLine", "source", "sticky"],
- iterate: function (str, idx) util.regexp.iterate(this, str, idx)
+ iterate: function iterate(str, idx) util.regexp.iterate(this, str, idx)
});
// Return a struct with properties for named parameters if we
* @param {RegExp} re The regexp showable source of which is to be returned.
* @returns {string}
*/
- getSource: function regexp_getSource(re) re.source.replace(/\\(.)/g, function (m0, m1) m1 === "/" ? "/" : m0),
+ getSource: function regexp_getSource(re) re.source.replace(/\\(.)/g,
+ (m0, m1) => m1 === "/" ? m1
+ : m0),
/**
* Iterates over all matches of the given regexp in the given
* Reloads dactyl in entirety by disabling the add-on and
* re-enabling it.
*/
- rehash: function (args) {
- storage.session.commandlineArgs = args;
+ rehash: function rehash(args) {
+ storage.storeForSession("commandlineArgs", args);
this.timeout(function () {
this.flushCache();
- this.rehashing = true;
+ cache.flush(bind("test", /^literal:/));
let addon = config.addon;
addon.userDisabled = true;
addon.userDisabled = false;
},
errorCount: 0,
- errors: Class.Memoize(function () []),
+ errors: Class.Memoize(() => []),
maxErrors: 15,
/**
* Reports an error to the Error Console and the standard output,
let obj = update({}, error, {
toString: function () String(error),
- stack: <>{util.stackLines(String(error.stack || Error().stack)).join("\n").replace(/^/mg, "\t")}</>
+ stack: Magic(util.stackLines(String(error.stack || Error().stack)).join("\n").replace(/^/mg, "\t"))
});
services.console.logStringMessage(obj.stack);
let ary = host.split(".");
ary = [ary.slice(i).join(".") for (i in util.range(ary.length, 0, -1))];
- return ary.filter(function (h) h.length >= base.length);
+ return ary.filter(h => h.length >= base.length);
},
/**
* @param {Window} window
* @returns {nsISelectionController}
*/
- selectionController: function (win)
+ selectionController: function selectionController(win)
win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay)
.QueryInterface(Ci.nsISelectionController),
*
* @param {number} delay The time period for which to sleep in milliseconds.
*/
- sleep: function (delay) {
+ sleep: function sleep(delay) {
let mainThread = services.threading.mainThread;
let end = Date.now() + delay;
* @param {number} limit The maximum number of elements to return.
* @returns {[string]}
*/
- split: function (str, re, limit) {
+ split: function split(str, re, limit) {
re.lastIndex = 0;
if (!re.global)
re = RegExp(re.source || re, "g");
* interrupted by pressing <C-c>, in which case,
* Error("Interrupted") will be thrown.
*/
- threadYield: function (flush, interruptable) {
+ threadYield: function threadYield(flush, interruptable) {
this.yielders++;
try {
let mainThread = services.threading.mainThread;
* Waits for the function *test* to return true, or *timeout*
* milliseconds to expire.
*
- * @param {function} test The predicate on which to wait.
+ * @param {function|Promise} test The predicate on which to wait.
* @param {object} self The 'this' object for *test*.
* @param {Number} timeout The maximum number of milliseconds to
* wait.
* thrown.
*/
waitFor: function waitFor(test, self, timeout, interruptable) {
+ if (!callable(test)) {
+ let done = false;
+ var promise = test,
+ retVal;
+ promise.then((arg) => { retVal = arg; done = true; },
+ (arg) => { retVal = arg; done = true; });
+ test = () => done;
+ }
+
let end = timeout && Date.now() + timeout, result;
let timer = services.Timer(function () {}, 10, services.Timer.TYPE_REPEATING_SLACK);
finally {
timer.cancel();
}
- return result;
+ return promise ? retVal: result;
},
/**
* @returns {function} A new function which may not execute
* synchronously.
*/
- yieldable: function yieldable(func)
+ yieldable: deprecated("Task.spawn", function yieldable(func)
function magic() {
let gen = func.apply(this, arguments);
(function next() {
}
catch (e if e instanceof StopIteration) {};
})();
- },
+ }),
/**
* Wraps a callback function such that its errors are not lost. This
* @param {function} func The function to call
* @param {object} self The 'this' object for the function.
*/
- trapErrors: function trapErrors(func, self) {
+ trapErrors: function trapErrors(func, self, ...args) {
try {
if (!callable(func))
func = self[func];
- return func.apply(self || this, Array.slice(arguments, 2));
+ return func.apply(self || this, args);
}
catch (e) {
this.reportError(e);
* @param {nsIDOMWindow} win The window for which to find domains.
* @returns {[string]} The visible domains.
*/
- visibleHosts: function (win) {
- let res = [], seen = {};
+ visibleHosts: function visibleHosts(win) {
+ let res = [],
+ seen = RealSet();
(function rec(frame) {
try {
if (frame.location.hostname)
catch (e) {}
Array.forEach(frame.frames, rec);
})(win);
- return res.filter(function (h) !Set.add(seen, h));
+ return res.filter(h => !seen.add(h));
},
/**
* @param {nsIDOMWindow} win The window for which to find URIs.
* @returns {[nsIURI]} The visible URIs.
*/
- visibleURIs: function (win) {
- let res = [], seen = {};
+ visibleURIs: function visibleURIs(win) {
+ let res = [],
+ seen = RealSet();
(function rec(frame) {
try {
res = res.concat(util.newURI(frame.location.href));
catch (e) {}
Array.forEach(frame.frames, rec);
})(win);
- return res.filter(function (h) !Set.add(seen, h.spec));
+ return res.filter(h => !seen.add(h.spec));
},
/**
* @param {object} self The 'this' object of the method.
* @param ... Arguments to pass to *meth*.
*/
- withProperErrors: function withProperErrors(meth, self) {
+ withProperErrors: function withProperErrors(meth, self, ...args) {
try {
- return (callable(meth) ? meth : self[meth]).apply(self, Array.slice(arguments, withProperErrors.length));
+ return (callable(meth) ? meth : self[meth]).apply(self, args);
}
catch (e) {
throw e.stack ? e : Error(e);
}
- },
-
- xmlToDom: function () DOM.fromXML.apply(DOM, arguments)
+ }
}, {
Array: array
});
-
/**
* Math utility methods.
* @singleton
*/
var GlobalMath = Math;
-var Math = update(Object.create(GlobalMath), {
+this.Math = update(Object.create(GlobalMath), {
/**
* Returns the specified *value* constrained to the range *min* - *max*.
*
} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
-// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript: