X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fmodules%2Fbase.jsm;h=d07ba1230732b78e0f69eb944b84e8017c91f3fc;hb=70740024f9c028c1fd63e1a1850ab062ff956054;hp=13bd9a03e93fcd3b88a5400ba38061e5b25bf08a;hpb=eeed0be1a8abf7e3c97f43b63c1d595e940fef21;p=dactyl.git diff --git a/common/modules/base.jsm b/common/modules/base.jsm index 13bd9a0..d07ba12 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -37,65 +37,83 @@ if (!Object.create) }; if (!Object.defineProperty) Object.defineProperty = function defineProperty(obj, prop, desc) { - let value = desc.value; - if ("value" in desc) - if (desc.writable && !__lookupGetter__.call(obj, prop) - && !__lookupSetter__.call(obj, prop)) - try { - obj[prop] = value; + 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; }); } - 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; }); - } - if ("get" in desc) - objproto.__defineGetter__.call(obj, prop, desc.get); - if ("set" in desc) - objproto.__defineSetter__.call(obj, prop, desc.set); + 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 undefined; - 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; + if (hasOwnProperty.call(obj, prop)) + return Object.getPropertyDescriptor(obj, prop); }; if (!Object.getOwnPropertyNames) Object.getOwnPropertyNames = function getOwnPropertyNames(obj, _debugger) { - // This is an ugly and unfortunately necessary hack. - if (hasOwnProperty.call(obj, "__iterator__")) { - var oldIter = obj.__iterator__; - delete obj.__iterator__; + 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; } - let res = [k for (k in obj) if (hasOwnProperty.call(obj, k))]; - if (oldIter !== undefined) { - obj.__iterator__ = oldIter; - res.push("__iterator__"); + catch (e) { + throw e.stack ? e : Error(e); } - return res; }; if (!Object.getPrototypeOf) Object.getPrototypeOf = function getPrototypeOf(obj) obj.__proto__; @@ -127,6 +145,7 @@ function defineModule(name, params, module) { use[mod].push(module); } currentModule = module; + module.startTime = Date.now(); } defineModule.loadLog = []; @@ -148,7 +167,6 @@ defineModule.dump = function dump_() { .replace(/^./gm, name + ": $&")); } defineModule.modules = []; -defineModule.times = { all: 0 }; defineModule.time = function time(major, minor, func, self) { let time = Date.now(); if (typeof func !== "function") @@ -161,13 +179,7 @@ defineModule.time = function time(major, minor, func, self) { loaded.util && util.reportError(e); } - let delta = Date.now() - time; - defineModule.times.all += delta; - defineModule.times[major] = (defineModule.times[major] || 0) + delta; - if (minor) { - defineModule.times[":" + minor] = (defineModule.times[":" + minor] || 0) + delta; - defineModule.times[major + ":" + minor] = (defineModule.times[major + ":" + minor] || 0) + delta; - } + JSMLoader.times.add(major, minor, Date.now() - time); return res; } @@ -185,8 +197,10 @@ function require(obj, name, from) { if (arguments.length === 1) [obj, name] = [{}, obj]; + let caller = Components.stack.caller; + if (!loaded[name]) - defineModule.loadLog.push((from || "require") + ": loading " + name + (obj.NAME ? " into " + obj.NAME : "")); + defineModule.loadLog.push((from || "require") + ": loading " + name + " into " + (obj.NAME || caller.filename + ":" + caller.lineNumber)); JSMLoader.load(name + ".jsm", obj); return obj; @@ -196,7 +210,7 @@ function require(obj, name, from) { if (loaded.util) util.reportError(e); else - defineModule.dump(" " + (e.filename || e.fileName) + ":" + e.lineNumber + ": " + e +"\n"); + defineModule.dump(" " + (e.filename || e.fileName) + ":" + e.lineNumber + ": " + e + "\n"); } } @@ -204,10 +218,10 @@ 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", - "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMUtils", "XPCSafeJSObjectWrapper", + "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", + "isString", "isSubclass", "iter", "iterAll", "iterOwnProperties", "keys", "memoize", "octal", "properties", "require", "set", "update", "values", "withCallerGlobal" ], use: ["config", "services", "util"] @@ -259,7 +273,7 @@ function properties(obj, prototypes, debugger_) { 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 && !Set.add(seen, key)) yield key; } catch (e) {} @@ -274,7 +288,7 @@ function properties(obj, prototypes, debugger_) { iter = (prop.name.stringValue for (prop in values(debuggerProperties(obj)))); for (let key in iter) - if (!prototypes || !set.add(seen, key) && obj != orig) + if (!prototypes || !Set.add(seen, key) && obj != orig) yield key; } } @@ -292,7 +306,8 @@ function deprecated(alternative, fn) { let name, func = callable(fn) ? fn : function () this[fn].apply(this, arguments); function deprecatedMethod() { - let obj = this.className ? this.className + "#" : + let obj = !this ? "" : + this.className ? this.className + "#" : this.constructor.className ? this.constructor.className + "#" : ""; @@ -307,17 +322,16 @@ function deprecated(alternative, fn) { } deprecated.warn = function warn(func, name, alternative, frame) { if (!func.seenCaller) - func.seenCaller = set([ + 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 + ": " + - name + " is deprecated: Please use " + alternative + " instead"); + if (!Set.add(func.seenCaller, filename)) + util.dactyl(func).warn([util.urlPath(filename), frame.lineNumber, " "].join(":") + + require("messages")._("warn.deprecated", name, alternative)); } /** @@ -359,7 +373,7 @@ var iterAll = deprecated("iter", function iterAll() iter.apply(null, arguments)) * @param {[string]} ary @optional * @returns {object} */ -function set(ary) { +function Set(ary) { let obj = {}; if (ary) for (let val in values(ary)) @@ -374,7 +388,7 @@ function set(ary) { * @param {string} key The key to add. * @returns boolean */ -set.add = curry(function set_add(set, key) { +Set.add = curry(function set_add(set, key) { let res = this.has(set, key); set[key] = true; return res; @@ -386,7 +400,7 @@ set.add = curry(function set_add(set, key) { * @param {string} key The key to check. * @returns {boolean} */ -set.has = curry(function set_has(set, key) hasOwnProperty.call(set, key) && +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 @@ -395,7 +409,7 @@ set.has = curry(function set_has(set, key) hasOwnProperty.call(set, key) && * @param {object} set The set. * @returns {object} */ -set.subtract = function set_subtract(set) { +Set.subtract = function set_subtract(set) { set = update({}, set); for (let i = 1; i < arguments.length; i++) for (let k in keys(arguments[i])) @@ -410,12 +424,23 @@ set.subtract = function set_subtract(set) { * @param {string} key The key to remove. * @returns boolean */ -set.remove = curry(function set_remove(set, key) { +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 @@ -464,9 +489,13 @@ function curry(fn, length, self, acc) { } if (curry.bind) - var bind = function bind(func) func.bind.apply(func, Array.slice(arguments, bind.length)); + 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))); }; @@ -582,7 +611,7 @@ function call(fn) { */ function memoize(obj, key, getter) { if (arguments.length == 1) { - obj = update({}, obj); + obj = update({ __proto__: obj.__proto__ }, obj); for (let prop in Object.getOwnPropertyNames(obj)) { let get = __lookupGetter__.call(obj, prop); if (get) @@ -591,17 +620,22 @@ function memoize(obj, key, getter) { return obj; } - Object.defineProperty(obj, key, { - configurable: true, - enumerable: true, + 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))), + 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) - }); + 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); @@ -648,12 +682,14 @@ function update(target) { if (typeof desc.value === "function" && target.__proto__) { let func = desc.value.wrapped || desc.value; - 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)); + 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); @@ -696,18 +732,28 @@ function Class() { if (callable(args[0])) superclass = args.shift(); - var Constructor = eval(String.replace(, - "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_"))); + }; + else + var Constructor = eval(String.replace(, + "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; @@ -735,19 +781,19 @@ function Class() { } if (Cu.getGlobalForObject) - Class.objectGlobal = function (caller) { + Class.objectGlobal = function (object) { try { - return Cu.getGlobalForObject(caller); + return Cu.getGlobalForObject(object); } catch (e) { return null; } }; else - Class.objectGlobal = function (caller) { - while (caller.__parent__) - caller = caller.__parent__; - return caller; + Class.objectGlobal = function (object) { + while (object.__parent__) + object = object.__parent__; + return object; }; /** @@ -791,7 +837,7 @@ Class.extend = function extend(subclass, superclass, overrides) { * * @param {function(string)} getter The function which returns the * property's value. - * @return {Class.Property} + * @returns {Class.Property} */ Class.memoize = function memoize(getter, wait) Class.Property({ @@ -883,7 +929,48 @@ Class.prototype = { 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; @@ -946,7 +1033,9 @@ var ErrorBase = Class("ErrorBase", Error, { level: 2, init: function EB_init(message, level) { level = level || 0; - update(this, Error(message)) + let error = Error(message); + update(this, error) + this.stack = error.stack; this.message = message; let frame = Components.stack; @@ -956,7 +1045,8 @@ var ErrorBase = Class("ErrorBase", Error, { } this.fileName = frame.filename; this.lineNumber = frame.lineNumber; - } + }, + toString: function () String(this.message) }); /** @@ -1368,7 +1458,7 @@ update(iter, { uniq: function uniq(iter) { let seen = {}; for (let item in iter) - if (!set.add(seen, item)) + if (!Set.add(seen, item)) yield item; }, @@ -1423,7 +1513,7 @@ var array = Class("array", Array, { * as such: * [["a", "b"], ["c", "d"]] -> { a: "b", c: "d" } * - * @param {Array[]} assoc + * @param {[Array]} assoc * @... {string} 0 - Key * @... 1 - Value */