diff options
-rw-r--r-- | common/content/autocommands.js | 12 | ||||
-rw-r--r-- | common/content/buffer.js | 6 | ||||
-rw-r--r-- | common/content/commands.js | 20 | ||||
-rw-r--r-- | common/content/contexts.js | 41 | ||||
-rw-r--r-- | common/content/dactyl.js | 4 | ||||
-rw-r--r-- | common/content/events.js | 70 | ||||
-rw-r--r-- | common/content/hints.js | 2 | ||||
-rw-r--r-- | common/content/mappings.js | 18 | ||||
-rw-r--r-- | common/content/marks.js | 2 | ||||
-rw-r--r-- | common/content/tabs.js | 4 | ||||
-rw-r--r-- | common/modules/styles.jsm | 1 |
11 files changed, 123 insertions, 57 deletions
diff --git a/common/content/autocommands.js b/common/content/autocommands.js index 81e38fac..e24d2e6e 100644 --- a/common/content/autocommands.js +++ b/common/content/autocommands.js @@ -17,16 +17,12 @@ update(AutoCommand.prototype, { } }); -var AutoCmdHive = Class("AutoCmdHive", { +var AutoCmdHive = Class("AutoCmdHive", Group.Hive, { init: function init(group) { - this.group = group; + init.supercall(this, group); this._store = []; }, - get toStringParams() [this.group.name], - - get builtin() this.group.builtin, - __iterator__: function () array.iterValues(this._store), /** @@ -111,7 +107,7 @@ var AutoCommands = Module("autocommands", { { template.map(this.activeHives, function (hive) <tr highlight="Title"> - <td colspan="3">{hive.group.name}</td> + <td colspan="3">{hive.name}</td> </tr> + <tr style="height: .5ex;"/> + template.map(cmds(hive), function ([event, items]) @@ -148,7 +144,7 @@ var AutoCommands = Module("autocommands", { event = event.toLowerCase(); for (let hive in this.hives.iterValues()) { let args = update({}, - hive.group.argsExtra(arguments[1]), + hive.argsExtra(arguments[1]), arguments[1]); for (let autoCmd in values(hive._store)) diff --git a/common/content/buffer.js b/common/content/buffer.js index b5e4d1ed..4b691261 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -1644,9 +1644,9 @@ var Buffer = Module("buffer", { }; }, events: function () { - events.addSessionListener(config.browser, "DOMContentLoaded", buffer.closure.onDOMContentLoaded, true); - events.addSessionListener(config.browser, "load", buffer.closure.onPageLoad, true); - events.addSessionListener(config.browser, "scroll", buffer.closure._updateBufferPosition, false); + events.listen(config.browser, "DOMContentLoaded", buffer.closure.onDOMContentLoaded, true); + events.listen(config.browser, "load", buffer.closure.onPageLoad, true); + events.listen(config.browser, "scroll", buffer.closure._updateBufferPosition, false); }, mappings: function () { var myModes = config.browserModes; diff --git a/common/content/commands.js b/common/content/commands.js index 981ea8cd..86d2e670 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -127,7 +127,7 @@ var Command = Class("Command", { this.options = this.options.map(CommandOption.fromArray, CommandOption); }, - get toStringParams() [this.name, this.hive.group.name], + get toStringParams() [this.name, this.hive.name], get helpTag() ":" + this.name, @@ -155,8 +155,8 @@ var Command = Class("Command", { if (args.bang && !this.bang) throw FailedAssertion("E477: No ! allowed"); - return !dactyl.trapErrors(function exec(command) { - // update({}, command.hive.group.argsExtra(args), args); + return !dactyl.trapErrors(function exec() { + update({}, this.hive.argsExtra(args), args); if (this.always) this.always(args, modifiers); @@ -397,17 +397,13 @@ var ex = { __noSuchMethod__: function (meth, args) this._run(meth).apply(this, args) }; -var CommandHive = Class("CommandHive", { +var CommandHive = Class("CommandHive", Group.Hive, { init: function init(group) { - this.group = group; + init.supercall(this, group); this._map = {}; this._list = []; }, - get toStringParams() [this.group.name], - - get builtin() this.group.builtin, - /** @property {Iterator(Command)} @private */ __iterator__: function () array.iterValues(this._list.sort(function (a, b) a.name > b.name)), @@ -610,7 +606,7 @@ var Commands = Module("commands", { template.map(hive, function (cmd) template.map(cmd.names, function (name) <tr> - <td highlight="Title">{!i++ ? hive.group.name : ""}</td> + <td highlight="Title">{!i++ ? hive.name : ""}</td> <td>{cmd.bang ? "!" : " "}</td> <td>{cmd.name}</td> <td>{cmd.argCount}</td> @@ -1425,7 +1421,7 @@ var Commands = Module("commands", { literal: 1, serialize: function () array(commands.userHives) - .filter(function (h) h.group.persist) + .filter(function (h) h.persist) .map(function (hive) [ { command: this.name, @@ -1485,7 +1481,7 @@ var Commands = Module("commands", { iterate: function (args) commands.iterator().map(function (cmd) ({ __proto__: cmd, columns: [ - cmd.hive == commands.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{cmd.hive.group.name}</span> + cmd.hive == commands.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{cmd.hive.name}</span> ] })), format: { diff --git a/common/content/contexts.js b/common/content/contexts.js index e3f2a0d4..9e57e90f 100644 --- a/common/content/contexts.js +++ b/common/content/contexts.js @@ -16,8 +16,11 @@ var Group = Class("Group", { cleanup: function cleanup() { for (let hive in values(this.hives)) - if (hive.cleanup) - hive.cleanup(); + dactyl.trapErrors("cleanup", hive); + }, + destroy: function destroy() { + for (let hive in values(this.hives)) + dactyl.trapErrors("destroy", hive); }, argsExtra: function argsExtra() ({}), @@ -58,6 +61,32 @@ var Group = Class("Group", { hiveMap: {}, + Hive: Class("Hive", { + init: function init(group) { + this.group = group; + }, + + cleanup: function cleanup() {}, + destroy: function destroy() {}, + + get argsExtra() this.group.argsExtra, + get builtin() this.group.builtin, + + get name() this.group.name, + set name(val) this.group.name = val, + + get description() this.group.description, + set description(val) this.group.description = val, + + get filter() this.group.filter, + set filter(val) this.group.filter = val, + + get persist() this.group.persist, + set persist(val) this.group.persist = val, + + get toStringParams() [this.name] + }), + Hives: Class("Hives", Class.Property, { init: function init(name, constructor) { const self = this; @@ -100,6 +129,13 @@ var Contexts = Module("contexts", { this.builtinGroups = [this.system, this.user]; }, + destroy: function () { + for (let hive in values(this.groupList)) { + dactyl.trapErrors("cleanup", hive); + dactyl.trapErrors("destroy", hive); + } + }, + context: null, groups: Class.memoize(function () Object.create(Group.groupsProto, { @@ -145,6 +181,7 @@ var Contexts = Module("contexts", { if (group) { this.groupList.splice(this.groupList.indexOf(group), 1); group.cleanup(); + group.destroy(); } if (this.context && this.context.group === group) diff --git a/common/content/dactyl.js b/common/content/dactyl.js index cddbf583..ee2c9b3a 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -1459,8 +1459,8 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { } }, { events: function () { - events.addSessionListener(window, "click", dactyl.closure.onClick, true); - events.addSessionListener(window, "dactyl.execute", dactyl.closure.onExecute, true); + events.listen(window, "click", dactyl.closure.onClick, true); + events.listen(window, "dactyl.execute", dactyl.closure.onExecute, true); }, // Only general options are added here, which are valid for all Dactyl extensions options: function () { diff --git a/common/content/events.js b/common/content/events.js index 26217d4a..bebd5808 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -255,6 +255,54 @@ var KeyArgProcessor = Class("KeyArgProcessor", KeyProcessor, { } }); +var EventHive = Class("EventHive", Group.Hive, { + init: function init(group) { + init.supercall(this, group); + this.sessionListeners = []; + }, + + cleanup: function cleanup() { + this.unlisten(null); + }, + + /** + * Adds an event listener for this session and removes it on + * dactyl shutdown. + * + * @param {Element} target The element on which to listen. + * @param {string} event The event to listen for. + * @param {function} callback The function to call when the event is received. + * @param {boolean} capture When true, listen during the capture + * phase, otherwise during the bubbling phase. + */ + listen: function (target, event, callback, capture) { + let args = Array.slice(arguments, 0); + args[2] = this.wrapListener(callback); + args[0].addEventListener.apply(args[0], args.slice(1)); + args[0] = Cu.getWeakReference(args[0]); + this.sessionListeners.push(args); + }, + + /** + * Remove an event listener. + * + * @param {Element} target The element on which to listen. + * @param {string} event The event to listen for. + * @param {function} callback The function to call when the event is received. + * @param {boolean} capture When true, listen during the capture + * phase, otherwise during the bubbling phase. + */ + unlisten: function (target, event, callback, capture) { + this.sessionListeners = this.sessionListeners.filter(function (args) { + if (target == null || args[0].get() == target && args[1] == event && args[2] == callback && args[3] == capture) { + args[0].get().removeEventListener.apply(args[0].get(), args.slice(1)); + return true; + } + return !args[0].get(); + }); + } +}); + /** * @instance events */ @@ -283,7 +331,9 @@ var Events = Module("events", { this._macroKeys = []; this._lastMacro = ""; - this.sessionListeners = []; + EventHive.prototype.wrapListener = this.closure.wrapListener; + this.user = contexts.hives.events.user; + this.builtin = contexts.hives.events.builtin; this._macros = storage.newMap("macros", { privateData: true, store: true }); for (let [k, m] in this._macros) @@ -344,19 +394,14 @@ var Events = Module("events", { this._activeMenubar = false; for (let [event, callback] in Iterator(this.events)) - this.addSessionListener(window, event, callback, true); + this.listen(window, event, callback, true); dactyl.registerObserver("modeChange", function () { delete self.processor; }); }, - destroy: function () { - util.dump("Removing all event listeners"); - for (let args in values(this.sessionListeners)) - if (args[0].get()) - args[0].get().removeEventListener.apply(args[0].get(), args.slice(1)); - }, + hives: Group.Hives("events", EventHive), /** * Adds an event listener for this session and removes it on @@ -368,13 +413,8 @@ var Events = Module("events", { * @param {boolean} capture When true, listen during the capture * phase, otherwise during the bubbling phase. */ - addSessionListener: function (target, event, callback, capture) { - let args = Array.slice(arguments, 0); - args[2] = this.wrapListener(callback); - args[0].addEventListener.apply(args[0], args.slice(1)); - args[0] = Cu.getWeakReference(args[0]); - this.sessionListeners.push(args); - }, + get addSessionListener() this.builtin.closure.listen, + get listen() this.builtin.closure.listen, /** * Wraps an event listener to ensure that errors are reported. diff --git a/common/content/hints.js b/common/content/hints.js index 9a9a7502..7b6d6d52 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -677,7 +677,7 @@ var Hints = Module("hints", { let appContent = document.getElementById("appcontent"); if (appContent) - events.addSessionListener(appContent, "scroll", this.resizeTimer.closure.tell, false); + events.listen(appContent, "scroll", this.resizeTimer.closure.tell, false); const Mode = Hints.Mode; Mode.defaultValue("tags", function () function () options["hinttags"]); diff --git a/common/content/mappings.js b/common/content/mappings.js index 3f05549a..9512e087 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -108,7 +108,7 @@ var Map = Class("Map", { .toObject(); args = update({ context: contexts.context }, - this.hive.group.argsExtra(args), + this.hive.argsExtra(args), args); let self = this; @@ -138,16 +138,12 @@ var Map = Class("Map", { id: 0 }); -var MapHive = Class("MapHive", { +var MapHive = Class("MapHive", Group.Hive, { init: function init(group) { - this.group = group; + init.supercall(this, group); this.stacks = {}; }, - get toStringParams() [this.group.name], - - get builtin() this.group.builtin, - /** * Iterates over all mappings present in all of the given *modes*. * @@ -423,7 +419,7 @@ var Mappings = Module("mappings", { template.map(maps(hive), function (map) template.map(map.names, function (name, i) <tr> - <td highlight="Title">{!i ? hive.group.name : ""}</td> + <td highlight="Title">{!i ? hive.name : ""}</td> <td>{modeSign}</td> <td>{name}</td> <td>{map.rhs || map.action.toSource()}</td> @@ -532,12 +528,12 @@ var Mappings = Module("mappings", { serialize: function () { return this.name != "map" ? [] : array(mappings.userHives) - .filter(function (h) h.group.persist) + .filter(function (h) h.persist) .map(function (hive) [ { command: "map", options: array([ - hive !== mappings.user && ["-group", hive.group.name], + hive !== mappings.user && ["-group", hive.name], ["-modes", uniqueModes(map.modes)], ["-description", map.description], map.silent && ["-silent"]]) @@ -678,7 +674,7 @@ var Mappings = Module("mappings", { name: name, columns: [ mode == mainMode ? "" : <span highlight="Object" style="padding-right: 1em;">{mode.name}</span>, - hive == mappings.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{hive.group.name}</span> + hive == mappings.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{hive.name}</span> ], __proto__: map }; diff --git a/common/content/marks.js b/common/content/marks.js index 729e23ac..b7df2c89 100644 --- a/common/content/marks.js +++ b/common/content/marks.js @@ -208,7 +208,7 @@ var Marks = Module("marks", { events: function () { let appContent = document.getElementById("appcontent"); if (appContent) - events.addSessionListener(appContent, "load", marks.closure._onPageLoad, true); + events.listen(appContent, "load", marks.closure._onPageLoad, true); }, mappings: function () { var myModes = config.browserModes; diff --git a/common/content/tabs.js b/common/content/tabs.js index 13ec4df4..d14d8bbc 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -874,8 +874,8 @@ var Tabs = Module("tabs", { tabs.timeout(function () { this.updateTabCount(); }); } for (let event in values(["TabMove", "TabOpen", "TabClose"])) - events.addSessionListener(tabContainer, event, callback, false); - events.addSessionListener(tabContainer, "TabSelect", tabs.closure._onTabSelect, false); + events.listen(tabContainer, event, callback, false); + events.listen(tabContainer, "TabSelect", tabs.closure._onTabSelect, false); }, mappings: function () { mappings.add([modes.NORMAL], ["g0", "g^"], diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm index a7259259..aebdc528 100644 --- a/common/modules/styles.jsm +++ b/common/modules/styles.jsm @@ -93,6 +93,7 @@ var Hive = Class("Hive", { for (let sheet in values(this.sheets)) sheet.enabled = false; }, + destroy: function destroy() {}, __iterator__: function () Iterator(this.sheets), |