12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- /* 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/. */
- // Parts of this module were taken from narwhal:
- //
- // http://narwhaljs.org
- module.metadata = {
- "stability": "experimental"
- };
- const { on, off } = require('./events');
- const unloadSubject = require('@loader/unload');
- const observers = [];
- const unloaders = [];
- var when = exports.when = function when(observer) {
- if (observers.indexOf(observer) != -1)
- return;
- observers.unshift(observer);
- };
- var ensure = exports.ensure = function ensure(obj, destructorName) {
- if (!destructorName)
- destructorName = "unload";
- if (!(destructorName in obj))
- throw new Error("object has no '" + destructorName + "' property");
- let called = false;
- let originalDestructor = obj[destructorName];
- function unloadWrapper(reason) {
- if (!called) {
- called = true;
- let index = unloaders.indexOf(unloadWrapper);
- if (index == -1)
- throw new Error("internal error: unloader not found");
- unloaders.splice(index, 1);
- originalDestructor.call(obj, reason);
- originalDestructor = null;
- destructorName = null;
- obj = null;
- }
- };
- // TODO: Find out why the order is inverted here. It seems that
- // it may be causing issues!
- unloaders.push(unloadWrapper);
- obj[destructorName] = unloadWrapper;
- };
- function unload(reason) {
- observers.forEach(function(observer) {
- try {
- observer(reason);
- }
- catch (error) {
- console.exception(error);
- }
- });
- }
- when(function(reason) {
- unloaders.slice().forEach(function(unloadWrapper) {
- unloadWrapper(reason);
- });
- });
- on('sdk:loader:destroy', function onunload({ subject, data: reason }) {
- // If this loader is unload then `subject.wrappedJSObject` will be
- // `destructor`.
- if (subject.wrappedJSObject === unloadSubject) {
- off('sdk:loader:destroy', onunload);
- unload(reason);
- }
- // Note that we use strong reference to listener here to make sure it's not
- // GC-ed, which may happen otherwise since nothing keeps reference to `onunolad`
- // function.
- }, true);
|