diff --git a/common/bootstrap.js b/common/bootstrap.js index 8ecb3b1f..92b5133b 100755 --- a/common/bootstrap.js +++ b/common/bootstrap.js @@ -56,7 +56,7 @@ function httpGet(uri) { let moduleName; let initialized = false; -let addon = null; +var addon = null; let addonData = null; let basePath = null; let bootstrap; @@ -199,23 +199,27 @@ let JSMLoader = { manager.unregisterFactory(factory.classID, factory); }, - Factory: function Factory(class_) ({ - __proto__: class_.prototype, + Factory(class_) { + let res = Object.create(class_.prototype); - createInstance: function (outer, iid) { + res.createInstance = function (outer, iid) { try { if (outer != null) throw Cr.NS_ERROR_NO_AGGREGATION; + if (!class_.instance) class_.instance = new class_(); + return class_.instance.QueryInterface(iid); } catch (e) { Cu.reportError(e); throw e; } - } - }), + }; + + return res; + }, registerFactory: function registerFactory(factory) { manager.registerFactory(factory.classID, diff --git a/common/content/abbreviations.js b/common/content/abbreviations.js index a3d8d0fe..e264666a 100644 --- a/common/content/abbreviations.js +++ b/common/content/abbreviations.js @@ -1,6 +1,6 @@ // Copyright (c) 2006-2009 by Martin Stubenschrott // Copyright (c) 2010 by anekos -// Copyright (c) 2010-2014 Kris Maglione +// Copyright (c) 2010-2015 Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. @@ -142,8 +142,8 @@ var AbbrevHive = Class("AbbrevHive", Contexts.Hive, { */ get: function (mode, lhs) { let abbrevs = this._store[mode]; - return abbrevs && hasOwnProperty(abbrevs, lhs) ? abbrevs[lhs] - : null; + return abbrevs && hasOwnProp(abbrevs, lhs) ? abbrevs[lhs] + : null; }, /** @@ -225,28 +225,29 @@ var Abbreviations = Module("abbreviations", { nonkeyword: /[ "']/ }; - this._match = util.regexp(literal(function () /* + this._match = util.regexp(String.raw` (^ | \s | ) (+ )$ | // full-id (^ | \s | ) (+ )$ | // end-id (^ | \s ) (\S* )$ // non-id - */$), "x", params); - this._check = util.regexp(literal(function () /* + `, "x", params); + + this._check = util.regexp(String.raw` ^ (?: + | // full-id + | // end-id \S* // non-id ) $ - */$), "x", params); + `, "x", params); }, get allHives() { return contexts.allGroups.abbrevs; }, get userHives() { return this.allHives.filter(h => h !== this.builtin); }, - get: deprecated("group.abbrevs.get", { get: function get() this.user.bound.get }), - set: deprecated("group.abbrevs.set", { get: function set() this.user.bound.set }), - remove: deprecated("group.abbrevs.remove", { get: function remove() this.user.bound.remove }), - removeAll: deprecated("group.abbrevs.clear", { get: function removeAll() this.user.bound.clear }), + get: deprecated("group.abbrevs.get", { get: function get() { return this.user.bound.get; } }), + set: deprecated("group.abbrevs.set", { get: function set() { return this.user.bound.set; } }), + remove: deprecated("group.abbrevs.remove", { get: function remove() { return this.user.bound.remove; } }), + removeAll: deprecated("group.abbrevs.clear", { get: function removeAll() { return this.user.bound.clear; } }), /** * Returns the abbreviation for the given *mode* if *text* matches the diff --git a/common/content/autocommands.js b/common/content/autocommands.js index 8407f90d..a09ac10d 100644 --- a/common/content/autocommands.js +++ b/common/content/autocommands.js @@ -79,9 +79,9 @@ var AutoCommands = Module("autocommands", { return contexts.allGroups.autocmd.filter(h => h._store.length); }, - add: deprecated("group.autocmd.add", { get: function add() autocommands.user.bound.add }), - get: deprecated("group.autocmd.get", { get: function get() autocommands.user.bound.get }), - remove: deprecated("group.autocmd.remove", { get: function remove() autocommands.user.bound.remove }), + add: deprecated("group.autocmd.add", { get: function add() { return autocommands.user.bound.add; } }), + get: deprecated("group.autocmd.get", { get: function get() { return autocommands.user.bound.get; } }), + remove: deprecated("group.autocmd.remove", { get: function remove() { return autocommands.user.bound.remove; } }), /** * Lists all autocommands with a matching *event*, *regexp* and optionally diff --git a/common/content/bookmarks.js b/common/content/bookmarks.js index b53c722d..080a65c7 100644 --- a/common/content/bookmarks.js +++ b/common/content/bookmarks.js @@ -77,7 +77,7 @@ var Bookmarks = Module("bookmarks", { if (id != null) var bmark = bookmarkcache.bookmarks[id]; else if (!force) { - if (keyword && hasOwnProperty(bookmarkcache.keywords, keyword)) + if (keyword && hasOwnProp(bookmarkcache.keywords, keyword)) bmark = bookmarkcache.keywords[keyword]; else if (bookmarkcache.isBookmarked(uri)) for (bmark of bookmarkcache) @@ -178,7 +178,7 @@ var Bookmarks = Module("bookmarks", { } }, - isBookmarked: deprecated("bookmarkcache.isBookmarked", { get: function isBookmarked() bookmarkcache.bound.isBookmarked }), + isBookmarked: deprecated("bookmarkcache.isBookmarked", { get: function isBookmarked() { return bookmarkcache.bound.isBookmarked; } }), /** * Remove a bookmark or bookmarks. If *ids* is an array, removes the @@ -213,7 +213,7 @@ var Bookmarks = Module("bookmarks", { } }, - getSearchEngines: deprecated("bookmarks.searchEngines", function getSearchEngines() this.searchEngines), + getSearchEngines: deprecated("bookmarks.searchEngines", function getSearchEngines() { return this.searchEngines; }), /** * Returns a list of all visible search engines in the search * services, augmented with keyword, title, and icon properties for @@ -228,7 +228,7 @@ var Bookmarks = Module("bookmarks", { if (!alias) alias = "search"; // for search engines which we can't find a suitable alias - if (hasOwnProperty(aliases, alias)) + if (hasOwnProp(aliases, alias)) alias += ++aliases[alias]; else aliases[alias] = 0; @@ -252,10 +252,10 @@ var Bookmarks = Module("bookmarks", { hasSuggestions: function hasSuggestions(engineName, query, callback) { const responseType = "application/x-suggestions+json"; - if (hasOwnProperty(this.suggestionProviders, engineName)) + if (hasOwnProp(this.suggestionProviders, engineName)) return true; - let engine = hasOwnProperty(this.searchEngines, engineName) && this.searchEngines[engineName]; + let engine = hasOwnProp(this.searchEngines, engineName) && this.searchEngines[engineName]; if (engine && engine.supportsResponseType(responseType)) return true; @@ -281,10 +281,10 @@ var Bookmarks = Module("bookmarks", { getSuggestions: function getSuggestions(engineName, query, callback) { const responseType = "application/x-suggestions+json"; - if (hasOwnProperty(this.suggestionProviders, engineName)) + if (hasOwnProp(this.suggestionProviders, engineName)) return this.suggestionProviders[engineName](query, callback); - let engine = hasOwnProperty(this.searchEngines, engineName) && this.searchEngines[engineName]; + let engine = hasOwnProp(this.searchEngines, engineName) && this.searchEngines[engineName]; if (engine && engine.supportsResponseType(responseType)) var queryURI = engine.getSubmission(query, responseType).uri.spec; @@ -347,7 +347,7 @@ var Bookmarks = Module("bookmarks", { let [keyword, param] = util.split(query, " ", 2); param = param || ""; - var engine = hasOwnProperty(bookmarks.searchEngines, keyword) && bookmarks.searchEngines[keyword]; + var engine = hasOwnProp(bookmarks.searchEngines, keyword) && bookmarks.searchEngines[keyword]; if (engine) { if (engine.searchForm && !param) return engine.searchForm; diff --git a/common/content/commandline.js b/common/content/commandline.js index 326d84c3..def05642 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -975,7 +975,7 @@ var CommandLine = Module("commandline", { } }, - updateOutputHeight: deprecated("mow.resize", function updateOutputHeight(open, extra) mow.resize(open, extra)), + updateOutputHeight: deprecated("mow.resize", function updateOutputHeight(open, extra) { return mow.resize(open, extra); }), withOutputToString: function withOutputToString(fn, self, ...args) { dactyl.registerObserver("echoLine", observe, true); diff --git a/common/content/dactyl.js b/common/content/dactyl.js index f8d5b738..e82ae90a 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -54,9 +54,9 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { delete window.liberator; // Prevents box ordering bugs after our stylesheet is removed. - styles.system.add("cleanup-sheet", config.styleableChrome, literal(function () /* + styles.system.add("cleanup-sheet", config.styleableChrome, String.raw` #TabsToolbar tab { display: none; } - */$)); + `); styles.unregisterSheet("resource://dactyl-skin/dactyl.css"); DOM('#TabsToolbar tab', document).style.display; }, @@ -113,15 +113,15 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { } }, - profileName: deprecated("config.profileName", { get: function profileName() config.profileName }), + profileName: deprecated("config.profileName", { get: function profileName() { return config.profileName; } }), /** * @property {Modes.Mode} The current main mode. * @see modes#mainModes */ mode: deprecated("modes.main", { - get: function mode() modes.main, - set: function mode(val) modes.main = val + get: function mode() { return modes.main; }, + set: function mode(val) { modes.main = val; }, }), getMenuItems: function getMenuItems(targetPath) { @@ -176,7 +176,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { this[v] = val[k]; }, - version: deprecated("config.version", { get: function version() config.version }), + version: deprecated("config.version", { get: function version() { return config.version; } }), /** * @property {Object} The map of command-line options. These are @@ -280,7 +280,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { for (let obj of results) { let res = dactyl.generateHelp(obj, null, null, true); - if (!hasOwnProperty(help.tags, obj.helpTag)) + if (!hasOwnProp(help.tags, obj.helpTag)) res[0][1].tag = obj.helpTag; yield res; @@ -386,9 +386,9 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }, dump: deprecated("util.dump", - { get: function dump() util.bound.dump }), + { get: function dump() { return util.bound.dump; } }), dumpStack: deprecated("util.dumpStack", - { get: function dumpStack() util.bound.dumpStack }), + { get: function dumpStack() { return util.bound.dumpStack; } }), /** * Outputs a plain message to the command line. @@ -638,8 +638,8 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { } }, - help: deprecated("help.help", { get: function help() modules.help.bound.help }), - findHelp: deprecated("help.findHelp", { get: function findHelp() help.bound.findHelp }), + help: deprecated("help.help", { get: function help() { return modules.help.bound.help; } }), + findHelp: deprecated("help.findHelp", { get: function findHelp() { return help.bound.findHelp; } }), /** * @private @@ -762,7 +762,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { */ _globalVariables: {}, globalVariables: deprecated(_("deprecated.for.theOptionsSystem"), { - get: function globalVariables() this._globalVariables + get: function globalVariables() { return this._globalVariables }, }), loadPlugins: function loadPlugins(args, force) { @@ -1053,15 +1053,15 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }, this); }, stringToURLArray: deprecated("dactyl.parseURLs", "parseURLs"), - urlish: Class.Memoize(() => util.regexp(literal(function () /* + urlish: Class.Memoize(() => util.regexp(String.raw` ^ ( + (:\d+)? (/ .*) | + (:\d+) | + \. [a-z0-9]+ | localhost ) $ - */$), "ix", { - domain: util.regexp(String.replace(literal(function () /* + `, "ix", { + domain: util.regexp(String.raw` [^ U0000-U002c // U002d-U002e --. U002f // / @@ -1070,7 +1070,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { U005b-U0060 // U0061-U007a A-Z U007b-U007f ] - */$), /U/g, "\\u"), "x") + `.replace(/U/g, "\\u"), "x") })), pluginFiles: {}, @@ -1878,8 +1878,8 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { context.anchored = false; context.keys = { text: "dactylPath", - description: function (item) item.getAttribute("label"), - highlight: function (item) item.disabled ? "Disabled" : "" + description: item => item.getAttribute("label"), + highlight: item => item.disabled ? "Disabled" : "", }; context.generate = () => dactyl.menuItems; }; @@ -1888,7 +1888,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { context.title = ["Toolbar"]; context.keys = { text: Dactyl.getToolbarName, - description: function () "" + description: () => "", }; context.completions = config.toolbars; }; @@ -1905,7 +1905,12 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { dactyl.log(_("dactyl.modulesLoaded"), 3); - userContext.DOM = Class("DOM", DOM, { init: function DOM_(sel, ctxt) DOM(sel, ctxt || buffer.focusedFrame.document) }); + userContext.DOM = Class("DOM", DOM, { + init(sel, ctxt) { + return DOM(sel, ctxt || buffer.focusedFrame.document); + } + }); + userContext.$ = modules.userContext.DOM; // Hack: disable disabling of Personas in private windows. @@ -2038,6 +2043,13 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { statusline.update(); dactyl.log(_("dactyl.initialized", config.appName), 0); dactyl.initialized = true; + + util.delay(() => { + if (services.focus.activeWindow === window) + overlay.activeWindow = window; + + util.flushLateMethods(dactyl); + }); } }); diff --git a/common/content/editor.js b/common/content/editor.js index eff4c0b0..31eaa58e 100644 --- a/common/content/editor.js +++ b/common/content/editor.js @@ -75,7 +75,7 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), { name = 0; if (name == "_") var res = null; - else if (hasOwnProperty(this.selectionRegisters, name)) + else if (hasOwnProp(this.selectionRegisters, name)) res = { text: dactyl.clipboardRead(this.selectionRegisters[name]) || "" }; else if (!/^[0-9]$/.test(name)) res = this.registers.get(name); @@ -113,7 +113,7 @@ var Editor = Module("editor", XPCOM(Ci.nsIEditActionListener, ModuleBase), { n = 0; if (n == "_") ; - else if (hasOwnProperty(this.selectionRegisters, n)) + else if (hasOwnProp(this.selectionRegisters, n)) dactyl.clipboardWrite(value.text, verbose, this.selectionRegisters[n]); else if (!/^[0-9]$/.test(n)) this.registers.set(n, value); diff --git a/common/content/events.js b/common/content/events.js index b833372d..abe17cf3 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -28,7 +28,7 @@ var EventHive = Class("EventHive", Contexts.Hive, { else [self, events] = [event, event[callback || "events"]]; - if (hasOwnProperty(events, "input") && !hasOwnProperty(events, "dactyl-input")) + if (hasOwnProp(events, "input") && !hasOwnProp(events, "dactyl-input")) events["dactyl-input"] = events.input; return [self, events]; @@ -79,7 +79,7 @@ var EventHive = Class("EventHive", Contexts.Hive, { let elem = args[0].get(); if (target == null || elem == target && self == args[1].get() - && hasOwnProperty(events, args[2]) + && hasOwnProp(events, args[2]) && args[3].wrapped == events[args[2]] && args[4] == capture) { @@ -212,7 +212,7 @@ var Events = Module("events", { }, get listen() { return this.builtin.bound.listen; }, - addSessionListener: deprecated("events.listen", { get: function addSessionListener() this.listen }), + addSessionListener: deprecated("events.listen", { get: function addSessionListener() { return this.listen; } }), /** * Wraps an event listener to ensure that errors are reported. @@ -423,11 +423,11 @@ var Events = Module("events", { return true; }, - canonicalKeys: deprecated("DOM.Event.canonicalKeys", { get: function canonicalKeys() DOM.Event.bound.canonicalKeys }), - create: deprecated("DOM.Event", function create() DOM.Event.apply(null, arguments)), - dispatch: deprecated("DOM.Event.dispatch", function dispatch() apply(DOM.Event, "dispatch", arguments)), - fromString: deprecated("DOM.Event.parse", { get: function fromString() DOM.Event.bound.parse }), - iterKeys: deprecated("DOM.Event.iterKeys", { get: function iterKeys() DOM.Event.bound.iterKeys }), + canonicalKeys: deprecated("DOM.Event.canonicalKeys", { get: function canonicalKeys() { return DOM.Event.bound.canonicalKeys; } }), + create: deprecated("DOM.Event", function create() { return DOM.Event.apply(null, arguments); }), + dispatch: deprecated("DOM.Event.dispatch", function dispatch() { return apply(DOM.Event, "dispatch", arguments); }), + fromString: deprecated("DOM.Event.parse", { get: function fromString() { return DOM.Event.bound.parse; } }), + iterKeys: deprecated("DOM.Event.iterKeys", { get: function iterKeys() { return DOM.Event.bound.iterKeys; } }), toString: function toString() { if (!arguments.length) @@ -1152,7 +1152,7 @@ var Events = Module("events", { has: function (key) { return this.pass.has(key) || - hasOwnProperty(this.commandHive.stack.mappings, key); + hasOwnProp(this.commandHive.stack.mappings, key); }, get pass() { this.flush(); return this.pass; }, diff --git a/common/content/mappings.js b/common/content/mappings.js index cfa2a989..9e4c7e20 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -39,7 +39,7 @@ var Map = Class("Map", { Object.freeze(this.modes); if (info) { - if (hasOwnProperty(Map.types, info.type)) + if (hasOwnProp(Map.types, info.type)) this.update(Map.types[info.type]); this.update(info); } @@ -370,7 +370,7 @@ var Mappings = Module("mappings", { get userHives() { return this.allHives.filter(h => h !== this.builtin); }, - expandLeader: deprecated("your brain", function expandLeader(keyString) keyString), + expandLeader: deprecated("your brain", function expandLeader(keyString) { return keyString; }), prefixes: Class.Memoize(function () { let list = Array.map("CASM", s => s + "-"); @@ -415,11 +415,11 @@ var Mappings = Module("mappings", { return this.iterate(modes.NORMAL); }, - getDefault: deprecated("mappings.builtin.get", function getDefault(mode, cmd) this.builtin.get(mode, cmd)), - getUserIterator: deprecated("mappings.user.iterator", function getUserIterator(modes) this.user.iterator(modes)), - hasMap: deprecated("group.mappings.has", function hasMap(mode, cmd) this.user.has(mode, cmd)), - remove: deprecated("group.mappings.remove", function remove(mode, cmd) this.user.remove(mode, cmd)), - removeAll: deprecated("group.mappings.clear", function removeAll(mode) this.user.clear(mode)), + getDefault: deprecated("mappings.builtin.get", function getDefault(mode, cmd) { return this.builtin.get(mode, cmd); }), + getUserIterator: deprecated("mappings.user.iterator", function getUserIterator(modes) { return this.user.iterator(modes); }), + hasMap: deprecated("group.mappings.has", function hasMap(mode, cmd) { return this.user.has(mode, cmd); }), + remove: deprecated("group.mappings.remove", function remove(mode, cmd) { return this.user.remove(mode, cmd); }), + removeAll: deprecated("group.mappings.clear", function removeAll(mode) { return this.user.clear(mode); }), /** * Adds a new default key mapping. @@ -839,7 +839,7 @@ var Mappings = Module("mappings", { iterateIndex: function (args) { let self = this; let prefix = /^[bCmn]$/.test(mode.char) ? "" : mode.char + "_"; - let haveTag = k => hasOwnProperty(help.tags, k); + let haveTag = k => hasOwnProp(help.tags, k); return ({ helpTag: prefix + map.name, __proto__: map } for (map of self.iterate(args, true)) diff --git a/common/content/modes.js b/common/content/modes.js index 3a3d8332..c1842f4d 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -659,7 +659,7 @@ var Modes = Module("modes", { return (this.value.find(v => val.some(m => m.name === v.mode)) || { result: default_ }).result; - return hasOwnProperty(this.valueMap, val) ? this.valueMap[val] : default_; + return hasOwnProp(this.valueMap, val) ? this.valueMap[val] : default_; }, setter: function (vals) { @@ -678,7 +678,7 @@ var Modes = Module("modes", { validator: function validator(vals) { return vals.map(v => v.replace(/^!/, "")) - .every(k => hasOwnProperty(this.values, k)); + .every(k => hasOwnProp(this.values, k)); }, get values() { diff --git a/common/content/mow.js b/common/content/mow.js index f31217a8..fe26b3af 100644 --- a/common/content/mow.js +++ b/common/content/mow.js @@ -7,8 +7,22 @@ "use strict"; var MOW = Module("mow", { - init: function init() { + init() { + let proxy = new Proxy(this, { + get(target, prop, receiver) { + if (prop in target) + return target[prop]; + if (prop in Buffer) + return Buffer[prop].bind(Buffer, receiver.body); + }, + }); + + proxy._init(); + return proxy; + }, + + _init() { this._resize = Timer(20, 400, function _resize() { if (this.visible) this.resize(false); @@ -66,10 +80,6 @@ var MOW = Module("mow", { }); }, - __noSuchMethod__: function (meth, args) { - return apply(Buffer, meth, [this.body].concat(args)); - }, - get widget() { return this.widgets.multilineOutput; }, widgets: Class.Memoize(function widgets() { diff --git a/common/content/statusline.js b/common/content/statusline.js index 8d312632..dd863166 100644 --- a/common/content/statusline.js +++ b/common/content/statusline.js @@ -37,27 +37,31 @@ var StatusLine = Module("statusline", { config.tabbrowser.getStatusPanel().hidden = true; if (this.statusBar.localName == "toolbar") { - styles.system.add("addon-bar", config.styleableChrome, literal(function () /* + styles.system.add("addon-bar", config.styleableChrome, String.raw` #status-bar, #dactyl-status-bar { margin-top: 0 !important; } #dactyl-status-bar { min-height: 0 !important; } :-moz-any(#addon-bar, #dactyl-addon-bar) > statusbar { -moz-box-flex: 1 } :-moz-any(#addon-bar, #dactyl-addon-bar) > xul|toolbarspring { visibility: collapse; } #browser-bottombox>#addon-bar > #addonbar-closebutton { visibility: collapse; } - */$)); + `); overlay.overlayWindow(window, { append: [ ["statusbar", { id: this._statusLine.id, ordinal: "0" }]] }); - highlight.loadCSS(util.compileMacro(literal(function () /* + let padding = ""; + if (config.OS.isMacOSX) + padding = "padding-right: 10px !important;"; + + highlight.loadCSS(String.raw` !AddonBar;#browser-bottombox>#addon-bar,#dactyl-addon-bar { padding-left: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; min-height: 18px !important; -moz-appearance: none !important; - + ${padding} } !AddonButton;#browser-bottombox>#addon-bar xul|toolbarbutton, #dactyl-addon-bar xul|toolbarbutton { -moz-appearance: none !important; @@ -67,12 +71,12 @@ var StatusLine = Module("statusline", { color: inherit !important; } AddonButton:not(:hover) background: transparent; - */$))({ padding: config.OS.isMacOSX ? "padding-right: 10px !important;" : "" })); + `); if (document.getElementById("appmenu-button")) - highlight.loadCSS(literal(function () /* + highlight.loadCSS(String.raw` AppmenuButton min-width: 0 !important; padding: 0 .5em !important; - */$)); + `); } let prepend = [ @@ -239,8 +243,8 @@ var StatusLine = Module("statusline", { this.updateZoomLevel(); }, - unsafeURI: deprecated("util.unsafeURI", { get: function unsafeURI() util.unsafeURI }), - losslessDecodeURI: deprecated("util.losslessDecodeURI", function losslessDecodeURI() apply(util, "losslessDecodeURI", arguments)), + unsafeURI: deprecated("util.unsafeURI", { get: function unsafeURI() { return util.unsafeURI; } }), + losslessDecodeURI: deprecated("util.losslessDecodeURI", function losslessDecodeURI() { return apply(util, "losslessDecodeURI", arguments); }), /** * Update the URL displayed in the status line. Also displays status diff --git a/common/content/tabs.js b/common/content/tabs.js index acc20f4f..8ac04faf 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -36,9 +36,11 @@ var Tabs = Module("tabs", { tabs.switchTo(event.originalTarget.getAttribute("identifier")); }; - this.tabBinding = styles.system.add("tab-binding", "chrome://browser/content/browser.xul", literal(function () /* + this.tabBinding = styles.system.add( + "tab-binding", "chrome://browser/content/browser.xul", + String.raw` xul|tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#tab) !important; } - */$).replace(/tab-./g, m => config.OS.isMacOSX ? "tab-mac" : m), + `, false, true); this.timeout(function () { @@ -133,10 +135,11 @@ var Tabs = Module("tabs", { * in the current window. */ get browsers() { - let browsers = config.tabbrowser.browsers; - for (let i = 0; i < browsers.length; i++) - if (browsers[i] !== undefined) // Bug in Google's Page Speed add-on. - yield [i, browsers[i]]; + return function* () { + for (let [i, browser] of config.tabbrowser.browsers.entries()) + if (browser !== undefined) // Bug in Google's Page Speed add-on. + yield [i, browser]; + }(); }, /** @@ -1064,7 +1067,7 @@ var Tabs = Module("tabs", { tabs.getGroups(); tabs[visible ? "visibleTabs" : "allTabs"].forEach(function (tab, i) { let group = (tab.tabItem || tab._tabViewTabItem || defItem).parent || defItem.parent; - if (!hasOwnProperty(tabGroups, group.id)) + if (!hasOwnProp(tabGroups, group.id)) tabGroups[group.id] = [group.getTitle(), []]; group = tabGroups[group.id]; diff --git a/common/modules/addons.jsm b/common/modules/addons.jsm index 7e448d73..f51480ab 100644 --- a/common/modules/addons.jsm +++ b/common/modules/addons.jsm @@ -167,7 +167,7 @@ var Addon = Class("Addon", { }, commandAllowed: function commandAllowed(cmd) { - util.assert(hasOwnProperty(actions, cmd), + util.assert(hasOwnProp(actions, cmd), _("addon.unknownCommand")); let action = actions[cmd]; diff --git a/common/modules/base.jsm b/common/modules/base.jsm index d2d4b39b..709406c8 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -26,10 +26,12 @@ try { catch (e) {} let objproto = Object.prototype; -let { __lookupGetter__, __lookupSetter__, __defineGetter__, __defineSetter__, +var { __lookupGetter__, __lookupSetter__, __defineGetter__, __defineSetter__, hasOwnProperty, propertyIsEnumerable } = objproto; -hasOwnProperty = Function.call.bind(hasOwnProperty); +var hasOwnProp = Function.call.bind(hasOwnProperty); + +hasOwnProperty = hasOwnProp; propertyIsEnumerable = Function.call.bind(propertyIsEnumerable); function require(module_, target) { @@ -43,7 +45,7 @@ function lazyRequire(module, names, target) { memoize(target || this, name, name => require(module)[name]); } -let jsmodules = { lazyRequire: lazyRequire }; +var jsmodules = { lazyRequire: lazyRequire }; jsmodules.jsmodules = jsmodules; function toString() { @@ -62,10 +64,10 @@ function objToString(obj) { } } -let use = {}; -let loaded = {}; -let currentModule; -let global = this; +var use = {}; +var loaded = {}; +var currentModule; +var global = this; function defineModule(name, params, module) { if (!module) module = this; @@ -203,6 +205,7 @@ defineModule("base", { "deprecated", "endModule", "hasOwnProperty", + "hasOwnProp", "identity", "isArray", "isGenerator", @@ -238,9 +241,7 @@ if (typeof Symbol == "undefined") iterator: "@@iterator" }; -literal.files = {}; -literal.locations = {}; -function literal(comment) { +let literal_ = function literal(comment) { if (comment) return /^function.*?\/\*([^]*)\*\/(?:\/\* use strict \*\/)\s*\S$/.exec(comment)[1]; @@ -248,6 +249,9 @@ function literal(comment) { while (caller && caller.language != 2) caller = caller.caller; + // Immediate caller is the `deprecate` helper. + caller = caller.caller; + let file = caller.filename.replace(/.* -> /, ""); let key = "literal:" + file + ":" + caller.lineNumber; return cache.get(key, function() { @@ -258,7 +262,15 @@ function literal(comment) { ".*literal\\(/\\*([^]*?)\\*/\\)").exec(source); return match[1]; }); -} +}; +literal_.files = {}; +literal_.locations = {}; + +// This needs to happen after `files` and `locations` have been defined +// as properties of the real `literal` function. +var literal = deprecated("template strings", literal_); +literal.files = literal_.files; +literal.locations = literal_.locations; function apply(obj, meth, args) { // The function's own apply method breaks in strange ways @@ -403,7 +415,7 @@ function keys(obj) { return iter(obj.keys()); return iter(k for (k in obj) - if (hasOwnProperty(obj, k))); + if (hasOwnProp(obj, k))); } /** @@ -424,7 +436,7 @@ function values(obj) { return iter(obj[Symbol.iterator]()); return iter(obj[k] for (k in obj) - if (hasOwnProperty(obj, k))); + if (hasOwnProp(obj, k))); } var RealSet = Set; @@ -513,7 +525,7 @@ Set.has = deprecated("hasOwnProperty or Set#has", if (isinstance(set, ["Set"])) return set.has(key); - return hasOwnProperty(set, key) && + return hasOwnProp(set, key) && propertyIsEnumerable(set, key); })); /** @@ -807,13 +819,17 @@ function memoize(obj, key, getter) { function update(target) { for (let i = 1; i < arguments.length; i++) { let src = arguments[i]; + Object.getOwnPropertyNames(src || {}).forEach(function (k) { let desc = Object.getOwnPropertyDescriptor(src, k); if (desc.value instanceof Class.Property) desc = desc.value.init(k, target) || desc.value; try { - if (callable(desc.value) && target.__proto__) { + if (callable(desc.value) && + Cu.getClassName(desc.value, true) != "Proxy" && + Object.getPrototypeOf(target)) { + let func = desc.value.wrapped || desc.value; if (!func.superapply) { func.__defineGetter__("super", function get_super() { @@ -836,7 +852,9 @@ function update(target) { Object.defineProperty(target, k, desc); } - catch (e) {} + catch (e) { + dump("Hmm... " + e + "\n" + (e && e.stack || new Error().stack) + "\n"); + } }); } return target; @@ -1184,7 +1202,7 @@ for (let name of properties(Class.prototype)) { var closureHooks = { get: function closure_get(target, prop) { - if (hasOwnProperty(target._closureCache, prop)) + if (hasOwnProp(target._closureCache, prop)) return target._closureCache[prop]; let p = target[prop]; @@ -1347,7 +1365,9 @@ Module.INIT = { module.isLocalModule = true; modules.jsmodules[this.constructor.className] = module; - locals.reverse().forEach((fn, i) => { update(objs[i], fn.apply(module, args)); }); + locals.reverse().forEach((fn, i) => { + update(objs[i], fn.apply(module, args)); + }); memoize(module, "closure", Class.makeClosure); module.instance = module; @@ -1544,7 +1564,7 @@ function UTF8(str) { } } -var octal = deprecated("octal integer literals", function octal(decimal) parseInt(decimal, 8)); +var octal = deprecated("octal integer literals", function octal(decimal) { return parseInt(decimal, 8); }); /** * Iterates over an arbitrary object. The following iterator types are @@ -1777,8 +1797,8 @@ update(iter, { } }); -const Iter = Class("Iter", { - init: function init(iter) { +var Iter = Class("Iter", { + init(iter) { this.iter = iter; if (!(Symbol.iterator in iter) && "__iterator__" in iter) this.iter = iter.__iterator__(); @@ -1789,11 +1809,11 @@ const Iter = Class("Iter", { }; }, - next: function next() this.iter.next(), + next() { return this.iter.next() }, - send: function send() apply(this.iter, "send", arguments), + send() { return apply(this.iter, "send", arguments) }, - "@@iterator": function () this.iter, + "@@iterator": function () { return this.iter }, __iterator__: function () { Cu.reportError( @@ -1837,7 +1857,7 @@ var Ary = Class("Ary", Array, { if (prop == "array") return target; - if (hasOwnProperty(Ary, prop) && callable(Ary[prop])) + if (hasOwnProp(Ary, prop) && callable(Ary[prop])) return arrayWrap(Ary[prop].bind(Ary, target)); let p = target[prop]; @@ -1882,7 +1902,7 @@ var Ary = Class("Ary", Array, { * @param {Array} ary * @returns {Array} */ - compact: function compact(ary) ary.filter(item => item != null), + compact(ary) { return ary.filter(item => item != null) }, /** * Returns true if each element of ary1 is equal to the @@ -1892,8 +1912,10 @@ var Ary = Class("Ary", Array, { * @param {Array} ary2 * @returns {boolean} */ - equals: function (ary1, ary2) - ary1.length === ary2.length && Array.every(ary1, (e, i) => e === ary2[i]), + equals(ary1, ary2) { + return (ary1.length === ary2.length && + Array.every(ary1, (e, i) => e === ary2[i])); + }, /** * Flattens an array, such that all elements of the array are @@ -1903,7 +1925,11 @@ var Ary = Class("Ary", Array, { * @param {Array} ary * @returns {Array} */ - flatten: function flatten(ary) ary.length ? Array.prototype.concat.apply([], ary) : [], + flatten(ary) { + if (ary.length) + return [].concat(...ary); + return []; + }, /** * Returns an Iterator for an array's values. @@ -1980,11 +2006,10 @@ var Ary = Class("Ary", Array, { } }); -/* Make Minefield not explode, because Minefield exploding is not fun. */ let iterProto = Iter.prototype; Object.keys(iter).forEach(function (k) { iterProto[k] = function (...args) { - let res = apply(iter, k, [this].concat(args)); + let res = iter[k](this, ...args); if (k == "toArray") return res; @@ -1999,7 +2024,7 @@ Object.keys(iter).forEach(function (k) { Object.keys(Ary).forEach(function (k) { if (!(k in iterProto)) iterProto[k] = function (...args) { - let res = apply(Ary, k, [this.toArray()].concat(args)); + let res = Ary[k]([...this], ...args); if (isArray(res)) return Ary(res); @@ -2012,9 +2037,8 @@ Object.keys(Ary).forEach(function (k) { Object.getOwnPropertyNames(Array.prototype).forEach(function (k) { if (!(k in iterProto) && callable(Array.prototype[k])) - iterProto[k] = function () { - let ary = this.toArray(); - let res = apply(ary, k, arguments); + iterProto[k] = function (...args) { + let res = [...this][k](...args); if (isArray(res)) return Ary(res); @@ -2024,7 +2048,7 @@ Object.getOwnPropertyNames(Array.prototype).forEach(function (k) { }); Object.defineProperty(Class.prototype, "closure", - deprecated("bound", { get: function closure() this.bound })); + deprecated("bound", { get: function closure() { return this.bound; } })); if (false) var array = Class("array", Ary, { diff --git a/common/modules/buffer.jsm b/common/modules/buffer.jsm index fee773ca..7b19719d 100644 --- a/common/modules/buffer.jsm +++ b/common/modules/buffer.jsm @@ -385,7 +385,8 @@ var Buffer = Module("Buffer", { * @returns {string} */ get currentWord() { return Buffer.currentWord(this.focusedFrame); }, - getCurrentWord: deprecated("buffer.currentWord", function getCurrentWord() Buffer.currentWord(this.focusedFrame, true)), + getCurrentWord: deprecated("buffer.currentWord", + function getCurrentWord() { return Buffer.currentWord(this.focusedFrame, true); }), /** * Returns true if a scripts are allowed to focus the given input @@ -770,7 +771,8 @@ var Buffer = Module("Buffer", { * * @param {Node} elem The context element. */ - openContextMenu: deprecated("DOM#contextmenu", function openContextMenu(elem) DOM(elem).contextmenu()), + openContextMenu: deprecated("DOM#contextmenu", + function openContextMenu(elem) { return DOM(elem).contextmenu(); }), /** * Saves a page link to disk. @@ -1415,14 +1417,14 @@ var Buffer = Module("Buffer", { }, getAllFrames: deprecated("buffer.allFrames", "allFrames"), - scrollTop: deprecated("buffer.scrollToPercent", function scrollTop() this.scrollToPercent(null, 0)), - scrollBottom: deprecated("buffer.scrollToPercent", function scrollBottom() this.scrollToPercent(null, 100)), - scrollStart: deprecated("buffer.scrollToPercent", function scrollStart() this.scrollToPercent(0, null)), - scrollEnd: deprecated("buffer.scrollToPercent", function scrollEnd() this.scrollToPercent(100, null)), - scrollColumns: deprecated("buffer.scrollHorizontal", function scrollColumns(cols) this.scrollHorizontal("columns", cols)), - scrollPages: deprecated("buffer.scrollHorizontal", function scrollPages(pages) this.scrollVertical("pages", pages)), - scrollTo: deprecated("Buffer.scrollTo", function scrollTo(x, y) this.win.scrollTo(x, y)), - textZoom: deprecated("buffer.zoomValue/buffer.fullZoom", function textZoom() this.contentViewer.markupDocumentViewer.textZoom * 100) + scrollTop: deprecated("buffer.scrollToPercent", function scrollTop() { return this.scrollToPercent(null, 0); }), + scrollBottom: deprecated("buffer.scrollToPercent", function scrollBottom() { return this.scrollToPercent(null, 100); }), + scrollStart: deprecated("buffer.scrollToPercent", function scrollStart() { return this.scrollToPercent(0, null); }), + scrollEnd: deprecated("buffer.scrollToPercent", function scrollEnd() { return this.scrollToPercent(100, null); }), + scrollColumns: deprecated("buffer.scrollHorizontal", function scrollColumns(cols) { return this.scrollHorizontal("columns", cols); }), + scrollPages: deprecated("buffer.scrollHorizontal", function scrollPages(pages) { return this.scrollVertical("pages", pages); }), + scrollTo: deprecated("Buffer.scrollTo", function scrollTo(x, y) { return this.win.scrollTo(x, y); }), + textZoom: deprecated("buffer.zoomValue/buffer.fullZoom", function textZoom() { return this.contentViewer.markupDocumentViewer.textZoom * 100; }), }, { /** * The pattern used to search for a scrollable element when we have @@ -1508,9 +1510,9 @@ var Buffer = Module("Buffer", { get ZOOM_MAX() { return prefs.get("zoom.maxPercent"); }, setZoom: deprecated("buffer.setZoom", - function setZoom(...args) apply(overlay.activeModules.buffer, "setZoom", args)), + function setZoom(...args) { return apply(overlay.activeModules.buffer, "setZoom", args); }), bumpZoomLevel: deprecated("buffer.bumpZoomLevel", - function bumpZoomLevel(...args) apply(overlay.activeModules.buffer, "bumpZoomLevel", args)), + function bumpZoomLevel(...args) { return apply(overlay.activeModules.buffer, "bumpZoomLevel", args); }), /** * Returns the currently selected word in *win*. If the selection is @@ -1585,9 +1587,9 @@ var Buffer = Module("Buffer", { }, findScrollableWindow: deprecated("buffer.findScrollableWindow", - function findScrollableWindow() apply(overlay.activeModules, "findScrollableWindow", arguments)), + function findScrollableWindow() { return apply(overlay.activeModules, "findScrollableWindow", arguments); }), findScrollable: deprecated("buffer.findScrollable", - function findScrollable() apply(overlay.activeModules, "findScrollable", arguments)), + function findScrollable() { return apply(overlay.activeModules, "findScrollable", arguments); }), isScrollable: function isScrollable(elem, dir, horizontal) { if (!DOM(elem).isScrollable(horizontal ? "horizontal" : "vertical")) diff --git a/common/modules/cache.jsm b/common/modules/cache.jsm index 450a881a..89c36a07 100644 --- a/common/modules/cache.jsm +++ b/common/modules/cache.jsm @@ -207,7 +207,7 @@ var Cache = Module("Cache", XPCOM(Ci.nsIRequestObserver), { return cache.force(name, true); } - if (hasOwnProperty(this.providers, name)) { + if (hasOwnProp(this.providers, name)) { util.assert(!this.providing.add(name), "Already generating cache for " + name, false); @@ -238,7 +238,7 @@ var Cache = Module("Cache", XPCOM(Ci.nsIRequestObserver), { if (this.storage.has(name)) return this.storage.get(name); - if (callback && !(hasOwnProperty(this.providers, name) || + if (callback && !(hasOwnProp(this.providers, name) || this.localProviders.has(name))) this.register(name, callback, long); @@ -249,14 +249,14 @@ var Cache = Module("Cache", XPCOM(Ci.nsIRequestObserver), { }, _has: function _has(name) { - return hasOwnProperty(this.providers, name) || + return hasOwnProp(this.providers, name) || this.storage.has(name); }, has: function has(name) { return [this.globalProviders, this.localProviders] .some(obj => isinstance(obj, ["Set"]) ? obj.has(name) - : hasOwnProperty(obj, name)); + : hasOwnProp(obj, name)); }, register: function register(name, callback, long) { diff --git a/common/modules/commands.jsm b/common/modules/commands.jsm index 4009b921..24035957 100644 --- a/common/modules/commands.jsm +++ b/common/modules/commands.jsm @@ -349,8 +349,8 @@ var Command = Class("Command", { explicitOpts: Class.Memoize(() => ({})), has: function AP_has(opt) { - return hasOwnProperty(this.explicitOpts, opt) || - typeof opt === "number" && hasOwnProperty(this, opt); + return hasOwnProp(this.explicitOpts, opt) || + typeof opt === "number" && hasOwnProp(this, opt); }, get literalArg() { @@ -465,14 +465,36 @@ var Command = Class("Command", { // Prototype. var Ex = Module("Ex", { - Local: function Local(dactyl, modules, window) { + Local(dactyl, modules, window) { return { + init() {}, + get commands() { return modules.commands; }, get context() { return modules.contexts.context; } }; }, - _args: function E_args(cmd, args) { + commands: null, + + init() { + let proxy = new Proxy(this, { + get(target, prop, receiver) { + if (prop === "isProxy") + return [true, receiver === proxy].join(","); + + if (prop in target || receiver === proxy) + return target[prop]; + + return function (...args) { + return this._run(prop)(...args); + }; + }, + }); + + return proxy; + }, + + _args(cmd, args) { args = Array.slice(args); let res = cmd.newArgs({ context: this.context }); @@ -492,12 +514,13 @@ var Ex = Module("Ex", { Class.replaceProperty(res, opt.names[0], val); res.explicitOpts[opt.names[0]] = val; } + for (let [i, val] of Ary.iterItems(args)) res[i] = String(val); return res; }, - _complete: function E_complete(cmd) { + _complete(cmd) { return (context, func, obj, args) => { args = this._args(cmd, args); args.completeArg = args.length - 1; @@ -506,7 +529,7 @@ var Ex = Module("Ex", { }; }, - _run: function E_run(name) { + _run(name) { const self = this; let cmd = this.commands.get(name); util.assert(cmd, _("command.noSuch")); @@ -519,10 +542,6 @@ var Ex = Module("Ex", { dactylCompleter: self._complete(cmd) }); }, - - __noSuchMethod__: function __noSuchMethod__(meth, args) { - return this._run(meth).apply(this, args); - } }); var CommandHive = Class("CommandHive", Contexts.Hive, { @@ -616,7 +635,18 @@ var CommandHive = Class("CommandHive", Contexts.Hive, { } for (let name of names) { - ex.__defineGetter__(name, function () { return this._run(name); }); + if (false) + // For some reason, the `this` object of the getter gets + // mutilated if we do this in recent Firefox versions. + // Just rely on the proxy for now. + Object.defineProperty(ex, name, { + configurable: true, + enumerable: true, + get() { + return this._run(name); + }, + }); + if (name in this._map && !this._map[name].isPlaceholder) this.remove(name); } @@ -888,9 +918,9 @@ var Commands = Module("commands", { extra.definedAt = contexts.getCaller(caller); return apply(group, "add", arguments); }, - addUserCommand: deprecated("group.commands.add", { get: function addUserCommand() this.user.bound._add }), - getUserCommands: deprecated("iter(group.commands)", function getUserCommands() iter(this.user).toArray()), - removeUserCommand: deprecated("group.commands.remove", { get: function removeUserCommand() this.user.bound.remove }), + addUserCommand: deprecated("group.commands.add", { get: function addUserCommand() { return this.user.bound._add } }), + getUserCommands: deprecated("iter(group.commands)", function getUserCommands() { return iter(this.user).toArray(); }), + removeUserCommand: deprecated("group.commands.remove", { get: function removeUserCommand() { return this.user.bound.remove; } }), /** * Returns the specified command invocation object serialized to @@ -1074,7 +1104,7 @@ var Commands = Module("commands", { let matchOpts = function matchOpts(arg) { // Push possible option matches into completions if (complete && !onlyArgumentsRemaining) - completeOpts = options.filter(opt => (opt.multiple || !hasOwnProperty(args, opt.names[0]))); + completeOpts = options.filter(opt => (opt.multiple || !hasOwnProp(args, opt.names[0]))); }; let resetCompletions = function resetCompletions() { completeOpts = null; @@ -1306,14 +1336,14 @@ var Commands = Module("commands", { } }, - nameRegexp: util.regexp(literal(function () /* + nameRegexp: util.regexp(String.raw` [^ 0-9 ] [^ ]* - */$), "gx", { - forbid: util.regexp(String.replace(literal(function () /* + `, "gx", { + forbid: util.regexp(String.replace(String.raw` U0000-U002c // U002d - U002e-U002f U003a-U0040 // U0041-U005a a-z @@ -1336,7 +1366,7 @@ var Commands = Module("commands", { Ufe70-Ufeff // Arabic Presentation Forms-B Uff00-Uffef // Halfwidth and Fullwidth Forms Ufff0-Uffff // Specials - */$), /U/g, "\\u"), "x") + `, /U/g, "\\u"), "x") }), validName: Class.Memoize(function validName() { @@ -1344,7 +1374,7 @@ var Commands = Module("commands", { }), commandRegexp: Class.Memoize(function commandRegexp() { - return util.regexp(literal(function () /* + return util.regexp(String.raw` ^ (?P (?P [:\s]*) @@ -1359,7 +1389,7 @@ var Commands = Module("commands", { (?:. | \n)*? )? $ - */$), "x", { + `, "x", { name: this.nameRegexp }); }), @@ -1832,7 +1862,7 @@ var Commands = Module("commands", { iterateIndex: function (args) { let tags = help.tags; return this.iterate(args).filter(cmd => (cmd.hive === commands.builtin || - hasOwnProperty(tags, cmd.helpTag))); + hasOwnProp(tags, cmd.helpTag))); }, format: { headings: ["Command", "Group", "Description"], diff --git a/common/modules/completion.jsm b/common/modules/completion.jsm index 85ea1b19..76a39cf6 100644 --- a/common/modules/completion.jsm +++ b/common/modules/completion.jsm @@ -222,9 +222,13 @@ var CompletionContext = Class("CompletionContext", { * @function */ this.getKey = function getKey(item, key) { - return (typeof self.keys[key] == "function") ? self.keys[key].call(this, item.item) : - key in self.keys ? item.item[self.keys[key]] - : item.item[key]; + if (typeof self.keys[key] == "function") + return self.keys[key].call(this, item.item); + + if (key in self.keys) + return item.item[self.keys[key]]; + + return item.item[key]; }; return this; }, @@ -1318,8 +1322,8 @@ var Completion = Module("completion", { }, setter: function setter(values) { - if (values.length == 1 && !hasOwnProperty(values[0], this.values) - && Array.every(values[0], v => hasOwnProperty(this.valueMap, v))) + if (values.length == 1 && !hasOwnProp(values[0], this.values) + && Array.every(values[0], v => hasOwnProp(this.valueMap, v))) return Array.map(values[0], v => this.valueMap[v]); return values; diff --git a/common/modules/config.jsm b/common/modules/config.jsm index 1f2551c0..aa8d842e 100644 --- a/common/modules/config.jsm +++ b/common/modules/config.jsm @@ -17,6 +17,7 @@ lazyRequire("cache", ["cache"]); lazyRequire("dom", ["DOM"]); lazyRequire("highlight", ["highlight"]); lazyRequire("messages", ["_"]); +lazyRequire("overlay", ["overlay"]); lazyRequire("prefs", ["localPrefs", "prefs"]); lazyRequire("storage", ["storage", "File"]); lazyRequire("styles", ["Styles"]); @@ -504,7 +505,7 @@ var ConfigBase = Class("ConfigBase", { oncommand: "toggleSidebar(this.id || this.observes);" }]); } - util.overlayWindow(window, { append: append }); + overlay.overlayWindow(window, { append: append }); }, get window() { return window; }, @@ -632,14 +633,14 @@ config.INIT = update(Object.create(config.INIT), config.INIT, { let img = new window.Image; img.src = this.logo || "resource://dactyl-local-content/logo.png"; img.onload = util.wrapCallback(function () { - highlight.loadCSS(literal(function () /* + highlight.loadCSS(` !Logo { display: inline-block; - background: url({src}); - width: {width}px; - height: {height}px; + background: url(${img.src}); + width: ${img.width}px; + height: ${img.height}px; } - */$).replace(/\{(.*?)\}/g, (m, m1) => img[m1])); + `); img = null; }); }, diff --git a/common/modules/contexts.jsm b/common/modules/contexts.jsm index 9535f033..d251948d 100644 --- a/common/modules/contexts.jsm +++ b/common/modules/contexts.jsm @@ -1,4 +1,4 @@ -// Copyright (c) 2010-2014 Kris Maglione +// Copyright (c) 2010-2015 Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. @@ -220,7 +220,7 @@ var Contexts = Module("contexts", { memoize(contexts.groupsProto, name, function () { return [group[name] for (group of values(this.groups)) - if (hasOwnProperty(group, name))]; + if (hasOwnProp(group, name))]; }); }, @@ -242,13 +242,13 @@ var Contexts = Module("contexts", { let id = util.camelCase(name.replace(/\.[^.]*$/, "")); let contextPath = file.path; - let self = hasOwnProperty(plugins, contextPath) && plugins.contexts[contextPath]; + let self = hasOwnProp(plugins, contextPath) && plugins.contexts[contextPath]; if (!self && isPlugin && false) - self = hasOwnProperty(plugins, id) && plugins[id]; + self = hasOwnProp(plugins, id) && plugins[id]; if (self) { - if (hasOwnProperty(self, "onUnload")) + if (hasOwnProp(self, "onUnload")) util.trapErrors("onUnload", self); } else { @@ -340,7 +340,7 @@ var Contexts = Module("contexts", { .replace(File.PATH_SEP, "-"); let id = util.camelCase(name.replace(/\.[^.]*$/, "")); - let self = hasOwnProperty(this.pluginModules, canonical) && this.pluginModules[canonical]; + let self = hasOwnProp(this.pluginModules, canonical) && this.pluginModules[canonical]; if (!self) { self = Object.create(jsmodules); @@ -446,7 +446,7 @@ var Contexts = Module("contexts", { let need = hive ? [hive] : Object.keys(this.hives); - return this.groupList.filter(group => need.some(hasOwnProperty.bind(null, group))); + return this.groupList.filter(group => need.some(hasOwnProp.bind(null, group))); }, addGroup: function addGroup(name, description, filter, persist, replace) { @@ -506,7 +506,7 @@ var Contexts = Module("contexts", { getGroup: function getGroup(name, hive) { if (name === "default") var group = this.context && this.context.context && this.context.context.GROUP; - else if (hasOwnProperty(this.groupMap, name)) + else if (hasOwnProp(this.groupMap, name)) group = this.groupMap[name]; if (group && hive) @@ -691,7 +691,7 @@ var Contexts = Module("contexts", { util.assert(!group.builtin || !["-description", "-locations", "-nopersist"] - .some(hasOwnProperty.bind(null, args.explicitOpts)), + .some(prop => hasOwnProp(args.explicitOpts, prop)), _("group.cantModifyBuiltin")); }, { argCount: "?", @@ -842,7 +842,9 @@ var Contexts = Module("contexts", { context.keys = { active: group => group.filter(uri), text: "name", - description: function (g) ["", g.filter.toJSONXML ? g.filter.toJSONXML(modules).concat("\u00a0") : "", g.description || ""] + description: g => ["", + g.filter.toJSONXML ? g.filter.toJSONXML(modules).concat("\u00a0") : "", + g.description || ""], }; context.completions = (active === undefined ? contexts.groupList : contexts.initializedGroups(active)) .slice(0, -1); diff --git a/common/modules/dom.jsm b/common/modules/dom.jsm index fb593499..ba765a8d 100644 --- a/common/modules/dom.jsm +++ b/common/modules/dom.jsm @@ -702,7 +702,7 @@ var DOM = Class("DOM", { if (callable(v)) v = v.call(this, elem, i); - if (hasOwnProperty(hooks, k) && hooks[k].set) + if (hasOwnProp(hooks, k) && hooks[k].set) hooks[k].set.call(this, elem, v, k); else if (v == null) elem.removeAttributeNS(ns, k); @@ -714,7 +714,7 @@ var DOM = Class("DOM", { if (!this.length) return null; - if (hasOwnProperty(hooks, key) && hooks[key].get) + if (hasOwnProp(hooks, key) && hooks[key].get) return hooks[key].get.call(this, this[0], key); if (!this[0].hasAttributeNS(ns, key)) @@ -1435,20 +1435,24 @@ var DOM = Class("DOM", { submit: { cancelable: true } }, - types: Class.Memoize(() => iter( - { - Mouse: "click mousedown mouseout mouseover mouseup dblclick " + - "hover " + - "popupshowing popupshown popuphiding popuphidden " + - "contextmenu", - Key: "keydown keypress keyup", - "": "change command dactyl-input input submit " + - "load unload pageshow pagehide DOMContentLoaded " + - "resize scroll" - } - ).map(([k, v]) => v.split(" ").map(v => [v, k])) - .flatten() - .toObject()), + types: Class.Memoize(() => { + return iter( + { + Mouse: "click mousedown mouseout mouseover mouseup dblclick " + + "hover " + + "popupshowing popupshown popuphiding popuphidden " + + "contextmenu", + + Key: "keydown keypress keyup", + + "": "change command dactyl-input input submit " + + "load unload pageshow pagehide DOMContentLoaded " + + "resize scroll" + } + ).map(([k, v]) => v.split(" ").map(v => [v, k])) + .flatten() + .toObject(); + }), /** * Dispatches an event to an element as if it were a native event. @@ -1831,7 +1835,7 @@ var DOM = Class("DOM", { let res = [indent, "<", name]; for (let [key, val] of iter(attr)) { - if (hasOwnProperty(skipAttr, key)) + if (hasOwnProp(skipAttr, key)) continue; let vals = parseNamespace(key); @@ -1984,7 +1988,7 @@ var DOM = Class("DOM", { Object.keys(DOM.Event.types).forEach(function (event) { let name = event.replace(/-(.)/g, (m, m1) => m1.toUpperCase()); - if (!hasOwnProperty(DOM.prototype, name)) + if (!hasOwnProp(DOM.prototype, name)) DOM.prototype[name] = function _event(arg, extra) { return this[callable(arg) ? "listen" : "dispatch"](event, arg, extra); diff --git a/common/modules/downloads.jsm b/common/modules/downloads.jsm index 42441f00..23f44dd8 100644 --- a/common/modules/downloads.jsm +++ b/common/modules/downloads.jsm @@ -97,10 +97,10 @@ var Download = Class("Download", { }), command: function command(name) { - util.assert(hasOwnProperty(this.allowedCommands, name), _("download.unknownCommand")); + util.assert(hasOwnProp(this.allowedCommands, name), _("download.unknownCommand")); util.assert(this.allowedCommands[name], _("download.commandNotAllowed")); - if (hasOwnProperty(this.commands, name)) + if (hasOwnProp(this.commands, name)) this.commands[name].call(this); }, @@ -560,7 +560,7 @@ var Downloads_ = Module("downloads", XPCOM(Ci.nsIDownloadProgressListener), { validator: function (value) { let seen = new RealSet(); - return value.every(val => /^[+-]/.test(val) && hasOwnProperty(this.values, val.substr(1)) + return value.every(val => /^[+-]/.test(val) && hasOwnProp(this.values, val.substr(1)) && !seen.add(val.substr(1))) && value.length; } diff --git a/common/modules/help.jsm b/common/modules/help.jsm index 07a77119..db5278af 100644 --- a/common/modules/help.jsm +++ b/common/modules/help.jsm @@ -1,4 +1,4 @@ -// Copyright (c) 2008-2014 Kris Maglione +// Copyright (c) 2008-2015 Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. @@ -111,13 +111,13 @@ var Help = Module("Help", { { mimeType: "text/plain;charset=UTF-8" }) .responseText; - let re = util.regexp(UTF8(literal(function () /* + let re = util.regexp(UTF8(String.raw` ^ (?P \s* # .*\n) | ^ (?P \s*) (?P [-•*+]) \ // (?P .*\n - (?: \2\ \ .*\n | \s*\n)* ) + (?: ${"\\2"} // This is incorrectly interpreted as an octal literal otherwise}\ \ .*\n | \s*\n)* ) | (?P (?: ^ [^\S\n]* @@ -127,7 +127,7 @@ var Help = Module("Help", { ) | (?: ^ [^\S\n]* \n) + - */$)), "gmxy"); + `), "gmxy"); let betas = util.regexp(/\[((?:b|rc)\d)\]/, "gx"); @@ -241,7 +241,7 @@ var Help = Module("Help", { * @returns {string} */ findHelp: function (topic, consolidated) { - if (!consolidated && hasOwnProperty(help.files, topic)) + if (!consolidated && hasOwnProp(help.files, topic)) return topic; let items = modules.completion._runCompleter("help", topic, null, !!consolidated).items; let partialMatch = null; @@ -274,7 +274,7 @@ var Help = Module("Help", { if (!topic) { let helpFile = consolidated ? "all" : modules.options["helpfile"]; - if (hasOwnProperty(help.files, helpFile)) + if (hasOwnProp(help.files, helpFile)) dactyl.open("dactyl://help/" + helpFile, { from: "help" }); else dactyl.echomsg(_("help.noFile", JSON.stringify(helpFile))); diff --git a/common/modules/highlight.jsm b/common/modules/highlight.jsm index 25eae285..8c7693fa 100644 --- a/common/modules/highlight.jsm +++ b/common/modules/highlight.jsm @@ -251,14 +251,15 @@ var Highlights = Module("Highlight", { }); }, - groupRegexp: util.regexp(literal(function () /* + groupRegexp: util.regexp(String.raw` ^ (\s* (?:\S|\s\S)+ \s+) \{ ([^}]*) \} \s* $ - */$), "gmx"), - sheetRegexp: util.regexp(literal(function () /* + `, "gmx"), + + sheetRegexp: util.regexp(String.raw` ^\s* !? \*? (?P (?:[^;\s]|\s[^;\s])+ ) @@ -267,7 +268,7 @@ var Highlights = Module("Highlight", { (?:; (?P (?:[^;\s]|\s[^;\s])+ )? )? \s* (?P .*) $ - */$), "x"), + `, "x"), // /** @@ -351,7 +352,7 @@ var Highlights = Module("Highlight", { commands.add(["hi[ghlight]"], "Set the style of certain display elements", function (args) { - let style = literal(function () /* + let style = ` ; display: inline-block !important; position: static !important; @@ -359,7 +360,7 @@ var Highlights = Module("Highlight", { width: 3em !important; min-width: 3em !important; max-width: 3em !important; height: 1em !important; min-height: 1em !important; max-height: 1em !important; overflow: hidden !important; - */$); + `; let clear = args[0] == "clear"; if (clear) args.shift(); diff --git a/common/modules/io.jsm b/common/modules/io.jsm index 62772543..b2c8a243 100644 --- a/common/modules/io.jsm +++ b/common/modules/io.jsm @@ -313,7 +313,7 @@ var IO = Module("io", { */ sourcing: null, - expandPath: deprecated("File.expandPath", function expandPath() apply(File, "expandPath", arguments)), + expandPath: deprecated("File.expandPath", function expandPath() { return apply(File, "expandPath", arguments); }), /** * Returns the first user RC file found in *dir*. @@ -530,15 +530,20 @@ var IO = Module("io", { stdin.write(input); function result(status, output) { - return { - __noSuchMethod__: function (meth, args) { - return apply(this.output, meth, args); - }, - valueOf: function () { return this.output; }, - output: output.replace(/^(.*)\n$/, "$1"), - returnValue: status, - toString: function () { return this.output; } - }; + return new Proxy( + { + valueOf: function () { return this.output; }, + output: output.replace(/^(.*)\n$/, "$1"), + returnValue: status, + toString: function () { return this.output; }, + }, { + get(target, prop) { + if (prop in target) + return target[prop]; + + return target.output[prop]; + }, + }); } function async(status) { @@ -615,7 +620,7 @@ var IO = Module("io", { /** * @property {string} The current platform's path separator. */ - PATH_SEP: deprecated("File.PATH_SEP", { get: function PATH_SEP() File.PATH_SEP }) + PATH_SEP: deprecated("File.PATH_SEP", { get: function PATH_SEP() { return File.PATH_SEP; } }) }, { commands: function initCommands(dactyl, modules, window) { const { commands, completion, io } = modules; @@ -723,13 +728,13 @@ var IO = Module("io", { } rtItems.ftdetect.template = //{{{ -literal(function () /*" Vim filetype detection file +String.raw`" Vim filetype detection file
au BufNewFile,BufRead *rc*,*. set filetype= -*/$);//}}} +`;//}}} rtItems.ftplugin.template = //{{{ -literal(function () /*" Vim filetype plugin file +String.raw`" Vim filetype plugin file
if exists("b:did_ftplugin") @@ -754,9 +759,9 @@ endif let &cpo = s:cpo_save unlet s:cpo_save -*/$);//}}} +`; //}}} rtItems.syntax.template = //{{{ -literal(function () /*" Vim syntax file +String.raw`" Vim syntax file
if exists("b:current_syntax") @@ -835,7 +840,7 @@ let &cpo = s:cpo_save unlet s:cpo_save " vim: tw=130 et ts=8 sts=4 sw=4: -*/$);//}}} +`;//}}} const { options } = modules; @@ -1034,12 +1039,26 @@ unlet s:cpo_save context.title = [full ? "Path" : "Filename", "Type"]; context.keys = { - text: !full ? "leafName" : function (f) this.path, - path: function (f) dir + f.leafName, - description: function (f) this.isdir ? "Directory" : "File", - isdir: function (f) f.isDirectory(), - icon: function (f) this.isdir ? "resource://gre/res/html/folder.png" - : "moz-icon://" + f.leafName + text: !full ? "leafName" : function (f) { return this.path }, + + path(f) { + return dir + f.leafName; + }, + + description(f) { + return this.isdir ? "Directory" : "File"; + }, + + isdir(f) { + return f.isDirectory(); + }, + + icon(f) { + if (this.isdir) + return "resource://gre/res/html/folder.png"; + + return "moz-icon://" + f.leafName; + }, }; context.compare = (a, b) => b.isdir - a.isdir || String.localeCompare(a.text, b.text); @@ -1051,20 +1070,20 @@ unlet s:cpo_save let uri = io.isJarURL(dir); if (uri) context.generate = function generate_jar() { - return [ - { - isDirectory: function () s.substr(-1) == "/", - leafName: /([^\/]*)\/?$/.exec(s)[1] - } - for (s of io.listJar(uri.JARFile, getDir(uri.JAREntry)))]; + return Array.from(io.listJar(uri.JARFile, getDir(uri.JAREntry)), + path => ({ + isDirectory: () => path.substr(-1) == "/", + leafName: /([^\/]*)\/?$/.exec(s)[1] + })); }; else context.generate = function generate_file() { try { return io.File(file || dir).readDirectory(); } - catch (e) {} - return []; + catch (e) { + return []; + } }; }; @@ -1098,7 +1117,7 @@ unlet s:cpo_save }; completion.addUrlCompleter("file", "Local files", function (context, full) { - let match = util.regexp(literal(function () /* + let match = util.regexp(String.raw` ^ (?P (?P @@ -1109,7 +1128,7 @@ unlet s:cpo_save ) (?P \/[^\/]* )? $ - */$), "x").exec(context.filter); + `, "x").exec(context.filter); if (match) { if (!match.path) { context.key = match.proto; diff --git a/common/modules/javascript.jsm b/common/modules/javascript.jsm index 5f2e4875..77d6c2e1 100644 --- a/common/modules/javascript.jsm +++ b/common/modules/javascript.jsm @@ -732,6 +732,16 @@ var JavaScript = Module("javascript", { init: function init(context) { this.context = context; this.results = []; + + return new Proxy(this, { + get(target, prop) { + if (prop in target) + return target[prop]; + + if (prop in Buffer) + return Buffer[prop].bind(Buffer, target.rootNode); + }, + }); }, addOutput: function addOutput(js) { @@ -775,10 +785,6 @@ var JavaScript = Module("javascript", { return this.rootNode; }), - - __noSuchMethod__: function (meth, args) { - return apply(Buffer, meth, [this.rootNode].concat(args)); - } }); modules.CommandREPLMode = Class("CommandREPLMode", modules.CommandMode, { diff --git a/common/modules/main.jsm b/common/modules/main.jsm index ff7f7cca..0835d606 100644 --- a/common/modules/main.jsm +++ b/common/modules/main.jsm @@ -341,12 +341,12 @@ overlay.overlayWindow(Object.keys(config.overlays), let className = mod.className || mod.constructor.className; - if (!hasOwnProperty(init, className)) { + if (!hasOwnProp(init, className)) { init[className] = function callee() { function finish() { this.currentDependency = className; defineModule.time(className, name, INIT[name], mod, - modules.dactyl, modules, window); + modules.dactyl, modules, window); } if (!callee.frobbed) { callee.frobbed = true; diff --git a/common/modules/messages.jsm b/common/modules/messages.jsm index a28c23a4..01bb4469 100644 --- a/common/modules/messages.jsm +++ b/common/modules/messages.jsm @@ -160,7 +160,7 @@ var Messages = Module("messages", { return { configurable: true, enumerable: true, value: this.default, writable: true }; */ - if (!hasOwnProperty(obj, "localizedProperties")) + if (!hasOwnProp(obj, "localizedProperties")) obj.localizedProperties = new RealSet(obj.localizedProperties); obj.localizedProperties.add(prop); diff --git a/common/modules/options.jsm b/common/modules/options.jsm index 475c9efc..63ddec28 100644 --- a/common/modules/options.jsm +++ b/common/modules/options.jsm @@ -150,7 +150,7 @@ var Option = Class("Option", { if ((scope & Option.SCOPE_GLOBAL) && (values == undefined)) values = this.globalValue; - if (hasOwnProperty(this, "_value")) + if (hasOwnProp(this, "_value")) values = this._value; if (this.getter) @@ -354,7 +354,7 @@ var Option = Class("Option", { let defaultValue = this._defaultValue; delete this._defaultValue; - if (hasOwnProperty(this.modules.config.optionDefaults, this.name)) + if (hasOwnProp(this.modules.config.optionDefaults, this.name)) defaultValue = this.modules.config.optionDefaults[this.name]; if (defaultValue == null && this.getter) @@ -551,7 +551,7 @@ var Option = Class("Option", { return [Option.quote(k, /:/) + ":" + Option.quote(v, /:/) for ([k, v] of iter(vals))].join(","); }, - regexplist: function (vals) { return vals.join(","); }, + regexplist: vals => vals.join(","), get regexpmap() { return this.regexplist; }, get sitelist() { return this.regexplist; }, get sitemap() { return this.regexplist; } @@ -820,8 +820,8 @@ var Option = Class("Option", { let k = values(completions.call(this, { values: {} })).toObject(); let v = values(completions.call(this, { value: "" })).toObject(); - return Object.keys(vals).every(hasOwnProperty.bind(null, k)) && - values(vals).every(hasOwnProperty.bind(null, v)); + return Object.keys(vals).every(hasOwnProp.bind(null, k)) && + values(vals).every(hasOwnProp.bind(null, v)); } if (this.values) @@ -894,7 +894,7 @@ var OptionHive = Class("OptionHive", Contexts.Hive, { init: function init(group) { init.supercall(this, group); this.values = {}; - this.has = v => hasOwnProperty(this.values, v); + this.has = v => hasOwnProp(this.values, v); }, add: function add(names, description, type, defaultValue, extra) { @@ -1067,18 +1067,18 @@ var Options = Module("options", { return values(this._options.sort((a, b) => String.localeCompare(a.name, b.name))); }, - allPrefs: deprecated("prefs.getNames", function allPrefs() apply(prefs, "getNames", arguments)), - getPref: deprecated("prefs.get", function getPref() apply(prefs, "get", arguments)), - invertPref: deprecated("prefs.invert", function invertPref() apply(prefs, "invert", arguments)), + allPrefs: deprecated("prefs.getNames", function allPrefs() { return apply(prefs, "getNames", arguments); }), + getPref: deprecated("prefs.get", function getPref() { return apply(prefs, "get", arguments); }), + invertPref: deprecated("prefs.invert", function invertPref() { return apply(prefs, "invert", arguments); }), listPrefs: deprecated("prefs.list", function listPrefs() { this.modules.commandline.commandOutput(apply(prefs, "list", arguments)); }), - observePref: deprecated("prefs.observe", function observePref() apply(prefs, "observe", arguments)), - popContext: deprecated("prefs.popContext", function popContext() apply(prefs, "popContext", arguments)), - pushContext: deprecated("prefs.pushContext", function pushContext() apply(prefs, "pushContext", arguments)), - resetPref: deprecated("prefs.reset", function resetPref() apply(prefs, "reset", arguments)), - safeResetPref: deprecated("prefs.safeReset", function safeResetPref() apply(prefs, "safeReset", arguments)), - safeSetPref: deprecated("prefs.safeSet", function safeSetPref() apply(prefs, "safeSet", arguments)), - setPref: deprecated("prefs.set", function setPref() apply(prefs, "set", arguments)), - withContext: deprecated("prefs.withContext", function withContext() apply(prefs, "withContext", arguments)), + observePref: deprecated("prefs.observe", function observePref() { return apply(prefs, "observe", arguments); }), + popContext: deprecated("prefs.popContext", function popContext() { return apply(prefs, "popContext", arguments); }), + pushContext: deprecated("prefs.pushContext", function pushContext() { return apply(prefs, "pushContext", arguments); }), + resetPref: deprecated("prefs.reset", function resetPref() { return apply(prefs, "reset", arguments); }), + safeResetPref: deprecated("prefs.safeReset", function safeResetPref() { return apply(prefs, "safeReset", arguments); }), + safeSetPref: deprecated("prefs.safeSet", function safeSetPref() { return apply(prefs, "safeSet", arguments); }), + setPref: deprecated("prefs.set", function setPref() { return apply(prefs, "set", arguments); }), + withContext: deprecated("prefs.withContext", function withContext() { return apply(prefs, "withContext", arguments); }), cleanupPrefs: Class.Memoize(() => config.prefs.Branch("cleanup.option.")), @@ -1431,7 +1431,7 @@ var Options = Module("options", { util.assert(scope == "g:" || scope == null, _("command.let.illegalVar", scope + name)); - util.assert(hasOwnProperty(globalVariables, name) || (expr && !op), + util.assert(hasOwnProp(globalVariables, name) || (expr && !op), _("command.let.undefinedVar", fullName)); if (!expr) @@ -1535,7 +1535,7 @@ var Options = Module("options", { function (args) { for (let name of args) { name = name.replace(/^g:/, ""); // throw away the scope prefix - if (!hasOwnProperty(dactyl._globalVariables, name)) { + if (!hasOwnProp(dactyl._globalVariables, name)) { if (!args.bang) dactyl.echoerr(_("command.let.noSuch", name)); return; @@ -1620,7 +1620,7 @@ var Options = Module("options", { let val = [].find.call(obj, re => (re.key == extra.key)); return val && val.result; } - if (hasOwnProperty(opt.defaultValue, extra.key)) + if (hasOwnProp(opt.defaultValue, extra.key)) return obj[extra.key]; } diff --git a/common/modules/overlay.jsm b/common/modules/overlay.jsm index 1bb2266c..ba9f4fe7 100644 --- a/common/modules/overlay.jsm +++ b/common/modules/overlay.jsm @@ -489,7 +489,12 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen return this.windows.has(win) && win; }, - set activeWindow(win) { this._activeWindow = util.weakReference(win); }, + set activeWindow(win) { + this._activeWindow = util.weakReference(win); + + if (win.dactyl) + util.flushLateMethods(win.dactyl); + }, /** * A list of extant dactyl windows. diff --git a/common/modules/prefs.jsm b/common/modules/prefs.jsm index aca5325c..04b7380e 100644 --- a/common/modules/prefs.jsm +++ b/common/modules/prefs.jsm @@ -134,7 +134,8 @@ var Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) } }, - getDefault: deprecated("Prefs#defaults.get", function getDefault(name, defaultValue) this.defaults.get(name, defaultValue)), + getDefault: deprecated("Prefs#defaults.get", + function getDefault(name, defaultValue) { return this.defaults.get(name, defaultValue); }), /** * Returns an array of all preference names in this branch or the diff --git a/common/modules/promises.jsm b/common/modules/promises.jsm index 974e6d6a..6c7fcf6d 100644 --- a/common/modules/promises.jsm +++ b/common/modules/promises.jsm @@ -18,7 +18,7 @@ function withCallbacks(fn) { return function wrapper(...args) { let deferred = Promise.defer(); function resolve(arg) { deferred.resolve(arg); } - function reject(arg) { deferred.reject(arg); } + function reject(arg) { deferred.reject(arg); } fn.apply(this, [[resolve, reject, deferred]].concat(args)); return deferred.promise; }; diff --git a/common/modules/protocol.jsm b/common/modules/protocol.jsm index 03cfc737..53ade751 100644 --- a/common/modules/protocol.jsm +++ b/common/modules/protocol.jsm @@ -86,6 +86,8 @@ function ProtocolBase() { this.pages = {}; this.providers = { + __proto__: null, + "content": function (uri, path) { return this.pages[path] || this.contentBase + path; }, @@ -98,7 +100,7 @@ function ProtocolBase() { channel.owner = systemPrincipal; channel.originalURI = uri; return channel; - } + }, }; } ProtocolBase.prototype = { @@ -196,7 +198,7 @@ function XMLChannel(uri, contentType, noErrorChannel, unprivileged) { let type = this.channel.contentType; if (/^text\/|[\/+]xml$/.test(type)) { let stream = services.InputStream(channelStream); - let [, pre, doctype, url, extra, open, post] = util.regexp(literal(function () /* + let [, pre, doctype, url, extra, open, post] = util.regexp(String.raw` ^ ([^]*?) (?: (\s]|\s[^[])*)) @@ -204,8 +206,10 @@ function XMLChannel(uri, contentType, noErrorChannel, unprivileged) { ([^]*) )? $ - */$), "x").exec(stream.read(4096)); + `, "x").exec(stream.read(4096)); + this.writes.push(pre); + if (doctype) { this.writes.push(doctype + (extra || "") + " [\n"); if (url) diff --git a/common/modules/sanitizer.jsm b/common/modules/sanitizer.jsm index 7ccbafd6..f4877c41 100644 --- a/common/modules/sanitizer.jsm +++ b/common/modules/sanitizer.jsm @@ -28,8 +28,13 @@ tmp.Sanitizer.prototype.__proto__ = Class.prototype; var Range = Struct("min", "max"); update(Range.prototype, { - contains: function (date) date == null || - (this.min == null || date >= this.min) && (this.max == null || date <= this.max), + contains: function (date) { + if (date != null) + return ((this.min == null || date >= this.min) && + (this.max == null || date <= this.max)); + + return false; + }, get isEternity() { return this.max == null && this.min == null; @@ -662,7 +667,7 @@ var Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakRef validator: function (values) { return values.length && - values.every(val => (val === "all" || hasOwnProperty(sanitizer.itemMap, val.replace(/^!/, "")))); + values.every(val => (val === "all" || hasOwnProp(sanitizer.itemMap, val.replace(/^!/, "")))); } }); diff --git a/common/modules/services.jsm b/common/modules/services.jsm index 90f25604..93939cda 100644 --- a/common/modules/services.jsm +++ b/common/modules/services.jsm @@ -194,14 +194,14 @@ var Services = Module("Services", { * * @param {string} name The class's cache key. */ - create: deprecated("services.*name*()", function create(name) this[util.capitalize(name)]()), + create: deprecated("services.*name*()", function create(name) { return this[util.capitalize(name)](); }), /** * Returns the cached service with the specified name. * * @param {string} name The service's cache key. */ - get: deprecated("services.*name*", function get(name) this[name]), + get: deprecated("services.*name*", function get(name) { return this[name]; }), /** * Returns true if the given service is available. @@ -209,7 +209,7 @@ var Services = Module("Services", { * @param {string} name The service's cache key. */ has: function has(name) { - return hasOwnProperty(this.services, name) && + return hasOwnProp(this.services, name) && this.services[name].class in Cc && this.services[name].interfaces.every(iface => iface in Ci); } diff --git a/common/modules/storage.jsm b/common/modules/storage.jsm index 8feb637f..b885ec78 100644 --- a/common/modules/storage.jsm +++ b/common/modules/storage.jsm @@ -70,7 +70,7 @@ var StoreBase = Class("StoreBase", { save: function () { (this.storage || storage)._saveData(this); }, - "@@iterator": function () iter(this._object) + "@@iterator": function () { return iter(this._object); }, }); var ArrayStore = Class("ArrayStore", StoreBase, { @@ -160,7 +160,7 @@ var ObjectStore = Class("ObjectStore", StoreBase, { }, has: function has(key) { - return hasOwnProperty(this._object, key); + return hasOwnProp(this._object, key); }, keys: function keys() { @@ -257,11 +257,14 @@ var Storage = Module("Storage", { delete this.dactylSession[key]; }, - infoPath: Class.Memoize(() => - File(IO.runtimePath.split(",")[0]) - .child("info").child(config.profileName)), + infoPath: Class.Memoize(function () { + return File(IO.runtimePath.split(",")[0]) + .child("info").child(config.profileName); + }), - exists: function exists(key) this.infoPath.child(key).exists(), + exists: function exists(key) { + return this.infoPath.child(key).exists(); + }, remove: function remove(key) { if (this.exists(key)) { @@ -327,7 +330,7 @@ var Storage = Module("Storage", { if (window instanceof Ci.nsIDOMWindow) observers = overlay.getData(window, "storage-observers", Object); - if (!hasOwnProperty(observers, key)) + if (!hasOwnProp(observers, key)) observers[key] = new RealSet; observers[key].add(callback); @@ -559,7 +562,7 @@ var File = Class("File", { * * @returns {nsIFileURL} */ - toURI: deprecated("#URI", function toURI() services.io.newFileURI(this.file)), + toURI: deprecated("#URI", function toURI() { return services.io.newFileURI(this.file); }), /** * Writes the string *buf* to this file. @@ -724,14 +727,17 @@ var File = Class("File", { }), DoesNotExist: function DoesNotExist(path, error) { - return { + return new Proxy({ __proto__: DoesNotExist.prototype, path: path, exists: function () { return false; }, - __noSuchMethod__: function () { - throw error || Error("Does not exist"); + }, { + get(target, prop) { + if (prop in target) + return target[prop]; + return () => { error || Error("Does not exist")}; } - }; + }); }, defaultEncoding: "UTF-8", diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm index 31f72c52..bfaa45fd 100644 --- a/common/modules/styles.jsm +++ b/common/modules/styles.jsm @@ -274,7 +274,7 @@ var Styles = Module("Styles", { update(services["dactyl:"].providers, { "style": function styleProvider(uri, path) { let id = parseInt(path); - if (hasOwnProperty(styles.allSheets, id)) + if (hasOwnProp(styles.allSheets, id)) return ["text/css", styles.allSheets[id].fullCSS]; return null; } @@ -311,16 +311,16 @@ var Styles = Module("Styles", { return apply(obj, name, Array.slice(args, 1)); }, - addSheet: deprecated("Styles#{user,system}.add", function addSheet() this._proxy("add", arguments)), - findSheets: deprecated("Styles#{user,system}.find", function findSheets() this._proxy("find", arguments)), - get: deprecated("Styles#{user,system}.get", function get() this._proxy("get", arguments)), - removeSheet: deprecated("Styles#{user,system}.remove", function removeSheet() this._proxy("remove", arguments)), + addSheet: deprecated("Styles#{user,system}.add", function addSheet() { return this._proxy("add", arguments); }), + findSheets: deprecated("Styles#{user,system}.find", function findSheets() { return this._proxy("find", arguments); }), + get: deprecated("Styles#{user,system}.get", function get() { return this._proxy("get", arguments); }), + removeSheet: deprecated("Styles#{user,system}.remove", function removeSheet() { return this._proxy("remove", arguments); }), - userSheets: Class.Property({ get: deprecated("Styles#user.sheets", function userSheets() this.user.sheets) }), - systemSheets: Class.Property({ get: deprecated("Styles#system.sheets", function systemSheets() this.system.sheets) }), - userNames: Class.Property({ get: deprecated("Styles#user.names", function userNames() this.user.names) }), - systemNames: Class.Property({ get: deprecated("Styles#system.names", function systemNames() this.system.names) }), - sites: Class.Property({ get: deprecated("Styles#user.sites", function sites() this.user.sites) }), + userSheets: Class.Property({ get: deprecated("Styles#user.sheets", function userSheets() { return this.user.sheets; }) }), + systemSheets: Class.Property({ get: deprecated("Styles#system.sheets", function systemSheets() { return this.system.sheets; }) }), + userNames: Class.Property({ get: deprecated("Styles#user.names", function userNames() { return this.user.names; }) }), + systemNames: Class.Property({ get: deprecated("Styles#system.names", function systemNames() { return this.system.names; }) }), + sites: Class.Property({ get: deprecated("Styles#user.sites", function sites() { return this.user.sites; }) }), list: function list(content, sites, name, hives) { const { commandline, dactyl } = this.modules; @@ -376,8 +376,9 @@ var Styles = Module("Styles", { this.unregisterSheet(url, agent); let type = services.stylesheet[agent ? "AGENT_SHEET" : "USER_SHEET"]; - if (reload || !services.stylesheet.sheetRegistered(uri, type)) + if (reload || !services.stylesheet.sheetRegistered(uri, type)) { services.stylesheet.loadAndRegisterSheet(uri, type); + } }, unregisterSheet: function unregisterSheet(url, agent) { @@ -493,7 +494,7 @@ var Styles = Module("Styles", { } }, - propertyPattern: util.regexp(literal(function () /* + propertyPattern: util.regexp(String.raw` (?: (?P *) (?P [-a-z]*) @@ -515,7 +516,7 @@ var Styles = Module("Styles", { )? ) (?P * (?: ; | $) ) - */$), "gix", + `, "gix", { space: /(?: \s | \/\* .*? \*\/ )/, string: /(?:" (?:[^\\"]|\\.)* (?:"|$) | '(?:[^\\']|\\.)* (?:'|$) )/ @@ -523,7 +524,7 @@ var Styles = Module("Styles", { patterns: memoize({ get property() { - return util.regexp(literal(function () /* + return util.regexp(String.raw` (?: (?P *) (?P [-a-z]*) @@ -534,32 +535,32 @@ var Styles = Module("Styles", { )? ) (?P * (?: ; | $) ) - */$), "gix", this); + `, "gix", this); }, get function() { - return util.regexp(literal(function () /* + return util.regexp(String.raw` (?P \s* \( \s* (?: | [^)]* ) \s* (?: \) | $) ) - */$), "gx", this); + `, "gx", this); }, space: /(?: \s | \/\* .*? \*\/ )/, get string() { - return util.regexp(literal(function () /* + return util.regexp(String.raw` (?P " (?:[^\\"]|\\.)* (?:"|$) | ' (?:[^\\']|\\.)* (?:'|$) ) - */$), "gx", this); + `, "gx", this); }, get token() { - return util.regexp(literal(function () /* + return util.regexp(String.raw` (?P (?P [-\w]+) ? @@ -569,7 +570,7 @@ var Styles = Module("Styles", { | + | [^;}\s]+ ) - */$), "gix", this); + `, "gix", this); } }), @@ -744,16 +745,21 @@ var Styles = Module("Styles", { init: function init(group) { init.superapply(this, arguments); this.hive = styles.addHive(group.name, this, this.persist); + + return new Proxy(this, { + get(target, prop) { + if (prop in target) + return target[prop]; + + return target.hive[prop]; + }, + }); }, get names() { return this.hive.names; }, get sheets() { return this.hive.sheets; }, get sites() { return this.hive.sites; }, - __noSuchMethod__: function __noSuchMethod__(meth, args) { - return apply(this.hive, meth, args); - }, - destroy: function () { this.hive.dropRef(this); } diff --git a/common/modules/template.jsm b/common/modules/template.jsm index a0005455..1d05b199 100644 --- a/common/modules/template.jsm +++ b/common/modules/template.jsm @@ -16,12 +16,28 @@ var Binding = Class("Binding", { init: function (node, nodes) { this.node = node; this.nodes = nodes; - node.dactylBinding = this; Object.defineProperties(node, this.constructor.properties); for (let [event, handler] of this.constructor.events) node.addEventListener(event, util.wrapCallback(handler, true), false); + + let proxy = new Proxy(this, { + get(target, prop) { + if (prop in target) + return target[prop]; + + let { node } = target; + let value = node[prop]; + + if (callable(value)) + return value.bind(node); + return value; + }, + }); + + node.dactylBinding = proxy; + return proxy; }, set collapsed(collapsed) { @@ -30,20 +46,16 @@ var Binding = Class("Binding", { else this.removeAttribute("collapsed"); }, - get collapsed() { return !!this.getAttribute("collapsed"); }, - __noSuchMethod__: Class.Property({ - configurable: true, - writeable: true, - value: function __noSuchMethod__(meth, args) { - return apply(this.node, meth, args); - } - }) + get collapsed() { return !!this.getAttribute("collapsed"); }, }, { get bindings() { return function* () { let bindingProto = Object.getPrototypeOf(Binding.prototype); - for (let obj = this.prototype; obj !== bindingProto; obj = Object.getPrototypeOf(obj)) + + for (let obj = this.prototype; + obj !== bindingProto; + obj = Object.getPrototypeOf(obj)) /* FIXME: Symbols */ yield obj; }.call(this); @@ -63,15 +75,18 @@ var Binding = Class("Binding", { events: Class.Memoize(function () { let res = []; + for (let obj of this.bindings) if (Object.getOwnPropertyDescriptor(obj, "events")) for (let [event, handler] of iter(obj.events)) res.push([event, this.bind(handler)]); + return res; }), properties: Class.Memoize(function () { let res = {}; + for (let obj of this.bindings) for (let prop of properties(obj)) { let desc = Object.getOwnPropertyDescriptor(obj, prop); @@ -82,6 +97,7 @@ var Binding = Class("Binding", { res[prop] = desc; } } + return res; }) }); @@ -114,7 +130,7 @@ var Template = Module("Template", { "click": function onClick(event) { event.preventDefault(); if (this.commandAllowed) { - if (hasOwnProperty(this.target.commands || {}, this.command)) + if (hasOwnProp(this.target.commands || {}, this.command)) this.target.commands[this.command].call(this.target); else this.target.command(this.command); @@ -123,7 +139,7 @@ var Template = Module("Template", { }, get commandAllowed() { - if (hasOwnProperty(this.target.allowedCommands || {}, this.command)) + if (hasOwnProp(this.target.allowedCommands || {}, this.command)) return this.target.allowedCommands[this.command]; if ("commandAllowed" in this.target) return this.target.commandAllowed(this.command); @@ -148,7 +164,7 @@ var Template = Module("Template", { let obj = params.eventTarget; let events = obj[this.getAttribute("events") || "events"]; - if (hasOwnProperty(events, "input")) + if (hasOwnProp(events, "input")) events["dactyl-input"] = events["input"]; for (let [event, handler] of iter(events)) @@ -231,7 +247,7 @@ var Template = Module("Template", { else if (/^n_/.test(topic)) topic = topic.slice(2); - if (help.initialized && !hasOwnProperty(help.tags, topic)) + if (help.initialized && !hasOwnProp(help.tags, topic)) return ["span", { highlight: type || ""}, text || token]; type = type || (/^'.*'$/.test(token) ? "HelpOpt" : @@ -253,7 +269,7 @@ var Template = Module("Template", { else if (/^n_/.test(topic)) topic = topic.slice(2); - if (help.initialized && !hasOwnProperty(help.tags, topic)) + if (help.initialized && !hasOwnProp(help.tags, topic)) return token; let tag = (/^'.*'$/.test(token) ? "o" : @@ -264,11 +280,11 @@ var Template = Module("Template", { return [tag, { xmlns: "dactyl" }, topic]; }, linkifyHelp: function linkifyHelp(str, help) { - let re = util.regexp(literal(function () /* + let re = util.regexp(String.raw` (?P
 [/\s]|^)
             (?P '[\w-]+' | :(?:[\w-]+!?|!) | (?:._)?<[\w-]+>\w* | \b[a-zA-Z]_(?:[\w[\]]+|.) | \[[\w-;]+\] | E\d{3} )
             (?=      [[\)!,:;./\s]|$)
