123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- ;(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') >= 0) { // JSM
- this[factory.name] = {};
- try {
- this.console = this['Components'].utils
- .import('resource://gre/modules/devtools/Console.jsm', {}).console;
- }
- catch (ex) {
- // Avoid failures on different toolkit configurations.
- }
- factory(function require(uri) {
- var imports = {};
- this['Components'].utils.import(uri, imports);
- return imports;
- }, this[factory.name], { uri: __URI__, id: id });
- this.EXPORTED_SYMBOLS = [factory.name];
- } else if (~String(this).indexOf('Sandbox')) { // Sandbox
- factory(function require(uri) {}, this, { id: id });
- } 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, 'promise/core', function Promise(require, exports, module) {
- 'use strict';
- module.metadata = {
- "stability": "unstable"
- };
- /**
- * Internal utility: Wraps given `value` into simplified promise, successfully
- * fulfilled to a given `value`. Note the result is not a complete promise
- * implementation, as its method `then` does not returns anything.
- */
- function fulfilled(value) {
- return { then: function then(fulfill) { fulfill(value); } };
- }
- /**
- * Internal utility: Wraps given input into simplified promise, pre-rejected
- * with a given `reason`. Note the result is not a complete promise
- * implementation, as its method `then` does not returns anything.
- */
- function rejected(reason) {
- return { then: function then(fulfill, reject) { reject(reason); } };
- }
- /**
- * Internal utility: Returns `true` if given `value` is a promise. Value is
- * assumed to be a promise if it implements method `then`.
- */
- function isPromise(value) {
- return value && typeof(value.then) === 'function';
- }
- /**
- * Creates deferred object containing fresh promise & methods to either resolve
- * or reject it. The result is an object with the following properties:
- * - `promise` Eventual value representation implementing CommonJS [Promises/A]
- * (http://wiki.commonjs.org/wiki/Promises/A) API.
- * - `resolve` Single shot function that resolves enclosed `promise` with a
- * given `value`.
- * - `reject` Single shot function that rejects enclosed `promise` with a given
- * `reason`.
- *
- * An optional `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`.
- *
- * ## Example
- *
- * function fetchURI(uri, type) {
- * var deferred = defer();
- * var request = new XMLHttpRequest();
- * request.open("GET", uri, true);
- * request.responseType = type;
- * request.onload = function onload() {
- * deferred.resolve(request.response);
- * }
- * request.onerror = function(event) {
- * deferred.reject(event);
- * }
- * request.send();
- *
- * return deferred.promise;
- * }
- */
- function defer(prototype) {
- // Define FIFO queue of observer pairs. Once promise is resolved & all queued
- // observers are forwarded to `result` and variable is set to `null`.
- var observers = [];
- // Promise `result`, which will be assigned a resolution value once promise
- // is resolved. Note that result will always be assigned promise (or alike)
- // object to take care of propagation through promise chains. If result is
- // `null` promise is not resolved yet.
- var result = null;
- prototype = (prototype || prototype === null) ? prototype : Object.prototype;
- // Create an object implementing promise API.
- var promise = Object.create(prototype, {
- then: { value: function then(onFulfill, onError) {
- var deferred = defer(prototype);
- function resolve(value) {
- // If `onFulfill` handler is provided resolve `deferred.promise` with
- // result of invoking it with a resolution value. If handler is not
- // provided propagate value through.
- try {
- deferred.resolve(onFulfill ? onFulfill(value) : value);
- }
- // `onFulfill` may throw exception in which case resulting promise
- // is rejected with thrown exception.
- catch(error) {
- if (exports._reportErrors && typeof(console) === 'object')
- console.error(error);
- // Note: Following is equivalent of `deferred.reject(error)`,
- // we use this shortcut to reduce a stack.
- deferred.resolve(rejected(error));
- }
- }
- function reject(reason) {
- try {
- if (onError) deferred.resolve(onError(reason));
- else deferred.resolve(rejected(reason));
- }
- catch(error) {
- if (exports._reportErrors && typeof(console) === 'object')
- console.error(error);
- deferred.resolve(rejected(error));
- }
- }
- // If enclosed promise (`this.promise`) observers queue is still alive
- // enqueue a new observer pair into it. Note that this does not
- // necessary means that promise is pending, it may already be resolved,
- // but we still have to queue observers to guarantee an order of
- // propagation.
- if (observers) {
- observers.push({ resolve: resolve, reject: reject });
- }
- // Otherwise just forward observer pair right to a `result` promise.
- else {
- result.then(resolve, reject);
- }
- return deferred.promise;
- }}
- })
- var deferred = {
- promise: promise,
- /**
- * Resolves associated `promise` to a given `value`, unless it's already
- * resolved or rejected. Note that resolved promise is not necessary a
- * successfully fulfilled. Promise may be resolved with a promise `value`
- * in which case `value` promise's fulfillment / rejection will propagate
- * up to a promise resolved with `value`.
- */
- resolve: function resolve(value) {
- if (!result) {
- // Store resolution `value` in a `result` as a promise, so that all
- // the subsequent handlers can be simply forwarded to it. Since
- // `result` will be a promise all the value / error propagation will
- // be uniformly taken care of.
- result = isPromise(value) ? value : fulfilled(value);
- // Forward already registered observers to a `result` promise in the
- // order they were registered. Note that we intentionally dequeue
- // observer at a time until queue is exhausted. This makes sure that
- // handlers registered as side effect of observer forwarding are
- // queued instead of being invoked immediately, guaranteeing FIFO
- // order.
- while (observers.length) {
- var observer = observers.shift();
- result.then(observer.resolve, observer.reject);
- }
- // Once `observers` queue is exhausted we `null`-ify it, so that
- // new handlers are forwarded straight to the `result`.
- observers = null;
- }
- },
- /**
- * Rejects associated `promise` with a given `reason`, unless it's already
- * resolved / rejected. This is just a (better performing) convenience
- * shortcut for `deferred.resolve(reject(reason))`.
- */
- reject: function reject(reason) {
- // Note that if promise is resolved that does not necessary means that it
- // is successfully fulfilled. Resolution value may be a promise in which
- // case its result propagates. In other words if promise `a` is resolved
- // with promise `b`, `a` is either fulfilled or rejected depending
- // on weather `b` is fulfilled or rejected. Here `deferred.promise` is
- // resolved with a promise pre-rejected with a given `reason`, there for
- // `deferred.promise` is rejected with a given `reason`. This may feel
- // little awkward first, but doing it this way greatly simplifies
- // propagation through promise chains.
- deferred.resolve(rejected(reason));
- }
- };
- return deferred;
- }
- exports.defer = defer;
- /**
- * Returns a promise resolved to a given `value`. Optionally a second
- * `prototype` argument may be provided to be used as a prototype for the
- * returned promise.
- */
- function resolve(value, prototype) {
- var deferred = defer(prototype);
- deferred.resolve(value);
- return deferred.promise;
- }
- exports.resolve = resolve;
- /**
- * Returns a promise rejected with a given `reason`. Optionally a second
- * `prototype` argument may be provided to be used as a prototype for the
- * returned promise.
- */
- function reject(reason, prototype) {
- 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;
- var all = promised(Array);
- exports.all = all;
- });
|