diff options
-rwxr-xr-x | common/bootstrap.js | 48 | ||||
-rw-r--r-- | common/content/commandline.js | 2 | ||||
-rw-r--r-- | common/content/dactyl.js | 114 | ||||
-rw-r--r-- | common/content/events.js | 4 | ||||
-rw-r--r-- | common/modules/addons.jsm | 1 | ||||
-rw-r--r-- | common/modules/base.jsm | 18 | ||||
-rw-r--r-- | common/modules/config.jsm | 4 | ||||
-rw-r--r-- | common/modules/dom.jsm | 5 | ||||
-rw-r--r-- | common/modules/help.jsm | 117 | ||||
-rw-r--r-- | common/modules/messages.jsm | 13 | ||||
-rw-r--r-- | common/modules/overlay.jsm | 69 | ||||
-rw-r--r-- | common/modules/services.jsm | 12 | ||||
-rw-r--r-- | common/modules/storage.jsm | 54 | ||||
-rw-r--r-- | common/modules/util.jsm | 28 |
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, """), - '"'); - } - 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, """), + '"'); + } + 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++; |