; } // Ideally, this should be done with a WeakMap() with xpcomBlocker // as a key, but XPCWrappedNative objects cannot serve as WeakMap keys, see // bug 1834365. const moduleBlocker = () => new Promise( // This promise is never resolved. By opposition to AsyncShutdown // blockers, `nsIAsyncShutdownBlocker`s are always lifted by calling // `removeBlocker`. () => xpcomBlocker.blockShutdown(this) ); this._byXpcomBlocker.set(xpcomBlocker, moduleBlocker); this._moduleClient.addBlocker(xpcomBlocker.name, moduleBlocker, { fetchState: () => new PropertyBagConverter().propertyBagToJsValue(xpcomBlocker.state), filename: fileName, lineNumber, stack, }); }, removeBlocker(xpcomBlocker) { let moduleBlocker = this._byXpcomBlocker.get(xpcomBlocker); if (!moduleBlocker) { return false; } this._byXpcomBlocker.delete(xpcomBlocker); return this._moduleClient.removeBlocker(moduleBlocker); }, QueryInterface: ChromeUtils.generateQI(["nsIAsyncShutdownClient"]), }; /** * Construct an instance of nsIAsyncShutdownBarrier from an instance * of AsyncShutdown.Barrier. * * @param {object} moduleBarrier an instance if * `AsyncShutdown.Barrier`. This instance will serve as back-end for * all methods. * @class */ function nsAsyncShutdownBarrier(moduleBarrier) { this._client = new nsAsyncShutdownClient(moduleBarrier.client); this._moduleBarrier = moduleBarrier; } nsAsyncShutdownBarrier.prototype = { get state() { return new PropertyBagConverter().jsValueToPropertyBag( this._moduleBarrier.state ); }, get client() { return this._client; }, wait(onReady) { this._moduleBarrier.wait().then(() => { onReady.done(); }); // By specification, _moduleBarrier.wait() cannot reject. }, QueryInterface: ChromeUtils.generateQI(["nsIAsyncShutdownBarrier"]), }; export function nsAsyncShutdownService() { // Cache for the getters for (let _k of [ // Parent process "appShutdownConfirmed", "profileBeforeChange", "profileChangeTeardown", "sendTelemetry", // Child processes // TODO: This seems obsolete from AsyncShutdown.sys.mjs ? "contentChildShutdown", // All processes "webWorkersShutdown", "xpcomWillShutdown", ]) { let k = _k; Object.defineProperty(this, k, { configurable: true, get() { delete this[k]; let wrapped = lazy.AsyncShutdown[k]; // May be undefined, if we're on the wrong process. let result = wrapped ? new nsAsyncShutdownClient(wrapped) : undefined; Object.defineProperty(this, k, { value: result, }); return result; }, }); } // Hooks for testing purpose this.wrappedJSObject = { _propertyBagConverter: PropertyBagConverter, }; } nsAsyncShutdownService.prototype = { makeBarrier(name) { return new nsAsyncShutdownBarrier(new lazy.AsyncShutdown.Barrier(name)); }, QueryInterface: ChromeUtils.generateQI(["nsIAsyncShutdownService"]), }; PK