mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-09 16:57:30 +09:00
Move Add-on SDK source to toolkit/jetpack
This commit is contained in:
parent
0a03067ee3
commit
23b67db438
993 changed files with 484 additions and 100663 deletions
186
toolkit/jetpack/sdk/core/disposable.js
Normal file
186
toolkit/jetpack/sdk/core/disposable.js
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/* 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": "experimental"
|
||||
};
|
||||
|
||||
const { Class } = require("./heritage");
|
||||
const { Observer, subscribe, unsubscribe, observe } = require("./observer");
|
||||
const { isWeak } = require("./reference");
|
||||
const SDKWeakSet = require("../lang/weak-set");
|
||||
|
||||
const method = require("../../method/core");
|
||||
|
||||
const unloadSubject = require('@loader/unload');
|
||||
const addonUnloadTopic = "sdk:loader:destroy";
|
||||
|
||||
const uninstall = method("disposable/uninstall");
|
||||
exports.uninstall = uninstall;
|
||||
|
||||
const shutdown = method("disposable/shutdown");
|
||||
exports.shutdown = shutdown;
|
||||
|
||||
const disable = method("disposable/disable");
|
||||
exports.disable = disable;
|
||||
|
||||
const upgrade = method("disposable/upgrade");
|
||||
exports.upgrade = upgrade;
|
||||
|
||||
const downgrade = method("disposable/downgrade");
|
||||
exports.downgrade = downgrade;
|
||||
|
||||
const unload = method("disposable/unload");
|
||||
exports.unload = unload;
|
||||
|
||||
const dispose = method("disposable/dispose");
|
||||
exports.dispose = dispose;
|
||||
dispose.define(Object, object => object.dispose());
|
||||
|
||||
const setup = method("disposable/setup");
|
||||
exports.setup = setup;
|
||||
setup.define(Object, (object, ...args) => object.setup(...args));
|
||||
|
||||
// DisposablesUnloadObserver is the class which subscribe the
|
||||
// Observer Service to be notified when the add-on loader is
|
||||
// unloading to be able to dispose all the existent disposables.
|
||||
const DisposablesUnloadObserver = Class({
|
||||
implements: [Observer],
|
||||
initialize: function(...args) {
|
||||
// Set of the non-weak disposables registered to be disposed.
|
||||
this.disposables = new Set();
|
||||
// Target of the weak disposables registered to be disposed
|
||||
// (and tracked on this target using the SDK weak-set module).
|
||||
this.weakDisposables = {};
|
||||
},
|
||||
subscribe(disposable) {
|
||||
if (isWeak(disposable)) {
|
||||
SDKWeakSet.add(this.weakDisposables, disposable);
|
||||
} else {
|
||||
this.disposables.add(disposable);
|
||||
}
|
||||
},
|
||||
unsubscribe(disposable) {
|
||||
if (isWeak(disposable)) {
|
||||
SDKWeakSet.remove(this.weakDisposables, disposable);
|
||||
} else {
|
||||
this.disposables.delete(disposable);
|
||||
}
|
||||
},
|
||||
tryUnloadDisposable(disposable) {
|
||||
try {
|
||||
if (disposable) {
|
||||
unload(disposable);
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("Error unloading a",
|
||||
isWeak(disposable) ? "weak disposable" : "disposable",
|
||||
disposable, e);
|
||||
}
|
||||
},
|
||||
unloadAll() {
|
||||
// Remove all the subscribed disposables.
|
||||
for (let disposable of this.disposables) {
|
||||
this.tryUnloadDisposable(disposable);
|
||||
}
|
||||
|
||||
this.disposables.clear();
|
||||
|
||||
// Remove all the subscribed weak disposables.
|
||||
for (let disposable of SDKWeakSet.iterator(this.weakDisposables)) {
|
||||
this.tryUnloadDisposable(disposable);
|
||||
}
|
||||
|
||||
SDKWeakSet.clear(this.weakDisposables);
|
||||
}
|
||||
});
|
||||
const disposablesUnloadObserver = new DisposablesUnloadObserver();
|
||||
|
||||
// The DisposablesUnloadObserver instance is the only object which subscribes
|
||||
// the Observer Service directly, it observes add-on unload notifications in
|
||||
// order to trigger `unload` on all its subscribed disposables.
|
||||
observe.define(DisposablesUnloadObserver, (obj, subject, topic, data) => {
|
||||
const isUnloadTopic = topic === addonUnloadTopic;
|
||||
const isUnloadSubject = subject.wrappedJSObject === unloadSubject;
|
||||
if (isUnloadTopic && isUnloadSubject) {
|
||||
unsubscribe(disposablesUnloadObserver, addonUnloadTopic);
|
||||
disposablesUnloadObserver.unloadAll();
|
||||
}
|
||||
});
|
||||
|
||||
subscribe(disposablesUnloadObserver, addonUnloadTopic, false);
|
||||
|
||||
// Set's up disposable instance.
|
||||
const setupDisposable = disposable => {
|
||||
disposablesUnloadObserver.subscribe(disposable);
|
||||
};
|
||||
exports.setupDisposable = setupDisposable;
|
||||
|
||||
// Tears down disposable instance.
|
||||
const disposeDisposable = disposable => {
|
||||
disposablesUnloadObserver.unsubscribe(disposable);
|
||||
};
|
||||
exports.disposeDisposable = disposeDisposable;
|
||||
|
||||
// Base type that takes care of disposing it's instances on add-on unload.
|
||||
// Also makes sure to remove unload listener if it's already being disposed.
|
||||
const Disposable = Class({
|
||||
initialize: function(...args) {
|
||||
// First setup instance before initializing it's disposal. If instance
|
||||
// fails to initialize then there is no instance to be disposed at the
|
||||
// unload.
|
||||
setup(this, ...args);
|
||||
setupDisposable(this);
|
||||
},
|
||||
destroy: function(reason) {
|
||||
// Destroying disposable removes unload handler so that attempt to dispose
|
||||
// won't be made at unload & delegates to dispose.
|
||||
disposeDisposable(this);
|
||||
unload(this, reason);
|
||||
},
|
||||
setup: function() {
|
||||
// Implement your initialize logic here.
|
||||
},
|
||||
dispose: function() {
|
||||
// Implement your cleanup logic here.
|
||||
}
|
||||
});
|
||||
exports.Disposable = Disposable;
|
||||
|
||||
const unloaders = {
|
||||
destroy: dispose,
|
||||
uninstall: uninstall,
|
||||
shutdown: shutdown,
|
||||
disable: disable,
|
||||
upgrade: upgrade,
|
||||
downgrade: downgrade
|
||||
};
|
||||
|
||||
const unloaded = new WeakMap();
|
||||
unload.define(Disposable, (disposable, reason) => {
|
||||
if (!unloaded.get(disposable)) {
|
||||
unloaded.set(disposable, true);
|
||||
// Pick an unload handler associated with an unload
|
||||
// reason (falling back to destroy if not found) and
|
||||
// delegate unloading to it.
|
||||
const unload = unloaders[reason] || unloaders.destroy;
|
||||
unload(disposable);
|
||||
}
|
||||
});
|
||||
|
||||
// If add-on is disabled manually, it's being upgraded, downgraded
|
||||
// or uninstalled `dispose` is invoked to undo any changes that
|
||||
// has being done by it in this session.
|
||||
disable.define(Disposable, dispose);
|
||||
downgrade.define(Disposable, dispose);
|
||||
upgrade.define(Disposable, dispose);
|
||||
uninstall.define(Disposable, dispose);
|
||||
|
||||
// If application is shut down no dispose is invoked as undo-ing
|
||||
// changes made by instance is likely to just waste of resources &
|
||||
// increase shutdown time. Although specefic components may choose
|
||||
// to implement shutdown handler that does something better.
|
||||
shutdown.define(Disposable, disposable => {});
|
||||
184
toolkit/jetpack/sdk/core/heritage.js
Normal file
184
toolkit/jetpack/sdk/core/heritage.js
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/* 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 = x => [...Object.getOwnPropertyNames(x),
|
||||
...Object.getOwnPropertySymbols(x)];
|
||||
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;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function isDataProperty(property) {
|
||||
var value = property.value;
|
||||
var type = typeof(property.value);
|
||||
return "value" in property &&
|
||||
(type !== "object" || value === null) &&
|
||||
type !== "function";
|
||||
}
|
||||
|
||||
function getDataProperties(object) {
|
||||
var properties = getOwnPropertyDescriptors(object);
|
||||
return getNames(properties).reduce(function(result, name) {
|
||||
var property = properties[name];
|
||||
if (isDataProperty(property)) {
|
||||
result[name] = {
|
||||
value: property.value,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: false
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}, {})
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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, {
|
||||
constructor: constructor
|
||||
});
|
||||
|
||||
// Note: we use reflection `apply` in the constructor instead of method
|
||||
// call since later may be overridden.
|
||||
function constructor() {
|
||||
var instance = create(prototype, attributes);
|
||||
if (initialize) apply(initialize, instance, arguments);
|
||||
return instance;
|
||||
}
|
||||
// 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));
|
||||
var initialize = prototype.initialize;
|
||||
|
||||
// Combine ancestor attributes with prototype's attributes so that
|
||||
// ancestors attributes also become initializeable.
|
||||
var attributes = mix(descriptor.extends.constructor.attributes || {},
|
||||
getDataProperties(prototype));
|
||||
|
||||
constructor.attributes = attributes;
|
||||
Object.defineProperty(constructor, 'prototype', {
|
||||
configurable: false,
|
||||
writable: false,
|
||||
value: prototype
|
||||
});
|
||||
return 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);
|
||||
43
toolkit/jetpack/sdk/core/namespace.js
Normal file
43
toolkit/jetpack/sdk/core/namespace.js
Normal file
|
|
@ -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;
|
||||
89
toolkit/jetpack/sdk/core/observer.js
Normal file
89
toolkit/jetpack/sdk/core/observer.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* 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": "experimental"
|
||||
};
|
||||
|
||||
|
||||
const { Cc, Ci, Cr, Cu } = require("chrome");
|
||||
const { Class } = require("./heritage");
|
||||
const { isWeak } = require("./reference");
|
||||
const method = require("../../method/core");
|
||||
|
||||
const observerService = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
|
||||
const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
|
||||
|
||||
// This is a method that will be invoked when notification observer
|
||||
// subscribed to occurs.
|
||||
const observe = method("observer/observe");
|
||||
exports.observe = observe;
|
||||
|
||||
// Method to subscribe to the observer notification.
|
||||
const subscribe = method("observe/subscribe");
|
||||
exports.subscribe = subscribe;
|
||||
|
||||
|
||||
// Method to unsubscribe from the observer notifications.
|
||||
const unsubscribe = method("observer/unsubscribe");
|
||||
exports.unsubscribe = unsubscribe;
|
||||
|
||||
|
||||
// This is wrapper class that takes a `delegate` and produces
|
||||
// instance of `nsIObserver` which will delegate to a given
|
||||
// object when observer notification occurs.
|
||||
const ObserverDelegee = Class({
|
||||
initialize: function(delegate) {
|
||||
this.delegate = delegate;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (!iid.equals(Ci.nsIObserver) &&
|
||||
!iid.equals(Ci.nsISupportsWeakReference) &&
|
||||
!iid.equals(Ci.nsISupports))
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return this;
|
||||
},
|
||||
observe: function(subject, topic, data) {
|
||||
observe(this.delegate, subject, topic, data);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Class that can be either mixed in or inherited from in
|
||||
// order to subscribe / unsubscribe for observer notifications.
|
||||
const Observer = Class({});
|
||||
exports.Observer = Observer;
|
||||
|
||||
// Weak maps that associates instance of `ObserverDelegee` with
|
||||
// an actual observer. It ensures that `ObserverDelegee` instance
|
||||
// won't be GC-ed until given `observer` is.
|
||||
const subscribers = new WeakMap();
|
||||
|
||||
// Implementation of `subscribe` for `Observer` type just registers
|
||||
// observer for an observer service. If `isWeak(observer)` is `true`
|
||||
// observer service won't hold strong reference to a given `observer`.
|
||||
subscribe.define(Observer, (observer, topic) => {
|
||||
if (!subscribers.has(observer)) {
|
||||
const delegee = new ObserverDelegee(observer);
|
||||
subscribers.set(observer, delegee);
|
||||
addObserver(delegee, topic, isWeak(observer));
|
||||
}
|
||||
});
|
||||
|
||||
// Unsubscribes `observer` from observer notifications for the
|
||||
// given `topic`.
|
||||
unsubscribe.define(Observer, (observer, topic) => {
|
||||
const delegee = subscribers.get(observer);
|
||||
if (delegee) {
|
||||
subscribers.delete(observer);
|
||||
removeObserver(delegee, topic);
|
||||
}
|
||||
});
|
||||
118
toolkit/jetpack/sdk/core/promise.js
Normal file
118
toolkit/jetpack/sdk/core/promise.js
Normal file
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
29
toolkit/jetpack/sdk/core/reference.js
Normal file
29
toolkit/jetpack/sdk/core/reference.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* 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": "experimental"
|
||||
};
|
||||
|
||||
const method = require("../../method/core");
|
||||
const { Class } = require("./heritage");
|
||||
|
||||
// Object that inherit or mix WeakRefence inn will register
|
||||
// weak observes for system notifications.
|
||||
const WeakReference = Class({});
|
||||
exports.WeakReference = WeakReference;
|
||||
|
||||
|
||||
// If `isWeak(object)` is `true` observer installed
|
||||
// for such `object` will be weak, meaning that it will
|
||||
// be GC-ed if nothing else but observer is observing it.
|
||||
// By default everything except `WeakReference` will return
|
||||
// `false`.
|
||||
const isWeak = method("reference/weak?");
|
||||
exports.isWeak = isWeak;
|
||||
|
||||
isWeak.define(Object, _ => false);
|
||||
isWeak.define(WeakReference, _ => true);
|
||||
Loading…
Add table
Add a link
Reference in a new issue