mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-21 13:37:59 +01:00
Automatically track and remove long-lived event listeners.
This commit is contained in:
@@ -19,11 +19,9 @@ const Point = new Struct("x", "y");
|
|||||||
* @instance buffer
|
* @instance buffer
|
||||||
*/
|
*/
|
||||||
const Buffer = Module("buffer", {
|
const Buffer = Module("buffer", {
|
||||||
requires: ["autocommands", "config"],
|
requires: ["config"],
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
const self = this;
|
|
||||||
|
|
||||||
this.pageInfo = {};
|
this.pageInfo = {};
|
||||||
|
|
||||||
this.addPageInfoSection("f", "Feeds", function (verbose) {
|
this.addPageInfoSection("f", "Feeds", function (verbose) {
|
||||||
@@ -144,32 +142,6 @@ const Buffer = Module("buffer", {
|
|||||||
return Array.map(metaNodes, function (node) [(node.name || node.httpEquiv), template.highlightURL(node.content)])
|
return Array.map(metaNodes, function (node) [(node.name || node.httpEquiv), template.highlightURL(node.content)])
|
||||||
.sort(function (a, b) util.compareIgnoreCase(a[0], b[0]));
|
.sort(function (a, b) util.compareIgnoreCase(a[0], b[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
window.XULBrowserWindow = this.progressListener;
|
|
||||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
|
||||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
|
||||||
.treeOwner
|
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIXULWindow)
|
|
||||||
.XULBrowserWindow = this.progressListener;
|
|
||||||
|
|
||||||
try {
|
|
||||||
getBrowser().addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
|
|
||||||
}
|
|
||||||
catch (e) {} // Why? --djk
|
|
||||||
|
|
||||||
let appContent = document.getElementById("appcontent");
|
|
||||||
appContent.addEventListener("DOMContentLoaded", this.closure.onDOMContentLoaded, true);
|
|
||||||
// this adds an event which is is called on each page load, even if the
|
|
||||||
// page is loaded in a background tab
|
|
||||||
appContent.addEventListener("load", this.closure.onPageLoad, true);
|
|
||||||
// called when the active document is scrolled
|
|
||||||
this._updateBufferPosition = function _updateBufferPosition() {
|
|
||||||
statusline.updateBufferPosition();
|
|
||||||
modes.show();
|
|
||||||
};
|
|
||||||
appContent.addEventListener("scroll", self._updateBufferPosition, false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
@@ -177,11 +149,6 @@ const Buffer = Module("buffer", {
|
|||||||
getBrowser().removeProgressListener(this.progressListener);
|
getBrowser().removeProgressListener(this.progressListener);
|
||||||
}
|
}
|
||||||
catch (e) {} // Why? --djk
|
catch (e) {} // Why? --djk
|
||||||
|
|
||||||
let appContent = document.getElementById("appcontent");
|
|
||||||
appContent.removeEventListener("DOMContentLoaded", this.closure.onDOMContentLoaded, true);
|
|
||||||
appContent.removeEventListener("load", this.closure.onPageLoad, true);
|
|
||||||
appContent.removeEventListener("scroll", buffer._updateBufferPosition, false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_triggerLoadAutocmd: function _triggerLoadAutocmd(name, doc) {
|
_triggerLoadAutocmd: function _triggerLoadAutocmd(name, doc) {
|
||||||
@@ -198,6 +165,12 @@ const Buffer = Module("buffer", {
|
|||||||
autocommands.trigger(name, args);
|
autocommands.trigger(name, args);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// called when the active document is scrolled
|
||||||
|
_updateBufferPosition: function _updateBufferPosition() {
|
||||||
|
statusline.updateBufferPosition();
|
||||||
|
modes.show();
|
||||||
|
},
|
||||||
|
|
||||||
onDOMContentLoaded: function onDOMContentLoaded(event) {
|
onDOMContentLoaded: function onDOMContentLoaded(event) {
|
||||||
let doc = event.originalTarget;
|
let doc = event.originalTarget;
|
||||||
if (doc instanceof HTMLDocument && !doc.defaultView.frameElement)
|
if (doc instanceof HTMLDocument && !doc.defaultView.frameElement)
|
||||||
@@ -205,6 +178,8 @@ const Buffer = Module("buffer", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// TODO: see what can be moved to onDOMContentLoaded()
|
// TODO: see what can be moved to onDOMContentLoaded()
|
||||||
|
// event listener which is is called on each page load, even if the
|
||||||
|
// page is loaded in a background tab
|
||||||
onPageLoad: function onPageLoad(event) {
|
onPageLoad: function onPageLoad(event) {
|
||||||
if (event.originalTarget instanceof HTMLDocument) {
|
if (event.originalTarget instanceof HTMLDocument) {
|
||||||
let doc = event.originalTarget;
|
let doc = event.originalTarget;
|
||||||
@@ -1335,6 +1310,26 @@ const Buffer = Module("buffer", {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
events: function () {
|
||||||
|
window.XULBrowserWindow = this.progressListener;
|
||||||
|
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||||
|
.treeOwner
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIXULWindow)
|
||||||
|
.XULBrowserWindow = this.progressListener;
|
||||||
|
|
||||||
|
try {
|
||||||
|
getBrowser().addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
|
||||||
|
}
|
||||||
|
catch (e) {} // Why? --djk
|
||||||
|
|
||||||
|
let appContent = document.getElementById("appcontent");
|
||||||
|
events.addSessionListener(appContent, "DOMContentLoaded", this.closure.onDOMContentLoaded, true);
|
||||||
|
events.addSessionListener(appContent, "load", this.closure.onPageLoad, true);
|
||||||
|
events.addSessionListener(appContent, "scroll", this.closure._updateBufferPosition, false);
|
||||||
|
},
|
||||||
mappings: function () {
|
mappings: function () {
|
||||||
var myModes = config.browserModes;
|
var myModes = config.browserModes;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ const Events = Module("events", {
|
|||||||
this._currentMacro = "";
|
this._currentMacro = "";
|
||||||
this._lastMacro = "";
|
this._lastMacro = "";
|
||||||
|
|
||||||
|
this.sessionListeners = [];
|
||||||
|
|
||||||
this._macros = storage.newMap("macros", true, { privateData: true });
|
this._macros = storage.newMap("macros", true, { privateData: true });
|
||||||
|
|
||||||
// NOTE: the order of ["Esc", "Escape"] or ["Escape", "Esc"]
|
// NOTE: the order of ["Esc", "Escape"] or ["Escape", "Esc"]
|
||||||
@@ -119,30 +121,39 @@ const Events = Module("events", {
|
|||||||
|
|
||||||
this._wrappedOnKeyPress = wrapListener("onKeyPress");
|
this._wrappedOnKeyPress = wrapListener("onKeyPress");
|
||||||
this._wrappedOnKeyUpOrDown = wrapListener("onKeyUpOrDown");
|
this._wrappedOnKeyUpOrDown = wrapListener("onKeyUpOrDown");
|
||||||
window.addEventListener("keypress", this.closure._wrappedOnKeyPress, true);
|
this.addSessionListener(window, "keypress", this.closure._wrappedOnKeyPress, true);
|
||||||
window.addEventListener("keydown", this.closure._wrappedOnKeyUpOrDown, true);
|
this.addSessionListener(window, "keydown", this.closure._wrappedOnKeyUpOrDown, true);
|
||||||
window.addEventListener("keyup", this.closure._wrappedOnKeyUpOrDown, true);
|
this.addSessionListener(window, "keyup", this.closure._wrappedOnKeyUpOrDown, true);
|
||||||
|
|
||||||
this._activeMenubar = false;
|
this._activeMenubar = false;
|
||||||
window.addEventListener("popupshown", this.closure.onPopupShown, true);
|
this.addSessionListener(window, "popupshown", this.closure.onPopupShown, true);
|
||||||
window.addEventListener("popuphidden", this.closure.onPopupHidden, true);
|
this.addSessionListener(window, "popuphidden", this.closure.onPopupHidden, true);
|
||||||
window.addEventListener("DOMMenuBarActive", this.closure.onDOMMenuBarActive, true);
|
this.addSessionListener(window, "DOMMenuBarActive", this.closure.onDOMMenuBarActive, true);
|
||||||
window.addEventListener("DOMMenuBarInactive", this.closure.onDOMMenuBarInactive, true);
|
this.addSessionListener(window, "DOMMenuBarInactive", this.closure.onDOMMenuBarInactive, true);
|
||||||
window.addEventListener("resize", this.closure.onResize, true);
|
this.addSessionListener(window, "resize", this.closure.onResize, true);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
liberator.dump("TODO: remove all event listeners");
|
liberator.dump("Removing all event listeners");
|
||||||
|
for (let args in values(this.sessionListeners))
|
||||||
|
args[0].removeEventListener.apply(args[0], args.slice(1));
|
||||||
|
},
|
||||||
|
|
||||||
window.removeEventListener("popupshown", this.closure.onPopupShown, true);
|
/**
|
||||||
window.removeEventListener("popuphidden", this.closure.onPopupHidden, true);
|
* Adds an event listener for this session and removes it on
|
||||||
window.removeEventListener("DOMMenuBarActive", this.closure.onDOMMenuBarActive, true);
|
* liberator shutdown.
|
||||||
window.removeEventListener("DOMMenuBarInactive", this.closure.onDOMMenuBarInactive, true);
|
*
|
||||||
window.removeEventListener("resize", this.closure.onResize, true);
|
* @param {Element} target The element on which to listen.
|
||||||
window.removeEventListener("keypress", this.closure._wrappedOnKeyPress, true);
|
* @param {string} event The event to listen for.
|
||||||
window.removeEventListener("keydown", this.closure._wrappedOnKeyUpOrDown, true);
|
* @param {function} callback The function to call when the event is received.
|
||||||
window.removeEventListener("keyup", this.closure._wrappedOnKeyUpOrDown, true);
|
* @param {boolean} capture When true, listen during the capture
|
||||||
|
* phase, otherwise during the bubbling phase.
|
||||||
|
*/
|
||||||
|
addSessionListener: function (target, event, callback, capture) {
|
||||||
|
let args = Array.slice(arguments, 0);
|
||||||
|
target.addEventListener.apply(target, args.slice(1));
|
||||||
|
this.sessionListeners.push(args);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ const Marks = Module("marks", {
|
|||||||
this._urlMarks = storage.newMap("url-marks", { store: true, privateData: true });
|
this._urlMarks = storage.newMap("url-marks", { store: true, privateData: true });
|
||||||
|
|
||||||
this._pendingJumps = [];
|
this._pendingJumps = [];
|
||||||
|
|
||||||
var appContent = document.getElementById("appcontent");
|
|
||||||
if (appContent)
|
|
||||||
appContent.addEventListener("load", this.closure._onPageLoad, true);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,6 +236,11 @@ const Marks = Module("marks", {
|
|||||||
isLocalMark: function isLocalMark(mark) /^['`a-z]$/.test(mark),
|
isLocalMark: function isLocalMark(mark) /^['`a-z]$/.test(mark),
|
||||||
isURLMark: function isURLMark(mark) /^[A-Z0-9]$/.test(mark),
|
isURLMark: function isURLMark(mark) /^[A-Z0-9]$/.test(mark),
|
||||||
}, {
|
}, {
|
||||||
|
events: function () {
|
||||||
|
let appContent = document.getElementById("appcontent");
|
||||||
|
if (appContent)
|
||||||
|
events.addSessionListener(appContent, "load", this.closure._onPageLoad, true);
|
||||||
|
},
|
||||||
mappings: function () {
|
mappings: function () {
|
||||||
var myModes = config.browserModes;
|
var myModes = config.browserModes;
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ Module.list = [];
|
|||||||
Module.constructors = {};
|
Module.constructors = {};
|
||||||
|
|
||||||
window.addEventListener("load", function () {
|
window.addEventListener("load", function () {
|
||||||
|
window.removeEventListener("load", arguments.callee, false);
|
||||||
|
|
||||||
function dump(str) window.dump(String.replace(str, /\n?$/, "\n").replace(/^/m, Config.prototype.name.toLowerCase() + ": "));
|
function dump(str) window.dump(String.replace(str, /\n?$/, "\n").replace(/^/m, Config.prototype.name.toLowerCase() + ": "));
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
const deferredInit = { load: [] };
|
const deferredInit = { load: [] };
|
||||||
@@ -124,6 +126,7 @@ window.addEventListener("load", function () {
|
|||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
window.addEventListener("unload", function () {
|
window.addEventListener("unload", function () {
|
||||||
|
window.removeEventListener("unload", arguments.callee, false);
|
||||||
for (let [, mod] in iter(modules))
|
for (let [, mod] in iter(modules))
|
||||||
if (mod instanceof ModuleBase && "destroy" in mod)
|
if (mod instanceof ModuleBase && "destroy" in mod)
|
||||||
mod.destroy();
|
mod.destroy();
|
||||||
|
|||||||
@@ -26,12 +26,17 @@ const Tabs = Module("tabs", {
|
|||||||
this._lastBufferSwitchArgs = "";
|
this._lastBufferSwitchArgs = "";
|
||||||
this._lastBufferSwitchSpecial = true;
|
this._lastBufferSwitchSpecial = true;
|
||||||
|
|
||||||
let tabContainer = this.getBrowser().mTabContainer;
|
// hide tabs initially to prevent flickering when 'stal' would hide them
|
||||||
this._updateTabCount = function () { statusline.updateTabCount(true); };
|
// on startup
|
||||||
["TabMove", "TabOpen", "TabClose"].forEach(function (event) {
|
if (config.hasTabbrowser)
|
||||||
tabContainer.addEventListener(event, this._updateTabCount, false);
|
this.getBrowser().mTabContainer.collapsed = true; // FIXME: see 'stal' comment
|
||||||
}, this);
|
},
|
||||||
this._onTabSelect = function () {
|
|
||||||
|
_updateTabCount: function () {
|
||||||
|
statusline.updateTabCount(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onTabSelect: function () {
|
||||||
// TODO: is all of that necessary?
|
// TODO: is all of that necessary?
|
||||||
// I vote no. --Kris
|
// I vote no. --Kris
|
||||||
modes.reset();
|
modes.reset();
|
||||||
@@ -39,21 +44,6 @@ const Tabs = Module("tabs", {
|
|||||||
this.updateSelectionHistory();
|
this.updateSelectionHistory();
|
||||||
if (options["focuscontent"])
|
if (options["focuscontent"])
|
||||||
setTimeout(function () { liberator.focusContent(true); }, 10); // just make sure, that no widget has focus
|
setTimeout(function () { liberator.focusContent(true); }, 10); // just make sure, that no widget has focus
|
||||||
};
|
|
||||||
tabContainer.addEventListener("TabSelect", this.closure._onTabSelect, false);
|
|
||||||
|
|
||||||
// hide tabs initially to prevent flickering when 'stal' would hide them
|
|
||||||
// on startup
|
|
||||||
if (config.hasTabbrowser)
|
|
||||||
this.getBrowser().mTabContainer.collapsed = true; // FIXME: see 'stal' comment
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function () {
|
|
||||||
let tabContainer = this.getBrowser().mTabContainer;
|
|
||||||
["TabMove", "TabOpen", "TabClose"].forEach(function (event) {
|
|
||||||
tabContainer.removeEventListener(event, this._updateTabCount, false);
|
|
||||||
}, this);
|
|
||||||
tabContainer.removeEventListener("TabSelect", this.closure._onTabSelect, false);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -942,6 +932,13 @@ const Tabs = Module("tabs", {
|
|||||||
"Open tabs",
|
"Open tabs",
|
||||||
completion.buffer);
|
completion.buffer);
|
||||||
},
|
},
|
||||||
|
events: function () {
|
||||||
|
let tabContainer = this.getBrowser().mTabContainer;
|
||||||
|
["TabMove", "TabOpen", "TabClose"].forEach(function (event) {
|
||||||
|
events.addSessionListener(tabContainer, event, this.closure._updateTabCount, false);
|
||||||
|
}, this);
|
||||||
|
events.addSessionListener(tabContainer, "TabSelect", this.closure._onTabSelect, false);
|
||||||
|
},
|
||||||
mappings: function () {
|
mappings: function () {
|
||||||
mappings.add([modes.NORMAL], ["g0", "g^"],
|
mappings.add([modes.NORMAL], ["g0", "g^"],
|
||||||
"Go to the first tab",
|
"Go to the first tab",
|
||||||
|
|||||||
Reference in New Issue
Block a user