1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
/* 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";
const { Class } = require("sdk/core/heritage");
const unloadNS = require("sdk/core/namespace").ns();
var Unloader = exports.Unloader = Class({
initialize: function Unloader() {
let unloaders = unloadNS(this).unloaders = [];
let unloadersUnlaod = unloadNS(this).unloadersUnlaod = function() {
unloaders.slice().forEach(function(u) u());
unloaders.length = 0;
}
require("sdk/system/unload").when(unloadersUnlaod);
},
unload: function unload(callback, container) {
// Calling with no arguments runs all the unloader callbacks
if (callback == null) {
unloadNS(this).unloadersUnlaod();
return null;
}
var remover = removeUnloader.bind(null, unloader, unloadNS(this).unloaders);
// The callback is bound to the lifetime of the container if we have one
if (container != null) {
// Remove the unloader when the container unloads
container.addEventListener("unload", remover, false);
// Wrap the callback to additionally remove the unload listener
let origCallback = callback;
callback = function() {
container.removeEventListener("unload", remover, false);
origCallback();
}
}
// Wrap the callback in a function that ignores failures
function unloader() {
try {
callback();
}
catch(e) {
console.error(e);
}
}
unloadNS(this).unloaders.push(unloader);
// Provide a way to remove the unloader
return remover;
}
});
function removeUnloader(unloader, unloaders) {
let index = unloaders.indexOf(unloader);
if (index != -1)
unloaders.splice(index, 1);
}
/**
* Save callbacks to run when unloading. Optionally scope the callback to a
* container, e.g., window. Provide a way to run all the callbacks.
*
* @usage unload(): Run all callbacks and release them.
*
* @usage unload(callback): Add a callback to run on unload.
* @param [function] callback: 0-parameter function to call on unload.
* @return [function]: A 0-parameter function that undoes adding the callback.
*
* @usage unload(callback, container) Add a scoped callback to run on unload.
* @param [function] callback: 0-parameter function to call on unload.
* @param [node] container: Remove the callback when this container unloads.
* @return [function]: A 0-parameter function that undoes adding the callback.
*/
const gUnload = Unloader();
exports.unload = gUnload.unload.bind(gUnload);
|