diff -r 000000000000 -r 6474c204b198 addon-sdk/source/lib/sdk/core/promise.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/addon-sdk/source/lib/sdk/core/promise.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,117 @@ +/* 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'; + +/* + * Uses `Promise.jsm` as a core implementation, with additional sugar + * from previous implementation, with inspiration from `Q` and `when` + * + * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm + * https://github.com/cujojs/when + * https://github.com/kriskowal/q + */ +const PROMISE_URI = 'resource://gre/modules/Promise.jsm'; + +getEnvironment.call(this, function ({ require, exports, module, Cu }) { + +const { defer, resolve, all, reject, race } = Cu.import(PROMISE_URI, {}).Promise; + +module.metadata = { + 'stability': 'unstable' +}; + +let 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) 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) 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; +exports.all = all; +exports.defer = defer; +exports.resolve = resolve; +exports.reject = reject; +exports.race = race; +exports.Promise = Promise; + +}); + +function getEnvironment (callback) { + let Cu, _exports, _module, _require; + + // CommonJS / SDK + if (typeof(require) === 'function') { + Cu = require('chrome').Cu; + _exports = exports; + _module = module; + _require = require; + } + // JSM + else if (String(this).indexOf('BackstagePass') >= 0) { + Cu = this['Components'].utils; + _exports = this.Promise = {}; + _module = { uri: __URI__, id: 'promise/core' }; + _require = uri => { + let imports = {}; + Cu.import(uri, imports); + return imports; + }; + this.EXPORTED_SYMBOLS = ['Promise']; + // mozIJSSubScriptLoader.loadSubscript + } else if (~String(this).indexOf('Sandbox')) { + Cu = this['Components'].utils; + _exports = this; + _module = { id: 'promise/core' }; + _require = uri => {}; + } + + callback({ + Cu: Cu, + exports: _exports, + module: _module, + require: _require + }); +} +