mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 21:28:00 +01:00
Document some crap.
This commit is contained in:
@@ -134,18 +134,41 @@ function isobject(obj) {
|
|||||||
return typeof obj === "object" && obj != null;
|
return typeof obj === "object" && obj != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isarray(obj) {
|
/**
|
||||||
return Object.prototype.toString.call(obj) == "[object Array]";
|
* 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).
|
||||||
|
*/
|
||||||
|
function isarray(val) {
|
||||||
|
return Object.prototype.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) {
|
function isgenerator(val) {
|
||||||
return Object.prototype.toString.call(val) == "[object Generator]";
|
return Object.prototype.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) {
|
function isstring(val) {
|
||||||
return typeof val === "string" || val instanceof String;
|
return Object.prototype.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) {
|
function callable(val) {
|
||||||
return typeof val === "function";
|
return typeof val === "function";
|
||||||
}
|
}
|
||||||
@@ -155,7 +178,28 @@ function call(fn) {
|
|||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
function curry(fn, length, acc) {
|
/**
|
||||||
|
* 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)(4)(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)
|
if (length == null)
|
||||||
length = fn.length;
|
length = fn.length;
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
@@ -164,7 +208,6 @@ function curry(fn, length, acc) {
|
|||||||
/* Close over function with 'this' */
|
/* Close over function with 'this' */
|
||||||
function close(self, fn) function () fn.apply(self, Array.slice(arguments));
|
function close(self, fn) function () fn.apply(self, Array.slice(arguments));
|
||||||
|
|
||||||
let first = (arguments.length < 3);
|
|
||||||
if (acc == null)
|
if (acc == null)
|
||||||
acc = [];
|
acc = [];
|
||||||
|
|
||||||
@@ -173,18 +216,35 @@ function curry(fn, length, acc) {
|
|||||||
|
|
||||||
/* The curried result should preserve 'this' */
|
/* The curried result should preserve 'this' */
|
||||||
if (arguments.length == 0)
|
if (arguments.length == 0)
|
||||||
return close(this, arguments.callee);
|
return close(self || this, arguments.callee);
|
||||||
|
|
||||||
if (args.length >= length)
|
if (args.length >= length)
|
||||||
return fn.apply(this, args);
|
return fn.apply(self || this, args);
|
||||||
|
|
||||||
if (first)
|
return curry(fn, length, self || this, args);
|
||||||
fn = close(this, fn);
|
|
||||||
return curry(fn, length, args);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(targ) {
|
/**
|
||||||
|
* 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 () arguments.callee.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++) {
|
for (let i=1; i < arguments.length; i++) {
|
||||||
let src = arguments[i];
|
let src = arguments[i];
|
||||||
foreach(keys(src || {}), function(k) {
|
foreach(keys(src || {}), function(k) {
|
||||||
@@ -192,10 +252,10 @@ function update(targ) {
|
|||||||
set = src.__lookupSetter__(k);
|
set = src.__lookupSetter__(k);
|
||||||
if (!get && !set) {
|
if (!get && !set) {
|
||||||
var v = src[k];
|
var v = src[k];
|
||||||
targ[k] = v;
|
target[k] = v;
|
||||||
if (targ.__proto__ && callable(v)) {
|
if (target.__proto__ && callable(v)) {
|
||||||
v.superapply = function(self, args) {
|
v.superapply = function(self, args) {
|
||||||
return targ.__proto__[k].apply(self, args);
|
return target.__proto__[k].apply(self, args);
|
||||||
}
|
}
|
||||||
v.supercall = function(self) {
|
v.supercall = function(self) {
|
||||||
return v.superapply(self, Array.slice(arguments, 1));
|
return v.superapply(self, Array.slice(arguments, 1));
|
||||||
@@ -203,28 +263,64 @@ function update(targ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (get)
|
if (get)
|
||||||
targ.__defineGetter__(k, get);
|
target.__defineGetter__(k, get);
|
||||||
if (set)
|
if (set)
|
||||||
targ.__defineSetter__(k, set);
|
target.__defineSetter__(k, set);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return targ;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extend(subc, superc, overrides) {
|
/**
|
||||||
subc.prototype = {};
|
* Extends a subclass with a superclass. The subclass's
|
||||||
update(subc.prototype, overrides);
|
* prototype is replaced with a new object, which inherits
|
||||||
// This is unduly expensive.
|
* from the super class's prototype, {@see update}d with the
|
||||||
subc.prototype.__proto__ = superc.prototype;
|
* members of 'overrides'.
|
||||||
|
*
|
||||||
|
* @param {function} subclass
|
||||||
|
* @param {function} superclass
|
||||||
|
* @param {Object} overrides @optional
|
||||||
|
*/
|
||||||
|
function extend(subclass, superclass, overrides) {
|
||||||
|
subclass.prototype = {};
|
||||||
|
update(subclass.prototype, overrides);
|
||||||
|
// This is unduly expensive. Unfortunately necessary since
|
||||||
|
// we apparently can't rely on the presence of the
|
||||||
|
// debugger to enumerate properties when we have
|
||||||
|
// __iterators__ attached to prototypes.
|
||||||
|
subclass.prototype.__proto__ = superclass.prototype;
|
||||||
|
|
||||||
subc.superclass = superc.prototype;
|
subclass.superclass = superclass.prototype;
|
||||||
subc.prototype.constructor = subc;
|
subclass.prototype.constructor = subclass;
|
||||||
subc.prototype.__class__ = subc;
|
subclass.prototype.__class__ = subclass;
|
||||||
|
|
||||||
if (superc.prototype.constructor === Object.prototype.constructor)
|
if (superclass.prototype.constructor === Object.prototype.constructor)
|
||||||
superc.prototype.constructor = superc;
|
superclass.prototype.constructor = superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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() {
|
function Class() {
|
||||||
function constructor() {
|
function constructor() {
|
||||||
let self = {
|
let self = {
|
||||||
@@ -274,10 +370,24 @@ function Class() {
|
|||||||
}
|
}
|
||||||
Class.toString = function () "[class " + this.constructor.name + "]",
|
Class.toString = function () "[class " + this.constructor.name + "]",
|
||||||
Class.prototype = {
|
Class.prototype = {
|
||||||
|
/**
|
||||||
|
* Initializes new instances of this class. Called automatically
|
||||||
|
* when new instances are created.
|
||||||
|
*/
|
||||||
init: function() {},
|
init: function() {},
|
||||||
|
|
||||||
toString: function () "[instance " + this.constructor.name + "]",
|
toString: function () "[instance " + this.constructor.name + "]",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exactly like {@see nsIDOMWindow#setTimeout}, except that it
|
||||||
|
* preserves the value of 'this' on invocation of 'callback'.
|
||||||
|
*
|
||||||
|
* @param {function} callback The function to call after 'timeout'
|
||||||
|
* @param {number} timeout The timeout, in seconds, to wait
|
||||||
|
* before calling 'callback'.
|
||||||
|
* @returns {integer} The ID of this timeout, to be passed to
|
||||||
|
* {@see nsIDOMWindow#clearTimeout}.
|
||||||
|
*/
|
||||||
setTimeout: function (callback, timeout) {
|
setTimeout: function (callback, timeout) {
|
||||||
const self = this;
|
const self = this;
|
||||||
function target() callback.call(self);
|
function target() callback.call(self);
|
||||||
@@ -285,9 +395,24 @@ Class.prototype = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 vary 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.
|
||||||
|
*/
|
||||||
const Struct = Class("Struct", {
|
const Struct = Class("Struct", {
|
||||||
init: function () {
|
init: function () {
|
||||||
let args = Array.slice(arguments);
|
let args = this._args = Array.slice(arguments);
|
||||||
this.__defineGetter__("length", function () args.length);
|
this.__defineGetter__("length", function () args.length);
|
||||||
this.__defineGetter__("members", function () args.slice());
|
this.__defineGetter__("members", function () args.slice());
|
||||||
for (let arg in Iterator(args)) {
|
for (let arg in Iterator(args)) {
|
||||||
@@ -305,6 +430,16 @@ const Struct = Class("Struct", {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
Struct.prototype = this;
|
Struct.prototype = this;
|
||||||
|
/**
|
||||||
|
* Sets a lazily constructed default value for a member of
|
||||||
|
* the struct. The value is constructed once, the first time
|
||||||
|
* it is accesed 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.
|
||||||
|
*/
|
||||||
Struct.defaultValue = function (key, val) {
|
Struct.defaultValue = function (key, val) {
|
||||||
let i = args.indexOf(key);
|
let i = args.indexOf(key);
|
||||||
Struct.prototype.__defineGetter__(i, function () (this[i] = val.call(this), this[i])); // Kludge for FF 3.0
|
Struct.prototype.__defineGetter__(i, function () (this[i] = val.call(this), this[i])); // Kludge for FF 3.0
|
||||||
|
|||||||
@@ -3,12 +3,60 @@
|
|||||||
// This work is licensed for reuse under an MIT license. Details are
|
// This work is licensed for reuse under an MIT license. Details are
|
||||||
// given in the LICENSE.txt file included with this file.
|
// given in the LICENSE.txt file included with this file.
|
||||||
|
|
||||||
const ModuleBase = Class("ModuleBase", { requires: [] });
|
/**
|
||||||
function Module(name, inst, clas, moduleInit) {
|
* @class ModuleBase
|
||||||
|
* The base class for all modules.
|
||||||
|
*/
|
||||||
|
const ModuleBase = Class("ModuleBase", {
|
||||||
|
/**
|
||||||
|
* @property {[string]} A list of module prerequisites which
|
||||||
|
* must be initialized before this module is loaded.
|
||||||
|
*/
|
||||||
|
requires: [],
|
||||||
|
|
||||||
|
toString: function () "[module " + this.constructor.name + "]",
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor Module
|
||||||
|
*
|
||||||
|
* Constructs a new ModuleBase class and makes arrangements for its
|
||||||
|
* initialization. Arguments marked as optional must be either
|
||||||
|
* entirely elided, or they must have the exact type specified.
|
||||||
|
* Loading semantics are as follows:
|
||||||
|
*
|
||||||
|
* - A module is garunteed not to be initialized before any of its
|
||||||
|
* prerequisites as listed in its {@see ModuleBase#requires} member.
|
||||||
|
* - A module is considered initialized once its been instantiated,
|
||||||
|
* it's {@see Class#init} method has been called, and its
|
||||||
|
* instance has been installed into the top-level {@see modules}
|
||||||
|
* object.
|
||||||
|
* - Once the module has been initialized, its module-dependent
|
||||||
|
* initialization functions will be called as described hereafter.
|
||||||
|
* @param {string} name The module's name as it will appear in the
|
||||||
|
* top-level {@see modules} object.
|
||||||
|
* @param {ModuleBase} base The base class for this module.
|
||||||
|
* @optional
|
||||||
|
* @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.
|
||||||
|
* @optional
|
||||||
|
* @param {Object} moduleInit The module initialization functions
|
||||||
|
* for the new module. Each function is called as soon as the
|
||||||
|
* named module has been initialized, but after the module
|
||||||
|
* itself. The constructors are garunteed to be called in the
|
||||||
|
* same order that the dependent modules were initialized.
|
||||||
|
* @optional
|
||||||
|
*
|
||||||
|
* @returns {function} The constructor for the resulting module.
|
||||||
|
*/
|
||||||
|
function Module(name, prototype, classProperties, moduleInit) {
|
||||||
var base = ModuleBase;
|
var base = ModuleBase;
|
||||||
if (callable(inst))
|
if (callable(prototype))
|
||||||
base = Array.splice(arguments, 1, 1)[0]
|
base = Array.splice(arguments, 1, 1)[0]
|
||||||
const module = Class(name, base, inst, clas);
|
const module = Class(name, base, prototype, classProperties);
|
||||||
module.INIT = moduleInit || {};
|
module.INIT = moduleInit || {};
|
||||||
module.requires = inst.requires || [];
|
module.requires = inst.requires || [];
|
||||||
Module.list.push(module);
|
Module.list.push(module);
|
||||||
|
|||||||
Reference in New Issue
Block a user