1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/system/unload.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,82 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +// Parts of this module were taken from narwhal: 1.9 +// 1.10 +// http://narwhaljs.org 1.11 + 1.12 +module.metadata = { 1.13 + "stability": "experimental" 1.14 +}; 1.15 + 1.16 +const { on, off } = require('./events'); 1.17 +const unloadSubject = require('@loader/unload'); 1.18 + 1.19 +const observers = []; 1.20 +const unloaders = []; 1.21 + 1.22 +var when = exports.when = function when(observer) { 1.23 + if (observers.indexOf(observer) != -1) 1.24 + return; 1.25 + observers.unshift(observer); 1.26 +}; 1.27 + 1.28 +var ensure = exports.ensure = function ensure(obj, destructorName) { 1.29 + if (!destructorName) 1.30 + destructorName = "unload"; 1.31 + if (!(destructorName in obj)) 1.32 + throw new Error("object has no '" + destructorName + "' property"); 1.33 + 1.34 + let called = false; 1.35 + let originalDestructor = obj[destructorName]; 1.36 + 1.37 + function unloadWrapper(reason) { 1.38 + if (!called) { 1.39 + called = true; 1.40 + let index = unloaders.indexOf(unloadWrapper); 1.41 + if (index == -1) 1.42 + throw new Error("internal error: unloader not found"); 1.43 + unloaders.splice(index, 1); 1.44 + originalDestructor.call(obj, reason); 1.45 + originalDestructor = null; 1.46 + destructorName = null; 1.47 + obj = null; 1.48 + } 1.49 + }; 1.50 + 1.51 + // TODO: Find out why the order is inverted here. It seems that 1.52 + // it may be causing issues! 1.53 + unloaders.push(unloadWrapper); 1.54 + 1.55 + obj[destructorName] = unloadWrapper; 1.56 +}; 1.57 + 1.58 +function unload(reason) { 1.59 + observers.forEach(function(observer) { 1.60 + try { 1.61 + observer(reason); 1.62 + } 1.63 + catch (error) { 1.64 + console.exception(error); 1.65 + } 1.66 + }); 1.67 +} 1.68 + 1.69 +when(function(reason) { 1.70 + unloaders.slice().forEach(function(unloadWrapper) { 1.71 + unloadWrapper(reason); 1.72 + }); 1.73 +}); 1.74 + 1.75 +on('sdk:loader:destroy', function onunload({ subject, data: reason }) { 1.76 + // If this loader is unload then `subject.wrappedJSObject` will be 1.77 + // `destructor`. 1.78 + if (subject.wrappedJSObject === unloadSubject) { 1.79 + off('sdk:loader:destroy', onunload); 1.80 + unload(reason); 1.81 + } 1.82 +// Note that we use strong reference to listener here to make sure it's not 1.83 +// GC-ed, which may happen otherwise since nothing keeps reference to `onunolad` 1.84 +// function. 1.85 +}, true);