-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2013 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("javascript", {
exports: ["JavaScript", "javascript"],
- use: ["services", "template", "util"]
-}, this);
+ require: ["util"]
+});
+
+lazyRequire("template", ["template"]);
let isPrototypeOf = Object.prototype.isPrototypeOf;
this.window = window;
init.supercall(this);
- },
+ }
}),
- globals: Class.memoize(function () [
- [this.modules.userContext, "Global Variables"],
+ globals: Class.Memoize(function () [
+ [this.modules.userContext, /*L*/"Global Variables"],
[this.modules, "modules"],
[this.window, "window"]
]),
- toplevel: Class.memoize(function () this.modules.jsmodules),
+ toplevel: Class.Memoize(function () this.modules.jsmodules),
lazyInit: true,
- newContext: function () this.modules.newContext(this.modules.userContext),
+ newContext: function () this.modules.newContext(this.modules.userContext, true, "Dactyl JS Temp Context"),
- get completers() JavaScript.completers, // For backward compatibility
+ completers: Class.Memoize(() => Object.create(JavaScript.completers)),
// Some object members are only accessible as function calls
getKey: function (obj, key) {
if (obj == null)
return;
- let seen = isinstance(obj, ["Sandbox"]) ? set(JavaScript.magicalNames) : {};
+ let seen = isinstance(obj, ["Sandbox"]) ? Set(JavaScript.magicalNames) : {};
let globals = values(toplevel && this.window === obj ? this.globalNames : []);
if (toplevel && isObject(obj) && "wrappedJSObject" in obj)
- if (!set.add(seen, "wrappedJSObject"))
+ if (!Set.add(seen, "wrappedJSObject"))
yield "wrappedJSObject";
for (let key in iter(globals, properties(obj, !toplevel, true)))
- if (!set.add(seen, key))
+ 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, true))
try {
- if (key in obj && !set.has(seen, key))
+ if (key in obj && !Set.has(seen, key))
yield key;
}
catch (e) {}
let completions = [k for (k in this.iter(obj, toplevel))];
if (obj === this.modules) // Hack.
- completions = completions.concat([k for (k in this.iter(this.modules.jsmodules, toplevel))]);
+ completions = array.uniq(completions.concat([k for (k in this.iter(this.modules.jsmodules, toplevel))]));
return completions;
},
return cache[key];
context[JavaScript.EVAL_TMP] = tmp;
- context[JavaScript.EVAL_EXPORT] = function export_(obj) cache[key] = obj;
try {
- if (tmp != null) // Temporary hack until bug 609949 is fixed.
- this.modules.dactyl.userEval(JavaScript.EVAL_EXPORT + "(" + arg + ")", context, "[Command Line Completion]", 1);
- else
- cache[key] = this.modules.dactyl.userEval(arg, context, "[Command Line Completion]", 1);
+ cache[key] = this.modules.dactyl.userEval(arg, context,
+ /*L*/"[Command Line Completion]", 1);
return cache[key];
}
catch (e) {
util.reportError(e);
- this.context.message = "Error: " + e;
+ this.context.message = _("error.error", e);
return null;
}
finally {
if (this._top.char != arg) {
this.context.highlight(this._top.offset, this._i - this._top.offset, "SPELLCHECK");
- throw Error("Invalid JS");
+ throw Error(/*L*/"Invalid JS");
}
// The closing character of this stack frame will have pushed a new
// Don't eval any function calls unless the user presses tab.
_checkFunction: function (start, end, key) {
- let res = this._functions.some(function (idx) idx >= start && idx < end);
+ let res = this._functions.some(idx => (idx >= start && idx < end));
if (!res || this.context.tabPressed || key in this.cache.evalled)
return false;
this.context.waitingForTab = true;
if (this._checkFunction(prev, dot, cacheKey))
return [];
if (prev != statement && obj == null) {
- this.context.message = "Error: " + cacheKey.quote() + " is " + String(obj);
+ this.context.message = /*L*/"Error: " + cacheKey.quote() + " is " + String(obj);
return [];
}
let end = (frame == -1 ? this._lastIdx : this._get(frame + 1).offset);
this._cacheKey = null;
- let obj = [[this.cache.evalContext, "Local Variables"]].concat(this.globals);
+ let obj = [[this.cache.evalContext, /*L*/"Local Variables"]].concat(this.globals);
// Is this an object dereference?
if (dot < statement) // No.
dot = statement - 1;
const self = this;
if (!getOwnPropertyNames && !services.debugger.isOn && !this.context.message)
- this.context.message = "For better completion data, please enable the JavaScript debugger (:set jsdebugger)";
+ this.context.message = /*L*/"For better completion data, please enable the JavaScript debugger (:set jsdebugger)";
let base = this.context.fork("js", this._top.offset);
base.forceAnchored = true;
let prefix = last != null ? key : "";
if (last == null) // We're not looking for a quoted string, so filter out anything that's not a valid identifier
- base.filters.push(function (item) /^[a-zA-Z_$][\w$]*$/.test(item.text));
+ base.filters.push(item => /^[a-zA-Z_$][\w$]*$/.test(item.text));
else {
- base.quote = [last, function (text) util.escapeString(text, ""), last];
+ base.quote = [last, text => util.escapeString(text, ""), last];
if (prefix)
- base.filters.push(function (item) item.item.indexOf(prefix) === 0);
+ base.filters.push(item => item.item.indexOf(prefix) === 0);
}
if (!compl) {
};
base.keys = {
- text: prefix ? function (text) text.substr(prefix.length) : util.identity,
+ text: prefix ? text => text.substr(prefix.length)
+ : text => text,
description: function (item) self.getKey(this.obj, item),
key: function (item) {
if (!isNaN(key))
objects.forEach(function (obj) {
let context = base.fork(obj[1]);
context.title = [obj[1]];
- context.keys.obj = function () obj[0];
+ context.keys.obj = () => obj[0];
context.key = obj[1] + last;
if (obj[0] == this.cache.evalContext)
context.regenerate = true;
obj.ctxt_t = context.fork("toplevel");
if (!compl) {
obj.ctxt_p = context.fork("prototypes");
- obj.ctxt_t.generate = function () self.objectKeys(obj[0], true);
- obj.ctxt_p.generate = function () self.objectKeys(obj[0], false);
+ obj.ctxt_t.generate = () => self.objectKeys(obj[0], true);
+ obj.ctxt_p.generate = () => self.objectKeys(obj[0], false);
}
}, this);
objects.forEach(function (obj) {
obj.ctxt_p.split(obj[1] + "/anchored", this, function (context) {
context.anchored = true;
- context.title[0] += " (prototypes)";
+ context.title[0] += /*L*/" (prototypes)";
});
});
objects.forEach(function (obj) {
obj.ctxt_t.split(obj[1] + "/unanchored", this, function (context) {
context.anchored = false;
- context.title[0] += " (substrings)";
+ context.title[0] += /*L*/" (substrings)";
context.filters.push(unanchored);
});
});
objects.forEach(function (obj) {
obj.ctxt_p.split(obj[1] + "/unanchored", this, function (context) {
context.anchored = false;
- context.title[0] += " (prototype substrings)";
+ context.title[0] += /*L*/" (prototype substrings)";
context.filters.push(unanchored);
});
});
let [, prefix, args] = /^(function .*?)\((.*?)\)/.exec(Function.prototype.toString.call(func));
let n = this._get(i).comma.length;
args = template.map(Iterator(args.split(", ")),
- function ([i, arg]) <span highlight={i == n ? "Filter" : ""}>{arg}</span>,
- <>, </>);
- this.context.message = <>{prefix}({args})</>;
+ ([i, arg]) => ["span", { highlight: i == n ? "Filter" : "" }, arg],
+ ",\u00a0");
+ this.context.message = ["", prefix + "(", args, ")"];
}
}
}
}
catch (e) {}
if (!completer)
- completer = JavaScript.completers[funcName];
+ completer = this.completers[funcName];
if (!completer)
return null;
for (let [i, idx] in Iterator(this._get(-2).comma)) {
let arg = this._str.substring(prev + 1, idx);
prev = idx;
- memoize(args, i, function () self.evalled(arg));
+ memoize(args, i, () => self.evalled(arg));
}
let key = this._getKey();
args.push(key + string);
// Wait for a keypress before completing when there's no key
if (!this.context.tabPressed && key == "" && obj.length > 1) {
+ let message = this.context.message || "";
this.context.waitingForTab = true;
- this.context.message = "Waiting for key press";
+ this.context.message = ["", message, "\n",
+ _("completion.waitingForKeyPress")];
return null;
}
return null;
},
- magicalNames: Class.memoize(function () Object.getOwnPropertyNames(Cu.Sandbox(this.window), true).sort()),
+ magicalNames: Class.Memoize(function () Object.getOwnPropertyNames(Cu.Sandbox(this.window), true).sort()),
/**
* A list of properties of the global object which are not
* enumerable by any standard method.
*/
- globalNames: Class.memoize(function () let (self = this) array.uniq([
- "Array", "ArrayBuffer", "AttributeName", "Boolean", "Components",
+ globalNames: Class.Memoize(function () let (self = this) array.uniq([
+ "Array", "ArrayBuffer", "AttributeName", "Audio", "Boolean", "Components",
"CSSFontFaceStyleDecl", "CSSGroupRuleRuleList", "CSSNameSpaceRule",
- "CSSRGBColor", "CSSRect", "ComputedCSSStyleDeclaration", "Date",
- "Error", "EvalError", "Float32Array", "Float64Array", "Function",
+ "CSSRGBColor", "CSSRect", "ComputedCSSStyleDeclaration", "Date", "Error",
+ "EvalError", "File", "Float32Array", "Float64Array", "Function",
"HTMLDelElement", "HTMLInsElement", "HTMLSpanElement", "Infinity",
"InnerModalContentWindow", "InnerWindow", "Int16Array", "Int32Array",
"Int8Array", "InternalError", "Iterator", "JSON", "KeyboardEvent",
"Math", "NaN", "Namespace", "Number", "Object", "Proxy", "QName",
"ROCSSPrimitiveValue", "RangeError", "ReferenceError", "RegExp",
"StopIteration", "String", "SyntaxError", "TypeError", "URIError",
- "Uint16Array", "Uint32Array", "Uint8Array", "XML",
- "XMLHttpProgressEvent", "XMLList", "XMLSerializer", "XPCNativeWrapper",
- "XPCSafeJSWrapper", "XULControllers", "constructor", "decodeURI",
- "decodeURIComponent", "encodeURI", "encodeURIComponent", "escape",
- "eval", "isFinite", "isNaN", "isXMLName", "parseFloat", "parseInt",
- "undefined", "unescape", "uneval"
+ "Uint16Array", "Uint32Array", "Uint8Array", "XML", "XMLHttpProgressEvent",
+ "XMLList", "XMLSerializer", "XPCNativeWrapper", "XPCSafeJSWrapper",
+ "XULControllers", "constructor", "decodeURI", "decodeURIComponent",
+ "encodeURI", "encodeURIComponent", "escape", "eval", "isFinite", "isNaN",
+ "isXMLName", "parseFloat", "parseInt", "undefined", "unescape", "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(this.magicalNames)
- .filter(function (k) k in self.window))),
+ .filter(k => k in self.window))),
}, {
EVAL_TMP: "__dactyl_eval_tmp",
- EVAL_EXPORT: "__dactyl_eval_export",
/**
* A map of argument completion functions for named methods. The
* time they are accessed, so they should be accessed
* judiciously.
*
- * @param {function|function[]} funcs The functions for which to
+ * @param {function|[function]} funcs The functions for which to
* install the completers.
- * @param {function[]} completers An array of completer
+ * @param {[function]} completers An array of completer
* functions.
*/
setCompleter: function (funcs, completers) {
modes.addMode("REPL", {
description: "JavaScript Read Eval Print Loop",
- bases: [modes.COMMAND_LINE]
+ bases: [modes.COMMAND_LINE],
+ displayName: Class.Memoize(function () this.name)
});
},
commandline: function initCommandLine(dactyl, modules, window) {
},
addOutput: function addOutput(js) {
- default xml namespace = XHTML;
this.count++;
try {
var result = dactyl.userEval(js, this.context);
- var xml = util.objectToString(result, true);
+ var xml = result === undefined ? "" : util.objectToString(result, true);
}
catch (e) {
util.reportError(e);
if (e.fileName)
e = util.fixURI(e.fileName) + ":" + e.lineNumber + ": " + e;
- xml = <span highlight="ErrorMsg">{e}</span>;
+ xml = ["span", { highlight: "ErrorMsg" }, e];
}
let prompt = "js" + this.count;
Class.replaceProperty(this.context, prompt, result);
- XML.ignoreWhitespace = XML.prettyPrinting = false;
let nodes = {};
this.rootNode.appendChild(
- util.xmlToDom(<e4x>
- <div highlight="REPL-E" key="e"><span highlight="REPL-R">{prompt}></span> {js}</div>
- <div highlight="REPL-P" key="p">{xml}</div>
- </e4x>.elements(), this.document, nodes));
+ DOM.fromJSON(
+ [["div", { highlight: "REPL-E", key: "e" },
+ ["span", { highlight: "REPL-R" },
+ prompt, ">"], " ", js],
+ ["div", { highlight: "REPL-P", key: "p" },
+ xml]],
+ this.document, nodes));
this.rootNode.scrollTop += nodes.e.getBoundingClientRect().top
- this.rootNode.getBoundingClientRect().top;
count: 0,
- message: Class.memoize(function () {
- default xml namespace = XHTML;
- util.xmlToDom(<div highlight="REPL" key="rootNode"/>,
+ message: Class.Memoize(function () {
+ DOM.fromJSON(["div", { highlight: "REPL", key: "rootNode" }],
this.document, this);
return this.rootNode;
init: function init(context) {
init.supercall(this);
- let self = this;
- let sandbox = isinstance(context, ["Sandbox"]);
+ let sandbox = true || isinstance(context, ["Sandbox"]);
- this.context = modules.newContext(context, !sandbox);
+ this.context = modules.newContext(context, !sandbox, "Dactyl REPL Context");
this.js = modules.JavaScript();
this.js.replContext = this.context;
- this.js.newContext = function newContext() modules.newContext(self.context, !sandbox);
+ this.js.newContext = () => modules.newContext(this.context, !sandbox, "Dactyl REPL Temp Context");
this.js.globals = [
- [this.context, "REPL Variables"],
- [context, "REPL Global"]
- ].concat(this.js.globals.filter(function ([global]) isPrototypeOf.call(global, context)));
+ [this.context, /*L*/"REPL Variables"],
+ [context, /*L*/"REPL Global"]
+ ].concat(this.js.globals.filter(([global]) => isPrototypeOf.call(global, context)));
if (!isPrototypeOf.call(modules.jsmodules, context))
this.js.toplevel = context;
if (!isPrototypeOf.call(window, context))
this.js.window = context;
- if (this.js.globals.slice(2).some(function ([global]) global === context))
+ if (this.js.globals.slice(2).some(([global]) => global === context))
this.js.globals.splice(1);
this.repl = REPL(this.context);
},
+
open: function open(context) {
- this.updatePrompt();
modules.mow.echo(this.repl);
this.widgets.message = null;
open.superapply(this, arguments);
+ this.updatePrompt();
},
complete: function complete(context) {
mode: modes.REPL,
+ get completionList() this.widgets.statusbar.commandline.id,
+
accept: function accept() {
- dactyl.trapErrors(function () { this.repl.addOutput(this.command) }, this);
+ dactyl.trapErrors(function () { this.repl.addOutput(this.command); }, this);
this.completions.cleanup();
this.history.save();
commands.add(["javas[cript]", "js"],
"Evaluate a JavaScript string",
function (args) {
- modules.commandline;
-
if (args[0] && !args.bang)
dactyl.userEval(args[0]);
else {
.open();
}
}, {
+ argCount: "?",
bang: true,
completer: function (context) modules.completion.javascript(context),
hereDoc: true,
mappings: function initMappings(dactyl, modules, window) {
const { mappings, modes } = modules;
- function bind() mappings.add.apply(mappings,
- [[modes.REPL]].concat(Array.slice(arguments)))
+ function bind(...args) mappings.add.apply(mappings, [[modes.REPL]].concat(args))
bind(["<Return>"], "Accept the current input",
function ({ self }) { self.accept(); });
bind(["<C-b>", "<PageUp>"], "Scroll up half a page",
function ({ self }) { self.repl.scrollVertical("pages", -1); });
},
- options: function (dactyl, modules, window) {
+ options: function initOptions(dactyl, modules, window) {
modules.options.add(["jsdebugger", "jsd"],
"Enable the JavaScript debugger service for use in JavaScript completion",
"boolean", false, {
} catch(e){ if (!e.stack) e = Error(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 sts=4 ts=8 et ft=javascript: