summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcommon/bootstrap.js48
-rw-r--r--common/content/commandline.js2
-rw-r--r--common/content/dactyl.js114
-rw-r--r--common/content/events.js4
-rw-r--r--common/modules/addons.jsm1
-rw-r--r--common/modules/base.jsm18
-rw-r--r--common/modules/config.jsm4
-rw-r--r--common/modules/dom.jsm5
-rw-r--r--common/modules/help.jsm117
-rw-r--r--common/modules/messages.jsm13
-rw-r--r--common/modules/overlay.jsm69
-rw-r--r--common/modules/services.jsm12
-rw-r--r--common/modules/storage.jsm54
-rw-r--r--common/modules/util.jsm28
14 files changed, 273 insertions, 216 deletions
diff --git a/common/bootstrap.js b/common/bootstrap.js
index e4f7d561..03e85b20 100755
--- a/common/bootstrap.js
+++ b/common/bootstrap.js
@@ -9,10 +9,7 @@
const NAME = "bootstrap";
const global = this;
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
+var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
function module(uri) {
let obj = {};
@@ -29,8 +26,8 @@ const resourceProto = Services.io.getProtocolHandler("resource")
const categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
const manager = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-const BOOTSTRAP_JSM = "resource://dactyl/bootstrap.jsm";
-
+const DISABLE_ACR = "resource://dactyl-content/disable-acr.jsm";
+const BOOTSTRAP_JSM = "resource://dactyl/bootstrap.jsm";
const BOOTSTRAP_CONTRACT = "@dactyl.googlecode.com/base/bootstrap";
var JSMLoader = BOOTSTRAP_CONTRACT in Cc && Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader;
@@ -206,7 +203,7 @@ function init() {
}
try {
- module("resource://dactyl-content/disable-acr.jsm").init(addon.id);
+ module(DISABLE_ACR).init(addon.id);
}
catch (e) {
reportError(e);
@@ -240,20 +237,21 @@ function init() {
JSMLoader.init(suffix);
JSMLoader.load("base.jsm", global);
- if (!(BOOTSTRAP_CONTRACT in Cc))
- manager.registerFactory(Components.ID("{f541c8b0-fe26-4621-a30b-e77d21721fb5}"),
- "{f541c8b0-fe26-4621-a30b-e77d21721fb5}",
- BOOTSTRAP_CONTRACT, {
+ if (!(BOOTSTRAP_CONTRACT in Cc)) {
+ let factory = {
+ classID: Components.ID("{f541c8b0-fe26-4621-a30b-e77d21721fb5}"),
+ contractID: BOOTSTRAP_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
- instance: {
- QueryInterface: XPCOMUtils.generateQI([]),
- contractID: BOOTSTRAP_CONTRACT,
- wrappedJSObject: {}
- },
- // Use Sandbox to prevent closure over this scope
- createInstance: Cu.evalInSandbox("(function () this.instance)",
+
+ // Use Sandbox to prevent closures over this scope
+ createInstance: Cu.evalInSandbox("(function () this)",
Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].getService()))
- });
+ };
+ factory.wrappedJSObject = factory;
+
+ manager.registerFactory(factory.classID, String(factory.classID),
+ BOOTSTRAP_CONTRACT, factory);
+ }
Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject.loader = !Cu.unload && JSMLoader;
@@ -271,7 +269,9 @@ function shutdown(data, reason) {
debug("bootstrap: shutdown " + reasonToString(reason));
if (reason != APP_SHUTDOWN) {
try {
- module("resource://dactyl-content/disable-acr.jsm").cleanup();
+ module(DISABLE_ACR).cleanup();
+ if (Cu.unload)
+ Cu.unload(DISABLE_ACR);
}
catch (e) {
reportError(e);
@@ -293,8 +293,14 @@ function shutdown(data, reason) {
function uninstall(data, reason) {
debug("bootstrap: uninstall " + reasonToString(reason));
- if (reason == ADDON_UNINSTALL)
+ if (reason == ADDON_UNINSTALL) {
Services.prefs.deleteBranch("extensions.dactyl.");
+
+ if (BOOTSTRAP_CONTRACT in Cc) {
+ let service = Cc[BOOTSTRAP_CONTRACT].getService().wrappedJSObject;
+ manager.unregisterFactory(service.classID, service);
+ }
+ }
}
function reasonToString(reason) {
diff --git a/common/content/commandline.js b/common/content/commandline.js
index 4b36f46e..46d22cbb 100644
--- a/common/content/commandline.js
+++ b/common/content/commandline.js
@@ -1351,7 +1351,7 @@ var CommandLine = Module("commandline", {
if (isObject(arg))
arg = util.objectToString(arg, useColor);
else if (callable(arg))
- arg = String(arg);
+ arg = String.replace(arg, "/* use strict */ \n", "/* use strict */ ");
else if (!isString(arg) && useColor)
arg = template.highlight(arg);
return arg;
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index 08175652..1cb3aa3f 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -737,120 +737,6 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
return UTF8(xml.toXMLString());
},
- exportHelp: JavaScript.setCompleter(function (path) {
- const FILE = io.File(path);
- const PATH = FILE.leafName.replace(/\..*/, "") + "/";
- const TIME = Date.now();
-
- if (!FILE.exists() && (/\/$/.test(path) && !/\./.test(FILE.leafName)))
- FILE.create(FILE.DIRECTORY_TYPE, octal(755));
-
- dactyl.initHelp();
- if (FILE.isDirectory()) {
- var addDataEntry = function addDataEntry(file, data) FILE.child(file).write(data);
- var addURIEntry = function addURIEntry(file, uri) addDataEntry(file, util.httpGet(uri).responseText);
- }
- else {
- var zip = services.ZipWriter();
- zip.open(FILE, File.MODE_CREATE | File.MODE_WRONLY | File.MODE_TRUNCATE);
-
- addURIEntry = function addURIEntry(file, uri)
- zip.addEntryChannel(PATH + file, TIME, 9,
- services.io.newChannel(uri, null, null), false);
- addDataEntry = function addDataEntry(file, data) // Unideal to an extreme.
- addURIEntry(file, "data:text/plain;charset=UTF-8," + encodeURI(data));
- }
-
- let empty = Set("area base basefont br col frame hr img input isindex link meta param"
- .split(" "));
- function fix(node) {
- switch(node.nodeType) {
- case Node.ELEMENT_NODE:
- if (isinstance(node, [HTMLBaseElement]))
- return;
-
- data.push("<"); data.push(node.localName);
- if (node instanceof HTMLHtmlElement)
- data.push(" xmlns=" + XHTML.uri.quote(),
- " xmlns:dactyl=" + NS.uri.quote());
-
- for (let { name, value } in array.iterValues(node.attributes)) {
- if (name == "dactyl:highlight") {
- Set.add(styles, value);
- name = "class";
- value = "hl-" + value;
- }
- if (name == "href") {
- value = node.href || value;
- if (value.indexOf("dactyl://help-tag/") == 0) {
- let uri = services.io.newChannel(value, null, null).originalURI;
- value = uri.spec == value ? "javascript:;" : uri.path.substr(1);
- }
- if (!/^#|[\/](#|$)|^[a-z]+:/.test(value))
- value = value.replace(/(#|$)/, ".xhtml$1");
- }
- if (name == "src" && value.indexOf(":") > 0) {
- chromeFiles[value] = value.replace(/.*\//, "");
- value = value.replace(/.*\//, "");
- }
-
- data.push(" ", name, '="',
- <>{value}</>.toXMLString().replace(/"/g, "&quot;"),
- '"');
- }
- if (node.localName in empty)
- data.push(" />");
- else {
- data.push(">");
- if (node instanceof HTMLHeadElement)
- data.push(<link rel="stylesheet" type="text/css" href="help.css"/>.toXMLString());
- Array.map(node.childNodes, fix);
- data.push("</", node.localName, ">");
- }
- break;
- case Node.TEXT_NODE:
- data.push(<>{node.textContent}</>.toXMLString());
- }
- }
-
- let chromeFiles = {};
- let styles = {};
- for (let [file, ] in Iterator(help.files)) {
- let url = "dactyl://help/" + file;
- dactyl.open(url);
- util.waitFor(function () content.location.href == url && buffer.loaded
- && content.document.documentElement instanceof HTMLHtmlElement,
- 15000);
- events.waitForPageLoad();
- var data = [
- '<?xml version="1.0" encoding="UTF-8"?>\n',
- '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n',
- ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n'
- ];
- fix(content.document.documentElement);
- addDataEntry(file + ".xhtml", data.join(""));
- }
-
- let data = [h for (h in highlight) if (Set.has(styles, h.class) || /^Help/.test(h.class))]
- .map(function (h) h.selector
- .replace(/^\[.*?=(.*?)\]/, ".hl-$1")
- .replace(/html\|/g, "") + "\t" + "{" + h.cssText + "}")
- .join("\n");
- addDataEntry("help.css", data.replace(/chrome:[^ ")]+\//g, ""));
-
- addDataEntry("tag-map.json", JSON.stringify(help.tags));
-
- let m, re = /(chrome:[^ ");]+\/)([^ ");]+)/g;
- while ((m = re.exec(data)))
- chromeFiles[m[0]] = m[2];
-
- for (let [uri, leaf] in Iterator(chromeFiles))
- addURIEntry(leaf, uri);
-
- if (zip)
- zip.close();
- }, [function (context, args) completion.file(context)]),
-
/**
* Generates a help entry and returns it as a string.
*
diff --git a/common/content/events.js b/common/content/events.js
index b8489697..04137c85 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -381,7 +381,7 @@ var EventHive = Class("EventHive", Contexts.Hive, {
*/
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) {
+ if (target == null || args[0].get() == target && args[1] == event && args[2].wrapped == callback && args[3] == capture) {
args[0].get().removeEventListener.apply(args[0].get(), args.slice(1));
return false;
}
@@ -1161,7 +1161,7 @@ var Events = Module("events", {
let win = (elem.ownerDocument || elem).defaultView || elem;
- if (!(services.focus.getLastFocusMethod(win) & 0x7000)
+ if (!(services.focus.getLastFocusMethod(win) & 0x3000)
&& events.isContentNode(elem)
&& !buffer.focusAllowed(elem)
&& isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement, Window])) {
diff --git a/common/modules/addons.jsm b/common/modules/addons.jsm
index 7613eb79..4c3b77b5 100644
--- a/common/modules/addons.jsm
+++ b/common/modules/addons.jsm
@@ -110,6 +110,7 @@ var actions = {
description: "Reload an extension",
action: function (addon) {
util.assert(config.haveGecko("2b"), _("command.notUseful", config.host));
+ util.flushCache();
util.timeout(function () {
addon.userDisabled = true;
addon.userDisabled = false;
diff --git a/common/modules/base.jsm b/common/modules/base.jsm
index 36088c93..6dce9d58 100644
--- a/common/modules/base.jsm
+++ b/common/modules/base.jsm
@@ -216,9 +216,9 @@ function require(obj, name, from, targetName) {
}
defineModule("base", {
- // sed -n 's/^(const|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
+ // sed -n 's/^(const|var|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
exports: [
- "ErrorBase", "Cc", "Ci", "Class", "Cr", "Cu", "Module", "JSMLoader", "Object", "Runnable",
+ "ErrorBase", "Cc", "Ci", "Class", "Cr", "Cu", "Module", "JSMLoader", "Object",
"Set", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMShim", "XPCOMUtils",
"XPCSafeJSObjectWrapper", "array", "bind", "call", "callable", "ctypes", "curry",
"debuggerProperties", "defineModule", "deprecated", "endModule", "forEach", "isArray",
@@ -228,14 +228,6 @@ defineModule("base", {
]
}, this);
-function Runnable(self, func, args) {
- return {
- __proto__: Runnable.prototype,
- run: function () { func.apply(self, args || []); }
- };
-}
-Runnable.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIRunnable]);
-
/**
* Returns a list of all of the top-level properties of an object, by
* way of the debugger.
@@ -845,7 +837,7 @@ Class.extend = function extend(subclass, superclass, overrides) {
* property's value.
* @returns {Class.Property}
*/
-Class.Memoize = Class.Memoize = function Memoize(getter, wait)
+Class.Memoize = function Memoize(getter, wait)
Class.Property({
configurable: true,
enumerable: true,
@@ -887,6 +879,8 @@ Class.Memoize = Class.Memoize = function Memoize(getter, wait)
}
});
+Class.memoize = deprecated("Class.Memoize", function memoize() Class.Memoize.apply(this, arguments));
+
/**
* Updates the given object with the object in the target class's
* prototype.
@@ -1184,7 +1178,7 @@ function Struct() {
});
return Struct;
}
-let StructBase = Class("StructBase", Array, {
+var StructBase = Class("StructBase", Array, {
init: function struct_init() {
for (let i = 0; i < arguments.length; i++)
if (arguments[i] != undefined)
diff --git a/common/modules/config.jsm b/common/modules/config.jsm
index fa03f927..1a45ca43 100644
--- a/common/modules/config.jsm
+++ b/common/modules/config.jsm
@@ -275,9 +275,9 @@ var ConfigBase = Class("ConfigBase", {
/** @property {boolean} True if the OS is Mac OS X. */
get isMacOSX() this._arch == "Darwin",
/** @property {boolean} True if the OS is some other *nix variant. */
- get isUnix() !this.isWindows && !this.isMacOSX,
+ get isUnix() !this.isWindows,
/** @property {RegExp} A RegExp which matches illegal characters in path components. */
- get illegalCharacters() this.isWindows ? /[<>:"/\\|?*\x00-\x1f]/g : /\//g,
+ get illegalCharacters() this.isWindows ? /[<>:"/\\|?*\x00-\x1f]/g : /[\/\x00]/g,
get pathListSep() this.isWindows ? ";" : ":"
}),
diff --git a/common/modules/dom.jsm b/common/modules/dom.jsm
index e1246b7f..8c7c0bda 100644
--- a/common/modules/dom.jsm
+++ b/common/modules/dom.jsm
@@ -669,7 +669,7 @@ var DOM = Class("DOM", {
val: function val(txt) {
return this.getSet(arguments,
function (elem) elem.value,
- function (elem, val) { elem.value = val });
+ function (elem, val) { elem.value = val == null ? "" : val });
},
listen: function listen(event, listener, capture) {
@@ -1094,3 +1094,6 @@ var $ = DOM;
endModule();
+// catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
+
+// vim: set sw=4 ts=4 et ft=javascript:
diff --git a/common/modules/help.jsm b/common/modules/help.jsm
index 9ae7622c..d6eee271 100644
--- a/common/modules/help.jsm
+++ b/common/modules/help.jsm
@@ -7,7 +7,7 @@
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("help", {
exports: ["help"],
- require: ["dom", "protocol", "services", "util"]
+ require: ["dom", "javascript", "protocol", "services", "util"]
}, this);
var Help = Module("Help", {
@@ -95,7 +95,120 @@ var Help = Module("Help", {
dactyl.assert(page != null, _("help.noTopic", topic));
dactyl.open("dactyl://help/" + page, { from: "help" });
- }
+ },
+
+ exportHelp: JavaScript.setCompleter(function (path) {
+ const FILE = io.File(path);
+ const PATH = FILE.leafName.replace(/\..*/, "") + "/";
+ const TIME = Date.now();
+
+ if (!FILE.exists() && (/\/$/.test(path) && !/\./.test(FILE.leafName)))
+ FILE.create(FILE.DIRECTORY_TYPE, octal(755));
+
+ dactyl.initHelp();
+ if (FILE.isDirectory()) {
+ var addDataEntry = function addDataEntry(file, data) FILE.child(file).write(data);
+ var addURIEntry = function addURIEntry(file, uri) addDataEntry(file, util.httpGet(uri).responseText);
+ }
+ else {
+ var zip = services.ZipWriter(FILE, File.MODE_CREATE | File.MODE_WRONLY | File.MODE_TRUNCATE);
+
+ addURIEntry = function addURIEntry(file, uri)
+ zip.addEntryChannel(PATH + file, TIME, 9,
+ services.io.newChannel(uri, null, null), false);
+ addDataEntry = function addDataEntry(file, data) // Unideal to an extreme.
+ addURIEntry(file, "data:text/plain;charset=UTF-8," + encodeURI(data));
+ }
+
+ let empty = Set("area base basefont br col frame hr img input isindex link meta param"
+ .split(" "));
+ function fix(node) {
+ switch(node.nodeType) {
+ case Node.ELEMENT_NODE:
+ if (isinstance(node, [HTMLBaseElement]))
+ return;
+
+ data.push("<"); data.push(node.localName);
+ if (node instanceof HTMLHtmlElement)
+ data.push(" xmlns=" + XHTML.uri.quote(),
+ " xmlns:dactyl=" + NS.uri.quote());
+
+ for (let { name, value } in array.iterValues(node.attributes)) {
+ if (name == "dactyl:highlight") {
+ Set.add(styles, value);
+ name = "class";
+ value = "hl-" + value;
+ }
+ if (name == "href") {
+ value = node.href || value;
+ if (value.indexOf("dactyl://help-tag/") == 0) {
+ let uri = services.io.newChannel(value, null, null).originalURI;
+ value = uri.spec == value ? "javascript:;" : uri.path.substr(1);
+ }
+ if (!/^#|[\/](#|$)|^[a-z]+:/.test(value))
+ value = value.replace(/(#|$)/, ".xhtml$1");
+ }
+ if (name == "src" && value.indexOf(":") > 0) {
+ chromeFiles[value] = value.replace(/.*\//, "");
+ value = value.replace(/.*\//, "");
+ }
+
+ data.push(" ", name, '="',
+ <>{value}</>.toXMLString().replace(/"/g, "&quot;"),
+ '"');
+ }
+ if (node.localName in empty)
+ data.push(" />");
+ else {
+ data.push(">");
+ if (node instanceof HTMLHeadElement)
+ data.push(<link rel="stylesheet" type="text/css" href="help.css"/>.toXMLString());
+ Array.map(node.childNodes, fix);
+ data.push("</", node.localName, ">");
+ }
+ break;
+ case Node.TEXT_NODE:
+ data.push(<>{node.textContent}</>.toXMLString());
+ }
+ }
+
+ let chromeFiles = {};
+ let styles = {};
+ for (let [file, ] in Iterator(help.files)) {
+ let url = "dactyl://help/" + file;
+ dactyl.open(url);
+ util.waitFor(function () content.location.href == url && buffer.loaded
+ && content.document.documentElement instanceof HTMLHtmlElement,
+ 15000);
+ events.waitForPageLoad();
+ var data = [
+ '<?xml version="1.0" encoding="UTF-8"?>\n',
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n',
+ ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n'
+ ];
+ fix(content.document.documentElement);
+ addDataEntry(file + ".xhtml", data.join(""));
+ }
+
+ let data = [h for (h in highlight) if (Set.has(styles, h.class) || /^Help/.test(h.class))]
+ .map(function (h) h.selector
+ .replace(/^\[.*?=(.*?)\]/, ".hl-$1")
+ .replace(/html\|/g, "") + "\t" + "{" + h.cssText + "}")
+ .join("\n");
+ addDataEntry("help.css", data.replace(/chrome:[^ ")]+\//g, ""));
+
+ addDataEntry("tag-map.json", JSON.stringify(help.tags));
+
+ let m, re = /(chrome:[^ ");]+\/)([^ ");]+)/g;
+ while ((m = re.exec(data)))
+ chromeFiles[m[0]] = m[2];
+
+ for (let [uri, leaf] in Iterator(chromeFiles))
+ addURIEntry(leaf, uri);
+
+ if (zip)
+ zip.close();
+ }, [function (context, args) completion.file(context)]),
}),
diff --git a/common/modules/messages.jsm b/common/modules/messages.jsm
index 5def642b..10bbd6a2 100644
--- a/common/modules/messages.jsm
+++ b/common/modules/messages.jsm
@@ -37,6 +37,10 @@ var Messages = Module("messages", {
});
},
+ cleanup: function cleanup() {
+ services.stringBundle.flushBundles();
+ },
+
bundles: Class.Memoize(function ()
array.uniq([JSMLoader.getTarget("dactyl://locale/" + this.name + ".properties"),
JSMLoader.getTarget("dactyl://locale-local/" + this.name + ".properties"),
@@ -53,10 +57,6 @@ var Messages = Module("messages", {
yield [key, value];
},
- cleanup: function cleanup() {
- services.stringBundle.flushBundles();
- },
-
get: function get(value, default_) {
for (let bundle in values(this.bundles))
try {
@@ -136,10 +136,7 @@ var Messages = Module("messages", {
}, {
javascript: function initJavascript(dactyl, modules, window) {
modules.JavaScript.setCompleter([this._, this.get, this.format], [
- function (context) {
- context.keys = { text: "key", description: "value" };
- return messages.iterate();
- }
+ function (context) messages.iterate()
]);
}
});
diff --git a/common/modules/overlay.jsm b/common/modules/overlay.jsm
index 4d048c4b..27c5cddb 100644
--- a/common/modules/overlay.jsm
+++ b/common/modules/overlay.jsm
@@ -189,7 +189,7 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
var { modules, Module } = window.dactyl.modules;
delete window.dactyl;
- const start = Date.now();
+ this.startTime = Date.now();
const deferredInit = { load: {} };
const seen = Set();
const loaded = Set();
@@ -268,6 +268,8 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
});
function frob(name) { values(deferredInit[name] || {}).forEach(call); }
+ this.frob = frob;
+ this.modules = modules;
frobModules();
frob("init");
@@ -289,21 +291,6 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
});
});
- function finish() {
- // Module.list.forEach(load);
- frob("load");
- modules.times = update({}, defineModule.times);
-
- defineModule.loadLog.push("Loaded in " + (Date.now() - start) + "ms");
-
- overlay.windows = array.uniq(overlay.windows.concat(window), true);
- }
-
- if (overlay.onWindowVisible)
- overlay.onWindowVisible.push(finish);
- else
- finish();
-
modules.events.listen(window, "unload", function onUnload() {
window.removeEventListener("unload", onUnload.wrapped, false);
@@ -316,12 +303,21 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
util.trapErrors("destroy", mod);
}
}, false);
+ },
+ visible: function visible(window) {
+ // Module.list.forEach(load);
+ this.frob("load");
+ this.modules.times = update({}, defineModule.times);
+
+ defineModule.loadLog.push("Loaded in " + (Date.now() - this.startTime) + "ms");
+
+ overlay.windows = array.uniq(overlay.windows.concat(window), true);
}
}));
},
cleanup: function cleanup() {
- for (let { document: doc } in iter(services.windowMediator.getEnumerator(null))) {
+ for (let doc in util.iterDocuments()) {
for (let elem in values(doc.dactylOverlayElements || []))
if (elem.parentNode)
elem.parentNode.removeChild(elem);
@@ -348,10 +344,9 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
"chrome-document-global-created": function (window, uri) { this.observe(window, "toplevel-window-ready", null); },
"content-document-global-created": function (window, uri) { this.observe(window, "toplevel-window-ready", null); },
"xul-window-visible": function () {
- if (this.onWindowVisible) {
+ if (this.onWindowVisible)
this.onWindowVisible.forEach(function (f) f.call(this), this);
- this.onWindowVisible = null;
- }
+ this.onWindowVisible = null;
}
},
@@ -367,11 +362,14 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
for (let doc in util.iterDocuments())
if (~["interactive", "complete"].indexOf(doc.readyState)) {
- this.onWindowVisible = null;
+ this.observe(doc.defaultView, "xul-window-visible");
this._loadOverlays(doc.defaultView);
}
- else
+ else {
+ if (!this.onWindowVisible)
+ this.onWindowVisible = [];
this.observe(doc.defaultView, "toplevel-window-ready");
+ }
}
},
@@ -394,7 +392,7 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
doc.dactylOverlayAttributes = [];
}
- function overlay(key, fn) {
+ function insert(key, fn) {
if (obj[key]) {
let iterator = Iterator(obj[key]);
if (!isObject(obj[key]))
@@ -423,21 +421,30 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
}
}
- overlay("before", function (elem, dom) elem.parentNode.insertBefore(dom, elem));
- overlay("after", function (elem, dom) elem.parentNode.insertBefore(dom, elem.nextSibling));
- overlay("append", function (elem, dom) elem.appendChild(dom));
- overlay("prepend", function (elem, dom) elem.insertBefore(dom, elem.firstChild));
+ insert("before", function (elem, dom) elem.parentNode.insertBefore(dom, elem));
+ insert("after", function (elem, dom) elem.parentNode.insertBefore(dom, elem.nextSibling));
+ insert("append", function (elem, dom) elem.appendChild(dom));
+ insert("prepend", function (elem, dom) elem.insertBefore(dom, elem.firstChild));
if (obj.init)
obj.init(window);
+ function load(event) {
+ obj.load(window, event);
+ if (obj.visible)
+ if (!event || !overlay.onWindowVisible || window != util.topWindow(window))
+ obj.visible(window);
+ else
+ overlay.onWindowVisible.push(function () { obj.visible(window) });
+ }
+
if (obj.load)
if (doc.readyState === "complete")
- obj.load(window);
+ load();
else
- doc.addEventListener("load", util.wrapCallback(function load(event) {
+ doc.addEventListener("load", util.wrapCallback(function onLoad(event) {
if (event.originalTarget === event.target) {
- doc.removeEventListener("load", load.wrapper, true);
- obj.load(window, event);
+ doc.removeEventListener("load", onLoad.wrapper, true);
+ load(event);
}
}), true);
},
diff --git a/common/modules/services.jsm b/common/modules/services.jsm
index b3272b9c..6072d4d0 100644
--- a/common/modules/services.jsm
+++ b/common/modules/services.jsm
@@ -70,7 +70,10 @@ var Services = Module("Services", {
this.add("zipReader", "@mozilla.org/libjar/zip-reader-cache;1", "nsIZipReaderCache");
this.addClass("CharsetConv", "@mozilla.org/intl/scriptableunicodeconverter", "nsIScriptableUnicodeConverter", "charset");
+ this.addClass("CharsetStream","@mozilla.org/intl/converter-input-stream;1", ["nsIConverterInputStream",
+ "nsIUnicharLineInputStream"], "init");
this.addClass("File", "@mozilla.org/file/local;1", "nsILocalFile");
+ this.addClass("FileInStream", "@mozilla.org/network/file-input-stream;1", "nsIFileInputStream", "init", false);
this.addClass("Find", "@mozilla.org/embedcomp/rangefind;1", "nsIFind");
this.addClass("HtmlConverter","@mozilla.org/widget/htmlformatconverter;1", "nsIFormatConverter");
this.addClass("HtmlEncoder", "@mozilla.org/layout/htmlCopyEncoder;1", "nsIDocumentEncoder");
@@ -79,6 +82,7 @@ var Services = Module("Services", {
this.addClass("Persist", "@mozilla.org/embedding/browser/nsWebBrowserPersist;1", "nsIWebBrowserPersist");
this.addClass("Pipe", "@mozilla.org/pipe;1", "nsIPipe", "init");
this.addClass("Process", "@mozilla.org/process/util;1", "nsIProcess", "init");
+ this.addClass("Pump", "@mozilla.org/network/input-stream-pump;1", "nsIInputStreamPump", "init")
this.addClass("StreamChannel","@mozilla.org/network/input-stream-channel;1",
["nsIInputStreamChannel", "nsIChannel"], "setURI");
this.addClass("StreamCopier", "@mozilla.org/network/async-stream-copier;1","nsIAsyncStreamCopier", "init");
@@ -91,7 +95,7 @@ var Services = Module("Services", {
this.addClass("XPathEvaluator", "@mozilla.org/dom/xpath-evaluator;1", "nsIDOMXPathEvaluator");
this.addClass("XMLDocument", "@mozilla.org/xml/xml-document;1", ["nsIDOMXMLDocument", "nsIDOMNodeSelector"]);
this.addClass("ZipReader", "@mozilla.org/libjar/zip-reader;1", "nsIZipReader", "open");
- this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", "nsIZipWriter");
+ this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", "nsIZipWriter", "open");
},
reinit: function () {},
@@ -112,7 +116,7 @@ var Services = Module("Services", {
}
return res;
}
- catch (e) {
+ catch (e if service.quiet !== false) {
if (typeof util !== "undefined")
util.reportError(e);
else
@@ -149,9 +153,9 @@ var Services = Module("Services", {
* @param {string} init Name of a property or method used to initialize the
* class.
*/
- addClass: function (name, class_, ifaces, init) {
+ addClass: function (name, class_, ifaces, init, quiet) {
const self = this;
- this.services[name] = { class: class_, interfaces: Array.concat(ifaces || []), method: "createInstance", init: init };
+ this.services[name] = { class: class_, interfaces: Array.concat(ifaces || []), method: "createInstance", init: init, quiet: quiet };
if (init)
memoize(this.services[name], "callable",
function () callable(XPCOMShim(this.interfaces)[this.init]));
diff --git a/common/modules/storage.jsm b/common/modules/storage.jsm
index dbc71555..23164566 100644
--- a/common/modules/storage.jsm
+++ b/common/modules/storage.jsm
@@ -292,11 +292,18 @@ var Storage = Module("Storage", {
* @param {nsIFile|string} path Expanded according to {@link IO#expandPath}
* @param {boolean} checkPWD Whether to allow expansion relative to the
* current directory. @default true
+ * @param {string} charset The charset of the file. @default File.defaultEncoding
*/
this.File = Class("File", {
- init: function (path, checkPWD) {
+ init: function (path, checkPWD, charset) {
let file = services.File();
+ if (charset)
+ this.charset = charset;
+
+ if (path instanceof Ci.nsIFileURL)
+ path = path.file;
+
if (path instanceof Ci.nsIFile)
file = path.clone();
else if (/file:\/\//.test(path))
@@ -320,10 +327,12 @@ this.File = Class("File", {
return self;
},
+ charset: Class.Memoize(function () File.defaultEncoding),
+
/**
* @property {nsIFileURL} Returns the nsIFileURL object for this file.
*/
- get URI() services.io.newFileURI(this),
+ get URI() services.io.newFileURI(this).QueryInterface(Ci.nsIFileURL),
/**
* Iterates over the objects in this directory.
@@ -348,18 +357,23 @@ this.File = Class("File", {
},
/**
+ * Returns an iterator for all lines in a file.
+ */
+ get lines() File.readLines(services.FileInStream(this, -1, 0, 0),
+ this.charset),
+
+ /**
* Reads this file's entire contents in "text" mode and returns the
* content as a string.
*
* @param {string} encoding The encoding from which to decode the file.
- * @default options["fileencoding"]
+ * @default #charset
* @returns {string}
*/
read: function (encoding) {
- let ifstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
- ifstream.init(this, -1, 0, 0);
+ let ifstream = services.FileInStream(this, -1, 0, 0);
- return File.readStream(ifstream, encoding);
+ return File.readStream(ifstream, encoding || this.charset);
},
/**
@@ -408,7 +422,7 @@ this.File = Class("File", {
* permissions if the file exists.
* @default 0644
* @param {string} encoding The encoding to used to write the file.
- * @default options["fileencoding"]
+ * @default #charset
*/
write: function (buf, mode, perms, encoding) {
let ofstream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
@@ -421,7 +435,7 @@ this.File = Class("File", {
buf = buf.read();
if (!encoding)
- encoding = File.defaultEncoding;
+ encoding = this.charset;
if (mode == ">>")
mode = File.MODE_WRONLY | File.MODE_CREATE | File.MODE_APPEND;
@@ -579,9 +593,10 @@ this.File = Class("File", {
readStream: function (ifstream, encoding) {
try {
- var icstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);
- icstream.init(ifstream, encoding || File.defaultEncoding, 4096, // 4096 bytes buffering
- Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
+ var icstream = services.CharsetStream(
+ ifstream, encoding || File.defaultEncoding, 4096, // buffer size
+ services.CharsetStream.DEFAULT_REPLACEMENT_CHARACTER);
+
let buffer = [];
let str = {};
while (icstream.readString(4096, str) != 0)
@@ -594,6 +609,23 @@ this.File = Class("File", {
}
},
+ readLines: function (ifstream, encoding) {
+ try {
+ var icstream = services.CharsetStream(
+ ifstream, encoding || File.defaultEncoding, 4096, // buffer size
+ services.CharsetStream.DEFAULT_REPLACEMENT_CHARACTER);
+
+ var value = {};
+ while (icstream.readLine(value))
+ yield value.value;
+ }
+ finally {
+ icstream.close();
+ ifstream.close();
+ }
+ },
+
+
isAbsolutePath: function (path) {
try {
services.File().initWithPath(path);
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index 7a8197d5..39a9094d 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -8,7 +8,6 @@
try {
- let global=this;
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("util", {
exports: ["DOM", "$", "FailedAssertion", "Math", "NS", "Point", "Util", "XBL", "XHTML", "XUL", "util"],
@@ -399,7 +398,9 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
*/
createURI: function createURI(str) {
try {
- return services.urifixup.createFixupURI(str, services.urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP);
+ let uri = services.urifixup.createFixupURI(str, services.urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP);
+ uri instanceof Ci.nsIURL;
+ return uri;
}
catch (e) {
return null;
@@ -673,6 +674,9 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
if (params.mimeType)
xmlhttp.overrideMimeType(params.mimeType);
+ if (params.responseType)
+ xmlhttp.responseType = params.responseType;
+
xmlhttp.open(params.method || "GET", url, async,
params.user, params.pass);
@@ -748,11 +752,14 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
* Iterates over all currently open documents, including all
* top-level window and sub-frames thereof.
*/
- iterDocuments: function iterDocuments() {
+ iterDocuments: function iterDocuments(types) {
+ types = types ? types.map(function (s) "type" + util.capitalize(s))
+ : ["typeChrome", "typeContent"];
+
let windows = services.windowMediator.getXULWindowEnumerator(null);
while (windows.hasMoreElements()) {
let window = windows.getNext().QueryInterface(Ci.nsIXULWindow);
- for each (let type in ["typeChrome", "typeContent"]) {
+ for each (let type in types) {
let docShells = window.docShell.getDocShellEnumerator(Ci.nsIDocShellTreeItem[type],
Ci.nsIDocShell.ENUMERATE_FORWARDS);
while (docShells.hasMoreElements())
@@ -820,7 +827,11 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
* @param {string} uri
* @returns {nsIURI}
*/
- newURI: function newURI(uri, charset, base) this.withProperErrors("newURI", services.io, uri, charset, base),
+ newURI: function newURI(uri, charset, base) {
+ let res = this.withProperErrors("newURI", services.io, uri, charset, base);
+ res instanceof Ci.nsIURL;
+ return res;
+ },
/**
* Removes leading garbage prepended to URIs by the subscript
@@ -1133,8 +1144,11 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
if (isString(error))
error = Error(error);
- if (Cu.reportError)
- Cu.reportError(error);
+ Cu.reportError(error);
+ try {
+ services.console.logStringMessage(error.stack || Error().stack);
+ }
+ catch (e) {}
try {
this.errorCount++;