1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-20 21:48:00 +01:00

Merge changes from bootstrapped.

This commit is contained in:
Kris Maglione
2010-12-24 20:59:29 -05:00
parent c507f63194
commit 5591ed6797
17 changed files with 259 additions and 125 deletions

View File

@@ -13,6 +13,7 @@ syntax: glob
*/contrib/vim/*.vba */contrib/vim/*.vba
*/bak/* */bak/*
downloads/* downloads/*
.git/*
*.py[co] *.py[co]

View File

@@ -48,5 +48,6 @@ if (XPCOMUtils.generateNSGetFactory)
const NSGetFactory = XPCOMUtils.generateNSGetFactory([CommandLineHandler]); const NSGetFactory = XPCOMUtils.generateNSGetFactory([CommandLineHandler]);
else else
const NSGetModule = XPCOMUtils.generateNSGetModule([CommandLineHandler]); const NSGetModule = XPCOMUtils.generateNSGetModule([CommandLineHandler]);
var EXPORTED_SYMBOLS = ["NSGetFactory"];
// vim: set fdm=marker sw=4 ts=4 et: // vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -202,5 +202,6 @@ if (XPCOMUtils.generateNSGetFactory)
const NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutHandler, ChromeData, Dactyl, Shim]); const NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutHandler, ChromeData, Dactyl, Shim]);
else else
const NSGetModule = XPCOMUtils.generateNSGetModule([AboutHandler, ChromeData, Dactyl, Shim]); const NSGetModule = XPCOMUtils.generateNSGetModule([AboutHandler, ChromeData, Dactyl, Shim]);
var EXPORTED_SYMBOLS = ["NSGetFactory"];
// vim: set fdm=marker sw=4 ts=4 et: // vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -147,6 +147,40 @@ const Buffer = Module("buffer", {
let elem = event.originalTarget; let elem = event.originalTarget;
buffer.viewSource([elem.getAttribute("href"), Number(elem.getAttribute("line"))]) buffer.viewSource([elem.getAttribute("href"), Number(elem.getAttribute("line"))])
}; };
this.replaceProgressListener(this.progressListener);
},
cleanup: function () {
for (let prop in properties(this.progressListener))
if (!this.progressListener.__lookupGetter__(prop) &&
!callable(this.progressListener[prop]))
this.origProgressListener[prop] = this.progressListener[prop]
this.replaceProgressListener(this.origProgressListener);
},
replaceProgressListener: function (newListener) {
// I hate this whole hack. --Kris
let obj = window.XULBrowserWindow, getter;
for (let prop in properties(obj))
if ((getter = obj.__lookupGetter__(prop)) && !obj.__lookupSetter__(prop)) {
newListener.__defineGetter__(prop, getter);
delete obj[prop];
}
this.origProgressListener = window.XULBrowserWindow;
try {
config.browser.removeProgressListener(window.XULBrowserWindow);
}
catch (e) {} // Why? --djk
config.browser.addProgressListener(newListener, Ci.nsIWebProgress.NOTIFY_ALL);
window.XULBrowserWindow = newListener;
window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIXULWindow)
.XULBrowserWindow = newListener;
}, },
destroy: function () { destroy: function () {
@@ -1502,26 +1536,6 @@ const Buffer = Module("buffer", {
}; };
}, },
events: function () { events: function () {
try {
config.browser.removeProgressListener(window.XULBrowserWindow);
}
catch (e) {} // Why? --djk
// I hate this whole hack. --Kris
let obj = window.XULBrowserWindow, getter;
for (let p in properties(obj))
if ((getter = obj.__lookupGetter__(p)) && !obj.__lookupSetter__(p)) {
this.progressListener.__defineGetter__(p, getter);
delete obj[p];
}
config.browser.addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
window.XULBrowserWindow = this.progressListener;
window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIXULWindow)
.XULBrowserWindow = this.progressListener;
events.addSessionListener(config.browser, "DOMContentLoaded", this.closure.onDOMContentLoaded, true); events.addSessionListener(config.browser, "DOMContentLoaded", this.closure.onDOMContentLoaded, true);
events.addSessionListener(config.browser, "load", this.closure.onPageLoad, true); events.addSessionListener(config.browser, "load", this.closure.onPageLoad, true);
events.addSessionListener(config.browser, "scroll", this.closure._updateBufferPosition, false); events.addSessionListener(config.browser, "scroll", this.closure._updateBufferPosition, false);

View File

@@ -67,6 +67,7 @@ const CommandWidgets = Class("CommandWidgets", {
getGroup: function (value) { getGroup: function (value) {
if (this.command && !options.get("guioptions").has("M")) if (this.command && !options.get("guioptions").has("M"))
return this.statusbar; return this.statusbar;
let statusElem = this.statusbar.message; let statusElem = this.statusbar.message;
if (value && statusElem.editor.rootElement.scrollWidth > statusElem.scrollWidth) if (value && statusElem.editor.rootElement.scrollWidth > statusElem.scrollWidth)
return this.commandbar; return this.commandbar;
@@ -84,6 +85,14 @@ const CommandWidgets = Class("CommandWidgets", {
return this.commandbar; return this.commandbar;
} }
}); });
let fontSize = util.computedStyle(document.getElementById(config.mainWindowId)).fontSize;
styles.registerSheet("chrome://dactyl/skin/dactyl.css");
styles.system.add("font-size", "chrome://dactyl/content/buffer.xhtml",
"body { font-size: " + fontSize + "; }");
},
cleanup: function cleanup() {
styles.unregisterSheet("chrome://dactyl/skin/dactyl.css");
}, },
addElement: function (obj) { addElement: function (obj) {
const self = this; const self = this;
@@ -1742,12 +1751,6 @@ const CommandLine = Module("commandline", {
host && (!item.domains || !item.domains.some(function (d) util.isSubdomain(d, host)))); host && (!item.domains || !item.domains.some(function (d) util.isSubdomain(d, host))));
} }
}); });
},
styles: function () {
let fontSize = util.computedStyle(document.getElementById(config.mainWindowId)).fontSize;
styles.registerSheet("chrome://dactyl/skin/dactyl.css");
styles.system.add("font-size", "chrome://dactyl/content/buffer.xhtml",
"body { font-size: " + fontSize + "; }");
} }
}); });

View File

@@ -530,9 +530,9 @@ const CompletionContext = Class("CompletionContext", {
// of the given string which also matches the current // of the given string which also matches the current
// item's text. // item's text.
let len = substring.length; let len = substring.length;
let i = 0, m, n = len; let i = 0, n = len;
while (n) { while (n) {
m = Math.floor(n / 2); let m = Math.floor(n / 2);
let keep = compare(fixCase(item.text), substring.substring(0, i + m)); let keep = compare(fixCase(item.text), substring.substring(0, i + m));
if (!keep) if (!keep)
len = i + m - 1; len = i + m - 1;

View File

@@ -37,6 +37,19 @@ const Dactyl = Module("dactyl", {
}; };
}, },
cleanup: function () {
delete window.dactyl;
delete window.liberator;
},
destroy: function () {
autocommands.trigger("LeavePre", {});
storage.saveAll();
dactyl.triggerObserver("shutdown", null);
util.dump("All dactyl modules destroyed\n");
autocommands.trigger("Leave", {});
},
/** @property {string} The name of the current user profile. */ /** @property {string} The name of the current user profile. */
profileName: Class.memoize(function () { profileName: Class.memoize(function () {
// NOTE: services.profile.selectedProfile.name doesn't return // NOTE: services.profile.selectedProfile.name doesn't return
@@ -52,14 +65,6 @@ const Dactyl = Module("dactyl", {
return "unknown"; return "unknown";
}), }),
destroy: function () {
autocommands.trigger("LeavePre", {});
storage.saveAll();
dactyl.triggerObserver("shutdown", null);
util.dump("All dactyl modules destroyed\n");
autocommands.trigger("Leave", {});
},
/** /**
* @property {number} The current main mode. * @property {number} The current main mode.
* @see modes#mainModes * @see modes#mainModes

View File

@@ -13,20 +13,21 @@ plugins.contexts = {};
function Script(file) { function Script(file) {
let self = set.has(plugins, file.path) && plugins[file.path]; let self = set.has(plugins, file.path) && plugins[file.path];
if (self) { if (self) {
if (self.onUnload) if (set.has(self, "onUnload"))
self.onUnload(); self.onUnload();
} }
else { else {
self = { __proto__: plugins }; self = update({ __proto__: plugins }, {
plugins[file.path] = self; NAME: file.leafName.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase()),
self.NAME = file.leafName.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase()); PATH: file.path,
self.PATH = file.path; CONTEXT: self
self.CONTEXT = self; });
Class.replaceProperty(plugins, file.path, self);
// This belongs elsewhere // This belongs elsewhere
if (io.getRuntimeDirectories("plugins").some( if (io.getRuntimeDirectories("plugins").some(
function (dir) dir.contains(file, false))) function (dir) dir.contains(file, false)))
plugins[self.NAME] = self; Class.replaceProperty(plugins, self.NAME, self);
} }
plugins.contexts[file.path] = self; plugins.contexts[file.path] = self;
return self; return self;
@@ -67,6 +68,13 @@ const IO = Module("io", {
services.downloadManager.addListener(this.downloadListener); services.downloadManager.addListener(this.downloadListener);
}, },
destroy: function () {
services.downloadManager.removeListener(this.downloadListener);
for (let [, plugin] in Iterator(plugins.contexts))
if (plugin.onUnload)
plugin.onUnload();
},
// TODO: there seems to be no way, short of a new component, to change // TODO: there seems to be no way, short of a new component, to change
// the process's CWD - see https://bugzilla.mozilla.org/show_bug.cgi?id=280953 // the process's CWD - see https://bugzilla.mozilla.org/show_bug.cgi?id=280953
/** /**
@@ -111,13 +119,6 @@ const IO = Module("io", {
return this.cwd; return this.cwd;
}, },
destroy: function () {
services.downloadManager.removeListener(this.downloadListener);
for (let [, plugin] in Iterator(plugins.contexts))
if (plugin.onUnload)
plugin.onUnload();
},
/** /**
* @property {function} File class. * @property {function} File class.
* @final * @final

View File

@@ -36,6 +36,15 @@ const Tabs = Module("tabs", {
}; };
}, },
cleanup: function cleanup() {
for (let [i, tab] in Iterator(this.allTabs)) {
function node(clas) document.getAnonymousElementByAttribute(tab, "class", clas);
for (let elem in values(["dactyl-tab-icon-number", "dactyl-tab-number"].map(node)))
if (elem)
elem.parentNode.parentNode.removeChild(elem.parentNode);
}
},
_updateTabCount: function () { _updateTabCount: function () {
if (dactyl.has("Gecko2")) if (dactyl.has("Gecko2"))
for (let [i, tab] in Iterator(this.visibleTabs)) { for (let [i, tab] in Iterator(this.visibleTabs)) {
@@ -43,15 +52,15 @@ const Tabs = Module("tabs", {
if (!node("dactyl-tab-number")) { if (!node("dactyl-tab-number")) {
let nodes = {}; let nodes = {};
let dom = util.xmlToDom(<xul xmlns:xul={XUL} xmlns:html={XHTML} let dom = util.xmlToDom(<xul xmlns:xul={XUL} xmlns:html={XHTML}
><xul:hbox highlight="tab-number"><xul:label key="icon" align="center" highlight="TabIconNumber" class="dactyl-tab-number"/></xul:hbox ><xul:hbox highlight="tab-number"><xul:label key="icon" align="center" highlight="TabIconNumber" class="dactyl-tab-icon-number"/></xul:hbox
><xul:hbox highlight="tab-number"><html:div key="label" highlight="TabNumber"/></xul:hbox ><xul:hbox highlight="tab-number"><html:div key="label" highlight="TabNumber" class="dactyl-tab-number"/></xul:hbox
></xul>.*, document, nodes); ></xul>.*, document, nodes);
let img = node("tab-icon-image"); let img = node("tab-icon-image");
img.parentNode.appendChild(dom); img.parentNode.appendChild(dom);
tab.__defineGetter__("ordinal", function () Number(nodes.icon.value)); tab.__defineGetter__("dactylOrdinal", function () Number(nodes.icon.value));
tab.__defineSetter__("ordinal", function (i) nodes.icon.value = nodes.label.textContent = i); tab.__defineSetter__("dactylOrdinal", function (i) nodes.icon.value = nodes.label.textContent = i);
} }
tab.ordinal = i + 1; tab.dactylOrdinal = i + 1;
} }
statusline.updateTabCount(true); statusline.updateTabCount(true);
}, },

View File

@@ -98,6 +98,7 @@ let loaded = {};
let currentModule; let currentModule;
function defineModule(name, params) { function defineModule(name, params) {
let module = Cu.getGlobalForObject ? Cu.getGlobalForObject(params) : params.__parent__; let module = Cu.getGlobalForObject ? Cu.getGlobalForObject(params) : params.__parent__;
defineModule.globals.push(module);
module.NAME = name; module.NAME = name;
module.EXPORTED_SYMBOLS = params.exports || []; module.EXPORTED_SYMBOLS = params.exports || [];
defineModule.loadLog.push("defineModule " + name); defineModule.loadLog.push("defineModule " + name);
@@ -114,6 +115,7 @@ function defineModule(name, params) {
currentModule = module; currentModule = module;
} }
defineModule.globals = [];
defineModule.loadLog = []; defineModule.loadLog = [];
Object.defineProperty(defineModule.loadLog, "push", { Object.defineProperty(defineModule.loadLog, "push", {
value: function (val) { defineModule.dump(val + "\n"); this[this.length] = val; } value: function (val) { defineModule.dump(val + "\n"); this[this.length] = val; }
@@ -150,8 +152,10 @@ defineModule.time = function time(major, minor, func, self) {
function endModule() { function endModule() {
defineModule.loadLog.push("endModule " + currentModule.NAME); defineModule.loadLog.push("endModule " + currentModule.NAME);
for (let [, mod] in Iterator(use[currentModule.NAME] || [])) for (let [, mod] in Iterator(use[currentModule.NAME] || []))
require(mod, currentModule.NAME, "use"); require(mod, currentModule.NAME, "use");
loaded[currentModule.NAME] = 1; loaded[currentModule.NAME] = 1;
} }
@@ -177,8 +181,8 @@ defineModule("base", {
"call", "callable", "ctypes", "curry", "debuggerProperties", "defineModule", "call", "callable", "ctypes", "curry", "debuggerProperties", "defineModule",
"deprecated", "endModule", "forEach", "isArray", "isGenerator", "deprecated", "endModule", "forEach", "isArray", "isGenerator",
"isinstance", "isObject", "isString", "isSubclass", "iter", "iterAll", "isinstance", "isObject", "isString", "isSubclass", "iter", "iterAll",
"keys", "memoize", "octal", "properties", "set", "update", "values", "keys", "memoize", "octal", "properties", "require", "set", "update",
"withCallerGlobal" "values", "withCallerGlobal"
], ],
use: ["services", "util"] use: ["services", "util"]
}); });

View File

@@ -42,6 +42,10 @@ const BookmarkCache = Module("BookmarkCache", XPCOM(Ci.nsINavBookmarkObserver),
services.bookmarks.addObserver(this, false); services.bookmarks.addObserver(this, false);
}, },
cleanup: function cleanup() {
services.bookmarks.removeObserver(this);
},
__iterator__: function () (val for ([, val] in Iterator(bookmarkcache.bookmarks))), __iterator__: function () (val for ([, val] in Iterator(bookmarkcache.bookmarks))),
get bookmarks() Class.replaceProperty(this, "bookmarks", this.load()), get bookmarks() Class.replaceProperty(this, "bookmarks", this.load()),

View File

@@ -28,6 +28,10 @@ const Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference
this.restore(); this.restore();
}, },
cleanup: function cleanup() {
this._branch.removeObserver("", this);
},
observe: { observe: {
"nsPref:changed": function (subject, data) { "nsPref:changed": function (subject, data) {
let observers = this._observers[data]; let observers = this._observers[data];

View File

@@ -12,6 +12,8 @@
// FIXME: // FIXME:
// - finish 1.9.0 support if we're going to support sanitizing in Melodactyl // - finish 1.9.0 support if we're going to support sanitizing in Melodactyl
try {
Components.utils.import("resource://dactyl/base.jsm"); Components.utils.import("resource://dactyl/base.jsm");
defineModule("sanitizer", { defineModule("sanitizer", {
exports: ["Range", "Sanitizer", "sanitizer"], exports: ["Range", "Sanitizer", "sanitizer"],
@@ -641,6 +643,6 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR
endModule(); 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: // vim: set fdm=marker sw=4 ts=4 et ft=javascript:

View File

@@ -8,8 +8,7 @@ try {
Components.utils.import("resource://dactyl/base.jsm"); Components.utils.import("resource://dactyl/base.jsm");
defineModule("services", { defineModule("services", {
exports: ["Services", "services"], exports: ["AddonManager", "Services", "services"]
use: ["util"]
}); });
/** /**
@@ -72,6 +71,9 @@ const Services = Module("Services", {
this.addClass("Xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", Ci.nsIXMLHttpRequest); this.addClass("Xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", Ci.nsIXMLHttpRequest);
this.addClass("ZipReader", "@mozilla.org/libjar/zip-reader;1", Ci.nsIZipReader, "open"); this.addClass("ZipReader", "@mozilla.org/libjar/zip-reader;1", Ci.nsIZipReader, "open");
this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", Ci.nsIZipWriter); this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", Ci.nsIZipWriter);
if (!this.extensionManager)
Components.utils.import("resource://gre/modules/AddonManager.jsm");
}, },
_create: function (classes, ifaces, meth, init, args) { _create: function (classes, ifaces, meth, init, args) {
@@ -85,7 +87,7 @@ const Services = Module("Services", {
return res; return res;
} }
catch (e) { catch (e) {
util.dump("Service creation failed for '" + classes + "': " + e + "\n"); dump("dactyl: Service creation failed for '" + classes + "': " + e + "\n");
return null; return null;
} }
}, },
@@ -105,8 +107,12 @@ const Services = Module("Services", {
if (name in this && ifaces && !this.__lookupGetter__(name) && !(this[name] instanceof Ci.nsISupports)) if (name in this && ifaces && !this.__lookupGetter__(name) && !(this[name] instanceof Ci.nsISupports))
throw TypeError(); throw TypeError();
this.__defineGetter__(name, function () { this.__defineGetter__(name, function () {
let res = self._create(class_, ifaces, meth);
if (!res)
return null;
delete this[name]; delete this[name];
return this[name] = self._create(class_, ifaces, meth); return this[name] = res;
}); });
}, },
@@ -140,10 +146,6 @@ const Services = Module("Services", {
get: function (name) this[name], get: function (name) this[name],
}, { }, {
}, { }, {
init: function (dactyl, modules) {
if (!modules.AddonManager && !this.get("extensionManager"))
Components.utils.import("resource://gre/modules/AddonManager.jsm", modules);
},
javascript: function (dactyl, modules) { javascript: function (dactyl, modules) {
modules.JavaScript.setCompleter(this.get, [function () [[k, v] for ([k, v] in Iterator(services)) if (v instanceof Ci.nsISupports)]]); modules.JavaScript.setCompleter(this.get, [function () [[k, v] for ([k, v] in Iterator(services)) if (v instanceof Ci.nsISupports)]]);
modules.JavaScript.setCompleter(this.create, [function () [[c, ""] for (c in services.classes)]]); modules.JavaScript.setCompleter(this.create, [function () [[c, ""] for (c in services.classes)]]);

View File

@@ -142,25 +142,39 @@ const ObjectStore = Class("ObjectStore", StoreBase, {
__iterator__: function () Iterator(this._object), __iterator__: function () Iterator(this._object),
}); });
var keys = {};
var observers = {};
const Storage = Module("Storage", { const Storage = Module("Storage", {
alwaysReload: {}, alwaysReload: {},
init: function () {
this.cleanup();
},
cleanup: function () {
for (let key in keys(this.keys))
delete this[key];
for (let ary in values(this.observers))
for (let obj in values(ary))
if (obj.ref && obj.ref.get())
delete obj.ref.get().dactylStorageRefs;
this.keys = {};
this.observers = {};
},
newObject: function newObject(key, constructor, params) { newObject: function newObject(key, constructor, params) {
if (params == null || !isObject(params)) if (params == null || !isObject(params))
throw Error("Invalid argument type"); throw Error("Invalid argument type");
if (!(key in keys) || params.reload || this.alwaysReload[key]) { if (!(key in this.keys) || params.reload || this.alwaysReload[key]) {
if (key in this && !(params.reload || this.alwaysReload[key])) if (key in this && !(params.reload || this.alwaysReload[key]))
throw Error(); throw Error();
let load = function () loadData(key, params.store, params.type || myObject); let load = function () loadData(key, params.store, params.type || myObject);
keys[key] = new constructor(key, params.store, load, params);
keys[key].timer = new Timer(1000, 10000, function () storage.save(key)); this.keys[key] = new constructor(key, params.store, load, params);
this.__defineGetter__(key, function () keys[key]); this.keys[key].timer = new Timer(1000, 10000, function () storage.save(key));
this.__defineGetter__(key, function () this.keys[key]);
} }
return keys[key]; return this.keys[key];
}, },
newMap: function newMap(key, options) { newMap: function newMap(key, options) {
@@ -182,38 +196,36 @@ const Storage = Module("Storage", {
callbackRef = { get: function () callback }; callbackRef = { get: function () callback };
} }
this.removeDeadObservers(); this.removeDeadObservers();
if (!(key in observers)) if (!(key in this.observers))
observers[key] = []; this.observers[key] = [];
if (!observers[key].some(function (o) o.callback.get() == callback)) if (!this.observers[key].some(function (o) o.callback.get() == callback))
observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef }); this.observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef });
}, },
removeObserver: function (key, callback) { removeObserver: function (key, callback) {
this.removeDeadObservers(); this.removeDeadObservers();
if (!(key in observers)) if (!(key in this.observers))
return; return;
observers[key] = observers[key].filter(function (elem) elem.callback.get() != callback); this.observers[key] = this.observers[key].filter(function (elem) elem.callback.get() != callback);
if (observers[key].length == 0) if (this.observers[key].length == 0)
delete obsevers[key]; delete obsevers[key];
}, },
removeDeadObservers: function () { removeDeadObservers: function () {
for (let [key, ary] in Iterator(observers)) { for (let [key, ary] in Iterator(this.observers)) {
observers[key] = ary = ary.filter(function (o) o.callback.get() && (!o.ref || o.ref.get() && o.ref.get().dactylStorageRefs)); this.observers[key] = ary = ary.filter(function (o) o.callback.get() && (!o.ref || o.ref.get() && o.ref.get().dactylStorageRefs));
if (!ary.length) if (!ary.length)
delete observers[key]; delete this.observers[key];
} }
}, },
get observers() observers,
fireEvent: function fireEvent(key, event, arg) { fireEvent: function fireEvent(key, event, arg) {
this.removeDeadObservers(); this.removeDeadObservers();
if (key in observers) if (key in this.observers)
// Safe, since we have our own Array object here. // Safe, since we have our own Array object here.
for each (let observer in observers[key]) for each (let observer in this.observers[key])
observer.callback.get()(key, event, arg); observer.callback.get()(key, event, arg);
if (key in keys) if (key in this.keys)
this[key].timer.tell(); this[key].timer.tell();
}, },
@@ -223,11 +235,11 @@ const Storage = Module("Storage", {
}, },
save: function save(key) { save: function save(key) {
saveData(keys[key]); saveData(this.keys[key]);
}, },
saveAll: function storeAll() { saveAll: function storeAll() {
for each (let obj in keys) for each (let obj in this.keys)
saveData(obj); saveData(obj);
}, },
@@ -237,7 +249,7 @@ const Storage = Module("Storage", {
if (val && !this._privateMode) if (val && !this._privateMode)
this.saveAll(); this.saveAll();
if (!val && this._privateMode) if (!val && this._privateMode)
for (let key in keys) for (let key in this.keys)
this.load(key); this.load(key);
return this._privateMode = Boolean(val); return this._privateMode = Boolean(val);
} }

View File

@@ -79,6 +79,11 @@ const Hive = Class("Hive", {
this.names = {}; this.names = {};
}, },
cleanup: function cleanup() {
for (let sheet in values(this.sheets))
sheet.enabled = false;
},
__iterator__: function () Iterator(this.sheets), __iterator__: function () Iterator(this.sheets),
get sites() array(this.sheets).map(function (s) s.sites).flatten().uniq().array, get sites() array(this.sheets).map(function (s) s.sites).flatten().uniq().array,
@@ -214,6 +219,11 @@ const Styles = Module("Styles", {
this.system = Hive(); this.system = Hive();
}, },
cleanup: function cleanup() {
for each (let hive in [this.user, this.system])
hive.cleanup();
},
__iterator__: function () Iterator(this.user.sheets.concat(this.system.sheets)), __iterator__: function () Iterator(this.user.sheets.concat(this.system.sheets)),
_proxy: function (name, args) _proxy: function (name, args)

View File

@@ -54,6 +54,16 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
this.overlays = {}; this.overlays = {};
}, },
cleanup: function cleanup() {
for (let win in iter(services.windowMediator.getEnumerator(null))) {
for (let elem in values(win.document.dactylOverlayElements || []))
if (elem.parentNode)
elem.parentNode.removeChild(elem);
delete win.document.dactylOverlayElements;
delete win.document.dactylOverlays;
}
},
// FIXME: Only works for Pentadactyl // FIXME: Only works for Pentadactyl
get activeWindow() services.windowMediator.getMostRecentWindow("navigator:browser"), get activeWindow() services.windowMediator.getMostRecentWindow("navigator:browser"),
dactyl: update(function dactyl(obj) { dactyl: update(function dactyl(obj) {
@@ -90,12 +100,13 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
let observers = obj.observe; let observers = obj.observe;
function register(meth) { function register(meth) {
services.observer[meth](obj, "quit-application", true); services.observer[meth](obj, "quit-application", true);
services.observer[meth](obj, "dactyl-unload", true);
for (let target in keys(observers)) for (let target in keys(observers))
services.observer[meth](obj, target, true); services.observer[meth](obj, target, true);
} }
Class.replaceProperty(obj, "observe", Class.replaceProperty(obj, "observe",
function (subject, target, data) { function (subject, target, data) {
if (target == "quit-application") if (target == "quit-application" || target == "dactyl-unload")
register("removeObserver"); register("removeObserver");
if (observers[target]) if (observers[target])
observers[target].call(obj, subject, data); observers[target].call(obj, subject, data);
@@ -838,7 +849,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
let tag = "<" + [namespaced(elem)].concat( let tag = "<" + [namespaced(elem)].concat(
[namespaced(a) + "=" + template.highlight(a.value, true) [namespaced(a) + "=" + template.highlight(a.value, true)
for ([i, a] in array.iterItems(elem.attributes))]).join(" "); for ([i, a] in array.iterItems(elem.attributes))]).join(" ");
return tag + (hasChildren ? "/>" : ">...</" + namespaced(elem) + ">"); return tag + (!hasChildren ? "/>" : ">...</" + namespaced(elem) + ">");
} }
catch (e) { catch (e) {
return {}.toString.call(elem); return {}.toString.call(elem);
@@ -899,19 +910,51 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
observe: { observe: {
"toplevel-window-ready": function (window, data) { "toplevel-window-ready": function (window, data) {
window.addEventListener("DOMContentLoaded", wrapCallback(function listener(event) { window.addEventListener("DOMContentLoaded", wrapCallback(function listener(event) {
if (event.originalTarget === window.document) {
window.removeEventListener("DOMContentLoaded", listener.wrapper, true); window.removeEventListener("DOMContentLoaded", listener.wrapper, true);
util._loadOverlays(window);
}
}), true)
}
},
if (event.originalTarget !== window.document) _loadOverlays: function _loadOverlays(window) {
return; if (!window.dactylOverlays)
window.dactylOverlays = [];
let obj = util.overlays[window.document.documentURI]; util.dump("load overlays", window.document.documentURI);
if (obj) {
obj = obj(window); for each (let obj in util.overlays[window.document.documentURI] || []) {
if (window.dactylOverlays.indexOf(obj) >= 0)
continue;
window.dactylOverlays.push(obj);
this._loadOverlay(window, obj(window));
}
},
_loadOverlay: function _loadOverlay(window, obj) {
let doc = window.document;
if (!doc.dactylOverlayElements)
doc.dactylOverlayElements = [];
util.dump("load overlay", doc.documentURI, String(obj).substr(0, 60));
function overlay(key, fn) { function overlay(key, fn) {
for (let [elem, xml] in Iterator(obj[key] || {})) if (obj[key]) {
if (elem = window.document.getElementById(elem)) let iterator = Iterator(obj[key]);
fn(elem, util.xmlToDom(xml, window.document)); if (!isObject(obj[key]))
iterator = ([elem.@id, elem.elements(), elem.@*::*.(function::name() != "id")] for each (elem in obj[key]));
for (let [elem, xml, attr] in iterator) {
if (elem = doc.getElementById(elem)) {
let node = util.xmlToDom(xml, doc, obj.objects);
for (let n in array.iterValues(node.childNodes))
doc.dactylOverlayElements.push(n);
fn(elem, node);
for each (let attr in attr || []) // FIXME: Cleanup...
elem.setAttributeNS(attr.namespace(), attr.localName(), attr);
}
}
}
} }
overlay("before", function (elem, dom) elem.parentNode.insertBefore(dom, elem)); overlay("before", function (elem, dom) elem.parentNode.insertBefore(dom, elem));
@@ -919,22 +962,36 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
overlay("append", function (elem, dom) elem.appendChild(dom)); overlay("append", function (elem, dom) elem.appendChild(dom));
overlay("prepend", function (elem, dom) elem.insertBefore(dom, elem.firstChild)); overlay("prepend", function (elem, dom) elem.insertBefore(dom, elem.firstChild));
if (obj.init) if (obj.init)
obj.init(window, event); obj.init(window);
if (obj.load) if (obj.load)
window.document.addEventListener("load", function (event) { if (doc.readyState === "complete")
if (event.originalTarget === event.target) obj.load(window);
else
doc.addEventListener("load", wrapCallback(function load(event) {
if (event.originalTarget === event.target) {
doc.removeEventListener("load", load.wrapper, true);
obj.load(window, event); obj.load(window, event);
}, true);
}
}), true)
} }
}), true);
}, },
overlayWindow: function (url, fn) { overlayWindow: function (url, fn) {
if (url instanceof Ci.nsIDOMWindow)
util._loadOverlay(url, fn);
else {
Array.concat(url).forEach(function (url) { Array.concat(url).forEach(function (url) {
this.overlays[url] = fn; if (!this.overlays[url])
this.overlays[url] = [];
this.overlays[url].push(fn);
}, this); }, this);
for (let win in iter(services.windowMediator.getEnumerator(null)))
if (["interactive", "complete"].indexOf(win.document.readyState) >= 0)
this._loadOverlays(win);
else
this.observe(win, "toplevel-window-ready");
}
}, },
/** /**
@@ -1085,7 +1142,11 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
this.dump(""); this.dump("");
} }
catch (e) { catch (e) {
this.dump(e); try {
this.dump(String(error));
this.dump(error.stack)
}
catch (e) { dump(e + "\n"); }
} }
}, },