diff --git a/devtools/server/actors/inspector/constants.js b/devtools/server/actors/inspector/constants.js new file mode 100644 index 000000000000..c253c67b02d5 --- /dev/null +++ b/devtools/server/actors/inspector/constants.js @@ -0,0 +1,17 @@ +/* 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"; + +/** + * Any event listener flagged with this symbol will not be considered when + * the EventCollector class enumerates listeners for nodes. For example: + * + * const someListener = () => {}; + * someListener[EXCLUDED_LISTENER] = true; + * eventListenerService.addSystemEventListener(node, "event", someListener); + */ +const EXCLUDED_LISTENER = Symbol("event-collector-excluded-listener"); + +exports.EXCLUDED_LISTENER = EXCLUDED_LISTENER; diff --git a/devtools/server/actors/inspector/event-collector.js b/devtools/server/actors/inspector/event-collector.js index e537aa71c80d..3c467dba2ef7 100644 --- a/devtools/server/actors/inspector/event-collector.js +++ b/devtools/server/actors/inspector/event-collector.js @@ -17,6 +17,9 @@ const { } = require("devtools/shared/layout/utils"); const Debugger = require("Debugger"); const ReplayInspector = require("devtools/server/actors/replay/inspector"); +const { + EXCLUDED_LISTENER, +} = require("devtools/server/actors/inspector/constants"); // eslint-disable-next-line const JQUERY_LIVE_REGEX = /return typeof \w+.*.event\.triggered[\s\S]*\.event\.(dispatch|handle).*arguments/; @@ -253,6 +256,7 @@ class MainEventCollector { * An array of unfiltered event listeners or an empty array */ getDOMListeners(node) { + let listeners; if (typeof node.nodeName !== "undefined" && node.nodeName.toLowerCase() === "html") { const winListeners = Services.els.getListenerInfoFor(node.ownerGlobal) || []; @@ -261,9 +265,15 @@ class MainEventCollector { const docListeners = Services.els.getListenerInfoFor(node.parentNode) || []; - return [...winListeners, ...docElementListeners, ...docListeners]; + listeners = [...winListeners, ...docElementListeners, ...docListeners]; + } else { + listeners = Services.els.getListenerInfoFor(node) || []; } - return Services.els.getListenerInfoFor(node) || []; + + return listeners.filter(listener => { + const obj = this.unwrap(listener.listenerObject); + return !obj || !obj[EXCLUDED_LISTENER]; + }); } getJQuery(node) { diff --git a/devtools/server/actors/inspector/moz.build b/devtools/server/actors/inspector/moz.build index e7e60f1e5d6e..276f7ccd5e8c 100644 --- a/devtools/server/actors/inspector/moz.build +++ b/devtools/server/actors/inspector/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. DevToolsModules( + 'constants.js', 'css-logic.js', 'custom-element-watcher.js', 'document-walker.js', diff --git a/devtools/server/actors/inspector/walker.js b/devtools/server/actors/inspector/walker.js index 508981eb1f38..6c1a04749577 100644 --- a/devtools/server/actors/inspector/walker.js +++ b/devtools/server/actors/inspector/walker.js @@ -12,6 +12,9 @@ const {walkerSpec} = require("devtools/shared/specs/inspector"); const {LongStringActor} = require("devtools/server/actors/string"); const InspectorUtils = require("InspectorUtils"); const ReplayInspector = require("devtools/server/actors/replay/inspector"); +const { + EXCLUDED_LISTENER, +} = require("devtools/server/actors/inspector/constants"); loader.lazyRequireGetter(this, "getFrameElement", "devtools/shared/layout/utils", true); loader.lazyRequireGetter(this, "isAfterPseudoElement", "devtools/shared/layout/utils", true); @@ -160,9 +163,14 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, { this._retainedOrphans = new Set(); this.onNodeInserted = this.onNodeInserted.bind(this); + this.onNodeInserted[EXCLUDED_LISTENER] = true; this.onNodeRemoved = this.onNodeRemoved.bind(this); + this.onNodeRemoved[EXCLUDED_LISTENER] = true; this.onAttributeModified = this.onAttributeModified.bind(this); + this.onAttributeModified[EXCLUDED_LISTENER] = true; this.onNodeRemovedFromDocument = this.onNodeRemovedFromDocument.bind(this); + this.onNodeRemovedFromDocument[EXCLUDED_LISTENER] = true; + this.onMutations = this.onMutations.bind(this); this.onSlotchange = this.onSlotchange.bind(this); this.onShadowrootattached = this.onShadowrootattached.bind(this);