michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: */ michael@0: michael@0: 'use strict'; michael@0: michael@0: /* michael@0: * Uses `Promise.jsm` as a core implementation, with additional sugar michael@0: * from previous implementation, with inspiration from `Q` and `when` michael@0: * michael@0: * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm michael@0: * https://github.com/cujojs/when michael@0: * https://github.com/kriskowal/q michael@0: */ michael@0: const PROMISE_URI = 'resource://gre/modules/Promise.jsm'; michael@0: michael@0: getEnvironment.call(this, function ({ require, exports, module, Cu }) { michael@0: michael@0: const { defer, resolve, all, reject, race } = Cu.import(PROMISE_URI, {}).Promise; michael@0: michael@0: module.metadata = { michael@0: 'stability': 'unstable' michael@0: }; michael@0: michael@0: let promised = (function() { michael@0: // Note: Define shortcuts and utility functions here in order to avoid michael@0: // slower property accesses and unnecessary closure creations on each michael@0: // call of this popular function. michael@0: michael@0: var call = Function.call; michael@0: var concat = Array.prototype.concat; michael@0: michael@0: // Utility function that does following: michael@0: // execute([ f, self, args...]) => f.apply(self, args) michael@0: function execute (args) call.apply(call, args) michael@0: michael@0: // Utility function that takes promise of `a` array and maybe promise `b` michael@0: // as arguments and returns promise for `a.concat(b)`. michael@0: function promisedConcat(promises, unknown) { michael@0: return promises.then(function (values) { michael@0: return resolve(unknown) michael@0: .then(function (value) values.concat([value])); michael@0: }); michael@0: } michael@0: michael@0: return function promised(f, prototype) { michael@0: /** michael@0: Returns a wrapped `f`, which when called returns a promise that resolves to michael@0: `f(...)` passing all the given arguments to it, which by the way may be michael@0: promises. Optionally second `prototype` argument may be provided to be used michael@0: a prototype for a returned promise. michael@0: michael@0: ## Example michael@0: michael@0: var promise = promised(Array)(1, promise(2), promise(3)) michael@0: promise.then(console.log) // => [ 1, 2, 3 ] michael@0: **/ michael@0: michael@0: return function promised() { michael@0: // create array of [ f, this, args... ] michael@0: return concat.apply([ f, this ], arguments). michael@0: // reduce it via `promisedConcat` to get promised array of fulfillments michael@0: reduce(promisedConcat, resolve([], prototype)). michael@0: // finally map that to promise of `f.apply(this, args...)` michael@0: then(execute); michael@0: }; michael@0: }; michael@0: })(); michael@0: michael@0: exports.promised = promised; michael@0: exports.all = all; michael@0: exports.defer = defer; michael@0: exports.resolve = resolve; michael@0: exports.reject = reject; michael@0: exports.race = race; michael@0: exports.Promise = Promise; michael@0: michael@0: }); michael@0: michael@0: function getEnvironment (callback) { michael@0: let Cu, _exports, _module, _require; michael@0: michael@0: // CommonJS / SDK michael@0: if (typeof(require) === 'function') { michael@0: Cu = require('chrome').Cu; michael@0: _exports = exports; michael@0: _module = module; michael@0: _require = require; michael@0: } michael@0: // JSM michael@0: else if (String(this).indexOf('BackstagePass') >= 0) { michael@0: Cu = this['Components'].utils; michael@0: _exports = this.Promise = {}; michael@0: _module = { uri: __URI__, id: 'promise/core' }; michael@0: _require = uri => { michael@0: let imports = {}; michael@0: Cu.import(uri, imports); michael@0: return imports; michael@0: }; michael@0: this.EXPORTED_SYMBOLS = ['Promise']; michael@0: // mozIJSSubScriptLoader.loadSubscript michael@0: } else if (~String(this).indexOf('Sandbox')) { michael@0: Cu = this['Components'].utils; michael@0: _exports = this; michael@0: _module = { id: 'promise/core' }; michael@0: _require = uri => {}; michael@0: } michael@0: michael@0: callback({ michael@0: Cu: Cu, michael@0: exports: _exports, michael@0: module: _module, michael@0: require: _require michael@0: }); michael@0: } michael@0: