summaryrefslogtreecommitdiffstats
path: root/toolkit/jetpack/sdk/core/promise.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/jetpack/sdk/core/promise.js')
-rw-r--r--toolkit/jetpack/sdk/core/promise.js118
1 files changed, 118 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/core/promise.js b/toolkit/jetpack/sdk/core/promise.js
new file mode 100644
index 000000000..f4bd7b0f5
--- /dev/null
+++ b/toolkit/jetpack/sdk/core/promise.js
@@ -0,0 +1,118 @@
+/* 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 Promise = Cu.import(PROMISE_URI, {}).Promise;
+const { Debugging, defer, resolve, all, reject, race } = Promise;
+
+module.metadata = {
+ 'stability': 'unstable'
+};
+
+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(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(...args) {
+ // create array of [ f, this, args... ]
+ return [f, this, ...args].
+ // 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;
+exports.Debugging = Debugging;
+});
+
+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
+ });
+}
+