-        */$), "gx");
+        `, "gx");
         return this.highlightSubstrings(str, (function* () {
             for (let res of re.iterate(str))
                 yield [res.index + res.pre.length, res.tag.length];
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index d79003f7..c3aa1e9f 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -61,6 +61,17 @@ var wrapCallback = function wrapCallback(fn, isEvent) {
     return fn.wrapper;
 };
 
+let anythingObjectHack = new Proxy({}, {
+    get(target, prop) {
+        util.dump("Attempt to access UI method before UI ready: " + prop);
+        return function(...args) {
+            util.dump(`Attempt to use UI method before UI ready: ${prop}(${args})`);
+
+            util.lateDactylMethods.push([prop, args]);
+        };
+    },
+});
+
 var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), {
     Magic: Magic,
 
@@ -69,61 +80,68 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
         this.addObserver(this);
         this.windows = [];
+        this.lateDactylMethods = [];
     },
 
-    activeWindow: deprecated("overlay.activeWindow", { get: function activeWindow() overlay.activeWindow }),
-    overlayObject: deprecated("overlay.overlayObject", { get: function overlayObject() overlay.bound.overlayObject }),
-    overlayWindow: deprecated("overlay.overlayWindow", { get: function overlayWindow() overlay.bound.overlayWindow }),
+    activeWindow: deprecated("overlay.activeWindow", { get: function activeWindow() { return overlay.activeWindow; } }),
+    overlayObject: deprecated("overlay.overlayObject", { get: function overlayObject() { return overlay.bound.overlayObject; } }),
+    overlayWindow: deprecated("overlay.overlayWindow", { get: function overlayWindow() { return overlay.bound.overlayWindow; } }),
+
+    compileMatcher: deprecated("DOM.compileMatcher", { get: function compileMatcher() { return DOM.compileMatcher; } }),
+    computedStyle: deprecated("DOM#style", function computedStyle(elem) { return DOM(elem).style; }),
+    domToString: deprecated("DOM.stringify", { get: function domToString() { return DOM.stringify; } }),
+    editableInputs: deprecated("DOM.editableInputs", { get: function editableInputs(elem) { return DOM.editableInputs; } }),
+    escapeHTML: deprecated("DOM.escapeHTML", { get: function escapeHTML(elem) { return DOM.escapeHTML; } }),
 
-    compileMatcher: deprecated("DOM.compileMatcher", { get: function compileMatcher() DOM.compileMatcher }),
-    computedStyle: deprecated("DOM#style", function computedStyle(elem) DOM(elem).style),
-    domToString: deprecated("DOM.stringify", { get: function domToString() DOM.stringify }),
-    editableInputs: deprecated("DOM.editableInputs", { get: function editableInputs(elem) DOM.editableInputs }),
-    escapeHTML: deprecated("DOM.escapeHTML", { get: function escapeHTML(elem) DOM.escapeHTML }),
     evaluateXPath: deprecated("DOM.XPath",
-        function evaluateXPath(path, elem, asIterator) DOM.XPath(path, elem || util.activeWindow.content.document, asIterator)),
-    isVisible: deprecated("DOM#isVisible", function isVisible(elem) DOM(elem).isVisible),
-    makeXPath: deprecated("DOM.makeXPath", { get: function makeXPath(elem) DOM.makeXPath }),
-    namespaces: deprecated("DOM.namespaces", { get: function namespaces(elem) DOM.namespaces }),
-    namespaceNames: deprecated("DOM.namespaceNames", { get: function namespaceNames(elem) DOM.namespaceNames }),
-    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 }),
+                              function evaluateXPath(path, elem, asIterator) {
+                                  return DOM.XPath(path, elem || util.activeWindow.content.document, asIterator);
+                              }),
 
-    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)),
+    isVisible: deprecated("DOM#isVisible", function isVisible(elem) { return DOM(elem).isVisible; }),
+    makeXPath: deprecated("DOM.makeXPath", { get: function makeXPath(elem) { return DOM.makeXPath; } }),
+    namespaces: deprecated("DOM.namespaces", { get: function namespaces(elem) { return DOM.namespaces; } }),
+    namespaceNames: deprecated("DOM.namespaceNames", { get: function namespaceNames(elem) { return DOM.namespaceNames; } }),
+    parseForm: deprecated("DOM#formData", function parseForm(elem) { return values(DOM(elem).formData).toArray(); }),
+    scrollIntoView: deprecated("DOM#scrollIntoView", function scrollIntoView(elem, alignWithTop) { return DOM(elem).scrollIntoView(alignWithTop); }),
+    validateMatcher: deprecated("DOM.validateMatcher", { get: function validateMatcher() { return DOM.validateMatcher; } }),
 
-    chromePackages: deprecated("config.chromePackages", { get: function chromePackages() config.chromePackages }),
-    haveGecko: deprecated("config.haveGecko", { get: function haveGecko() config.bound.haveGecko }),
-    OS: deprecated("config.OS", { get: function OS() config.OS }),
+    map: deprecated("iter.map", function map(obj, fn, self) { return iter(obj).map(fn, self).toArray(); }),
+    writeToClipboard: deprecated("dactyl.clipboardWrite", function writeToClipboard(str, verbose) { return util.dactyl.clipboardWrite(str, verbose); }),
+    readFromClipboard: deprecated("dactyl.clipboardRead", function readFromClipboard() { return util.dactyl.clipboardRead(false); }),
 
-    identity: deprecated("identity", { get: function identity() global.identity }),
+    chromePackages: deprecated("config.chromePackages", { get: function chromePackages() { return config.chromePackages; } }),
+    haveGecko: deprecated("config.haveGecko", { get: function haveGecko() { return config.bound.haveGecko; } }),
+    OS: deprecated("config.OS", { get: function OS() { return config.OS; } }),
 
-    dactyl: update(function dactyl(obj) {
+    identity: deprecated("identity", { get: function identity() { return global.identity; } }),
+
+    dactyl: new Proxy(function (obj) {
+        let global;
         if (obj)
-            var global = Class.objectGlobal(obj);
+            global = Class.objectGlobal(obj);
 
-        return {
-            __noSuchMethod__: function __noSuchMethod__(meth, args) {
-                let win = overlay.activeWindow;
-
-                var dactyl = global && global.dactyl || win && win.dactyl;
-                if (!dactyl)
-                    return null;
-
-                let prop = dactyl[meth];
-                if (callable(prop))
-                    return prop.apply(dactyl, args);
-                return prop;
-            }
-        };
+        return (global && global.dactyl ||
+                overlay.activeWindow && overlay.activeWindow.dactyl ||
+                anythingObjectHack);
     }, {
-        __noSuchMethod__: function __noSuchMethod__() {
-            return this().__noSuchMethod__.apply(null, arguments);
-        }
+        get(target, prop) {
+            if (prop in target)
+                return target[prop];
+
+            if (loaded.overlay)
+                return target()[prop];
+        },
     }),
 
+    flushLateMethods(dactyl) {
+        while (this.lateDactylMethods.length) {
+            let [meth, args] = this.lateDactylMethods.shift();
+
+            this.trapErrors(meth, dactyl, ...args);
+        }
+    },
+
     /**
      * Registers a obj as a new observer with the observer service. obj.observe
      * must be an object where each key is the name of a target to observe and
@@ -379,14 +397,15 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
         let defaults = { lt: "<", gt: ">" };
 
-        let re = util.regexp(literal(function () /*
+        let re = util.regexp(String.raw`
             ([^]*?) // 1
             (?:
                 (<\{) | // 2
                 (< ((?:[a-z]-)?[a-z-]+?) (?:\[([0-9]+)\])? >) | // 3 4 5
                 (\}>) // 6
             )
