-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2013 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cr = Components.results;
-var Cu = Components.utils;
+var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
try {
var ctypes;
- Components.utils.import("resource://gre/modules/ctypes.jsm");
+ Cu.import("resource://gre/modules/ctypes.jsm");
}
catch (e) {}
let objproto = Object.prototype;
-let { __lookupGetter__, __lookupSetter__, hasOwnProperty, propertyIsEnumerable } = objproto;
+let { __lookupGetter__, __lookupSetter__, __defineGetter__, __defineSetter__,
+ hasOwnProperty, propertyIsEnumerable } = objproto;
if (typeof XPCSafeJSObjectWrapper === "undefined")
this.XPCSafeJSObjectWrapper = XPCNativeWrapper;
-if (!XPCNativeWrapper.unwrap)
- XPCNativeWrapper.unwrap = function unwrap(obj) {
- if (hasOwnProperty.call(obj, "wrappedJSObject"))
- return obj.wrappedJSObject;
- return obj;
- };
-if (!Object.create)
- Object.create = function create(proto, props) {
- let obj = { __proto__: proto };
- for (let k in properties(props || {}))
- Object.defineProperty(obj, k, props[k]);
- return obj;
- };
-if (!Object.defineProperty)
- Object.defineProperty = function defineProperty(obj, prop, desc) {
- try {
- let value = desc.value;
- if ("value" in desc)
- if (desc.writable && !__lookupGetter__.call(obj, prop)
- && !__lookupSetter__.call(obj, prop))
- try {
- obj[prop] = value;
- }
- catch (e if e instanceof TypeError) {}
- else {
- objproto.__defineGetter__.call(obj, prop, function () value);
- if (desc.writable)
- objproto.__defineSetter__.call(obj, prop, function (val) { value = val; });
- }
+let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;
- if ("get" in desc)
- objproto.__defineGetter__.call(obj, prop, desc.get);
- if ("set" in desc)
- objproto.__defineSetter__.call(obj, prop, desc.set);
- }
- catch (e) {
- throw e.stack ? e : Error(e);
- }
- };
-if (!Object.defineProperties)
- Object.defineProperties = function defineProperties(obj, props) {
- for (let [k, v] in Iterator(props))
- Object.defineProperty(obj, k, v);
- };
-if (!Object.freeze)
- Object.freeze = function freeze(obj) {};
-if (!Object.getPropertyDescriptor)
- Object.getPropertyDescriptor = function getPropertyDescriptor(obj, prop) {
- try {
- let desc = {
- configurable: true,
- enumerable: propertyIsEnumerable.call(obj, prop)
- };
- var get = __lookupGetter__.call(obj, prop),
- set = __lookupSetter__.call(obj, prop);
- if (!get && !set) {
- desc.value = obj[prop];
- desc.writable = true;
- }
- if (get)
- desc.get = get;
- if (set)
- desc.set = set;
- return desc;
- }
- catch (e) {
- throw e.stack ? e : Error(e);
- }
- };
-if (!Object.getOwnPropertyDescriptor)
- Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(obj, prop) {
- if (hasOwnProperty.call(obj, prop))
- return Object.getPropertyDescriptor(obj, prop);
- };
-if (!Object.getOwnPropertyNames)
- Object.getOwnPropertyNames = function getOwnPropertyNames(obj, _debugger) {
- try {
- // This is an ugly and unfortunately necessary hack.
- if (hasOwnProperty.call(obj, "__iterator__")) {
- var oldIter = obj.__iterator__;
- delete obj.__iterator__;
- }
- let res = [k for (k in obj) if (hasOwnProperty.call(obj, k))];
- if (oldIter !== undefined) {
- obj.__iterator__ = oldIter;
- res.push("__iterator__");
- }
- return res;
- }
- catch (e) {
- throw e.stack ? e : Error(e);
- }
- };
-if (!Object.getPrototypeOf)
- Object.getPrototypeOf = function getPrototypeOf(obj) obj.__proto__;
-if (!Object.keys)
- Object.keys = function keys(obj)
- Object.getOwnPropertyNames(obj).filter(function (k) propertyIsEnumerable.call(obj, k));
+function require(module, target) JSMLoader.load(module, target);
-let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;
+function lazyRequire(module, names, target) {
+ for each (let name in names)
+ memoize(target || this, name, function (name) require(module)[name]);
+}
+
+let jsmodules = { lazyRequire: lazyRequire };
+jsmodules.jsmodules = jsmodules;
+
+function toString() "[module-global " + this.NAME + "]";
let use = {};
let loaded = {};
let global = this;
function defineModule(name, params, module) {
if (!module)
- module = getGlobalForObject(params);
+ module = this;
module.NAME = name;
module.EXPORTED_SYMBOLS = params.exports || [];
- defineModule.loadLog.push("defineModule " + name);
+ if (!~module.EXPORTED_SYMBOLS.indexOf("File"))
+ delete module.File;
+
+ defineModule.loadLog.push("[Begin " + name + "]");
+ defineModule.prefix += " ";
+
for (let [, mod] in Iterator(params.require || []))
- require(module, mod);
+ require(mod, module);
- for (let [, mod] in Iterator(params.use || []))
- if (loaded.hasOwnProperty(mod))
- require(module, mod, "use");
- else {
- use[mod] = use[mod] || [];
- use[mod].push(module);
- }
+ module._lastModule = currentModule;
currentModule = module;
module.startTime = Date.now();
}
defineModule.loadLog = [];
Object.defineProperty(defineModule.loadLog, "push", {
value: function (val) {
- if (false)
+ val = defineModule.prefix + val;
+ if (true)
defineModule.dump(val + "\n");
this[this.length] = Date.now() + " " + val;
}
});
-defineModule.dump = function dump_() {
- let msg = Array.map(arguments, function (msg) {
+defineModule.prefix = "";
+defineModule.dump = function dump_(...args) {
+ let msg = args.map(function (msg) {
if (loaded.util && typeof msg == "object")
msg = util.objectToString(msg);
return msg;
}).join(", ");
- let name = loaded.config ? config.name : "dactyl";
dump(String.replace(msg, /\n?$/, "\n")
- .replace(/^./gm, name + ": $&"));
+ .replace(/^./gm, JSMLoader.name + ": $&"));
}
defineModule.modules = [];
-defineModule.time = function time(major, minor, func, self) {
+defineModule.time = function time(major, minor, func, self, ...args) {
let time = Date.now();
if (typeof func !== "function")
func = self[func];
try {
- var res = func.apply(self, Array.slice(arguments, 4));
+ var res = func.apply(self, args);
}
catch (e) {
loaded.util && util.reportError(e);
}
function endModule() {
- defineModule.loadLog.push("endModule " + currentModule.NAME);
-
- for (let [, mod] in Iterator(use[currentModule.NAME] || []))
- require(mod, currentModule.NAME, "use");
+ defineModule.prefix = defineModule.prefix.slice(0, -2);
+ defineModule.loadLog.push("(End " + currentModule.NAME + ")");
loaded[currentModule.NAME] = 1;
+ require(currentModule.NAME, jsmodules);
+ currentModule = currentModule._lastModule;
}
-function require(obj, name, from) {
+function require_(obj, name, from, targetName) {
try {
if (arguments.length === 1)
[obj, name] = [{}, obj];
let caller = Components.stack.caller;
if (!loaded[name])
- defineModule.loadLog.push((from || "require") + ": loading " + name + " into " + (obj.NAME || caller.filename + ":" + caller.lineNumber));
+ defineModule.loadLog.push((from || "require") + ": loading " + name +
+ " into " + (targetName || obj.NAME || caller.filename + ":" + caller.lineNumber));
JSMLoader.load(name + ".jsm", obj);
+
+ if (!loaded[name] && obj != jsmodules)
+ JSMLoader.load(name + ".jsm", jsmodules);
+
return obj;
}
catch (e) {
}
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",
- "Set", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMUtils", "XPCSafeJSObjectWrapper",
- "array", "bind", "call", "callable", "ctypes", "curry", "debuggerProperties", "defineModule",
- "deprecated", "endModule", "forEach", "isArray", "isGenerator", "isinstance", "isObject",
- "isString", "isSubclass", "iter", "iterAll", "iterOwnProperties", "keys", "memoize", "octal",
- "properties", "require", "set", "update", "values", "withCallerGlobal"
- ],
- use: ["config", "services", "util"]
-}, this);
-
-function Runnable(self, func, args) {
- return {
- __proto__: Runnable.prototype,
- run: function () { func.apply(self, args || []); }
- };
+ "ErrorBase", "Cc", "Ci", "Class", "Cr", "Cu", "Finished", "Module", "JSMLoader",
+ "Set", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMShim", "XPCOMUtils",
+ "XPCSafeJSObjectWrapper", "array", "bind", "call", "callable", "ctypes", "curry",
+ "debuggerProperties", "defineModule", "deprecated", "endModule", "forEach", "isArray",
+ "isGenerator", "isinstance", "isObject", "isString", "isSubclass", "isXML", "iter",
+ "iterAll", "iterOwnProperties", "keys", "literal", "memoize", "octal", "properties",
+ "require", "set", "update", "values", "update_"
+ ]
+});
+
+this.lazyRequire("cache", ["cache"]);
+this.lazyRequire("config", ["config"]);
+this.lazyRequire("messages", ["_", "Messages"]);
+this.lazyRequire("services", ["services"]);
+this.lazyRequire("storage", ["File"]);
+this.lazyRequire("util", ["FailedAssertion", "util"]);
+
+function literal(/* comment */) {
+ let { caller } = Components.stack;
+ while (caller && caller.language != 2)
+ caller = caller.caller;
+
+ let file = caller.filename.replace(/.* -> /, "");
+ let key = "literal:" + file + ":" + caller.line;
+
+ let source = File.readURL(file);
+
+ let match = RegExp("(?:.*\\n){" + (caller.lineNumber - 1) + "}" +
+ ".*literal\\(/\\*([^]*?)\\*/\\)").exec(source);
+ return match[1];
+
+ // Later...
+ return cache.get(key, function () {
+ let source = cache.get("literal:" + file,
+ function () util.httpGet(file).responseText);
+
+ let match = RegExp("(?:.*\\n){" + (caller.lineNumber - 1) + "}" +
+ ".*literal\\(/\\*([^]*?)\\*/\\)").exec(source);
+ return match[1];
+ });
}
-Runnable.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIRunnable]);
/**
* Returns a list of all of the top-level properties of an object, by
* @returns {Generator}
*/
function prototype(obj)
- /* Temporary hack: */ typeof obj === "xml" || obj.__proto__ !== obj.__proto__ ? null :
obj.__proto__ || Object.getPrototypeOf(obj) ||
XPCNativeWrapper.unwrap(obj).__proto__ ||
Object.getPrototypeOf(XPCNativeWrapper.unwrap(obj));
}
catch (e) {}
+ function props(obj) {
+ // Grr.
+ try {
+ return Object.getOwnPropertyNames(obj);
+ }
+ catch (e) {
+ if (e.result === Cr.NS_ERROR_FAILURE) {
+ // This is being thrown for PDF.js content windows,
+ // currently.
+ let filter = function filter(prop) {
+ try {
+ return prop in obj;
+ }
+ catch (e) {
+ util.reportError("Filtering properties for " +
+ String.quote(obj) + ", " +
+ "error checking presence of " +
+ String.quote(prop) + ": " + e);
+ }
+ return false;
+ };
+ return array.uniq([k for (k in obj)].concat(
+ Object.getOwnPropertyNames(
+ XPCNativeWrapper.unwrap(obj))
+ .filter(filter)));
+ }
+ else if (!e.stack) {
+ throw Error(e);
+ }
+ }
+ }
+
for (; obj; obj = prototypes && prototype(obj)) {
try {
- if (sandbox.Object.getOwnPropertyNames || !debugger_ || !services.debugger.isOn)
- var iter = values(Object.getOwnPropertyNames(obj));
+ if (!debugger_ || !services.debugger.isOn)
+ var iter = (v for each (v in props(obj)));
}
catch (e) {}
if (!iter)
deprecated.warn = function warn(func, name, alternative, frame) {
if (!func.seenCaller)
func.seenCaller = Set([
- "resource://dactyl" + JSMLoader.suffix + "/javascript.jsm",
- "resource://dactyl" + JSMLoader.suffix + "/util.jsm"
+ "resource://dactyl/javascript.jsm",
+ "resource://dactyl/util.jsm"
]);
frame = frame || Components.stack.caller.caller;
let filename = util.fixURI(frame.filename || "unknown");
if (!Set.add(func.seenCaller, filename))
util.dactyl(func).warn([util.urlPath(filename), frame.lineNumber, " "].join(":")
- + require("messages")._("warn.deprecated", name, alternative));
+ + _("warn.deprecated", name, alternative));
}
/**
if (hasOwnProperty.call(obj, k))
yield k;
}());
+
/**
* Iterates over all of the top-level, iterable property values of an
* object.
* @returns {Generator}
*/
function values(obj) iter(function values() {
- if (isinstance(obj, ["Generator", "Iterator"]))
+ if (isinstance(obj, ["Generator", "Iterator", Iter]))
for (let k in obj)
yield k;
else
return fn;
// Close over function with 'this'
- function close(self, fn) function () fn.apply(self, Array.slice(arguments));
+ function close(self, fn) function () fn.apply(self, arguments);
if (acc == null)
acc = [];
- return function curried() {
- let args = acc.concat(Array.slice(arguments));
-
+ return function curried(...args) {
// The curried result should preserve 'this'
- if (arguments.length == 0)
+ if (args.length == 0)
return close(self || this, curried);
+ let args = acc.concat(args);
+
if (args.length >= length)
return fn.apply(self || this, args);
}
if (curry.bind)
- var bind = function bind(meth, self) let (func = callable(meth) ? meth : self[meth])
- func.bind.apply(func, Array.slice(arguments, 1));
+ var bind = function bind(meth, self, ...args) let (func = callable(meth) ? meth : self[meth])
+ func.bind.apply(func, [self].concat(args));
else
- var bind = function bind(func, self) {
+ var bind = function bind(func, self, ...args) {
if (!callable(func))
func = self[func];
- let args = Array.slice(arguments, bind.length);
- return function bound() func.apply(self, args.concat(Array.slice(arguments)));
+ return function bound(...args2) func.apply(self, args.concat(args2));
};
/**
*/
function isObject(obj) typeof obj === "object" && obj != null || obj instanceof Ci.nsISupports;
+/**
+ * Returns true if obje is an E4X XML object.
+ * @deprecated
+ */
+function isXML(obj) typeof obj === "xml";
+
/**
* Returns true if and only if its sole argument is an
* instance of the builtin Array type. The array may come from
* Returns true if and only if its sole argument may be called
* as a function. This includes classes and function objects.
*/
-function callable(val) typeof val === "function";
+function callable(val) typeof val === "function" && !(val instanceof Ci.nsIDOMElement);
-function call(fn) {
- fn.apply(arguments[1], Array.slice(arguments, 2));
+function call(fn, self, ...args) {
+ fn.apply(self, args);
return fn;
}
*/
function memoize(obj, key, getter) {
if (arguments.length == 1) {
- obj = update({ __proto__: obj.__proto__ }, obj);
- for (let prop in Object.getOwnPropertyNames(obj)) {
+ let res = update(Object.create(obj), obj);
+ for each (let prop in Object.getOwnPropertyNames(obj)) {
let get = __lookupGetter__.call(obj, prop);
if (get)
- memoize(obj, prop, get);
+ memoize(res, prop, get);
}
- return obj;
+ return res;
}
try {
configurable: true,
enumerable: true,
- get: function g_replaceProperty() (
- Class.replaceProperty(this.instance || this, key, null),
- Class.replaceProperty(this.instance || this, key, getter.call(this, key))),
+ get: function g_replaceProperty() {
+ try {
+ Class.replaceProperty(this.instance || this, key, null);
+ return Class.replaceProperty(this.instance || this, key, getter.call(this, key));
+ }
+ catch (e) {
+ util.reportError(e);
+ }
+ },
set: function s_replaceProperty(val)
Class.replaceProperty(this.instance || this, key, val)
}
}
-let sandbox = Cu.Sandbox(this);
+let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"].createInstance());
sandbox.__proto__ = this;
-/**
- * Wraps a function so that when called, the global object of the caller
- * is prepended to its arguments.
- */
-// Hack to get around lack of access to caller in strict mode.
-var withCallerGlobal = Cu.evalInSandbox(<![CDATA[
- (function withCallerGlobal(fn)
- function withCallerGlobal_wrapped()
- fn.apply(this,
- [Class.objectGlobal(withCallerGlobal_wrapped.caller)]
- .concat(Array.slice(arguments))))
-]]>, Cu.Sandbox(this), "1.8");
/**
* Updates an object with the properties of another object. Getters
if (desc.value instanceof Class.Property)
desc = desc.value.init(k, target) || desc.value;
- if (typeof desc.value === "function" && target.__proto__) {
- let func = desc.value.wrapped || desc.value;
- if (!func.superapply) {
- func.__defineGetter__("super", function () Object.getPrototypeOf(target)[k]);
- func.superapply = function superapply(self, args)
- let (meth = Object.getPrototypeOf(target)[k])
- meth && meth.apply(self, args);
- func.supercall = function supercall(self)
- func.superapply(self, Array.slice(arguments, 1));
+ try {
+ if (typeof desc.value === "function" && target.__proto__ && !(desc.value instanceof Ci.nsIDOMElement /* wtf? */)) {
+ let func = desc.value.wrapped || desc.value;
+ if (!func.superapply) {
+ func.__defineGetter__("super", function get_super() Object.getPrototypeOf(target)[k]);
+ func.superapply = function superapply(self, args)
+ let (meth = Object.getPrototypeOf(target)[k])
+ meth && meth.apply(self, args);
+ func.supercall = function supercall(self, ...args)
+ func.superapply(self, args);
+ }
}
+ Object.defineProperty(target, k, desc);
}
+ catch (e) {}
+ });
+ }
+ return target;
+}
+function update_(target) {
+ for (let i = 1; i < arguments.length; i++) {
+ let src = arguments[i];
+ Object.getOwnPropertyNames(src || {}).forEach(function (k) {
+ let desc = Object.getOwnPropertyDescriptor(src, k);
+ if (desc.value instanceof Class.Property)
+ desc = desc.value.init(k, target) || desc.value;
+
try {
+ if (typeof desc.value === "function" && target.__proto__ && !(desc.value instanceof Ci.nsIDOMElement /* wtf? */)) {
+ let func = desc.value.wrapped || desc.value;
+ if (!func.superapply) {
+ func.__defineGetter__("super", function get_super_() Object.getPrototypeOf(target)[k]);
+ func.superapply = function super_apply(self, args)
+ let (meth = Object.getPrototypeOf(target)[k])
+ meth && meth.apply(self, args);
+ func.supercall = function super_call(self, ...args)
+ func.superapply(self, args);
+ }
+ }
Object.defineProperty(target, k, desc);
}
catch (e) {}
*
* @returns {function} The constructor for the resulting class.
*/
-function Class() {
+function Class(...args) {
- var args = Array.slice(arguments);
if (isString(args[0]))
var name = args.shift();
var superclass = Class;
if (callable(args[0]))
superclass = args.shift();
- if (loaded.util && util.haveGecko("6.0a1")) // Bug 657418.
+ if (loaded.config && (config.haveGecko("5.*", "6.0") || config.haveGecko("6.*"))) // Bug 657418.
var Constructor = function Constructor() {
- var self = Object.create(Constructor.prototype, {
- constructor: { value: Constructor },
- });
+ var self = Object.create(Constructor.prototype);
self.instance = self;
+ self.globalInstance = self;
+
+ if ("_metaInit_" in self && self._metaInit_)
+ self._metaInit_.apply(self, arguments);
+
var res = self.init.apply(self, arguments);
return res !== undefined ? res : self;
};
else
- var Constructor = eval(String.replace(<![CDATA[
- (function constructor(PARAMS) {
- var self = Object.create(Constructor.prototype, {
- constructor: { value: Constructor },
- });
- self.instance = self;
- var res = self.init.apply(self, arguments);
- return res !== undefined ? res : self;
- })]]>,
+ var Constructor = eval(String.replace('\n\
+ (function constructor(PARAMS) { \n\
+ var self = Object.create(Constructor.prototype); \n\
+ self.instance = self; \n\
+ self.globalInstance = self; \n\
+ \n\
+ if ("_metaInit_" in self && self._metaInit_) \n\
+ self._metaInit_.apply(self, arguments); \n\
+ \n\
+ var res = self.init.apply(self, arguments); \n\
+ return res !== undefined ? res : self; \n\
+ })',
"constructor", (name || superclass.className).replace(/\W/g, "_"))
.replace("PARAMS", /^function .*?\((.*?)\)/.exec(args[0] && args[0].init || Class.prototype.init)[1]
.replace(/\b(self|res|Constructor)\b/g, "$1_")));
}
Class.extend(Constructor, superclass, args[0]);
+ memoize(Constructor, "closure", Class.makeClosure);
update(Constructor, args[1]);
+
Constructor.__proto__ = superclass;
- args = args.slice(2);
- Array.forEach(args, function (obj) {
+
+ args.slice(2).forEach(function (obj) {
if (callable(obj))
obj = obj.prototype;
update(Constructor.prototype, obj);
* property's value.
* @returns {Class.Property}
*/
-Class.memoize = function memoize(getter, wait)
+Class.Memoize = function Memoize(getter, wait)
Class.Property({
configurable: true,
enumerable: true,
let done = false;
if (wait)
+ // Crazy, yeah, I know. -- Kris
this.get = function replace() {
let obj = this.instance || this;
Object.defineProperty(obj, key, {
return this[key];
};
else
- this.get = function replace() {
+ this.get = function g_Memoize() {
let obj = this.instance || this;
- Class.replaceProperty(obj, key, null);
- return Class.replaceProperty(obj, key, getter.call(this, key));
+ try {
+ Class.replaceProperty(obj, key, null);
+ return Class.replaceProperty(obj, key, getter.call(this, key));
+ }
+ catch (e) {
+ util.reportError(e);
+ }
};
- this.set = function replace(val) Class.replaceProperty(this.instance || this, val);
+ this.set = function s_Memoize(val) Class.replaceProperty(this.instance || this, key, val);
+ }
+ });
+
+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.
+ */
+Class.Update = function Update(obj)
+ Class.Property({
+ configurable: true,
+ enumerable: true,
+ writable: true,
+ init: function (key, target) {
+ this.value = update({}, target[key], obj);
}
});
*/
init: function c_init() {},
+ get instance() ({}),
+ set instance(val) Class.replaceProperty(this, "instance", val),
+
withSavedValues: function withSavedValues(names, callback, self) {
let vals = names.map(function (name) this[name], this);
try {
* @returns {nsITimer} The timer which backs this timeout.
*/
timeout: function timeout(callback, timeout) {
- const self = this;
- function timeout_notify(timer) {
- if (self.stale ||
+ let timeout_notify = (timer) => {
+ if (this.stale ||
util.rehashing && !isinstance(Cu.getGlobalForObject(callback), ["BackstagePass"]))
return;
- util.trapErrors(callback, self);
- }
- return services.Timer(timeout_notify, timeout || 0, services.Timer.TYPE_ONE_SHOT);
+ this.timeouts.splice(this.timeouts.indexOf(timer), 1);
+ util.trapErrors(callback, this);
+ };
+ let timer = services.Timer(timeout_notify, timeout || 0, services.Timer.TYPE_ONE_SHOT);
+ this.timeouts.push(timer);
+ return timer;
},
+ timeouts: [],
/**
* Updates this instance with the properties of the given objects.
* localized properties.
*/
update: function update() {
- let self = this;
// XXX: Duplication.
for (let i = 0; i < arguments.length; i++) {
let src = arguments[i];
- Object.getOwnPropertyNames(src || {}).forEach(function (k) {
+ Object.getOwnPropertyNames(src || {}).forEach((k) => {
let desc = Object.getOwnPropertyDescriptor(src, k);
if (desc.value instanceof Class.Property)
desc = desc.value.init(k, this) || desc.value;
if (typeof desc.value === "function") {
let func = desc.value.wrapped || desc.value;
if (!func.superapply) {
- func.__defineGetter__("super", function () Object.getPrototypeOf(self)[k]);
- func.superapply = function superapply(self, args)
- let (meth = Object.getPrototypeOf(self)[k])
- meth && meth.apply(self, args);
- func.supercall = function supercall(self)
- func.superapply(self, Array.slice(arguments, 1));
+ func.__defineGetter__("super", () => Object.getPrototypeOf(this)[k]);
+
+ func.superapply = function superapply(self, args) {
+ let meth = Object.getPrototypeOf(self)[k];
+ return meth && meth.apply(self, args);
+ };
+
+ func.supercall = function supercall(self, ...args) {
+ return func.superapply(self, args);
+ }
}
}
catch (e) {}
}, this);
}
+ return this;
},
+ localizedProperties: {},
magicalProperties: {}
};
+for (let name in properties(Class.prototype)) {
+ let desc = Object.getOwnPropertyDescriptor(Class.prototype, name);
+ desc.enumerable = false;
+ Object.defineProperty(Class.prototype, name, desc);
+}
+
Class.makeClosure = function makeClosure() {
const self = this;
function closure(fn) {
function XPCOM(interfaces, superClass) {
interfaces = Array.concat(interfaces);
- let shim = interfaces.reduce(function (shim, iface) shim.QueryInterface(iface),
- Cc["@dactyl.googlecode.com/base/xpc-interface-shim"].createInstance());
+ let shim = XPCOMShim(interfaces);
+
+ let res = Class("XPCOM(" + interfaces + ")", superClass || Class,
+ update(iter([k,
+ v === undefined || callable(v) ? stub : v]
+ for ([k, v] in Iterator(shim))).toObject(),
+ { QueryInterface: XPCOMUtils.generateQI(interfaces) }));
- let res = Class("XPCOM(" + interfaces + ")", superClass || Class, update(
- iter.toObject([k, v === undefined || callable(v) ? function stub() null : v]
- for ([k, v] in Iterator(shim))),
- { QueryInterface: XPCOMUtils.generateQI(interfaces) }));
- shim = interfaces = null;
return res;
}
+function XPCOMShim(interfaces) {
+ let ip = services.InterfacePointer({
+ QueryInterface: function (iid) {
+ if (iid.equals(Ci.nsISecurityCheckedComponent))
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ return this;
+ },
+ getHelperForLanguage: function () null,
+ getInterfaces: function (count) { count.value = 0; }
+ });
+ return (interfaces || []).reduce(function (shim, iface) shim.QueryInterface(Ci[iface]),
+ ip.data);
+};
+let stub = Class.Property({
+ configurable: true,
+ enumerable: false,
+ value: function stub() null,
+ writable: true
+});
/**
* An abstract base class for classes that wish to inherit from Error.
init: function EB_init(message, level) {
level = level || 0;
let error = Error(message);
- update(this, error)
+ update(this, error);
this.stack = error.stack;
this.message = message;
toString: function () String(this.message)
});
+/**
+ * An Error subclass to throw in order to stop sourcing a plugin without
+ * printing a stack trace.
+ */
+var Finished = Class("Finished", ErrorBase);
+
/**
* Constructs a new Module class and instantiates an instance into the current
* module global object.
* @param {Object} classProperties Properties to be applied to the class constructor.
* @returns {Class}
*/
-function Module(name, prototype) {
- let init = callable(prototype) ? 4 : 3;
- const module = Class.apply(Class, Array.slice(arguments, 0, init));
- let instance = module();
- module.className = name.toLowerCase();
-
- instance.INIT = update(Object.create(Module.INIT),
- arguments[init] || {});
-
- currentModule[module.className] = instance;
- defineModule.modules.push(instance);
- return module;
+function Module(name, prototype, ...args) {
+ try {
+ let init = callable(prototype) ? 2 : 1;
+ let proto = callable(prototype) ? args[0] : prototype;
+
+ proto._metaInit_ = function () {
+ delete module.prototype._metaInit_;
+ currentModule[name.toLowerCase()] = this;
+ };
+
+ const module = Class.apply(Class, [name, prototype, ...args.slice(0, init)]);
+ let instance = module();
+ module.className = name.toLowerCase();
+
+ instance.INIT = update(Object.create(Module.INIT),
+ args[init] || {});
+
+ currentModule[module.className] = instance;
+ defineModule.modules.push(instance);
+ return module;
+ }
+ catch (e) {
+ if (typeof e === "string")
+ e = Error(e);
+
+ dump(e.fileName + ":" + e.lineNumber + ": " + e + "\n" + (e.stack || Error().stack));
+ }
}
Module.INIT = {
init: function Module_INIT_init(dactyl, modules, window) {
module.isLocalModule = true;
modules.jsmodules[this.constructor.className] = module;
- locals.reverse().forEach(function (fn, i) update(objs[i], fn.apply(module, args)))
+ locals.reverse().forEach(function (fn, i) update(objs[i], fn.apply(module, args)));
memoize(module, "closure", Class.makeClosure);
module.instance = module;
*
* @returns {function} The constructor for the new Struct.
*/
-function Struct() {
- if (!/^[A-Z]/.test(arguments[0]))
- var args = Array.slice(arguments, 0);
- else {
- var className = arguments[0];
- args = Array.slice(arguments, 1);
- }
+function Struct(...args) {
+ if (/^[A-Z]/.test(args[0]))
+ var className = args.shift();
const Struct = Class(className || "Struct", StructBase, {
length: args.length,
});
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)
this[i] = arguments[i];
},
+ get toStringParams() this,
+
clone: function struct_clone() this.constructor.apply(null, this.slice()),
closure: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "closure")),
localize: function localize(key, defaultValue) {
let i = this.prototype.members[key];
- Object.defineProperty(this.prototype, i, require("messages").Messages.Localized(defaultValue).init(key, this.prototype));
+ Object.defineProperty(this.prototype, i, Messages.Localized(defaultValue).init(key, this.prototype));
return this;
}
});
}
catch (e) {
if (typeof util === "undefined")
- dump("dactyl: " + e + "\n" + (e.stack || Error().stack));
+ dump(JSMLoader.name + ": " + e + "\n" + (e.stack || Error().stack));
else
util.reportError(e);
}
* function.
*
* @param {object} obj
+ * @param {nsIJSIID} iface The interface to which to query all elements.
* @returns {Generator}
*/
-function iter(obj) {
+function iter(obj, iface) {
+ if (arguments.length == 2 && iface instanceof Ci.nsIJSIID)
+ return iter(obj).map(function (item) item.QueryInterface(iface));
+
let args = arguments;
let res = Iterator(obj);
}
else if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))
res = array.iterItems(obj);
- else if (obj instanceof Ci.nsIDOMNamedNodeMap)
+ else if (Ci.nsIDOMNamedNodeMap && obj instanceof Ci.nsIDOMNamedNodeMap ||
+ Ci.nsIDOMMozNamedAttrMap && obj instanceof Ci.nsIDOMMozNamedAttrMap)
res = (function () {
for (let i = 0; i < obj.length; i++)
yield [obj.name, obj];
return iter(obj.enumerator());
return iter(obj.enumerator);
}
- res.__noSuchMethod__ = function __noSuchMethod__(meth, args) {
- if (meth in iter)
- var res = iter[meth].apply(iter, [this].concat(args));
- else
- res = let (ary = array(this))
- ary[meth] ? ary[meth].apply(ary, args) : ary.__noSuchMethod__(meth, args);
- if (isinstance(res, ["Iterator", "Generator"]))
- return iter(res);
- return res;
- };
- return res;
+ return Iter(res);
}
update(iter, {
toArray: function toArray(iter) array(iter).array,
}
});
+const Iter = Class("Iter", {
+ init: function init(iter) {
+ this.iter = iter;
+ if ("__iterator__" in iter)
+ this.iter = iter.__iterator__();
+
+ if (this.iter.finalize)
+ this.finalize = function finalize() this.iter.finalize.apply(this.iter, arguments);
+ },
+
+ next: function next() this.iter.next(),
+
+ send: function send() this.iter.send.apply(this.iter, arguments),
+
+ __iterator__: function () this.iter
+});
+
/**
* Array utility methods.
*/
},
array: ary,
toString: function () this.array.toString(),
- concat: function () this.__noSuchMethod__("concat", Array.slice(arguments)),
- filter: function () this.__noSuchMethod__("filter", Array.slice(arguments)),
- map: function () this.__noSuchMethod__("map", Array.slice(arguments))
+ concat: function (...args) this.__noSuchMethod__("concat", args),
+ filter: function (...args) this.__noSuchMethod__("filter", args),
+ map: function (...args) this.__noSuchMethod__("map", args)
};
}
}, {
}
});
+/* Make Minefield not explode, because Minefield exploding is not fun. */
+let iterProto = Iter.prototype;
+Object.keys(iter).forEach(function (k) {
+ iterProto[k] = function (...args) {
+ let res = iter[k].apply(iter, [this].concat(args));
+ if (isinstance(res, ["Iterator", "Generator"]))
+ return Iter(res);
+ return res;
+ };
+});
+
+Object.keys(array).forEach(function (k) {
+ if (!(k in iterProto))
+ iterProto[k] = function (...args) {
+ let res = array[k].apply(array, [this.toArray()].concat(args));
+ if (isinstance(res, ["Iterator", "Generator"]))
+ return Iter(res);
+ if (isArray(res))
+ return array(res);
+ return res;
+ };
+});
+
+Object.getOwnPropertyNames(Array.prototype).forEach(function (k) {
+ if (!(k in iterProto) && callable(Array.prototype[k]))
+ iterProto[k] = function () {
+ let ary = iter(this).toArray();
+ let res = ary[k].apply(ary, arguments);
+ if (isArray(res))
+ return array(res);
+ return res;
+ };
+});
+
endModule();
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}
-// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript: