aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.12/lib/sdk/core
diff options
context:
space:
mode:
Diffstat (limited to 'tools/addon-sdk-1.12/lib/sdk/core')
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/core/heritage.js146
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/core/namespace.js43
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/core/promise.js230
3 files changed, 419 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.12/lib/sdk/core/heritage.js b/tools/addon-sdk-1.12/lib/sdk/core/heritage.js
new file mode 100644
index 0000000..1c62e6c
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/core/heritage.js
@@ -0,0 +1,146 @@
+/* vim:set ts=2 sw=2 sts=2 expandtab */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+'use strict';
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+var getPrototypeOf = Object.getPrototypeOf;
+var getNames = Object.getOwnPropertyNames;
+var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+var create = Object.create;
+var freeze = Object.freeze;
+var unbind = Function.call.bind(Function.bind, Function.call);
+
+// This shortcut makes sure that we do perform desired operations, even if
+// associated methods have being overridden on the used object.
+var owns = unbind(Object.prototype.hasOwnProperty);
+var apply = unbind(Function.prototype.apply);
+var slice = Array.slice || unbind(Array.prototype.slice);
+var reduce = Array.reduce || unbind(Array.prototype.reduce);
+var map = Array.map || unbind(Array.prototype.map);
+var concat = Array.concat || unbind(Array.prototype.concat);
+
+// Utility function to get own properties descriptor map.
+function getOwnPropertyDescriptors(object) {
+ return reduce(getNames(object), function(descriptor, name) {
+ descriptor[name] = getOwnPropertyDescriptor(object, name);
+ return descriptor;
+ }, {});
+}
+
+/**
+ * Takes `source` object as an argument and returns identical object
+ * with the difference that all own properties will be non-enumerable
+ */
+function obscure(source) {
+ var descriptor = reduce(getNames(source), function(descriptor, name) {
+ var property = getOwnPropertyDescriptor(source, name);
+ property.enumerable = false;
+ descriptor[name] = property;
+ return descriptor;
+ }, {});
+ return create(getPrototypeOf(source), descriptor);
+}
+exports.obscure = obscure;
+
+/**
+ * Takes arbitrary number of source objects and returns fresh one, that
+ * inherits from the same prototype as a first argument and implements all
+ * own properties of all argument objects. If two or more argument objects
+ * have own properties with the same name, the property is overridden, with
+ * precedence from right to left, implying, that properties of the object on
+ * the left are overridden by a same named property of the object on the right.
+ */
+var mix = function(source) {
+ var descriptor = reduce(slice(arguments), function(descriptor, source) {
+ return reduce(getNames(source), function(descriptor, name) {
+ descriptor[name] = getOwnPropertyDescriptor(source, name);
+ return descriptor;
+ }, descriptor);
+ }, {});
+
+ return create(getPrototypeOf(source), descriptor);
+};
+exports.mix = mix;
+
+/**
+ * Returns a frozen object with that inherits from the given `prototype` and
+ * implements all own properties of the given `properties` object.
+ */
+function extend(prototype, properties) {
+ return freeze(create(prototype, getOwnPropertyDescriptors(properties)));
+}
+exports.extend = extend;
+
+/**
+ * Returns a constructor function with a proper `prototype` setup. Returned
+ * constructor's `prototype` inherits from a given `options.extends` or
+ * `Class.prototype` if omitted and implements all the properties of the
+ * given `option`. If `options.implemens` array is passed, it's elements
+ * will be mixed into prototype as well. Also, `options.extends` can be
+ * a function or a prototype. If function than it's prototype is used as
+ * an ancestor of the prototype, if it's an object that it's used directly.
+ * Also `options.implements` may contain functions or objects, in case of
+ * functions their prototypes are used for mixing.
+ */
+var Class = new function() {
+ function prototypeOf(input) {
+ return typeof(input) === 'function' ? input.prototype : input;
+ }
+ var none = freeze([]);
+
+ return function Class(options) {
+ // Create descriptor with normalized `options.extends` and
+ // `options.implements`.
+ var descriptor = {
+ // Normalize extends property of `options.extends` to a prototype object
+ // in case it's constructor. If property is missing that fallback to
+ // `Type.prototype`.
+ extends: owns(options, 'extends') ?
+ prototypeOf(options.extends) : Class.prototype,
+ // Normalize `options.implements` to make sure that it's array of
+ // prototype objects instead of constructor functions.
+ implements: owns(options, 'implements') ?
+ freeze(map(options.implements, prototypeOf)) : none
+ };
+
+ // Create array of property descriptors who's properties will be defined
+ // on the resulting prototype. Note: Using reflection `concat` instead of
+ // method as it may be overridden.
+ var descriptors = concat(descriptor.implements, options, descriptor);
+ // Create `prototype` that inherits from given ancestor passed as
+ // `options.extends`, falling back to `Type.prototype`, implementing all
+ // properties of given `options.implements` and `options` itself.
+ var prototype = extend(descriptor.extends, mix.apply(mix, descriptors));
+
+ // Note: we use reflection `apply` in the constructor instead of method
+ // call since later may be overridden.
+ function constructor() {
+ return apply(prototype.constructor, create(prototype), arguments);
+ }
+ constructor.prototype = prototype;
+ return freeze(constructor);
+ };
+}
+Class.prototype = extend(null, obscure({
+ constructor: function constructor() {
+ this.initialize.apply(this, arguments);
+ return this;
+ },
+ initialize: function initialize() {
+ // Do your initialization logic here
+ },
+ // Copy useful properties from `Object.prototype`.
+ toString: Object.prototype.toString,
+ toLocaleString: Object.prototype.toLocaleString,
+ toSource: Object.prototype.toSource,
+ valueOf: Object.prototype.valueOf,
+ isPrototypeOf: Object.prototype.isPrototypeOf
+}));
+exports.Class = freeze(Class);
diff --git a/tools/addon-sdk-1.12/lib/sdk/core/namespace.js b/tools/addon-sdk-1.12/lib/sdk/core/namespace.js
new file mode 100644
index 0000000..3ceb73b
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/core/namespace.js
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+const create = Object.create;
+const prototypeOf = Object.getPrototypeOf;
+
+/**
+ * Returns a new namespace, function that may can be used to access an
+ * namespaced object of the argument argument. Namespaced object are associated
+ * with owner objects via weak references. Namespaced objects inherit from the
+ * owners ancestor namespaced object. If owner's ancestor is `null` then
+ * namespaced object inherits from given `prototype`. Namespaces can be used
+ * to define internal APIs that can be shared via enclosing `namespace`
+ * function.
+ * @examples
+ * const internals = ns();
+ * internals(object).secret = secret;
+ */
+function ns() {
+ const map = new WeakMap();
+ return function namespace(target) {
+ if (!target) // If `target` is not an object return `target` itself.
+ return target;
+ // If target has no namespaced object yet, create one that inherits from
+ // the target prototype's namespaced object.
+ if (!map.has(target))
+ map.set(target, create(namespace(prototypeOf(target) || null)));
+
+ return map.get(target);
+ };
+};
+
+// `Namespace` is a e4x function in the scope, so we export the function also as
+// `ns` as alias to avoid clashing.
+exports.ns = ns;
+exports.Namespace = ns;
diff --git a/tools/addon-sdk-1.12/lib/sdk/core/promise.js b/tools/addon-sdk-1.12/lib/sdk/core/promise.js
new file mode 100644
index 0000000..2506c80
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/core/promise.js
@@ -0,0 +1,230 @@
+/* vim:set ts=2 sw=2 sts=2 expandtab */
+/*jshint asi: true undef: true es5: true node: true browser: true devel: true
+ forin: true latedef: false */
+/*global define: true, Cu: true, __URI__: true */
+;(function(id, factory) { // Module boilerplate :(
+ if (typeof(define) === 'function') { // RequireJS
+ define(factory);
+ } else if (typeof(require) === 'function') { // CommonJS
+ factory.call(this, require, exports, module);
+ } else if (~String(this).indexOf('BackstagePass')) { // JSM
+ factory(function require(uri) {
+ var imports = {};
+ this['Components'].utils.import(uri, imports);
+ return imports;
+ }, this, { uri: __URI__, id: id });
+ this.EXPORTED_SYMBOLS = Object.keys(this);
+ } else { // Browser or alike
+ var globals = this
+ factory(function require(id) {
+ return globals[id];
+ }, (globals[id] = {}), { uri: document.location.href + '#' + id, id: id });
+ }
+}).call(this, 'loader', function(require, exports, module) {
+
+'use strict';
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+function resolution(value) {
+ /**
+ Returns non-standard compliant (`then` does not returns a promise) promise
+ that resolves to a given `value`. Used just internally only.
+ **/
+ return { then: function then(resolve) { resolve(value) } }
+}
+
+function rejection(reason) {
+ /**
+ Returns non-standard compliant promise (`then` does not returns a promise)
+ that rejects with a given `reason`. This is used internally only.
+ **/
+ return { then: function then(resolve, reject) { reject(reason) } }
+}
+
+function attempt(f) {
+ /**
+ Returns wrapper function that delegates to `f`. If `f` throws then captures
+ error and returns promise that rejects with a thrown error. Otherwise returns
+ return value. (Internal utility)
+ **/
+ return function effort(options) {
+ try { return f(options) }
+ catch(error) { return rejection(error) }
+ }
+}
+
+function isPromise(value) {
+ /**
+ Returns true if given `value` is promise. Value is assumed to be promise if
+ it implements `then` method.
+ **/
+ return value && typeof(value.then) === 'function'
+}
+
+function defer(prototype) {
+ /**
+ Returns object containing following properties:
+ - `promise` Eventual value representation implementing CommonJS [Promises/A]
+ (http://wiki.commonjs.org/wiki/Promises/A) API.
+ - `resolve` Single shot function that resolves returned `promise` with a given
+ `value` argument.
+ - `reject` Single shot function that rejects returned `promise` with a given
+ `reason` argument.
+
+ Given `prototype` argument is used as a prototype of the returned `promise`
+ allowing one to implement additional API. If prototype is not passed then
+ it falls back to `Object.prototype`.
+
+ ## Examples
+
+ // Simple usage.
+ var deferred = defer()
+ deferred.promise.then(console.log, console.error)
+ deferred.resolve(value)
+
+ // Advanced usage
+ var prototype = {
+ get: function get(name) {
+ return this.then(function(value) {
+ return value[name];
+ })
+ }
+ }
+
+ var foo = defer(prototype)
+ deferred.promise.get('name').then(console.log)
+ deferred.resolve({ name: 'Foo' })
+ //=> 'Foo'
+ */
+ var pending = [], result
+ prototype = (prototype || prototype === null) ? prototype : Object.prototype
+
+ // Create an object implementing promise API.
+ var promise = Object.create(prototype, {
+ then: { value: function then(resolve, reject) {
+ // create a new deferred using a same `prototype`.
+ var deferred = defer(prototype)
+ // If `resolve / reject` callbacks are not provided.
+ resolve = resolve ? attempt(resolve) : resolution
+ reject = reject ? attempt(reject) : rejection
+
+ // Create a listeners for a enclosed promise resolution / rejection that
+ // delegate to an actual callbacks and resolve / reject returned promise.
+ function resolved(value) { deferred.resolve(resolve(value)) }
+ function rejected(reason) { deferred.resolve(reject(reason)) }
+
+ // If promise is pending register listeners. Otherwise forward them to
+ // resulting resolution.
+ if (pending) pending.push([ resolved, rejected ])
+ else result.then(resolved, rejected)
+
+ return deferred.promise
+ }}
+ })
+
+ var deferred = {
+ promise: promise,
+ resolve: function resolve(value) {
+ /**
+ Resolves associated `promise` to a given `value`, unless it's already
+ resolved or rejected.
+ **/
+ if (pending) {
+ // store resolution `value` as a promise (`value` itself may be a
+ // promise), so that all subsequent listeners can be forwarded to it,
+ // which either resolves immediately or forwards if `value` is
+ // a promise.
+ result = isPromise(value) ? value : resolution(value)
+ // forward all pending observers.
+ while (pending.length) result.then.apply(result, pending.shift())
+ // mark promise as resolved.
+ pending = null
+ }
+ },
+ reject: function reject(reason) {
+ /**
+ Rejects associated `promise` with a given `reason`, unless it's already
+ resolved / rejected.
+ **/
+ deferred.resolve(rejection(reason))
+ }
+ }
+
+ return deferred
+}
+exports.defer = defer
+
+function resolve(value, prototype) {
+ /**
+ Returns a promise resolved to a given `value`. Optionally second `prototype`
+ arguments my be provided to be used as a prototype for a returned promise.
+ **/
+ var deferred = defer(prototype)
+ deferred.resolve(value)
+ return deferred.promise
+}
+exports.resolve = resolve
+
+function reject(reason, prototype) {
+ /**
+ Returns a promise that is rejected with a given `reason`. Optionally second
+ `prototype` arguments my be provided to be used as a prototype for a returned
+ promise.
+ **/
+ var deferred = defer(prototype)
+ deferred.reject(reason)
+ return deferred.promise
+}
+exports.reject = reject
+
+var promised = (function() {
+ // Note: Define shortcuts and utility functions here in order to avoid
+ // slower property accesses and unnecessary closure creations on each
+ // call of this popular function.
+
+ var call = Function.call
+ var concat = Array.prototype.concat
+
+ // Utility function that does following:
+ // execute([ f, self, args...]) => f.apply(self, args)
+ function execute(args) { return call.apply(call, args) }
+
+ // Utility function that takes promise of `a` array and maybe promise `b`
+ // as arguments and returns promise for `a.concat(b)`.
+ function promisedConcat(promises, unknown) {
+ return promises.then(function(values) {
+ return resolve(unknown).then(function(value) {
+ return values.concat([ value ])
+ })
+ })
+ }
+
+ return function promised(f, prototype) {
+ /**
+ Returns a wrapped `f`, which when called returns a promise that resolves to
+ `f(...)` passing all the given arguments to it, which by the way may be
+ promises. Optionally second `prototype` argument may be provided to be used
+ a prototype for a returned promise.
+
+ ## Example
+
+ var promise = promised(Array)(1, promise(2), promise(3))
+ promise.then(console.log) // => [ 1, 2, 3 ]
+ **/
+
+ return function promised() {
+ // create array of [ f, this, args... ]
+ return concat.apply([ f, this ], arguments).
+ // reduce it via `promisedConcat` to get promised array of fulfillments
+ reduce(promisedConcat, resolve([], prototype)).
+ // finally map that to promise of `f.apply(this, args...)`
+ then(execute)
+ }
+ }
+})()
+exports.promised = promised
+
+})