diff --git a/common/content/contexts.js b/common/content/contexts.js index bed6f126..b1494f3f 100644 --- a/common/content/contexts.js +++ b/common/content/contexts.js @@ -130,11 +130,14 @@ var Contexts = Module("contexts", { this.builtinGroups = [this.builtin, this.user]; }, - destroy: function () { - for (let hive in values(this.groupList)) { + cleanup: function () { + for (let hive in values(this.groupList)) dactyl.trapErrors("cleanup", hive); + }, + + destroy: function () { + for (let hive in values(this.groupList)) dactyl.trapErrors("destroy", hive); - } for (let plugin in values(plugins.contexts)) if (plugin.onUnload) @@ -191,8 +194,7 @@ var Contexts = Module("contexts", { if (group) { name = group.name; this.groupList.splice(this.groupList.indexOf(group), 1); - group.cleanup(); - group.destroy(); + dactyl.trapErrors("destroy", group); } if (this.context && this.context.group === group) @@ -295,18 +297,25 @@ var Contexts = Module("contexts", { } else { let name = isPlugin ? file.getRelativeDescriptor(isPlugin).replace(File.PATH_SEP, "-") : file.leafName; + self = update(modules.newContext.apply(null, args || [userContext]), { NAME: Const(name.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase())), + PATH: Const(file.path), + CONTEXT: Const(self), + unload: Const(function unload() { if (plugins[this.NAME] === this || plugins[this.PATH] === this) if (this.onUnload) this.onUnload(); + if (plugins[this.NAME] === this) delete plugins[this.NAME]; + if (plugins[this.PATH] === this) delete plugins[this.PATH]; + if (!this.GROUP.builtin) contexts.removeGroup(this.GROUP); }) diff --git a/common/modules/base.jsm b/common/modules/base.jsm index 12f3c9be..614b0aa7 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -61,6 +61,8 @@ if (!Object.defineProperties) for (let [k, v] in Iterator(props)) Object.defineProperty(obj, k, v); } +if (!Object.freeze) + Object.freeze = function freeze(obj) {}; if (!Object.getOwnPropertyDescriptor) Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(obj, prop) { if (!hasOwnProperty.call(obj, prop)) @@ -101,13 +103,15 @@ if (!Object.keys) Object.keys = function keys(obj) Object.getOwnPropertyNames(obj).filter(function (k) objproto.propertyIsEnumerable.call(obj, k)); +let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__; + let use = {}; let loaded = {}; let currentModule; let global = this; function defineModule(name, params, module) { if (!module) - module = Cu.getGlobalForObject ? Cu.getGlobalForObject(params) : params.__parent__; + module = getGlobalForObject(params); module.NAME = name; module.EXPORTED_SYMBOLS = params.exports || []; diff --git a/common/modules/highlight.jsm b/common/modules/highlight.jsm index 02d8e15b..dbe669d4 100644 --- a/common/modules/highlight.jsm +++ b/common/modules/highlight.jsm @@ -23,8 +23,7 @@ Highlight.liveProperty = function (name, prop) { val = Array.slice(val); else val = update({}, val); - if (Object.freeze) - Object.freeze(val); + Object.freeze(val); } this.set(name, val); diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm index aebdc528..c9f59d6d 100644 --- a/common/modules/styles.jsm +++ b/common/modules/styles.jsm @@ -23,7 +23,7 @@ Sheet.liveProperty = function (name) { this.prototype.__defineSetter__(name, function (val) { if (isArray(val)) val = Array.slice(val); - if (isArray(val) && Object.freeze) + if (isArray(val)) Object.freeze(val); this[i] = val; this.enabled = this.enabled; @@ -87,13 +87,25 @@ var Hive = Class("Hive", { this.name = name; this.sheets = []; this.names = {}; + this.refs = []; + }, + + addRef: function (obj) { + this.refs.push(Cu.getWeakReference(obj)); + this.dropRef(null); + }, + dropRef: function (obj) { + this.refs = this.refs.filter(function (ref) ref.get() && ref.get() !== obj); + if (!this.refs.length) { + this.cleanup(); + styles.hives = styles.hives.filter(function (h) h !== this, this); + } }, cleanup: function cleanup() { for (let sheet in values(this.sheets)) sheet.enabled = false; }, - destroy: function destroy() {}, __iterator__: function () Iterator(this.sheets), @@ -220,7 +232,6 @@ var Hive = Class("Hive", { }, }); -try { /** * Manages named and unnamed user style sheets, which apply to both * chrome and content pages. @@ -230,7 +241,6 @@ try { var Styles = Module("Styles", { init: function () { this._id = 0; - this.hives = []; this.cleanup(); this.allSheets = {}; @@ -244,17 +254,20 @@ var Styles = Module("Styles", { cleanup: function cleanup() { for each (let hive in this.hives) - hive.cleanup(); - this.user = this.addHive("user"); - this.system = this.addHive("system"); + util.trapErrors("cleanup", hive); + this.hives = []; + this.user = this.addHive("user", this); + this.system = this.addHive("system", this); }, - addHive: function addHive(name) { + addHive: function addHive(name, ref) { let hive = array.nth(this.hives, function (h) h.name === name, 0); if (!hive) { hive = Hive(name); this.hives.push(hive); } + if (ref) + hive.addRef(ref); return hive; }, @@ -601,7 +614,23 @@ var Styles = Module("Styles", { }); }, contexts: function (dactyl, modules, window) { - modules.Group.Hives("styles", function (group) styles.addHive(group.name)); + modules.Group.Hives("styles", + Class("LocalHive", modules.Group.Hive, { + init: function init(group) { + init.superapply(this, arguments); + + this.hive = styles.addHive(group.name); + this.hive.addRef(this); + }, + + __noSuchMethod__: function __noSuchMethod__(meth, args) { + return this.hive[meth].apply(this.hive, args); + }, + + destroy: function () { + this.hive.dropRef(this); + } + })); }, completion: function (dactyl, modules, window) { const names = Array.slice(util.computedStyle(window.document.createElement("div"))); @@ -658,6 +687,6 @@ var Styles = Module("Styles", { endModule(); -} catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);} +// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);} // vim: set fdm=marker sw=4 ts=4 et ft=javascript: