All pastes #2078527 Raw Edit

Mine

public javascript v1 · immutable
#2078527 ·published 2011-08-26 13:39 UTC
rendered paste body
// Copyright (c) 2009-2011 by 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 { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;Cu.import("resource://dactyl/bootstrap.jsm");Cu.import("resource://gre/modules/XPCOMUtils.jsm");try {    var ctypes;    Cu.import("resource://gre/modules/ctypes.jsm");}catch (e) {}let objproto = Object.prototype;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 {                    __defineGetter__.call(obj, prop, function () value);                    if (desc.writable)                        __defineSetter__.call(obj, prop, function (val) { value = val; });                }            if ("get" in desc)                __defineGetter__.call(obj, prop, desc.get);            if ("set" in desc)                __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));let getGlobalForObject = Cu.getGlobalForObject || function (obj) obj.__parent__;let jsmodules = {};let use = {};let loaded = {};let currentModule;let global = this;function defineModule(name, params, module) {    if (!module)        module = getGlobalForObject(params);    module.NAME = name;    module.EXPORTED_SYMBOLS = params.exports || [];    delete module.File;    defineModule.loadLog.push("[Begin " + name + "]");    defineModule.prefix += "  ";    for (let [, mod] in Iterator(params.require || []))        require(jsmodules, mod, null, name);    module.__proto__ = jsmodules;    module._lastModule = currentModule;    currentModule = module;    module.startTime = Date.now();}defineModule.loadLog = [];Object.defineProperty(defineModule.loadLog, "push", {    value: function (val) {        val = defineModule.prefix + val;        if (true)            defineModule.dump(val + "\n");        this[this.length] = Date.now() + " " + val;    }});defineModule.prefix = "";defineModule.dump = function dump_() {    let msg = Array.map(arguments, function (msg) {        if (loaded.util && typeof msg == "object")            msg = util.objectToString(msg);        return msg;    }).join(", ");    dump(String.replace(msg, /\n?$/, "\n")               .replace(/^./gm, JSMLoader.name + ": $&"));}defineModule.modules = [];defineModule.time = function time(major, minor, func, self) {    let time = Date.now();    if (typeof func !== "function")        func = self[func];    try {        var res = func.apply(self, Array.slice(arguments, 4));    }    catch (e) {        loaded.util && util.reportError(e);    }    JSMLoader.times.add(major, minor, Date.now() - time);    return res;}function endModule() {    defineModule.prefix = defineModule.prefix.slice(0, -2);    defineModule.loadLog.push("(End   " + currentModule.NAME + ")");    loaded[currentModule.NAME] = 1;    require(jsmodules, currentModule.NAME);    currentModule = currentModule._lastModule;}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 " + (targetName || obj.NAME || caller.filename + ":" + caller.lineNumber));        JSMLoader.load(name + ".jsm", obj);        return obj;    }    catch (e) {        defineModule.dump("loading " + String.quote(name + ".jsm") + "\n");        if (loaded.util)            util.reportError(e);        else            defineModule.dump("    " + (e.filename || e.fileName) + ":" + e.lineNumber + ": " + e + "\n");    }}defineModule("base", {    // sed -n 's/^(const|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", "XPCOMShim", "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"    ]}, 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. * * @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. * * @param {object} obj The object to inspect. * @param {boolean} properties Whether to inspect the prototype chain * @default false * @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));function properties(obj, prototypes, debugger_) {    let orig = obj;    let seen = { dactylPropertyNames: true };    try {        if ("dactylPropertyNames" in obj && !prototypes)            for (let key in values(obj.dactylPropertyNames))                if (key in obj && !Set.add(seen, key))                    yield key;    }    catch (e) {}    for (; obj; obj = prototypes && prototype(obj)) {        try {            if (sandbox.Object.getOwnPropertyNames || !debugger_ || !services.debugger.isOn)                var iter = values(Object.getOwnPropertyNames(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)                yield key;    }}function iterOwnProperties(obj) {    for (let prop in properties(obj))        yield [prop, Object.getOwnPropertyDescriptor(obj, prop)];}function deprecated(alternative, fn) {    if (isObject(fn))        return Class.Property(iter(fn).map(function ([k, v]) [k, callable(v) ? deprecated(alternative, v) : v])                                      .toObject());    let name, func = callable(fn) ? fn : function () this[fn].apply(this, arguments);    function deprecatedMethod() {        let obj = !this                      ? "" :                  this.className             ? this.className + "#" :                  this.constructor.className ? this.constructor.className + "#" :                      "";        deprecated.warn(func, obj + (fn.name || name), alternative);        return func.apply(this, arguments);    }    return callable(fn) ? deprecatedMethod : Class.Property({        get: function () deprecatedMethod,        init: function (prop) { name = prop; }    });}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"        ]);    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));}/** * Iterates over all of the top-level, iterable property names of an * object. * * @param {object} obj The object to inspect. * @returns {Generator} */function keys(obj) iter(function keys() {    for (var k in obj)        if (hasOwnProperty.call(obj, k))            yield k;}());/** * Iterates over all of the top-level, iterable property values of an * object. * * @param {object} obj The object to inspect. * @returns {Generator} */function values(obj) iter(function values() {    if (isinstance(obj, ["Generator", "Iterator"]))        for (let k in obj)            yield k;    else        for (var k in obj)            if (hasOwnProperty.call(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));/** * 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) {    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 {object} set The set. * @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;});/** * Returns true if the given set contains the given key. * * @param {object} set The set. * @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));/** * 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;};/** * Removes an element from a set and returns true if the element was * previously contained. * * @param {object} set The set. * @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;});function set() {    deprecated.warn(set, "set", "Set");    return Set.apply(this, arguments);}Object.keys(Set).forEach(function (meth) {    set[meth] = function proxy() {        deprecated.warn(proxy, "set." + meth, "Set." + meth);        return Set[meth].apply(Set, arguments);    };});/** * Curries a function to the given number of arguments. Each * call of the resulting function returns a new function. When * a call does not contain enough arguments to satisfy the * required number, the resulting function is another curried * function with previous arguments accumulated. * *     function foo(a, b, c) [a, b, c].join(" "); *     curry(foo)(1, 2, 3) -> "1 2 3"; *     curry(foo)(4)(5, 6) -> "4 5 6"; *     curry(foo)(7)(8)(9) -> "7 8 9"; * * @param {function} fn The function to curry. * @param {integer} length The number of arguments expected. *     @default fn.length *     @optional * @param {object} self The 'this' value for the returned function. When *     omitted, the value of 'this' from the first call to the function is *     preserved. *     @optional */function curry(fn, length, self, acc) {    if (length == null)        length = fn.length;    if (length == 0)        return fn;    // Close over function with 'this'    function close(self, fn) function () fn.apply(self, Array.slice(arguments));    if (acc == null)        acc = [];    return function curried() {        let args = acc.concat(Array.slice(arguments));        // The curried result should preserve 'this'        if (arguments.length == 0)            return close(self || this, curried);        if (args.length >= length)            return fn.apply(self || this, args);        return curry(fn, length, 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));else    var bind = function bind(func, self) {        if (!callable(func))            func = self[func];        let args = Array.slice(arguments, bind.length);        return function bound() func.apply(self, args.concat(Array.slice(arguments)));    };/** * Returns true if both arguments are functions and * (targ() instanceof src) would also return true. * * @param {function} targ * @param {function} src * @returns {boolean} */function isSubclass(targ, src) {    return src === targ ||        targ && typeof targ === "function" && targ.prototype instanceof src;}/** * Returns true if *object* is an instance of *interfaces*. If *interfaces* is * an array, returns true if *object* is an instance of any element of * *interfaces*. If *interfaces* is the object form of a primitive type, * returns true if *object* is a non-boxed version of the type, i.e., if * (typeof object == "string"), isinstance(object, String) is true. Finally, if * *interfaces* is a string, returns true if ({}.toString.call(object) == * "[object <interfaces>]"). * * @param {object} object The object to check. * @param {constructor|[constructor|string]} interfaces The types to check *object* against. * @returns {boolean} */var isinstance_types = {    boolean: Boolean,    string: String,    function: Function,    number: Number};function isinstance(object, interfaces) {    if (object == null)        return false;    return Array.concat(interfaces).some(function isinstance_some(iface) {        if (typeof iface === "string") {            if (objproto.toString.call(object) === "[object " + iface + "]")                return true;        }        else if (typeof object === "object" && "isinstance" in object && object.isinstance !== isinstance) {            if (object.isinstance(iface))                return true;        }        else {            if (object instanceof iface)                return true;            var type = isinstance_types[typeof object];            if (type && isSubclass(iface, type))                return true;        }        return false;    });}/** * Returns true if obj is a non-null object. */function isObject(obj) typeof obj === "object" && obj != null || obj instanceof Ci.nsISupports;/** * Returns true if and only if its sole argument is an * instance of the builtin Array type. The array may come from * any window, frame, namespace, or execution context, which * 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]";/** * Returns true if and only if its sole argument is an * instance of the builtin Generator type. This includes * functions containing the 'yield' statement and generator * statements such as (x for (x in obj)). */function isGenerator(val) objproto.toString.call(val) == "[object Generator]";/** * Returns true if and only if its sole argument is a String, * as defined by the builtin type. May be constructed via * String(foo) or new String(foo) from any window, frame, * namespace, or execution context, which is not the case when * using (obj instanceof String) or (typeof obj == "string"). */function isString(val) objproto.toString.call(val) == "[object String]";/** * 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 call(fn) {    fn.apply(arguments[1], Array.slice(arguments, 2));    return fn;}/** * Memoizes an object property value. * * @param {object} obj The object to add the property to. * @param {string} key The property name. * @param {function} getter The function which will return the initial * value of the property. */function memoize(obj, key, getter) {    if (arguments.length == 1) {        let res = update(Object.create(obj), obj);        for each (let prop in Object.getOwnPropertyNames(obj)) {            let get = __lookupGetter__.call(obj, prop);            if (get)                memoize(res, prop, get);        }        return res;    }    try {        Object.defineProperty(obj, key, {            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))),            set: function s_replaceProperty(val)                Class.replaceProperty(this.instance || this, key, val)        });    }    catch (e) {        obj[key] = getter.call(obj, key);    }}let sandbox = Cu.Sandbox(this);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 * and setters are copied as expected. Moreover, any function * properties receive new 'supercall' and 'superapply' properties, * which will call the identically named function in target's * prototype. * *    let a = { foo: function (arg) "bar " + arg } *    let b = { __proto__: a } *    update(b, { foo: function foo() foo.supercall(this, "baz") }); * *    a.foo("foo") -> "bar foo" *    b.foo()      -> "bar baz" * * @param {Object} target The object to update. * @param {Object} src The source object from which to update target. *    May be provided multiple times. * @returns {Object} Returns its updated first argument. */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;            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 {                Object.defineProperty(target, k, desc);            }            catch (e) {}        });    }    return target;}/** * @constructor Class * * Constructs a new Class. Arguments marked as optional must be * either entirely elided, or they must have the exact type * specified. * * @param {string} name The class's as it will appear when toString *     is called, as well as in stack traces. *     @optional * @param {function} base The base class for this module. May be any *     callable object. *     @optional *     @default Class * @param {Object} prototype The prototype for instances of this *     object. The object itself is copied and not used as a prototype *     directly. * @param {Object} classProperties The class properties for the new *     module constructor. More than one may be provided. *     @optional * * @returns {function} The constructor for the resulting class. */function Class() {    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.config && (config.haveGecko("5.*", "6.0") || config.haveGecko("6.*"))) // Bug 657418.        var Constructor = function Constructor() {            var self = Object.create(Constructor.prototype);            self.instance = 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);                self.instance = self;                if ("_metaInit_" in self && self._metaInit_)                    self._metaInit_.apply(self, arguments);                var res = self.init.apply(self, arguments);                return res !== undefined ? res : self;            })]]>,            "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;    if ("init" in superclass.prototype)        Constructor.__proto__ = superclass;    else {        let superc = superclass;        superclass = function Shim() {};        Class.extend(superclass, superc, {            init: superc        });        superclass.__proto__ = superc;    }    Class.extend(Constructor, superclass, args[0]);    update(Constructor, args[1]);    Constructor.__proto__ = superclass;    args.slice(2).forEach(function (obj) {        if (callable(obj))            obj = obj.prototype;        update(Constructor.prototype, obj);    });    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 Class.Property * A class which, when assigned to a property in a Class's prototype * or class property object, defines that property's descriptor * rather than its value. If the desc object has an init property, it * will be called with the property's name before the descriptor is * assigned. * * @param {Object} desc The property descriptor. */Class.Property = function Property(desc) update(    Object.create(Property.prototype), desc || { configurable: true, writable: true });Class.Property.prototype.init = function () {};/** * Extends a subclass with a superclass. The subclass's * prototype is replaced with a new object, which inherits * from the superclass's prototype, {@see update}d with the * members of *overrides*. * * @param {function} subclass * @param {function} superclass * @param {Object} overrides @optional */Class.extend = function extend(subclass, superclass, overrides) {    subclass.superclass = superclass;    subclass.prototype = Object.create(superclass.prototype);    update(subclass.prototype, overrides);    subclass.prototype.constructor = subclass;    subclass.prototype._class_ = subclass;    if (superclass.prototype.constructor === objproto.constructor)        superclass.prototype.constructor = superclass;}/** * Memoizes the value of a class property to the value returned by * the passed function the first time the property is accessed. * * @param {function(string)} getter The function which returns the *      property's value. * @returns {Class.Property} */Class.Memoize = Class.Memoize = function Memoize(getter, wait)    Class.Property({        configurable: true,        enumerable: true,        init: function (key) {            let done = false;            if (wait)                this.get = function replace() {                    let obj = this.instance || this;                    Object.defineProperty(obj, key,  {                        configurable: true, enumerable: false,                        get: function get() {                            util.waitFor(function () done);                            return this[key];                        }                    });                    util.yieldable(function () {                        let wait;                        for (var res in getter.call(obj)) {                            if (wait !== undefined)                                yield wait;                            wait = res;                        }                        Class.replaceProperty(obj, key, res);                        done = true;                    })();                    return this[key];                };            else                this.get = function replace() {                    let obj = this.instance || this;                    Class.replaceProperty(obj, key, null);                    return Class.replaceProperty(obj, key, getter.call(this, key));                };            this.set = function replace(val) Class.replaceProperty(this.instance || this, val);        }    });/** * Updates the given object with the object in the target class's * prototype. */Class.Update = function Update(obj)    Class.Property({        configurable: true,        enumerable: true,        init: function (key, target) {            this.value = update({}, target[key], obj);        }    });Class.replaceProperty = function replaceProperty(obj, prop, value) {    Object.defineProperty(obj, prop, { configurable: true, enumerable: true, value: value, writable: true });    return value;};Class.toString = function toString() "[class " + this.className + "]";Class.prototype = {    /**     * Initializes new instances of this class. Called automatically     * when new instances are created.     */    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 {            return callback.call(self || this);        }        finally {            names.forEach(function (name, i) this[name] = vals[i], this);        }    },    toString: function C_toString() {        if (this.toStringParams)            var params = "(" + this.toStringParams.map(function (m) isArray(m)  ? "[" + m + "]" :                                                                    isString(m) ? m.quote() : String(m))                                   .join(", ") + ")";        return "[instance " + this.constructor.className + (params || "") + "]";    },    /**     * Executes *callback* after *timeout* milliseconds. The value of     * 'this' is preserved in the invocation of *callback*.     *     * @param {function} callback The function to call after *timeout*     * @param {number} timeout The time, in milliseconds, to wait     *     before calling *callback*.     * @returns {nsITimer} The timer which backs this timeout.     */    timeout: function timeout(callback, timeout) {        const self = this;        function timeout_notify(timer) {            if (self.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);    },    /**     * Updates this instance with the properties of the given objects.     * Like the update function, but with special semantics for     * 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) {                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));                    }                }                try {                    if ("value" in desc && (k in this.localizedProperties || k in this.magicalProperties))                        this[k] = desc.value;                    else                        Object.defineProperty(this, k, desc);                }                catch (e) {}            }, this);        }    },    magicalProperties: {}};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);            }        }        _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;};memoize(Class.prototype, "closure", Class.makeClosure);/** * A base class generator for classes which implement XPCOM interfaces. * * @param {nsIIID|[nsIJSIID]} interfaces The interfaces which the class *      implements. * @param {Class} superClass A super class. @optional * @returns {Class} */function XPCOM(interfaces, superClass) {    interfaces = Array.concat(interfaces);    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) }));    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)};function stub() null;/** * An abstract base class for classes that wish to inherit from Error. */var ErrorBase = Class("ErrorBase", Error, {    level: 2,    init: function EB_init(message, level) {        level = level || 0;        let error = Error(message);        update(this, error)        this.stack = error.stack;        this.message = message;        let frame = Components.stack;        for (let i = 0; i < this.level + level; i++) {            frame = frame.caller;            this.stack = this.stack.replace(/^.*\n/, "");        }        this.fileName = frame.filename;        this.lineNumber = frame.lineNumber;    },    toString: function () String(this.message)});/** * Constructs a new Module class and instantiates an instance into the current * module global object. * * @param {string} name The name of the instance. * @param {Object} prototype The instance prototype. * @param {Object} classProperties Properties to be applied to the class constructor. * @returns {Class} */function Module(name, prototype) {    try {        let init = callable(prototype) ? 4 : 3;        let proto = arguments[callable(prototype) ? 2 : 1];        proto._metaInit_ = function () {            delete module.prototype._metaInit_;            currentModule[name.toLowerCase()] = this;        };        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;    }    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) {        let args = arguments;        let locals = [];        for (let local = this.Local; local; local = local.super)            locals.push(local);        if (locals.length) {            let module = this, objs = {};            for (let i in locals) {                module = objs[i] = Object.create(module);                module.modules = modules;            }            module.isLocalModule = true;            modules.jsmodules[this.constructor.className] = module;            locals.reverse().forEach(function (fn, i) update(objs[i], fn.apply(module, args)))            memoize(module, "closure", Class.makeClosure);            module.instance = module;            module.init();            if (module.signals)                modules.dactyl.registerObservers(module);        }    }}/** * @class Struct * * Creates a new Struct constructor, used for creating objects with * a fixed set of named members. Each argument should be the name of * a member in the resulting objects. These names will correspond to * the arguments passed to the resultant constructor. Instances of * the new struct may be treated very much like arrays, and provide * many of the same methods. * *     const Point = Struct("x", "y", "z"); *     let p1 = Point(x, y, z); * * @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);    }    const Struct = Class(className || "Struct", StructBase, {        length: args.length,        members: array.toObject(args.map(function (v, k) [v, k]))    });    args.forEach(function (name, i) {        Struct.prototype.__defineGetter__(name, function () this[i]);        Struct.prototype.__defineSetter__(name, function (val) { this[i] = val; });    });    return Struct;}let StructBase = Class("StructBase", Array, {    init: function struct_init() {        for (let i = 0; i < arguments.length; i++)            if (arguments[i] != undefined)                this[i] = arguments[i];    },    clone: function struct_clone() this.constructor.apply(null, this.slice()),    closure: Class.Property(Object.getOwnPropertyDescriptor(Class.prototype, "closure")),    get: function struct_get(key, val) this[this.members[key]],    set: function struct_set(key, val) this[this.members[key]] = val,    toString: function struct_toString() Class.prototype.toString.apply(this, arguments),    // Iterator over our named members    __iterator__: function struct__iterator__() {        let self = this;        return ([k, self[k]] for (k in keys(self.members)))    }}, {    fromArray: function fromArray(ary) {        if (!(ary instanceof this))            ary.__proto__ = this.prototype;        return ary;    },    /**     * Sets a lazily constructed default value for a member of     * the struct. The value is constructed once, the first time     * it is accessed and memoized thereafter.     *     * @param {string} key The name of the member for which to     *     provide the default value.     * @param {function} val The function which is to generate     *     the default value.     */    defaultValue: function defaultValue(key, val) {        let i = this.prototype.members[key];        this.prototype.__defineGetter__(i, function () (this[i] = val.call(this)));        this.prototype.__defineSetter__(i, function (value)            Class.replaceProperty(this, i, value));        return this;    },    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));        return this;    }});var Timer = Class("Timer", {    init: function init(minInterval, maxInterval, callback, self) {        this._timer = services.Timer();        this.callback = callback;        this.self = self || this;        this.minInterval = minInterval;        this.maxInterval = maxInterval;        this.doneAt = 0;        this.latest = 0;    },    notify: function notify(timer, force) {        try {            if (!loaded || loaded.util && util.rehashing || typeof util === "undefined" || !force && this.doneAt == 0)                return;            this._timer.cancel();            this.latest = 0;            // minInterval is the time between the completion of the command and the next firing            this.doneAt = Date.now() + this.minInterval;            this.callback.call(this.self, this.arg);        }        catch (e) {            if (typeof util === "undefined")                dump(JSMLoader.name + ": " + e + "\n" + (e.stack || Error().stack));            else                util.reportError(e);        }        finally {            this.doneAt = Date.now() + this.minInterval;        }    },    tell: function tell(arg) {        if (arguments.length > 0)            this.arg = arg;        let now = Date.now();        if (this.doneAt == -1)            this._timer.cancel();        let timeout = this.minInterval;        if (now > this.doneAt && this.doneAt > -1)            timeout = 0;        else if (this.latest)            timeout = Math.min(timeout, this.latest - now);        else            this.latest = now + this.maxInterval;        this._timer.initWithCallback(this, Math.max(timeout, 0), this._timer.TYPE_ONE_SHOT);        this.doneAt = -1;    },    reset: function reset() {        this._timer.cancel();        this.doneAt = 0;    },    flush: function flush(force) {        if (this.doneAt == -1 || force)            this.notify(null, true);    }});/** * Idempotent function which returns the UTF-8 encoded value of an * improperly-decoded string. * * @param {string} str * @returns {string} */function UTF8(str) {    try {        return decodeURIComponent(escape(str));    }    catch (e) {        return str;    }}function octal(decimal) parseInt(decimal, 8);/** * Iterates over an arbitrary object. The following iterator types are * supported, and work as a user would expect: * *  • nsIDOMNodeIterator *  • mozIStorageStatement * * Additionally, the following array-like objects yield a tuple of the * form [index, element] for each contained element: * *  • nsIDOMHTMLCollection *  • nsIDOMNodeList * * and the following likewise yield one element of the form * [name, element] for each contained element: * *  • nsIDOMNamedNodeMap * * Duck typing is implemented for any other type. If the object * contains the "enumerator" property, iter is called on that. If the * property is a function, it is called first. If it contains the * property "getNext" along with either "hasMoreItems" or "hasMore", it * is iterated over appropriately. * * For all other cases, this function behaves exactly like the Iterator * function. * * @param {object} obj * @param {nsIJSIID} iface The interface to which to query all elements. * @returns {Generator} */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);    if (args.length > 1)        res = (function () {            for (let i = 0; i < args.length; i++)                for (let j in iter(args[i]))                    yield j;        })();    else if (isinstance(obj, ["Iterator", "Generator"]))        ;    else if (ctypes && ctypes.CData && obj instanceof ctypes.CData) {        while (obj.constructor instanceof ctypes.PointerType)            obj = obj.contents;        if (obj.constructor instanceof ctypes.ArrayType)            res = array.iterItems(obj);        else if (obj.constructor instanceof ctypes.StructType)            res = (function () {                for (let prop in values(obj.constructor.fields))                    yield let ([name, type] = Iterator(prop).next()) [name, obj[name]];            })();        else            return iter({});    }    else if (isinstance(obj, [Ci.nsIDOMHTMLCollection, Ci.nsIDOMNodeList]))        res = array.iterItems(obj);    else if (obj instanceof Ci.nsIDOMNamedNodeMap)        res = (function () {            for (let i = 0; i < obj.length; i++)                yield [obj.name, obj];        })();    else if (obj instanceof Ci.mozIStorageStatement)        res = (function (obj) {            while (obj.executeStep())                yield obj.row;            obj.reset();        })(obj);    else if ("getNext" in obj) {        if ("hasMoreElements" in obj)            res = (function () {                while (obj.hasMoreElements())                    yield obj.getNext();            })();        else if ("hasMore" in obj)            res = (function () {                while (obj.hasMore())                    yield obj.getNext();            })();    }    else if ("enumerator" in obj) {        if (callable(obj.enumerator))            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;}update(iter, {    toArray: function toArray(iter) array(iter).array,    // See array.prototype for API docs.    toObject: function toObject(iter) {        let obj = {};        for (let [k, v] in iter)            if (v instanceof Class.Property)                Object.defineProperty(obj, k, v.init(k, obj) || v);            else                obj[k] = v;        return obj;    },    compact: function compact(iter) (item for (item in iter) if (item != null)),    every: function every(iter, pred, self) {        pred = pred || util.identity;        for (let elem in 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)            if (pred.call(self, elem))                return true;        return false;    },    filter: function filter(iter, pred, self) {        for (let elem in iter)            if (pred.call(self, elem))                yield elem;    },    /**     * Iterates over an iterable object and calls a callback for each     * element.     *     * @param {object} iter The iterator.     * @param {function} fn The callback.     * @param {object} self The this object for *fn*.     */    forEach: function forEach(iter, func, self) {        for (let val in iter)            func.call(self, val);    },    indexOf: function indexOf(iter, elem) {        let i = 0;        for (let item in iter) {            if (item == elem)                return i;            i++;        }    },    /**     * Returns the array that results from applying *func* to each property of     * *obj*.     *     * @param {Object} obj     * @param {function} func     * @returns {Array}     */    map: function map(iter, func, self) {        for (let i in iter)            yield func.call(self, i);    },    /**     * Returns the nth member of the given array that matches the     * given predicate.     */    nth: function nth(iter, pred, n, self) {        if (typeof pred === "number")            [pred, n] = [function () true, pred]; // Hack.        for (let elem in iter)            if (pred.call(self, elem) && n-- === 0)                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))                yield item;    },    /**     * Zips the contents of two arrays. The resulting array is the length of     * ary1, with any shortcomings of ary2 replaced with null strings.     *     * @param {Array} ary1     * @param {Array} ary2     * @returns {Array}     */    zip: function zip(iter1, iter2) {        try {            yield [iter1.next(), iter2.next()];        }        catch (e if e instanceof StopIteration) {}    }});/** * Array utility methods. */var array = Class("array", Array, {    init: function (ary) {        if (isinstance(ary, ["Iterator", "Generator"]) || "__iterator__" in ary)            ary = [k for (k in ary)];        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 () this.__noSuchMethod__("concat", Array.slice(arguments)),            filter: function () this.__noSuchMethod__("filter", Array.slice(arguments)),            map: function () this.__noSuchMethod__("map", Array.slice(arguments))        };    }}, {    /**     * Converts an array to an object. As in lisp, an assoc is an     * array of key-value pairs, which maps directly to an object,     * as such:     *    [["a", "b"], ["c", "d"]] -> { a: "b", c: "d" }     *     * @param {[Array]} assoc     * @... {string} 0 - Key     * @...          1 - Value     */    toObject: function toObject(assoc) {        let obj = {};        assoc.forEach(function ([k, v]) {            if (v instanceof Class.Property)                Object.defineProperty(obj, k, v.init(k, obj) || v);            else                obj[k] = v;        });        return obj;    },    /**     * Compacts an array, removing all elements that are null or undefined:     *    ["foo", null, "bar", undefined] -> ["foo", "bar"]     *     * @param {Array} ary     * @returns {Array}     */    compact: function compact(ary) ary.filter(function (item) item != null),    /**     * Returns true if each element of ary1 is equal to the     * corresponding element in ary2.     *     * @param {Array} ary1     * @param {Array} ary2     * @returns {boolean}     */    equals: function (ary1, ary2)        ary1.length === ary2.length && Array.every(ary1, function (e, i) e === ary2[i]),    /**     * Flattens an array, such that all elements of the array are     * joined into a single array:     *    [["foo", ["bar"]], ["baz"], "quux"] -> ["foo", ["bar"], "baz", "quux"]     *     * @param {Array} ary     * @returns {Array}     */    flatten: function flatten(ary) ary.length ? Array.prototype.concat.apply([], ary) : [],    /**     * Returns an Iterator for an array's values.     *     * @param {Array} ary     * @returns {Iterator(Object)}     */    iterValues: function iterValues(ary) {        for (let i = 0; i < ary.length; i++)            yield ary[i];    },    /**     * Returns an Iterator for an array's indices and values.     *     * @param {Array} ary     * @returns {Iterator([{number}, {Object}])}     */    iterItems: function iterItems(ary) {        let length = ary.length;        for (let i = 0; i < length; i++)            yield [i, ary[i]];    },    /**     * Returns the nth member of the given array that matches the     * given predicate.     */    nth: function nth(ary, pred, n, self) {        for (let elem in values(ary))            if (pred.call(self, elem) && n-- === 0)                return elem;        return undefined;    },    /**     * Filters out all duplicates from an array. If *unsorted* is false, the     * array is sorted before duplicates are removed.     *     * @param {Array} ary     * @param {boolean} unsorted     * @returns {Array}     */    uniq: function uniq(ary, unsorted) {        let res = [];        if (unsorted) {            for (let item in values(ary))                if (res.indexOf(item) == -1)                    res.push(item);        }        else {            for (let [, item] in Iterator(ary.sort())) {                if (item != last || !res.length)                    res.push(item);                var last = item;            }        }        return res;    },    /**     * Zips the contents of two arrays. The resulting array is the length of     * ary1, with any shortcomings of ary2 replaced with null strings.     *     * @param {Array} ary1     * @param {Array} ary2     * @returns {Array}     */    zip: function zip(ary1, ary2) {        let res = [];        for (let [i, item] in Iterator(ary1))            res.push([item, i in ary2 ? ary2[i] : ""]);        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: