aboutsummaryrefslogtreecommitdiffstats
path: root/packages/vold-utils/lib/unload+.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/vold-utils/lib/unload+.js')
-rw-r--r--packages/vold-utils/lib/unload+.js80
1 files changed, 80 insertions, 0 deletions
diff --git a/packages/vold-utils/lib/unload+.js b/packages/vold-utils/lib/unload+.js
new file mode 100644
index 0000000..285fd46
--- /dev/null
+++ b/packages/vold-utils/lib/unload+.js
@@ -0,0 +1,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);