mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-10-25 22:28:27 +00:00
77 lines
2.6 KiB
JavaScript
77 lines
2.6 KiB
JavaScript
/* 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";
|
|
|
|
module.metadata = {
|
|
"stability": "unstable"
|
|
};
|
|
|
|
const { Ci } = require("chrome");
|
|
|
|
var { emit } = require("./core");
|
|
var { when: unload } = require("../system/unload");
|
|
var listeners = new Map();
|
|
|
|
const { Cu } = require("chrome");
|
|
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
|
|
|
var getWindowFrom = x =>
|
|
x instanceof Ci.nsIDOMWindow ? x :
|
|
x instanceof Ci.nsIDOMDocument ? x.defaultView :
|
|
x instanceof Ci.nsIDOMNode ? x.ownerDocument.defaultView :
|
|
null;
|
|
|
|
function removeFromListeners() {
|
|
ShimWaiver.getProperty(this, "removeEventListener")("DOMWindowClose", removeFromListeners);
|
|
for (let cleaner of listeners.get(this))
|
|
cleaner();
|
|
|
|
listeners.delete(this);
|
|
}
|
|
|
|
// Simple utility function takes event target, event type and optional
|
|
// `options.capture` and returns node style event stream that emits "data"
|
|
// events every time event of that type occurs on the given `target`.
|
|
function open(target, type, options) {
|
|
let output = {};
|
|
let capture = options && options.capture ? true : false;
|
|
let listener = (event) => emit(output, "data", event);
|
|
|
|
// `open` is currently used only on DOM Window objects, however it was made
|
|
// to be used to any kind of `target` that supports `addEventListener`,
|
|
// therefore is safer get the `window` from the `target` instead assuming
|
|
// that `target` is the `window`.
|
|
let window = getWindowFrom(target);
|
|
|
|
// If we're not able to get a `window` from `target`, there is something
|
|
// wrong. We cannot add listeners that can leak later, or results in
|
|
// "dead object" exception.
|
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1001833
|
|
if (!window)
|
|
throw new Error("Unable to obtain the owner window from the target given.");
|
|
|
|
let cleaners = listeners.get(window);
|
|
if (!cleaners) {
|
|
cleaners = [];
|
|
listeners.set(window, cleaners);
|
|
|
|
// We need to remove from our map the `window` once is closed, to prevent
|
|
// memory leak
|
|
ShimWaiver.getProperty(window, "addEventListener")("DOMWindowClose", removeFromListeners);
|
|
}
|
|
|
|
cleaners.push(() => ShimWaiver.getProperty(target, "removeEventListener")(type, listener, capture));
|
|
ShimWaiver.getProperty(target, "addEventListener")(type, listener, capture);
|
|
|
|
return output;
|
|
}
|
|
|
|
unload(() => {
|
|
for (let window of listeners.keys())
|
|
removeFromListeners.call(window);
|
|
});
|
|
|
|
exports.open = open;
|