diff --git a/common/content/configbase.js b/common/content/configbase.js index 8edb176a..23a0d9ad 100644 --- a/common/content/configbase.js +++ b/common/content/configbase.js @@ -105,7 +105,7 @@ const ConfigBase = Class(ModuleBase, { /** * @property {string} The ID of the application's main XUL window. */ - mainWindowId: document.documentElement.id, + mainWindowId: window.document.documentElement.id, /** * @property {[[]]} An array of application specific mode specifications. @@ -133,7 +133,7 @@ const ConfigBase = Class(ModuleBase, { */ scripts: [], - tabStrip: Class.memoize(function () document.getElementById("TabsToolbar") || this.tabbrowser.mTabContainer), + tabStrip: Class.memoize(function () window.document.getElementById("TabsToolbar") || this.tabbrowser.mTabContainer), /** * @property {string} The leaf name of any temp files created by diff --git a/common/content/dactyl-overlay.js b/common/content/dactyl-overlay.js index fadaef41..488b4775 100644 --- a/common/content/dactyl-overlay.js +++ b/common/content/dactyl-overlay.js @@ -5,12 +5,21 @@ "use strict"; (function () { - const jsmodules = {} - const modules = { __proto__: jsmodules }; - const BASE = "chrome://dactyl/content/"; - + function newContext(proto) { + let sandbox = Components.utils.Sandbox(window); + if (jsmodules.__proto__ != window) + jsmodules.__proto__ = window; + // Hack: + sandbox.Object = jsmodules.Object; + sandbox.Math = jsmodules.Math; + sandbox.__proto__ = proto || modules; + return sandbox; + } + const jsmodules = {}; + const modules = { __proto__: jsmodules, jsmodules: jsmodules, newContext: newContext, window: window }; modules.modules = modules; + const BASE = "chrome://dactyl/content/"; const loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader); diff --git a/common/content/dactyl.js b/common/content/dactyl.js index 0492edec..13f05593 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -13,7 +13,7 @@ XML.ignoreWhitespace = false; XML.prettyPrinting = false; const plugins = { __proto__: modules }; -const userContext = { __proto__: modules }; +memoize(modules, "userContext", function () newContext(modules));; const EVAL_ERROR = "__dactyl_eval_error"; const EVAL_RESULT = "__dactyl_eval_result"; @@ -314,29 +314,16 @@ const Dactyl = Module("dactyl", { services.get("subscriptLoader").loadSubScript(uri, context, File.defaultEncoding); }, - userEval: function (str, context) { - try { - if (!context) - context = userContext; - context[EVAL_ERROR] = null; - context[EVAL_STRING] = str; - context[EVAL_RESULT] = null; - this.loadScript("chrome://dactyl/content/eval.js", context); - if (context[EVAL_ERROR]) { - try { - context[EVAL_ERROR].fileName = io.sourcing.file; - context[EVAL_ERROR].lineNumber += io.sourcing.line; - } - catch (e) {} - throw context[EVAL_ERROR]; - } - return context[EVAL_RESULT]; - } - finally { - delete context[EVAL_ERROR]; - delete context[EVAL_RESULT]; - delete context[EVAL_STRING]; - } + userEval: function (str, context, fileName, lineNumber) { + if (fileName == null) + if (io.sourcing) + ({ file: fileName, line: lineNumber }) = io.sourcing; + else if (String.indexOf(commandline.command, str) > -1) + [fileName, lineNumber] = ["[Command Line]", 1]; + + if (!context) + context = userContext; + return Cu.evalInSandbox(str, context, "1.8", fileName, lineNumber); }, /** @@ -885,11 +872,7 @@ const Dactyl = Module("dactyl", { pluginFiles: {}, - // namespace for plugins/scripts. Actually (only) the active plugin must/can set a - // v.plugins.mode = string to show on v.modes.CUSTOM - // v.plugins.stop = hooked on a v.modes.reset() - // v.plugins.onEvent = function triggered, on keypresses (unless ) (see events.js) - plugins: plugins, + get plugins() plugins, /** * Quit the host application, no matter how many tabs/windows are open. diff --git a/common/content/events.js b/common/content/events.js index 2102cba7..ea8b2a06 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -731,7 +731,7 @@ const Events = Module("events", { let win = window.document.commandDispatcher.focusedWindow; let elem = window.document.commandDispatcher.focusedElement; - if (win && win.top == content && dactyl.has("tabs")) + if (win && win.top == window.content && dactyl.has("tabs")) buffer.focusedFrame = win; try { diff --git a/common/content/io.js b/common/content/io.js index 35b8f763..bc3abb5c 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -9,7 +9,7 @@ /** @scope modules */ -plugins.contexts = {}; +plugins.contexts = plugins; function Script(file) { let self = plugins[file.path]; if (self) { @@ -19,11 +19,10 @@ function Script(file) { } else self = { __proto__: plugins }; - plugins.contexts[file.path] = self; plugins[file.path] = self; self.NAME = file.leafName.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase()); self.PATH = file.path; - self.__context__ = self; + self.CONTEXT = self; // This belongs elsewhere if (io.getRuntimeDirectories("plugins").some( @@ -366,6 +365,7 @@ lookup: this.readHeredoc = function (end) { let res = []; try { + io.sourcing.line++; while (true) let ([i, line] = iter.next()) { if (line === end) diff --git a/common/content/javascript.js b/common/content/javascript.js index ae7c2658..9bb0fe10 100644 --- a/common/content/javascript.js +++ b/common/content/javascript.js @@ -38,12 +38,12 @@ const JavaScript = Module("javascript", { if (obj == null) return; - let seen = {}; - let globals = values(toplevel && Class.objectGlobal(obj) === obj ? JavaScript.globalNames : []); - for (let key in iterAll(globals, properties(obj, !toplevel))) { - set.add(seen, key); - yield key; - } + let seen = isinstance(obj, ["Sandbox"]) ? set(JavaScript.magicalNames) : {}; + let globals = values(toplevel && window === obj ? JavaScript.globalNames : []); + for (let key in iterAll(globals, properties(obj, !toplevel))) + if (!set.add(seen, key)) + yield key; + // Properties aren't visible in an XPCNativeWrapper until // they're accessed. for (let key in properties(this.getKey(obj, "wrappedJSObject"), !toplevel)) @@ -58,7 +58,7 @@ const JavaScript = Module("javascript", { // Things we can dereference if (!obj || ["object", "string", "function"].indexOf(typeof obj) == -1) return []; - if (modules.isPrototypeOf(obj) && !toplevel) + if (jsmodules.isPrototypeOf(obj) && !toplevel) return []; let completions = [k for (k in this.iter(obj, toplevel))]; @@ -76,7 +76,7 @@ const JavaScript = Module("javascript", { context[JavaScript.EVAL_TMP] = tmp; try { - return cache[key] = dactyl.userEval(arg, context); + return cache[key] = dactyl.userEval(arg, context, "[Command Line Completion]", 1); } catch (e) { this.context.message = "Error: " + e; @@ -308,7 +308,7 @@ const JavaScript = Module("javascript", { context.filters.push(function (item) item.item.indexOf(args.prefix) === 0); } - args.completer.call(self, context, args); + args.completer.call(this, context, args); }, _complete: function (objects, key, compl, string, last) { @@ -428,7 +428,7 @@ const JavaScript = Module("javascript", { } this.context.getCache("evalled", Object); - this.context.getCache("evalContext", function () ({ __proto__: userContext })); + this.context.getCache("evalContext", function () newContext(userContext)); // Okay, have parse stack. Figure out what we're completing. @@ -594,6 +594,8 @@ const JavaScript = Module("javascript", { */ completers: {}, + magicalNames: Class.memoize(function () Object.getOwnPropertyNames(Cu.Sandbox(window), true).sort()), + /** * A list of properties of the global object which are not * enumerable by any standard method. @@ -616,6 +618,7 @@ const JavaScript = Module("javascript", { "isXMLName", "parseFloat", "parseInt", "undefined", "uneval" ].concat([k.substr(6) for (k in keys(Ci)) if (/^nsIDOM/.test(k))]) .concat([k.substr(3) for (k in keys(Ci)) if (/^nsI/.test(k))]) + .concat(JavaScript.magicalnames) .filter(function (k) k in window))), /** diff --git a/common/locale/en-US/browsing.xml b/common/locale/en-US/browsing.xml index 77c40487..2849d755 100644 --- a/common/locale/en-US/browsing.xml +++ b/common/locale/en-US/browsing.xml @@ -403,7 +403,6 @@ want to bypass &dactyl.appName;'s key handling and pass keys directly to :w :write :sav :saveas - :saveas! file

diff --git a/common/modules/base.jsm b/common/modules/base.jsm index 209e5658..1ca65827 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -66,7 +66,7 @@ if (!Object.getOwnPropertyDescriptor) return desc; }; if (!Object.getOwnPropertyNames) - Object.getOwnPropertyNames = function getOwnPropertyNames(obj) { + Object.getOwnPropertyNames = function getOwnPropertyNames(obj, _debugger) { // This is an ugly and unfortunately necessary hack. if (hasOwnProperty.call(obj, "__iterator__")) { var oldIter = obj.__iterator__; diff --git a/common/modules/services.jsm b/common/modules/services.jsm index c6197ba3..7460ab50 100644 --- a/common/modules/services.jsm +++ b/common/modules/services.jsm @@ -124,7 +124,7 @@ const Services = Module("Services", { }, { }, { init: function (dactyl, modules) { - if (!this.get("extensionManager")) + if (!modules.AddonManager && !this.get("extensionManager")) Components.utils.import("resource://gre/modules/AddonManager.jsm", modules); }, javascript: function (dactyl, modules) { diff --git a/pentadactyl/TODO b/pentadactyl/TODO index abf079af..408fd0f3 100644 --- a/pentadactyl/TODO +++ b/pentadactyl/TODO @@ -39,7 +39,6 @@ FEATURES: 8 / should work as in vim (i.e., save page positions as well as locations in the history list). 8 jump to the next heading with ]h, next image ]i, previous textbox [t and so on -8 pipe selected text/link/website to an external command 7 use ctrl-n/p in insert mode for word completion 7 implement QuickFix window based on ItemList 7 wherever possible: get rid of dialogs and ask console-like dialog questions