-// Copyright (c) 2009-2013 Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2014 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.
var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
+var Cs = new Proxy(Components.stack, {
+ get: function Cs_get(target, prop) Components.stack.caller[prop]
+});
+
+function module(url) {
+ let obj = {};
+ Cu.import(url, obj);
+ return obj;
+}
+
+var { XPCOMUtils } = module("resource://gre/modules/XPCOMUtils.jsm");
try {
- var ctypes;
- Cu.import("resource://gre/modules/ctypes.jsm");
+ var ctypes = module("resource://gre/modules/ctypes.jsm");
}
catch (e) {}
let { __lookupGetter__, __lookupSetter__, __defineGetter__, __defineSetter__,
hasOwnProperty, propertyIsEnumerable } = objproto;
-if (typeof XPCSafeJSObjectWrapper === "undefined")
- this.XPCSafeJSObjectWrapper = XPCNativeWrapper;
+hasOwnProperty = Function.call.bind(hasOwnProperty);
+propertyIsEnumerable = Function.call.bind(propertyIsEnumerable);
-let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;
+// Gecko 24.
+if (!("find" in Array.prototype))
+ Object.defineProperty(Array.prototype, "find", {
+ configurable: true,
+ writable: true,
+ value: function Array_find(pred, self) {
+ for (let [i, elem] in Iterator(this))
+ if (pred.call(self, elem, i, this))
+ return elem;
+ }
+ });
-function require(module, target) JSMLoader.load(module, target);
+if (!("findIndex" in Array.prototype))
+ Object.defineProperty(Array.prototype, "findIndex", {
+ configurable: true,
+ writable: true,
+ value: function Array_findIndex(pred, self) {
+ for (let [i, elem] in Iterator(this))
+ if (pred.call(self, elem, i, this))
+ return i;
+ return -1;
+ }
+ });
+
+function require(module_, target) {
+ if (/^[A-Za-z0-9]+:/.test(module_))
+ return module(module_);
+ return JSMLoader.load(module_, target);
+}
function lazyRequire(module, names, target) {
- for each (let name in names)
- memoize(target || this, name, function (name) require(module)[name]);
+ for (let name of names)
+ memoize(target || this, name, name => require(module)[name]);
}
let jsmodules = { lazyRequire: lazyRequire };
defineModule("base", {
// sed -n 's/^(const|var|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
exports: [
- "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_"
+ "Cc",
+ "Ci",
+ "Class",
+ "Cr",
+ "Cs",
+ "Cu",
+ "ErrorBase",
+ "Finished",
+ "JSMLoader",
+ "Module",
+ "RealSet",
+ "Set",
+ "Struct",
+ "StructBase",
+ "Timer",
+ "UTF8",
+ "XPCOM",
+ "XPCOMShim",
+ "XPCOMUtils",
+ "array",
+ "bind",
+ "call",
+ "callable",
+ "ctypes",
+ "curry",
+ "defineModule",
+ "deprecated",
+ "endModule",
+ "forEach",
+ "hasOwnProperty",
+ "isArray",
+ "isGenerator",
+ "isObject",
+ "isString",
+ "isSubclass",
+ "isinstance",
+ "iter",
+ "iterAll",
+ "iterOwnProperties",
+ "keys",
+ "literal",
+ "memoize",
+ "modujle",
+ "octal",
+ "properties",
+ "require",
+ "set",
+ "update",
+ "values",
]
});
this.lazyRequire("cache", ["cache"]);
this.lazyRequire("config", ["config"]);
this.lazyRequire("messages", ["_", "Messages"]);
+this.lazyRequire("promises", ["Task", "promises"]);
this.lazyRequire("services", ["services"]);
this.lazyRequire("storage", ["File"]);
this.lazyRequire("util", ["FailedAssertion", "util"]);
+literal.files = {};
+literal.locations = {};
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 key = "literal:" + file + ":" + caller.lineNumber;
+ return cache.get(key, function() {
+ let source = literal.files[file] || File.readURL(file);
+ literal.files[file] = source;
let match = RegExp("(?:.*\\n){" + (caller.lineNumber - 1) + "}" +
".*literal\\(/\\*([^]*?)\\*/\\)").exec(source);
});
}
-/**
- * Returns a list of all of the top-level properties of an object, by
- * way of the debugger.
- *
- * @param {object} obj
- * @returns [jsdIProperty]
- */
-function debuggerProperties(obj) {
- if (loaded.services && services.debugger.isOn) {
- let res = {};
- services.debugger.wrapValue(obj).getProperties(res, {});
- return res.value;
- }
-}
-
/**
* Iterates over the names of all of the top-level properties of an
* object or, if prototypes is given, all of the properties in the
- * prototype chain below the top. Uses the debugger if possible.
+ * prototype chain below the top.
*
* @param {object} obj The object to inspect.
* @param {boolean} properties Whether to inspect the prototype chain
XPCNativeWrapper.unwrap(obj).__proto__ ||
Object.getPrototypeOf(XPCNativeWrapper.unwrap(obj));
-function properties(obj, prototypes, debugger_) {
+function properties(obj, prototypes) {
let orig = obj;
- let seen = { dactylPropertyNames: true };
+ let seen = RealSet(["dactylPropertyNames"]);
try {
if ("dactylPropertyNames" in obj && !prototypes)
for (let key in values(obj.dactylPropertyNames))
- if (key in obj && !Set.add(seen, key))
+ if (key in obj && !seen.add(key))
yield key;
}
catch (e) {}
}
for (; obj; obj = prototypes && prototype(obj)) {
- try {
- if (!debugger_ || !services.debugger.isOn)
- var iter = (v for each (v in props(obj)));
- }
- catch (e) {}
- if (!iter)
- iter = (prop.name.stringValue for (prop in values(debuggerProperties(obj))));
-
- for (let key in iter)
- if (!prototypes || !Set.add(seen, key) && obj != orig)
+ for (let key of props(obj))
+ if (!prototypes || !seen.add(key) && obj != orig)
yield key;
}
}
function deprecated(alternative, fn) {
if (isObject(fn))
- return Class.Property(iter(fn).map(function ([k, v]) [k, callable(v) ? deprecated(alternative, v) : v])
+ return Class.Property(iter(fn).map(([k, v]) => [k,
+ callable(v) ? deprecated(alternative, v)
+ : v])
.toObject());
- let name, func = callable(fn) ? fn : function () this[fn].apply(this, arguments);
+ let name,
+ func = callable(fn) ? fn
+ : function () this[fn].apply(this, arguments);
function deprecatedMethod() {
let obj = !this ? "" :
this.constructor.className ? this.constructor.className + "#" :
"";
- deprecated.warn(func, obj + (fn.name || name), alternative);
+ deprecated.warn(func,
+ obj + (fn.realName || fn.name || name || "").replace(/__/g, "."),
+ alternative);
return func.apply(this, arguments);
}
+ if (func.name)
+ deprecatedMethod.realName = func.name;
return callable(fn) ? deprecatedMethod : Class.Property({
get: function () deprecatedMethod,
}
deprecated.warn = function warn(func, name, alternative, frame) {
if (!func.seenCaller)
- func.seenCaller = Set([
+ func.seenCaller = RealSet([
"resource://dactyl/javascript.jsm",
"resource://dactyl/util.jsm"
]);
+ if (!(loaded.util && util && loaded.config && config.protocolLoaded)) {
+ dump("DACTYL: deprecated method called too early [" + [name, alternative] + "]:\n" + Error().stack + "\n\n");
+ return;
+ }
+
frame = frame || Components.stack.caller.caller;
+
let filename = util.fixURI(frame.filename || "unknown");
- if (!Set.add(func.seenCaller, filename))
+ if (!func.seenCaller.add(filename))
util.dactyl(func).warn([util.urlPath(filename), frame.lineNumber, " "].join(":")
+ _("warn.deprecated", name, alternative));
}
* @returns {Generator}
*/
function keys(obj) iter(function keys() {
- for (var k in obj)
- if (hasOwnProperty.call(obj, k))
+ if (isinstance(obj, ["Map"]))
+ for (let [k, v] of obj)
yield k;
+ else
+ for (var k in obj)
+ if (hasOwnProperty(obj, k))
+ yield k;
}());
/**
* @returns {Generator}
*/
function values(obj) iter(function values() {
- if (isinstance(obj, ["Generator", "Iterator", Iter]))
+ if (isinstance(obj, ["Map"]))
+ for (let [k, v] of obj)
+ yield v;
+ else if (isinstance(obj, ["Generator", "Iterator", Iter]))
for (let k in obj)
yield k;
+ else if (iter.iteratorProp in obj)
+ for (let v of obj)
+ yield v;
else
for (var k in obj)
- if (hasOwnProperty.call(obj, k))
+ if (hasOwnProperty(obj, k))
yield obj[k];
}());
var forEach = deprecated("iter.forEach", function forEach() iter.forEach.apply(iter, arguments));
var iterAll = deprecated("iter", function iterAll() iter.apply(null, arguments));
+var RealSet = Set;
+let Set_add = RealSet.prototype.add;
+RealSet.prototype.add = function RealSet_add(val) {
+ let res = this.has(val);
+ Set_add.apply(this, arguments);
+ return res;
+};
+
+RealSet.prototype.difference = function RealSet_difference(set) {
+ return RealSet(i for (i of this) if (!set.has(i)));
+};
+
+RealSet.prototype.intersection = function RealSet_intersection(set) {
+ return RealSet(i for (i of this) if (set.has(i)));
+};
+
+RealSet.prototype.union = function RealSet_union(set) {
+ let res = RealSet(this);
+ for (let item of set)
+ res.add(item);
+ return res;
+};
+
/**
* Utility for managing sets of strings. Given an array, returns an
* object with one key for each value thereof.
* @param {[string]} ary @optional
* @returns {object}
*/
-function Set(ary) {
+this.Set = deprecated("RealSet", function Set(ary) {
let obj = {};
if (ary)
for (let val in values(ary))
obj[val] = true;
return obj;
-}
+});
/**
* Adds an element to a set and returns true if the element was
* previously contained.
* @param {string} key The key to add.
* @returns boolean
*/
-Set.add = curry(function set_add(set, key) {
- let res = this.has(set, key);
- set[key] = true;
- return res;
-});
+Set.add = deprecated("RealSet#add",
+ curry(function Set__add(set, key) {
+ if (isinstance(set, ["Set"])) {
+ let res = set.has(key);
+ set.add(key);
+ return res;
+ }
+
+ let res = this.has(set, key);
+ set[key] = true;
+ return res;
+ }));
/**
* Returns true if the given set contains the given key.
*
* @param {string} key The key to check.
* @returns {boolean}
*/
-Set.has = curry(function set_has(set, key) hasOwnProperty.call(set, key) &&
- propertyIsEnumerable.call(set, key));
+Set.has = deprecated("hasOwnProperty or Set#has",
+ curry(function Set__has(set, key) {
+ if (isinstance(set, ["Set"]))
+ return set.has(key);
+
+ return hasOwnProperty(set, key) &&
+ propertyIsEnumerable(set, key);
+ }));
/**
* Returns a new set containing the members of the first argument which
* do not exist in any of the other given arguments.
* @param {object} set The set.
* @returns {object}
*/
-Set.subtract = function set_subtract(set) {
- set = update({}, set);
- for (let i = 1; i < arguments.length; i++)
- for (let k in keys(arguments[i]))
- delete set[k];
- return set;
-};
+Set.subtract = deprecated("RealSet#difference",
+ function set_subtract(set) {
+ set = update({}, set);
+ for (let i = 1; i < arguments.length; i++)
+ for (let k in keys(arguments[i]))
+ delete set[k];
+ return set;
+ });
+
/**
* Removes an element from a set and returns true if the element was
* previously contained.
* @param {string} key The key to remove.
* @returns boolean
*/
-Set.remove = curry(function set_remove(set, key) {
- let res = set.has(set, key);
- delete set[key];
- return res;
-});
+Set.remove = deprecated("RealSet#delete",
+ curry(function Set__remove(set, key) {
+ if (isinstance(set, ["Set"]))
+ return set.delete(key);
+
+ let res = set.has(set, key);
+ delete set[key];
+ return res;
+ }));
function set() {
deprecated.warn(set, "set", "Set");
return fn;
// Close over function with 'this'
- function close(self, fn) function () fn.apply(self, arguments);
+ function close(self, fn) (...args) => fn.apply(self, args);
if (acc == null)
acc = [];
- return function curried(...args) {
+ function curried(...args) {
// The curried result should preserve 'this'
if (args.length == 0)
return close(self || this, curried);
return curry(fn, length, self || this, args);
};
+ curried.realName = fn.realName || fn.name;
+ return curried;
}
-if (curry.bind)
- var bind = function bind(meth, self, ...args) let (func = callable(meth) ? meth : self[meth])
+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, ...args) {
- if (!callable(func))
- func = self[func];
-
- return function bound(...args2) func.apply(self, args.concat(args2));
- };
/**
* Returns true if both arguments are functions and
*/
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
* is not the case when using (obj instanceof Array).
*/
var isArray =
- Array.isArray
- // This is bloody stupid.
- ? function isArray(val) Array.isArray(val) || val && val.constructor && val.constructor.name === "Array"
- : function isArray(val) objproto.toString.call(val) == "[object Array]";
+ // This is bloody stupid.
+ function isArray(val) Array.isArray(val) || val && val.constructor && val.constructor.name === "Array";
/**
* Returns true if and only if its sole argument is an
function memoize(obj, key, getter) {
if (arguments.length == 1) {
let res = update(Object.create(obj), obj);
- for each (let prop in Object.getOwnPropertyNames(obj)) {
+ for (let prop of Object.getOwnPropertyNames(obj)) {
let get = __lookupGetter__.call(obj, prop);
if (get)
memoize(res, prop, get);
}
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) {}
- });
- }
- return target;
-}
/**
* @constructor Class
if (callable(args[0]))
superclass = args.shift();
- if (loaded.config && (config.haveGecko("5.*", "6.0") || config.haveGecko("6.*"))) // Bug 657418.
- var Constructor = function 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('\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_")));
+ 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_")));
Constructor.className = name || superclass.className || superclass.name;
}
Class.extend(Constructor, superclass, args[0]);
- memoize(Constructor, "closure", Class.makeClosure);
+ memoize(Constructor, "bound", Class.makeClosure);
+ if (Iter && array) // Hack. :/
+ Object.defineProperty(Constructor, "closure",
+ deprecated("bound", { get: function closure() this.bound }));
update(Constructor, args[1]);
Constructor.__proto__ = superclass;
return Constructor;
}
-if (Cu.getGlobalForObject)
- Class.objectGlobal = function (object) {
- try {
- return Cu.getGlobalForObject(object);
- }
- catch (e) {
- return null;
- }
- };
-else
- Class.objectGlobal = function (object) {
- while (object.__parent__)
- object = object.__parent__;
- return object;
- };
+Class.objectGlobal = function (object) {
+ try {
+ return Cu.getGlobalForObject(object);
+ }
+ catch (e) {
+ return null;
+ }
+};
/**
* @class Class.Property
Object.defineProperty(obj, key, {
configurable: true, enumerable: false,
get: function get() {
- util.waitFor(function () done);
+ util.waitFor(() => done);
return this[key];
}
});
- util.yieldable(function () {
+ Task.spawn(function () {
let wait;
for (var res in getter.call(obj)) {
if (wait !== undefined)
- yield wait;
+ yield promises.sleep(wait);
wait = res;
}
Class.replaceProperty(obj, key, res);
done = true;
- })();
+ });
return this[key];
};
set instance(val) Class.replaceProperty(this, "instance", val),
withSavedValues: function withSavedValues(names, callback, self) {
- let vals = names.map(function (name) this[name], this);
+ let vals = names.map(name => this[name]);
try {
return callback.call(self || this);
}
finally {
- names.forEach(function (name, i) this[name] = vals[i], this);
+ names.forEach((name, i) => { this[name] = vals[i]; });
}
},
toString: function C_toString() {
if (this.toStringParams)
- var params = "(" + this.toStringParams.map(function (m) isArray(m) ? "[" + m + "]" :
- isString(m) ? m.quote() : String(m))
+ var params = "(" + this.toStringParams.map(m => (isArray(m) ? "[" + m + "]" :
+ isString(m) ? m.quote() : String(m)))
.join(", ") + ")";
return "[instance " + this.constructor.className + (params || "") + "]";
},
util.rehashing && !isinstance(Cu.getGlobalForObject(callback), ["BackstagePass"]))
return;
this.timeouts.splice(this.timeouts.indexOf(timer), 1);
- util.trapErrors(callback, this);
+ try {
+ callback.call(this);
+ }
+ catch (e) {
+ try {
+ util.dump("Error invoking timer callback registered at " +
+ [frame.filename, frame.lineNumber, ""].join(":"));
+ util.reportError(e);
+ }
+ catch (e) {
+ Cu.reportError(e);
+ }
+ }
};
+ let frame = Components.stack.caller;
let timer = services.Timer(timeout_notify, timeout || 0, services.Timer.TYPE_ONE_SHOT);
this.timeouts.push(timer);
return timer;
}
try {
- if ("value" in desc && (k in this.localizedProperties || k in this.magicalProperties))
+ if ("value" in desc && (this.localizedProperties.has(k) || this.magicalProperties.has(k)))
this[k] = desc.value;
else
Object.defineProperty(this, k, desc);
return this;
},
- localizedProperties: {},
- magicalProperties: {}
+ localizedProperties: RealSet(),
+ magicalProperties: RealSet()
};
for (let name in properties(Class.prototype)) {
let desc = Object.getOwnPropertyDescriptor(Class.prototype, name);
Object.defineProperty(Class.prototype, name, desc);
}
-Class.makeClosure = function makeClosure() {
- const self = this;
- function closure(fn) {
- function _closure() {
- try {
- return fn.apply(self, arguments);
- }
- catch (e if !(e instanceof FailedAssertion)) {
- util.reportError(e);
- throw e.stack ? e : Error(e);
- }
+var closureHooks = {
+ get: function closure_get(target, prop) {
+ if (hasOwnProperty(target._closureCache, prop))
+ return target._closureCache[prop];
+
+ let p = target[prop]
+ if (callable(p))
+ return target._closureCache[prop] = p.bind(target);
+ return p;
+ }
+
+ /*
+ getOwnPropertyNames: function getOwnPropertyNames(target) {
+ return [k for (k in properties(target, true))];
+ },
+
+ getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, prop) {
+ let self = this;
+ return {
+ configurable: false,
+ writable: false,
+ get value() self.get(target, prop)
}
- _closure.wrapped = fn;
- return _closure;
}
+ */
+};
- iter(properties(this), properties(this, true)).forEach(function (k) {
- if (!__lookupGetter__.call(this, k) && callable(this[k]))
- closure[k] = closure(this[k]);
- else if (!(k in closure))
- Object.defineProperty(closure, k, {
- configurable: true,
- enumerable: true,
- get: function get_proxy() self[k],
- set: function set_proxy(val) self[k] = val,
- });
- }, this);
-
- return closure;
+Class.makeClosure = function makeClosure() {
+ this._closureCache = {};
+
+ return new Proxy(this, closureHooks);
};
-memoize(Class.prototype, "closure", Class.makeClosure);
+memoize(Class.prototype, "bound", Class.makeClosure);
/**
* A base class generator for classes which implement XPCOM interfaces.
getHelperForLanguage: function () null,
getInterfaces: function (count) { count.value = 0; }
});
- return (interfaces || []).reduce(function (shim, iface) shim.QueryInterface(Ci[iface]),
+ return (interfaces || []).reduce((shim, iface) => shim.QueryInterface(Ci[iface]),
ip.data);
};
let stub = Class.Property({
*/
var ErrorBase = Class("ErrorBase", Error, {
level: 2,
- init: function EB_init(message, level) {
- level = level || 0;
+ init: function EB_init(message, level=0) {
let error = Error(message);
update(this, error);
this.stack = error.stack;
let proto = callable(prototype) ? args[0] : prototype;
proto._metaInit_ = function () {
- delete module.prototype._metaInit_;
+ module.prototype._metaInit_ = null;
currentModule[name.toLowerCase()] = this;
};
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((fn, i) => { update(objs[i], fn.apply(module, args)); });
memoize(module, "closure", Class.makeClosure);
module.instance = module;
const Struct = Class(className || "Struct", StructBase, {
length: args.length,
- members: array.toObject(args.map(function (v, k) [v, k]))
+ members: array.toObject(args.map((v, k) => [v, k]))
});
args.forEach(function (name, i) {
Struct.prototype.__defineGetter__(name, function () this[i]);
clone: function struct_clone() this.constructor.apply(null, this.slice()),
+ bound: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "bound")),
closure: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "closure")),
get: function struct_get(key, val) this[this.members[key]],
});
var Timer = Class("Timer", {
- init: function init(minInterval, maxInterval, callback, self) {
+ init: function init(minInterval, maxInterval, callback, self=this) {
this._timer = services.Timer();
this.callback = callback;
- this.self = self || this;
+ this.self = self;
this.minInterval = minInterval;
this.maxInterval = maxInterval;
this.doneAt = 0;
* @param {nsIJSIID} iface The interface to which to query all elements.
* @returns {Generator}
*/
+iter.iteratorProp = "@@iterator" in [] ? "@@iterator" : "iterator";
function iter(obj, iface) {
if (arguments.length == 2 && iface instanceof Ci.nsIJSIID)
- return iter(obj).map(function (item) item.QueryInterface(iface));
+ return iter(obj).map(item => item.QueryInterface(iface));
let args = arguments;
let res = Iterator(obj);
for (let j in iter(args[i]))
yield j;
})();
- else if (isinstance(obj, ["Iterator", "Generator"]))
+ else if (isinstance(obj, ["Iterator", "Generator", "Array"]))
;
+ else if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))
+ res = array.iterItems(obj);
+ else if (iter.iteratorProp in obj && callable(obj[iter.iteratorProp]) && !("__iterator__" in obj))
+ res = (x for (x of obj));
else if (ctypes && ctypes.CData && obj instanceof ctypes.CData) {
while (obj.constructor instanceof ctypes.PointerType)
obj = obj.contents;
else
return iter({});
}
- else if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))
- res = array.iterItems(obj);
else if (Ci.nsIDOMNamedNodeMap && obj instanceof Ci.nsIDOMNamedNodeMap ||
Ci.nsIDOMMozNamedAttrMap && obj instanceof Ci.nsIDOMMozNamedAttrMap)
res = (function () {
every: function every(iter, pred, self) {
pred = pred || util.identity;
- for (let elem in iter)
+ for (let elem of iter)
if (!pred.call(self, elem))
return false;
return true;
},
some: function every(iter, pred, self) {
pred = pred || util.identity;
- for (let elem in iter)
+ for (let elem of iter)
if (pred.call(self, elem))
return true;
return false;
},
filter: function filter(iter, pred, self) {
- for (let elem in iter)
+ for (let elem of iter)
if (pred.call(self, elem))
yield elem;
},
* @param {object} self The this object for *fn*.
*/
forEach: function forEach(iter, func, self) {
- for (let val in iter)
+ for (let val of iter)
func.call(self, val);
},
indexOf: function indexOf(iter, elem) {
let i = 0;
- for (let item in iter) {
+ for (let item of iter) {
if (item == elem)
return i;
i++;
* @returns {Array}
*/
map: function map(iter, func, self) {
- for (let i in iter)
+ for (let i of iter)
yield func.call(self, i);
},
*/
nth: function nth(iter, pred, n, self) {
if (typeof pred === "number")
- [pred, n] = [function () true, pred]; // Hack.
+ [pred, n] = [() => true, pred]; // Hack.
- for (let elem in iter)
+ for (let elem of iter)
if (pred.call(self, elem) && n-- === 0)
return elem;
return undefined;
},
+ /**
+ * Analog of Array.find method. Returns the first item in the
+ * iterator for which `pred` returns true.
+ */
+ find: function find(iter, pred, self) {
+ for (let elem of iter)
+ if (pred.call(self, elem))
+ return elem;
+ return undefined;
+ },
+
sort: function sort(iter, fn, self)
array(this.toArray(iter).sort(fn, self)),
uniq: function uniq(iter) {
- let seen = {};
- for (let item in iter)
- if (!Set.add(seen, item))
+ let seen = RealSet();
+ for (let item of iter)
+ if (!seen.add(item))
yield item;
},
__iterator__: function () this.iter
});
+iter.Iter = Iter;
+
+function arrayWrap(fn) {
+ function wrapper() {
+ let res = fn.apply(this, arguments);
+ if (isArray(res))
+ return array(res);
+ if (isinstance(res, ["Iterator", "Generator"]))
+ return iter(res);
+ return res;
+ }
+ wrapper.wrapped = fn;
+ return wrapper;
+}
/**
* Array utility methods.
else if (ary.length)
ary = Array.slice(ary);
- return {
- __proto__: ary,
- __iterator__: function () this.iterItems(),
- __noSuchMethod__: function (meth, args) {
- var res = array[meth].apply(null, [this.array].concat(args));
- if (isArray(res))
- return array(res);
- if (isinstance(res, ["Iterator", "Generator"]))
- return iter(res);
- return res;
- },
- array: ary,
- toString: function () this.array.toString(),
- concat: function (...args) this.__noSuchMethod__("concat", args),
- filter: function (...args) this.__noSuchMethod__("filter", args),
- map: function (...args) this.__noSuchMethod__("map", args)
- };
+ let self = this;
+ return new Proxy(ary, {
+ get: function array_get(target, prop) {
+ if (prop in array && callable(array[prop]))
+ return arrayWrap(array[prop].bind(array, target));
+
+ if (prop == "array")
+ return target;
+
+ let p = target[prop];
+ if (!/^\d+$/.test(prop) &&
+ prop != "toString" &&
+ prop != "toSource" &&
+ callable(p))
+ return arrayWrap(p);
+
+ return p;
+ }
+ });
}
}, {
/**
* @param {Array} ary
* @returns {Array}
*/
- compact: function compact(ary) ary.filter(function (item) item != null),
+ compact: function compact(ary) ary.filter(item => item != null),
/**
* Returns true if each element of ary1 is equal to the
* @returns {boolean}
*/
equals: function (ary1, ary2)
- ary1.length === ary2.length && Array.every(ary1, function (e, i) e === ary2[i]),
+ ary1.length === ary2.length && Array.every(ary1, (e, i) => e === ary2[i]),
/**
* Flattens an array, such that all elements of the array are
};
});
+Object.defineProperty(Class.prototype, "closure",
+ deprecated("bound", { get: function closure() this.bound }));
+
endModule();
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}