X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fmodules%2Futil.jsm;h=a0d0f090f2b06df38c674cce543b1170e1e46901;hb=247daf849abc85f4cfb10fa358c62c8daf8db95b;hp=d6eaf80ceaa1d0430d6886b9c8d6b860bd750bb8;hpb=354a049cce8415487552ce405cce167b7071fe1f;p=dactyl.git diff --git a/common/modules/util.jsm b/common/modules/util.jsm index d6eaf80..a0d0f09 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -1,6 +1,6 @@ // Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2011 by Doug Kearns -// Copyright (c) 2008-2013 Kris Maglione +// Copyright (c) 2008-2014 Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. @@ -10,7 +10,7 @@ try { defineModule("util", { exports: ["DOM", "$", "FailedAssertion", "Math", "NS", "Point", "Util", "XBL", "XHTML", "XUL", "util"], - require: ["dom", "services"] + require: ["dom", "promises", "services"] }); lazyRequire("overlay", ["overlay"]); @@ -72,8 +72,8 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), }, 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), @@ -89,14 +89,13 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), parseForm: deprecated("DOM#formData", function parseForm(elem) values(DOM(elem).formData).toArray()), scrollIntoView: deprecated("DOM#scrollIntoView", function scrollIntoView(elem, alignWithTop) DOM(elem).scrollIntoView(alignWithTop)), validateMatcher: deprecated("DOM.validateMatcher", { get: function validateMatcher() DOM.validateMatcher }), - xmlToDom: deprecated("DOM.fromJSON", function xmlToDom() DOM.fromXML.apply(DOM, arguments)), map: deprecated("iter.map", function map(obj, fn, self) iter(obj).map(fn, self).toArray()), writeToClipboard: deprecated("dactyl.clipboardWrite", function writeToClipboard(str, verbose) util.dactyl.clipboardWrite(str, verbose)), 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) { @@ -138,7 +137,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), 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); } @@ -354,7 +353,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), : "", { elements: [], - seen: {}, + seen: RealSet(), valid: function valid(obj) this.elements.every(e => (!e.test || e.test(obj))) }); @@ -387,15 +386,15 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } 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; @@ -403,7 +402,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), idx = Number(idx) - 1; stack.top.elements.push(update( obj => obj[name] != null && idx in obj[name] ? quote(obj[name][idx]) - : Set.has(obj, name) ? "" : unknown(full), + : hasOwnProperty(obj, name) ? "" : unknown(full), { test: function test(obj) obj[name] != null && idx in obj[name] && obj[name][idx] !== false @@ -413,7 +412,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), else { stack.top.elements.push(update( obj => obj[name] != null ? quote(obj[name]) - : Set.has(obj, name) ? "" : unknown(full), + : hasOwnProperty(obj, name) ? "" : unknown(full), { test: function test(obj) obj[name] != null && obj[name] !== false @@ -422,7 +421,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } for (let elem in array.iterValues(stack)) - elem.seen[name] = true; + elem.seen.add(name); } } } @@ -483,7 +482,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), return obj.res; } - if (pattern.indexOf("{") == -1) + if (!pattern.contains("{")) return [pattern]; let res = []; @@ -517,7 +516,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), 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"))); @@ -545,7 +544,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * @returns {string} */ dequote: function dequote(pattern, chars) - pattern.replace(/\\(.)/, (m0, m1) => chars.indexOf(m1) >= 0 ? m1 : m0), + pattern.replace(/\\(.)/, (m0, m1) => chars.contains(m1) ? m1 : m0), /** * Returns the nsIDocShell for the given window. @@ -750,19 +749,19 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * * @returns {XMLHttpRequest} */ - httpGet: function httpGet(url, callback, self) { - let params = callback; - if (!isObject(params)) - params = { callback: params && ((...args) => callback.apply(self, args)) }; + 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)) { @@ -810,6 +809,22 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } }, + /** + * 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. * @@ -880,7 +895,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), 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()) @@ -1018,12 +1033,18 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), // 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__)) + 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) { @@ -1032,6 +1053,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), value = object[i]; } catch (e) {} + if (!hasValue) { if (isArray(i) && i.length == 2) [i, value] = i; @@ -1088,9 +1110,9 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), function rec(data, level, seen) { if (isObject(data)) { - if (~seen.indexOf(data)) + seen = RealSet(seen); + if (seen.add(data)) throw Error("Recursive object passed"); - seen = seen.concat([data]); } let prefix = level + INDENT; @@ -1138,7 +1160,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } let res = []; - rec(data, "", []); + rec(data, "", RealSet()); return res.join(""); }, @@ -1151,28 +1173,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), 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 dactylRehash() { - 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 dactylPurge() { - this.rehashing = 1; - }, + } }, /** @@ -1230,7 +1231,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * * 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. @@ -1255,10 +1256,10 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), // Replace replacement . if (tokens) expr = String.replace(expr, /(\(?P)?<(\w+)>/g, - (m, n1, n2) => !n1 && Set.has(tokens, n2) ? tokens[n2].dactylSource - || tokens[n2].source - || tokens[n2] - : m); + (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)) @@ -1279,7 +1280,8 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } 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 iterate(str, idx) util.regexp.iterate(this, str, idx) }); @@ -1350,7 +1352,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), 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; @@ -1555,7 +1557,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * 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. @@ -1565,6 +1567,15 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * 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); @@ -1575,7 +1586,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), finally { timer.cancel(); } - return result; + return promise ? retVal: result; }, /** @@ -1595,7 +1606,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * @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() { @@ -1604,7 +1615,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } catch (e if e instanceof StopIteration) {}; })(); - }, + }), /** * Wraps a callback function such that its errors are not lost. This @@ -1673,7 +1684,8 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * @returns {[string]} The visible domains. */ visibleHosts: function visibleHosts(win) { - let res = [], seen = {}; + let res = [], + seen = RealSet(); (function rec(frame) { try { if (frame.location.hostname) @@ -1682,7 +1694,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), catch (e) {} Array.forEach(frame.frames, rec); })(win); - return res.filter(h => !Set.add(seen, h)); + return res.filter(h => !seen.add(h)); }, /** @@ -1693,7 +1705,8 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), * @returns {[nsIURI]} The visible URIs. */ visibleURIs: function visibleURIs(win) { - let res = [], seen = {}; + let res = [], + seen = RealSet(); (function rec(frame) { try { res = res.concat(util.newURI(frame.location.href)); @@ -1701,7 +1714,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), catch (e) {} Array.forEach(frame.frames, rec); })(win); - return res.filter(h => !Set.add(seen, h.spec)); + return res.filter(h => !seen.add(h.spec)); }, /**