mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 23:37:59 +01:00
Document some crap.
This commit is contained in:
@@ -134,18 +134,41 @@ function isobject(obj) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
return typeof val === "function";
|
||||
}
|
||||
@@ -155,7 +178,28 @@ function call(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)
|
||||
length = fn.length;
|
||||
if (length == 0)
|
||||
@@ -164,7 +208,6 @@ function curry(fn, length, acc) {
|
||||
/* Close over function with 'this' */
|
||||
function close(self, fn) function () fn.apply(self, Array.slice(arguments));
|
||||
|
||||
let first = (arguments.length < 3);
|
||||
if (acc == null)
|
||||
acc = [];
|
||||
|
||||
@@ -173,18 +216,35 @@ function curry(fn, length, acc) {
|
||||
|
||||
/* The curried result should preserve 'this' */
|
||||
if (arguments.length == 0)
|
||||
return close(this, arguments.callee);
|
||||
return close(self || this, arguments.callee);
|
||||
|
||||
if (args.length >= length)
|
||||
return fn.apply(this, args);
|
||||
return fn.apply(self || this, args);
|
||||
|
||||
if (first)
|
||||
fn = close(this, fn);
|
||||
return curry(fn, length, args);
|
||||
return curry(fn, length, self || this, 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++) {
|
||||
let src = arguments[i];
|
||||
foreach(keys(src || {}), function(k) {
|
||||
@@ -192,10 +252,10 @@ function update(targ) {
|
||||
set = src.__lookupSetter__(k);
|
||||
if (!get && !set) {
|
||||
var v = src[k];
|
||||
targ[k] = v;
|
||||
if (targ.__proto__ && callable(v)) {
|
||||
target[k] = v;
|
||||
if (target.__proto__ && callable(v)) {
|
||||
v.superapply = function(self, args) {
|
||||
return targ.__proto__[k].apply(self, args);
|
||||
return target.__proto__[k].apply(self, args);
|
||||
}
|
||||
v.supercall = function(self) {
|
||||
return v.superapply(self, Array.slice(arguments, 1));
|
||||
@@ -203,28 +263,64 @@ function update(targ) {
|
||||
}
|
||||
}
|
||||
if (get)
|
||||
targ.__defineGetter__(k, get);
|
||||
target.__defineGetter__(k, get);
|
||||
if (set)
|
||||
targ.__defineSetter__(k, set);
|
||||
target.__defineSetter__(k, set);
|
||||
});
|
||||
}
|
||||
return targ;
|
||||
return target;
|
||||
}
|
||||
|
||||
function extend(subc, superc, overrides) {
|
||||
subc.prototype = {};
|
||||
update(subc.prototype, overrides);
|
||||
// This is unduly expensive.
|
||||
subc.prototype.__proto__ = superc.prototype;
|
||||
/**
|
||||
* Extends a subclass with a superclass. The subclass's
|
||||
* prototype is replaced with a new object, which inherits
|
||||
* from the super class's prototype, {@see update}d with the
|
||||
* 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;
|
||||
subc.prototype.constructor = subc;
|
||||
subc.prototype.__class__ = subc;
|
||||
subclass.superclass = superclass.prototype;
|
||||
subclass.prototype.constructor = subclass;
|
||||
subclass.prototype.__class__ = subclass;
|
||||
|
||||
if (superc.prototype.constructor === Object.prototype.constructor)
|
||||
superc.prototype.constructor = superc;
|
||||
if (superclass.prototype.constructor === Object.prototype.constructor)
|
||||
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 constructor() {
|
||||
let self = {
|
||||
@@ -274,10 +370,24 @@ function Class() {
|
||||
}
|
||||
Class.toString = function () "[class " + this.constructor.name + "]",
|
||||
Class.prototype = {
|
||||
/**
|
||||
* Initializes new instances of this class. Called automatically
|
||||
* when new instances are created.
|
||||
*/
|
||||
init: function() {},
|
||||
|
||||
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) {
|
||||
const self = this;
|
||||
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", {
|
||||
init: function () {
|
||||
let args = Array.slice(arguments);
|
||||
let args = this._args = Array.slice(arguments);
|
||||
this.__defineGetter__("length", function () args.length);
|
||||
this.__defineGetter__("members", function () args.slice());
|
||||
for (let arg in Iterator(args)) {
|
||||
@@ -305,6 +430,16 @@ const Struct = Class("Struct", {
|
||||
return self;
|
||||
}
|
||||
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) {
|
||||
let i = args.indexOf(key);
|
||||
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
|
||||
// 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;
|
||||
if (callable(inst))
|
||||
if (callable(prototype))
|
||||
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.requires = inst.requires || [];
|
||||
Module.list.push(module);
|
||||
|
||||
Reference in New Issue
Block a user