-        */$), "gixy");
+        `, "gixy");
+
         macro = String(macro);
         let end = 0;
         for (let match of re.iterate(macro)) {
@@ -416,7 +435,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
                 if (flags.has("e"))
                     quote = function quote(obj) { return ""; };
 
-                if (hasOwnProperty(defaults, name))
+                if (hasOwnProp(defaults, name))
                     stack.top.elements.push(quote(defaults[name]));
                 else {
                     let index = idx;
@@ -424,7 +443,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])
-                                                                         : hasOwnProperty(obj, name) ? "" : unknown(full),
+                                                                         : hasOwnProp(obj, name) ? "" : unknown(full),
                             {
                                 test: function test(obj) {
                                     return obj[name] != null &&
@@ -437,7 +456,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
                     else {
                         stack.top.elements.push(update(
                             obj => obj[name] != null ? quote(obj[name])
-                                                     : hasOwnProperty(obj, name) ? "" : unknown(full),
+                                                     : hasOwnProp(obj, name) ? "" : unknown(full),
                             {
                                 test: function test(obj) {
                                     return obj[name] != null &&
@@ -509,7 +528,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
                 return obj.res;
             }
 
-            if (!pattern.contains("{"))
+            if (!pattern.includes("{"))
                 return [pattern];
 
             let res = [];
@@ -790,7 +809,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
         try {
             let xmlhttp = services.Xmlhttp();
-            xmlhttp.mozBackgroundRequest = hasOwnProperty(params, "background") ? params.background : true;
+            xmlhttp.mozBackgroundRequest = hasOwnProp(params, "background") ? params.background : true;
 
             let async = params.callback || params.onload || params.onerror;
             if (async) {
@@ -954,22 +973,26 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
     },
 
     // ripped from Firefox; modified
-    unsafeURI: Class.Memoize(() => util.regexp(String.replace(literal(function () /*
-            [
-                \s
-                // Invisible characters (bug 452979)
-                U001C U001D U001E U001F // file/group/record/unit separator
-                U00AD // Soft hyphen
-                UFEFF // BOM
-                U2060 // Word joiner
-                U2062 U2063 // Invisible times/separator
-                U200B UFFFC // Zero-width space/no-break space
+    unsafeURI: Class.Memoize(() => {
+        return util.regexp(
+            String.raw`
+                [
+                    \s
+                    // Invisible characters (bug 452979)
+                    U001C U001D U001E U001F // file/group/record/unit separator
+                    U00AD // Soft hyphen
+                    UFEFF // BOM
+                    U2060 // Word joiner
+                    U2062 U2063 // Invisible times/separator
+                    U200B UFFFC // Zero-width space/no-break space
+
+                    // Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6)
+                    U200E U200F U202A U202B U202C U202D U202E
+                ]
+            `.replace(/U/g, "\\u"),
+            "gx");
+    }),
 
-                // Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6)
-                U200E U200F U202A U202B U202C U202D U202E
-            ]
-        */$), /U/g, "\\u"),
-        "gx")),
     losslessDecodeURI: function losslessDecodeURI(url) {
         return url.split("%25").map(function (url) {
                 // Non-UTF-8 compliant URLs cause "malformed URI sequence" errors.
@@ -1303,10 +1326,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 && hasOwnProperty(tokens, n2) ?    tokens[n2].dactylSource
-                                                                                     || tokens[n2].source
-                                                                                     || tokens[n2]
-                                                                                   : m);
+                                  (m, n1, n2) => !n1 && hasOwnProp(tokens, n2) ?    tokens[n2].dactylSource
+                                                                                 || tokens[n2].source
+                                                                                 || tokens[n2]
+                                                                               : m);
 
         // Strip comments and white space.
         if (/x/.test(flags))
@@ -1717,11 +1740,11 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
      * @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);
diff --git a/pentadactyl/install.rdf b/pentadactyl/install.rdf
index 869f1309..25067ab2 100644
--- a/pentadactyl/install.rdf
+++ b/pentadactyl/install.rdf
@@ -31,8 +31,8 @@
         
             
+                em:minVersion="34.0"
+                em:maxVersion="46.*"/>