Diff
Modified: trunk/LayoutTests/ChangeLog (243243 => 243244)
--- trunk/LayoutTests/ChangeLog 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/LayoutTests/ChangeLog 2019-03-20 21:55:05 UTC (rev 243244)
@@ -1,5 +1,18 @@
2019-03-20 Devin Rousso <[email protected]>
+ Web Inspector: DOM: include window as part of any event listener chain
+ https://bugs.webkit.org/show_bug.cgi?id=195730
+ <rdar://problem/48916872>
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/dom/getEventListenersForNode.html:
+ * inspector/dom/getEventListenersForNode-expected.txt:
+ * inspector/dom/setEventListenerDisabled.html:
+ * inspector/dom/event-listener-add-remove.html:
+
+2019-03-20 Devin Rousso <[email protected]>
+
Web Inspector: Debugger: virtualize the list of variables in the Scope sidebar
https://bugs.webkit.org/show_bug.cgi?id=192648
<rdar://problem/46800949>
Modified: trunk/LayoutTests/inspector/dom/event-listener-add-remove.html (243243 => 243244)
--- trunk/LayoutTests/inspector/dom/event-listener-add-remove.html 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/LayoutTests/inspector/dom/event-listener-add-remove.html 2019-03-20 21:55:05 UTC (rev 243244)
@@ -53,10 +53,12 @@
}
function logListeners(expectedCount) {
- return DOMAgent.getEventListenersForNode(node.id).then((payload) => {
- InspectorTest.expectEqual(payload.listeners.length, expectedCount, `There should be ${expectedCount} event listeners.`);
+ return DOMAgent.getEventListenersForNode(node.id).then(({listeners}) => {
+ listeners = listeners.filter((listener) => listener.nodeId === node.id);
- for (let eventListener of payload.listeners)
+ InspectorTest.expectEqual(listeners.length, expectedCount, `There should be ${expectedCount} event listeners.`);
+
+ for (let eventListener of listeners)
InspectorTest.log(` - "${eventListener.type}"`);
});
}
@@ -67,10 +69,12 @@
name: "DOM.eventListeners.Initial",
description: "Test that the document has no event listeners.",
test(resolve, reject) {
- DOMAgent.getEventListenersForNode(node.id).then((payload) => {
- InspectorTest.expectEqual(payload.listeners.length, 0, "There should be no event listeners.");
+ DOMAgent.getEventListenersForNode(node.id).then(({listeners}) => {
+ listeners = listeners.filter((listener) => listener.nodeId === node.id);
- for (let eventListener of payload.listeners)
+ InspectorTest.expectEqual(listeners.length, 0, "There should be no event listeners.");
+
+ for (let eventListener of listeners)
InspectorTest.log(eventListener.type);
}).then(resolve, reject);
}
Modified: trunk/LayoutTests/inspector/dom/getEventListenersForNode-expected.txt (243243 => 243244)
--- trunk/LayoutTests/inspector/dom/getEventListenersForNode-expected.txt 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/LayoutTests/inspector/dom/getEventListenersForNode-expected.txt 2019-03-20 21:55:05 UTC (rev 243244)
@@ -4,73 +4,85 @@
== Running test suite: DOM.getEventListenersForNode
-- Running test case: DOM.getEventListenersForNode.Basic
Event: A
-Node: body
+Target: body
Capture: true
Attribute: false
Handler Name: bodyA
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: B
-Node: body
+Target: body
Capture: true
Attribute: false
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: E
-Node: div#x
+Target: div#x
Capture: false
Attribute: false
Handler Name: ObjectEventHandler
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: D
-Node: div#x
+Target: div#x
Capture: false
Attribute: false
Handler Name: handleEvent
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: C
-Node: div#x
+Target: div#x
Capture: false
Attribute: false
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: B
-Node: div#x
+Target: div#x
Capture: false
Attribute: false
Handler Name: xB
Once: true
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: A
-Node: div#x
+Target: div#x
Capture: false
Attribute: false
Handler Name: xA
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: click
-Node: div#x
+Target: div#x
Capture: false
Attribute: true
Handler Name: onclick
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: B
-Node: #document
+Target: #document
Capture: false
Attribute: false
Passive: true
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
Event: A
-Node: #document
+Target: #document
Capture: false
Attribute: false
Handler Name: documentA
Passive: true
-PASS: The Event Listener has a source location.
+The Event Listener has a source location.
+Event: load
+Target: window
+Capture: false
+Attribute: true
+Handler Name: onload
+The Event Listener has a source location.
+Event: error
+Target: window
+Capture: false
+Attribute: true
+
+
Modified: trunk/LayoutTests/inspector/dom/getEventListenersForNode.html (243243 => 243244)
--- trunk/LayoutTests/inspector/dom/getEventListenersForNode.html 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/LayoutTests/inspector/dom/getEventListenersForNode.html 2019-03-20 21:55:05 UTC (rev 243244)
@@ -19,11 +19,13 @@
}
for (let eventListener of eventListeners) {
- let node = WI.domManager.nodeForId(eventListener.nodeId);
-
-
InspectorTest.log(`Event: ${eventListener.type}`);
- InspectorTest.log(`Node: ${node.displayName}`);
+ if (eventListener.nodeId) {
+ let node = WI.domManager.nodeForId(eventListener.nodeId);
+ InspectorTest.log(`Target: ${node.displayName}`);
+ }
+ if (eventListener.onWindow)
+ InspectorTest.log("Target: window");
InspectorTest.log(`Capture: ${eventListener.useCapture}`);
InspectorTest.log(`Attribute: ${eventListener.isAttribute}`);
@@ -33,9 +35,9 @@
InspectorTest.log(`Passive: ${eventListener.passive}`);
if (eventListener.once)
InspectorTest.log(`Once: ${eventListener.once}`);
+ if (eventListener.location)
+ InspectorTest.log("The Event Listener has a source location.");
- InspectorTest.expectThat(eventListener.location, "The Event Listener has a source location.");
-
InspectorTest.log("");
}
Modified: trunk/LayoutTests/inspector/dom/setEventListenerDisabled.html (243243 => 243244)
--- trunk/LayoutTests/inspector/dom/setEventListenerDisabled.html 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/LayoutTests/inspector/dom/setEventListenerDisabled.html 2019-03-20 21:55:05 UTC (rev 243244)
@@ -16,6 +16,7 @@
function logListener() {
return DOMAgent.getEventListenersForNode(clickEventListener.nodeId).then(({listeners}) => {
+ listeners = listeners.filter((listener) => listener.nodeId === clickEventListener.nodeId);
InspectorTest.assert(listeners.length === 1, "There should only be one event listener.");
InspectorTest.assert(listeners[0].type === "click", `There event listener should be for "click".`);
InspectorTest.log("Click event listener is " + (listeners[0].disabled ? "disabled" : "enabled") + ".");
Modified: trunk/Source/_javascript_Core/ChangeLog (243243 => 243244)
--- trunk/Source/_javascript_Core/ChangeLog 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-03-20 21:55:05 UTC (rev 243244)
@@ -1,5 +1,18 @@
2019-03-20 Devin Rousso <[email protected]>
+ Web Inspector: DOM: include window as part of any event listener chain
+ https://bugs.webkit.org/show_bug.cgi?id=195730
+ <rdar://problem/48916872>
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/protocol/DOM.json:
+ Modify `DOM.getEventListenersForNode` to not save the handler object, as that was never
+ used by the frontend. Add an `onWindow` optional property to `DOM.EventListener` that is set
+ when the event listener was retrieved from the `window` object.
+
+2019-03-20 Devin Rousso <[email protected]>
+
Web Inspector: Runtime: lazily create the agent
https://bugs.webkit.org/show_bug.cgi?id=195972
<rdar://problem/49039655>
Modified: trunk/Source/_javascript_Core/inspector/protocol/DOM.json (243243 => 243244)
--- trunk/Source/_javascript_Core/inspector/protocol/DOM.json 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/_javascript_Core/inspector/protocol/DOM.json 2019-03-20 21:55:05 UTC (rev 243244)
@@ -87,10 +87,10 @@
{ "name": "type", "type": "string", "description": "<code>EventListener</code>'s type." },
{ "name": "useCapture", "type": "boolean", "description": "<code>EventListener</code>'s useCapture." },
{ "name": "isAttribute", "type": "boolean", "description": "<code>EventListener</code>'s isAttribute." },
- { "name": "nodeId", "$ref": "NodeId", "description": "Target <code>DOMNode</code> id." },
+ { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "The target <code>DOMNode</code> id if the event listener is for a node." },
+ { "name": "onWindow", "type": "boolean", "optional": true, "description": "True if the event listener was added to the window." },
{ "name": "location", "$ref": "Debugger.Location", "optional": true, "description": "Handler code location." },
{ "name": "handlerName", "type": "string", "optional": true, "description": "Event handler function name." },
- { "name": "handlerObject", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." },
{ "name": "passive", "type": "boolean", "optional": true, "description": "<code>EventListener</code>'s passive." },
{ "name": "once", "type": "boolean", "optional": true, "description": "<code>EventListener</code>'s once." },
{ "name": "disabled", "type": "boolean", "optional": true },
@@ -289,8 +289,7 @@
"name": "getEventListenersForNode",
"description": "Returns event listeners relevant to the node.",
"parameters": [
- { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get listeners for." },
- { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name for handler value. Handler value is not returned without this parameter specified." }
+ { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get listeners for." }
],
"returns": [
{ "name": "listeners", "type": "array", "items": { "$ref": "EventListener"}, "description": "Array of relevant listeners." }
Modified: trunk/Source/WebCore/ChangeLog (243243 => 243244)
--- trunk/Source/WebCore/ChangeLog 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebCore/ChangeLog 2019-03-20 21:55:05 UTC (rev 243244)
@@ -1,5 +1,22 @@
2019-03-20 Devin Rousso <[email protected]>
+ Web Inspector: DOM: include window as part of any event listener chain
+ https://bugs.webkit.org/show_bug.cgi?id=195730
+ <rdar://problem/48916872>
+
+ Reviewed by Timothy Hatcher.
+
+ Test: inspector/dom/getEventListenersForNode.html
+
+ * inspector/agents/InspectorDOMAgent.h:
+ (WebCore::EventListenerInfo::EventListenerInfo): Deleted.
+ * inspector/agents/InspectorDOMAgent.cpp:
+ (WebCore::InspectorDOMAgent::getEventListenersForNode):
+ (WebCore::InspectorDOMAgent::buildObjectForEventListener):
+ (WebCore::InspectorDOMAgent::getEventListeners): Deleted.
+
+2019-03-20 Devin Rousso <[email protected]>
+
Web Inspector: Runtime: lazily create the agent
https://bugs.webkit.org/show_bug.cgi?id=195972
<rdar://problem/49039655>
Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp (243243 => 243244)
--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2019-03-20 21:55:05 UTC (rev 243244)
@@ -876,14 +876,40 @@
errorString = "Not supported"_s;
}
-void InspectorDOMAgent::getEventListenersForNode(ErrorString& errorString, int nodeId, const String* objectGroup, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray)
+void InspectorDOMAgent::getEventListenersForNode(ErrorString& errorString, int nodeId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray)
{
listenersArray = JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>::create();
- Node* node = assertNode(errorString, nodeId);
+
+ auto* node = assertNode(errorString, nodeId);
if (!node)
return;
+
+ Vector<RefPtr<EventTarget>> ancestors;
+ ancestors.append(node);
+ for (auto* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
+ ancestors.append(ancestor);
+ if (auto* window = node->document().domWindow())
+ ancestors.append(window);
+
+ struct EventListenerInfo {
+ RefPtr<EventTarget> eventTarget;
+ const AtomicString eventType;
+ const EventListenerVector eventListeners;
+ };
+
Vector<EventListenerInfo> eventInformation;
- getEventListeners(node, eventInformation, true);
+ for (size_t i = ancestors.size(); i; --i) {
+ auto& ancestor = ancestors[i - 1];
+ for (auto& eventType : ancestor->eventTypes()) {
+ EventListenerVector filteredListeners;
+ for (auto& listener : ancestor->eventListeners(eventType)) {
+ if (listener->callback().type() == EventListener::JSEventListenerType)
+ filteredListeners.append(listener);
+ }
+ if (!filteredListeners.isEmpty())
+ eventInformation.append({ ancestor, eventType, WTFMove(filteredListeners) });
+ }
+ }
auto addListener = [&] (RegisteredEventListener& listener, const EventListenerInfo& info) {
int identifier = 0;
@@ -891,7 +917,7 @@
bool hasBreakpoint = false;
for (auto& inspectorEventListener : m_eventListenerEntries.values()) {
- if (inspectorEventListener.matches(*info.node, info.eventType, listener.callback(), listener.useCapture())) {
+ if (inspectorEventListener.matches(*info.eventTarget, info.eventType, listener.callback(), listener.useCapture())) {
identifier = inspectorEventListener.identifier;
disabled = inspectorEventListener.disabled;
hasBreakpoint = inspectorEventListener.hasBreakpoint;
@@ -900,7 +926,7 @@
}
if (!identifier) {
- InspectorEventListener inspectorEventListener(m_lastEventListenerId++, *info.node, info.eventType, listener.callback(), listener.useCapture());
+ InspectorEventListener inspectorEventListener(m_lastEventListenerId++, *info.eventTarget, info.eventType, listener.callback(), listener.useCapture());
identifier = inspectorEventListener.identifier;
disabled = inspectorEventListener.disabled;
@@ -909,13 +935,13 @@
m_eventListenerEntries.add(identifier, inspectorEventListener);
}
- listenersArray->addItem(buildObjectForEventListener(listener, identifier, info.eventType, info.node, objectGroup, disabled, hasBreakpoint));
+ listenersArray->addItem(buildObjectForEventListener(listener, identifier, *info.eventTarget, info.eventType, disabled, hasBreakpoint));
};
// Get Capturing Listeners (in this order)
size_t eventInformationLength = eventInformation.size();
for (auto& info : eventInformation) {
- for (auto& listener : info.eventListenerVector) {
+ for (auto& listener : info.eventListeners) {
if (listener->useCapture())
addListener(*listener, info);
}
@@ -924,7 +950,7 @@
// Get Bubbling Listeners (reverse order)
for (size_t i = eventInformationLength; i; --i) {
const EventListenerInfo& info = eventInformation[i - 1];
- for (auto& listener : info.eventListenerVector) {
+ for (auto& listener : info.eventListeners) {
if (!listener->useCapture())
addListener(*listener, info);
}
@@ -931,38 +957,6 @@
}
}
-void InspectorDOMAgent::getEventListeners(Node* node, Vector<EventListenerInfo>& eventInformation, bool includeAncestors)
-{
- // The Node's Ancestors including self.
- Vector<Node*> ancestors;
- // Push this node as the firs element.
- ancestors.append(node);
- if (includeAncestors) {
- for (ContainerNode* ancestor = node->parentOrShadowHostNode(); ancestor; ancestor = ancestor->parentOrShadowHostNode())
- ancestors.append(ancestor);
- }
-
- // Nodes and their Listeners for the concerned event types (order is top to bottom)
- for (size_t i = ancestors.size(); i; --i) {
- Node* ancestor = ancestors[i - 1];
- EventTargetData* d = ancestor->eventTargetData();
- if (!d)
- continue;
- // Get the list of event types this Node is concerned with
- for (auto& type : d->eventListenerMap.eventTypes()) {
- auto& listeners = ancestor->eventListeners(type);
- EventListenerVector filteredListeners;
- filteredListeners.reserveInitialCapacity(listeners.size());
- for (auto& listener : listeners) {
- if (listener->callback().type() == EventListener::JSEventListenerType)
- filteredListeners.uncheckedAppend(listener);
- }
- if (!filteredListeners.isEmpty())
- eventInformation.append(EventListenerInfo(ancestor, type, WTFMove(filteredListeners)));
- }
- }
-}
-
void InspectorDOMAgent::setEventListenerDisabled(ErrorString& errorString, int eventListenerId, bool disabled)
{
auto it = m_eventListenerEntries.find(eventListenerId);
@@ -1660,13 +1654,10 @@
return pseudoElements;
}
-Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, int identifier, const AtomicString& eventType, Node* node, const String* objectGroupId, bool disabled, bool hasBreakpoint)
+Ref<Inspector::Protocol::DOM::EventListener> InspectorDOMAgent::buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, int identifier, EventTarget& eventTarget, const AtomicString& eventType, bool disabled, bool hasBreakpoint)
{
Ref<EventListener> eventListener = registeredEventListener.callback();
- JSC::ExecState* exec = nullptr;
- JSC::JSObject* handlerObject = nullptr;
- JSC::JSFunction* handlerFunction = nullptr;
String handlerName;
int lineNumber = 0;
int columnNumber = 0;
@@ -1674,12 +1665,25 @@
if (is<JSEventListener>(eventListener.get())) {
auto& scriptListener = downcast<JSEventListener>(eventListener.get());
+ Document* document = nullptr;
+ if (auto* scriptExecutionContext = eventTarget.scriptExecutionContext()) {
+ if (is<Document>(scriptExecutionContext))
+ document = downcast<Document>(scriptExecutionContext);
+ } else if (is<Node>(eventTarget))
+ document = &downcast<Node>(eventTarget).document();
+
+ JSC::JSObject* handlerObject = nullptr;
+ JSC::ExecState* exec = nullptr;
+
JSC::JSLockHolder lock(scriptListener.isolatedWorld().vm());
- exec = execStateFromNode(scriptListener.isolatedWorld(), &node->document());
- handlerObject = scriptListener.jsFunction(node->document());
+ if (document) {
+ handlerObject = scriptListener.jsFunction(*document);
+ exec = execStateFromNode(scriptListener.isolatedWorld(), document);
+ }
+
if (handlerObject && exec) {
- handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(exec->vm(), handlerObject);
+ JSC::JSFunction* handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(exec->vm(), handlerObject);
if (!handlerFunction) {
auto scope = DECLARE_CATCH_SCOPE(exec->vm());
@@ -1716,13 +1720,11 @@
.setType(eventType)
.setUseCapture(registeredEventListener.useCapture())
.setIsAttribute(eventListener->isAttribute())
- .setNodeId(pushNodePathToFrontend(node))
.release();
- if (objectGroupId && handlerObject && exec) {
- InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(exec);
- if (!injectedScript.hasNoValue())
- value->setHandlerObject(injectedScript.wrapObject(handlerObject, *objectGroupId));
- }
+ if (is<Node>(eventTarget))
+ value->setNodeId(pushNodePathToFrontend(&downcast<Node>(eventTarget)));
+ else if (is<DOMWindow>(eventTarget))
+ value->setOnWindow(true);
if (!scriptID.isNull()) {
auto location = Inspector::Protocol::Debugger::Location::create()
.setScriptId(scriptID)
Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h (243243 => 243244)
--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.h 2019-03-20 21:55:05 UTC (rev 243244)
@@ -77,19 +77,6 @@
typedef String ErrorString;
-struct EventListenerInfo {
- EventListenerInfo(Node* node, const AtomicString& eventType, EventListenerVector&& eventListenerVector)
- : node(node)
- , eventType(eventType)
- , eventListenerVector(WTFMove(eventListenerVector))
- {
- }
-
- Node* node;
- const AtomicString eventType;
- const EventListenerVector eventListenerVector;
-};
-
class InspectorDOMAgent final : public InspectorAgentBase, public Inspector::DOMBackendDispatcherHandler {
WTF_MAKE_NONCOPYABLE(InspectorDOMAgent);
WTF_MAKE_FAST_ALLOCATED;
@@ -129,7 +116,7 @@
void getSupportedEventNames(ErrorString&, RefPtr<JSON::ArrayOf<String>>& eventNames) override;
void getDataBindingsForNode(ErrorString&, int nodeId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::DataBinding>>& dataArray) override;
void getAssociatedDataForNode(ErrorString&, int nodeId, Optional<String>& associatedData) override;
- void getEventListenersForNode(ErrorString&, int nodeId, const WTF::String* objectGroup, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray) override;
+ void getEventListenersForNode(ErrorString&, int nodeId, RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::EventListener>>& listenersArray) override;
void setEventListenerDisabled(ErrorString&, int eventListenerId, bool disabled) override;
void setBreakpointForEventListener(ErrorString&, int eventListenerId) override;
void removeBreakpointForEventListener(ErrorString&, int eventListenerId) override;
@@ -156,9 +143,6 @@
void focus(ErrorString&, int nodeId) override;
void setInspectedNode(ErrorString&, int nodeId) override;
- void getEventListeners(Node*, Vector<EventListenerInfo>& listenersArray, bool includeAncestors);
-
-
// InspectorInstrumentation
int identifierForNode(Node&);
void addEventListenersToNode(Node&);
@@ -248,7 +232,7 @@
Ref<JSON::ArrayOf<String>> buildArrayForElementAttributes(Element*);
Ref<JSON::ArrayOf<Inspector::Protocol::DOM::Node>> buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap);
RefPtr<JSON::ArrayOf<Inspector::Protocol::DOM::Node>> buildArrayForPseudoElements(const Element&, NodeToIdMap* nodesMap);
- Ref<Inspector::Protocol::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, int identifier, const AtomicString& eventType, Node*, const String* objectGroupId, bool disabled, bool hasBreakpoint);
+ Ref<Inspector::Protocol::DOM::EventListener> buildObjectForEventListener(const RegisteredEventListener&, int identifier, EventTarget&, const AtomicString& eventType, bool disabled, bool hasBreakpoint);
RefPtr<Inspector::Protocol::DOM::AccessibilityProperties> buildObjectForAccessibilityProperties(Node*);
void processAccessibilityChildren(AccessibilityObject&, JSON::ArrayOf<int>&);
Modified: trunk/Source/WebInspectorUI/ChangeLog (243243 => 243244)
--- trunk/Source/WebInspectorUI/ChangeLog 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/ChangeLog 2019-03-20 21:55:05 UTC (rev 243244)
@@ -1,5 +1,47 @@
2019-03-20 Devin Rousso <[email protected]>
+ Web Inspector: DOM: include window as part of any event listener chain
+ https://bugs.webkit.org/show_bug.cgi?id=195730
+ <rdar://problem/48916872>
+
+ Reviewed by Timothy Hatcher.
+
+ Allow non-nodes (e.g. `window`) to be listed as the target of an event listener.
+ Add support for the same concept when showing breakpoint details after pausing on a specific
+ event listener in the Debugger/Sources navigation sidebar.
+
+ * UserInterface/Views/DOMNodeDetailsSidebarPanel.js:
+ (WI.DOMNodeDetailsSidebarPanel.prototype.initialLayout):
+ (WI.DOMNodeDetailsSidebarPanel.prototype._refreshEventListeners.generateGroupsByEvent):
+ (WI.DOMNodeDetailsSidebarPanel.prototype._refreshEventListeners.generateGroupsByTarget): Added.
+ (WI.DOMNodeDetailsSidebarPanel.prototype._refreshEventListeners.eventListenersCallback):
+ (WI.DOMNodeDetailsSidebarPanel.prototype._refreshEventListeners):
+ (WI.DOMNodeDetailsSidebarPanel.prototype._refreshEventListeners.generateGroupsByNode): Deleted.
+
+ * UserInterface/Views/EventListenerSectionGroup.js:
+ (WI.EventListenerSectionGroup.prototype._targetTextOrLink): Added.
+ (WI.EventListenerSectionGroup.prototype._nodeTextOrLink): Deleted.
+
+ * UserInterface/Views/DebuggerSidebarPanel.js:
+ (WI.DebuggerSidebarPanel.prototype._addBreakpoint):
+ (WI.DebuggerSidebarPanel.prototype._breakpointTreeOutlineDeleteTreeElement):
+ (WI.DebuggerSidebarPanel.prototype._treeSelectionDidChange):
+ (WI.DebuggerSidebarPanel.prototype._updatePauseReasonSection):
+ * UserInterface/Views/DebuggerSidebarPanel.css:
+ (.sidebar > .panel.navigation.debugger > .content > .breakpoints .tree-outline .item.event-target-window .icon): Added.
+
+ * UserInterface/Views/SourcesNavigationSidebarPanel.js:
+ (WI.SourcesNavigationSidebarPanel):
+ (WI.SourcesNavigationSidebarPanel.prototype._addBreakpoint):
+ (WI.SourcesNavigationSidebarPanel.prototype._updatePauseReasonSection):
+ (WI.SourcesNavigationSidebarPanel.prototype._handleTreeSelectionDidChange):
+ * UserInterface/Views/SourcesNavigationSidebarPanel.css:
+ (.sidebar > .panel.navigation.sources > .content > .breakpoints .tree-outline .item.event-target-window .icon): Added.
+
+ * Localizations/en.lproj/localizedStrings.js:
+
+2019-03-20 Devin Rousso <[email protected]>
+
Web Inspector: Debugger: virtualize the list of variables in the Scope sidebar
https://bugs.webkit.org/show_bug.cgi?id=192648
<rdar://problem/46800949>
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (243243 => 243244)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2019-03-20 21:55:05 UTC (rev 243244)
@@ -515,8 +515,8 @@
localizedStrings["Group"] = "Group";
localizedStrings["Group Media Requests"] = "Group Media Requests";
localizedStrings["Group by Event"] = "Group by Event";
-localizedStrings["Group by Node"] = "Group by Node";
localizedStrings["Group by Path"] = "Group by Path";
+localizedStrings["Group by Target"] = "Group by Target";
localizedStrings["Group by Type"] = "Group by Type";
localizedStrings["Grouping Method"] = "Grouping Method";
localizedStrings["Grouping Mode"] = "Grouping Mode";
@@ -1028,6 +1028,7 @@
localizedStrings["Tabs"] = "Tabs";
localizedStrings["Tag"] = "Tag";
localizedStrings["Take snapshot"] = "Take snapshot";
+localizedStrings["Target"] = "Target";
localizedStrings["Template Content"] = "Template Content";
localizedStrings["Text"] = "Text";
localizedStrings["Text Frame"] = "Text Frame";
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js (243243 => 243244)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMNodeDetailsSidebarPanel.js 2019-03-20 21:55:05 UTC (rev 243244)
@@ -90,7 +90,7 @@
}
createOption(WI.UIString("Group by Event"), WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod.Event);
- createOption(WI.UIString("Group by Node"), WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod.Node);
+ createOption(WI.UIString("Group by Target"), WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod.Target);
eventListenersGroupMethodSelectElement.value = this._eventListenerGroupingMethodSetting.value;
@@ -341,6 +341,8 @@
if (!domNode)
return;
+ const windowTargetIdentifier = Symbol("window");
+
function createEventListenerSection(title, eventListeners, options = {}) {
let groups = eventListeners.map((eventListener) => new WI.EventListenerSectionGroup(eventListener, options));
@@ -354,12 +356,13 @@
function generateGroupsByEvent(eventListeners) {
let eventListenerTypes = new Map;
for (let eventListener of eventListeners) {
- eventListener.node = WI.domManager.nodeForId(eventListener.nodeId);
+ console.assert(eventListener.nodeId || eventListener.onWindow);
+ if (eventListener.nodeId)
+ eventListener.node = WI.domManager.nodeForId(eventListener.nodeId);
let eventListenersForType = eventListenerTypes.get(eventListener.type);
if (!eventListenersForType)
eventListenerTypes.set(eventListener.type, eventListenersForType = []);
-
eventListenersForType.push(eventListener);
}
@@ -373,33 +376,44 @@
return rows;
}
- function generateGroupsByNode(eventListeners) {
- let eventListenerNodes = new Map;
+ function generateGroupsByTarget(eventListeners) {
+ let eventListenerTargets = new Map;
for (let eventListener of eventListeners) {
- eventListener.node = WI.domManager.nodeForId(eventListener.nodeId);
+ console.assert(eventListener.nodeId || eventListener.onWindow);
+ if (eventListener.nodeId)
+ eventListener.node = WI.domManager.nodeForId(eventListener.nodeId);
- let eventListenersForNode = eventListenerNodes.get(eventListener.node);
- if (!eventListenersForNode)
- eventListenerNodes.set(eventListener.node, eventListenersForNode = []);
-
- eventListenersForNode.push(eventListener);
+ let target = eventListener.onWindow ? windowTargetIdentifier : eventListener.node;
+ let eventListenersForTarget = eventListenerTargets.get(target);
+ if (!eventListenersForTarget)
+ eventListenerTargets.set(target, eventListenersForTarget = []);
+ eventListenersForTarget.push(eventListener);
}
let rows = [];
- let currentNode = domNode;
- do {
- let eventListenersForNode = eventListenerNodes.get(currentNode);
- if (!eventListenersForNode)
- continue;
+ function generateSectionForTarget(target) {
+ let eventListenersForTarget = eventListenerTargets.get(target);
+ if (!eventListenersForTarget)
+ return;
- eventListenersForNode.sort((a, b) => a.type.toLowerCase().extendedLocaleCompare(b.type.toLowerCase()));
+ eventListenersForTarget.sort((a, b) => a.type.toLowerCase().extendedLocaleCompare(b.type.toLowerCase()));
- let section = createEventListenerSection(currentNode.displayName, eventListenersForNode, {hideNode: true});
- WI.bindInteractionsForNodeToElement(currentNode, section.titleElement, {ignoreClick: true});
+ let title = target === windowTargetIdentifier ? WI.unlocalizedString("window") : target.displayName;
+
+ let section = createEventListenerSection(title, eventListenersForTarget, {hideTarget: true});
+ if (target instanceof WI.DOMNode)
+ WI.bindInteractionsForNodeToElement(target, section.titleElement, {ignoreClick: true});
rows.push(section);
+ }
+
+ let currentNode = domNode;
+ do {
+ generateSectionForTarget(currentNode);
} while (currentNode = currentNode.parentNode);
+ generateSectionForTarget(windowTargetIdentifier);
+
return rows;
}
@@ -424,8 +438,8 @@
this._eventListenersSectionGroup.rows = generateGroupsByEvent.call(this, eventListeners);
break;
- case WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod.Node:
- this._eventListenersSectionGroup.rows = generateGroupsByNode.call(this, eventListeners);
+ case WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod.Target:
+ this._eventListenersSectionGroup.rows = generateGroupsByTarget.call(this, eventListeners);
break;
}
}
@@ -950,5 +964,5 @@
WI.DOMNodeDetailsSidebarPanel.EventListenerGroupingMethod = {
Event: "event",
- Node: "node",
+ Target: "target",
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.css (243243 => 243244)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.css 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.css 2019-03-20 21:55:05 UTC (rev 243244)
@@ -103,6 +103,10 @@
border-bottom: none;
}
+.sidebar > .panel.navigation.debugger > .content > .breakpoints .tree-outline .item.event-target-window .icon {
+ content: url(../Images/TypeObject.svg);
+}
+
@media (prefers-color-scheme: dark) {
.sidebar > .panel.navigation.debugger .warning-banner {
background-color: var(--yellow-highlight-background-color);
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js (243243 => 243244)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js 2019-03-20 21:55:05 UTC (rev 243244)
@@ -494,8 +494,23 @@
} else if (breakpoint instanceof WI.EventBreakpoint) {
constructor = WI.EventBreakpointTreeElement;
- if (breakpoint.eventListener)
- parentTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
+ if (breakpoint.eventListener) {
+ let eventTargetTreeElement = null;
+ if (breakpoint.eventListener.onWindow) {
+ if (!DebuggerSidebarPanel.__windowEventTargetRepresentedObject)
+ DebuggerSidebarPanel.__windowEventTargetRepresentedObject = {__window: true};
+
+ eventTargetTreeElement = this._breakpointsContentTreeOutline.findTreeElement(DebuggerSidebarPanel.__windowEventTargetRepresentedObject);
+ if (!eventTargetTreeElement) {
+ const subtitle = null;
+ eventTargetTreeElement = new WI.GeneralTreeElement(["event-target-window"], WI.unlocalizedString("window"), subtitle, DebuggerSidebarPanel.__windowEventTargetRepresentedObject);
+ this._addTreeElement(eventTargetTreeElement, parentTreeElement);
+ }
+ } else if (breakpoint.eventListener.node)
+ eventTargetTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
+ if (eventTargetTreeElement)
+ parentTreeElement = eventTargetTreeElement;
+ }
} else if (breakpoint instanceof WI.URLBreakpoint) {
constructor = WI.URLBreakpointTreeElement;
@@ -899,6 +914,14 @@
_breakpointTreeOutlineDeleteTreeElement(treeElement)
{
console.assert(treeElement.selected);
+
+ if (treeElement.representedObject === DebuggerSidebarPanel.__windowEventTargetRepresentedObject) {
+ let eventBreakpointsOnWindow = WI.domManager.eventListenerBreakpoints.filter((eventBreakpoint) => eventBreakpoint.eventListener.onWindow);
+ for (let eventBreakpoint of eventBreakpointsOnWindow)
+ WI.domManager.removeBreakpointForEventListener(eventBreakpoint.eventListener);
+ return true;
+ }
+
console.assert(treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement);
if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
return false;
@@ -955,6 +978,9 @@
|| treeElement instanceof WI.URLBreakpointTreeElement)
return;
+ if (treeElement.representedObject === DebuggerSidebarPanel.__windowEventTargetRepresentedObject)
+ return;
+
const options = {
ignoreNetworkTab: true,
ignoreSearchTab: true,
@@ -1231,8 +1257,13 @@
if (eventListener) {
console.assert(eventListener.eventListenerId === pauseData.eventListenerId);
- let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(eventListener.node));
- rows.push(ownerElementRow);
+ let value = null;
+ if (eventListener.onWindow)
+ value = WI.unlocalizedString("window");
+ else if (eventListener.node)
+ value = WI.linkifyNodeReference(eventListener.node);
+ if (value)
+ rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Target"), value));
}
this._pauseReasonGroup.rows = rows;
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js (243243 => 243244)
--- trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js 2019-03-20 21:55:05 UTC (rev 243244)
@@ -34,8 +34,8 @@
var rows = [];
if (!options.hideType)
rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Event"), this._eventListener.type));
- if (!options.hideNode)
- rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Node"), this._nodeTextOrLink()));
+ if (!options.hideTarget)
+ rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Target"), this._targetTextOrLink()));
rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Function"), this._functionTextOrLink()));
if (this._eventListener.useCapture)
@@ -65,17 +65,17 @@
// Private
- _nodeTextOrLink()
+ _targetTextOrLink()
{
- var node = this._eventListener.node;
- console.assert(node);
- if (!node)
- return "";
+ if (this._eventListener.onWindow)
+ return WI.unlocalizedString("window");
- if (node.nodeType() === Node.DOCUMENT_NODE)
- return "document";
+ let node = this._eventListener.node;
+ if (node)
+ return WI.linkifyNodeReference(node);
- return WI.linkifyNodeReference(node);
+ console.assert();
+ return "";
}
_functionTextOrLink()
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css (243243 => 243244)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css 2019-03-20 21:55:05 UTC (rev 243244)
@@ -141,6 +141,10 @@
}
}
+.sidebar > .panel.navigation.sources > .content > .breakpoints .tree-outline .item.event-target-window .icon {
+ content: url(../Images/TypeObject.svg);
+}
+
@media (prefers-dark-interface) {
.sidebar > .panel.navigation.sources > .content > .warning-banner {
color: var(--yellow-highlight-text-color);
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js (243243 => 243244)
--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js 2019-03-20 21:53:06 UTC (rev 243243)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js 2019-03-20 21:55:05 UTC (rev 243244)
@@ -142,6 +142,14 @@
this._breakpointsTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
this._breakpointsTreeOutline._ondelete_ = (treeElement) => {
console.assert(treeElement.selected);
+
+ if (treeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject) {
+ let eventBreakpointsOnWindow = WI.domManager.eventListenerBreakpoints.filter((eventBreakpoint) => eventBreakpoint.eventListener.onWindow);
+ for (let eventBreakpoint of eventBreakpointsOnWindow)
+ WI.domManager.removeBreakpointForEventListener(eventBreakpoint.eventListener);
+ return true;
+ }
+
console.assert(treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement);
if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
return false;
@@ -901,8 +909,23 @@
} else if (breakpoint instanceof WI.EventBreakpoint) {
constructor = WI.EventBreakpointTreeElement;
- if (breakpoint.eventListener)
- parentTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
+ if (breakpoint.eventListener) {
+ let eventTargetTreeElement = null;
+ if (breakpoint.eventListener.onWindow) {
+ if (!SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject)
+ SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject = {__window: true};
+
+ eventTargetTreeElement = this._breakpointsTreeOutline.findTreeElement(SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject);
+ if (!eventTargetTreeElement) {
+ const subtitle = null;
+ eventTargetTreeElement = new WI.GeneralTreeElement(["event-target-window"], WI.unlocalizedString("window"), subtitle, SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject);
+ this._insertDebuggerTreeElement(eventTargetTreeElement, parentTreeElement);
+ }
+ } else if (breakpoint.eventListener.node)
+ eventTargetTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
+ if (eventTargetTreeElement)
+ parentTreeElement = eventTargetTreeElement;
+ }
} else if (breakpoint instanceof WI.URLBreakpoint) {
constructor = WI.URLBreakpointTreeElement;
@@ -1255,8 +1278,13 @@
if (eventListener) {
console.assert(eventListener.eventListenerId === pauseData.eventListenerId);
- let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(eventListener.node));
- rows.push(ownerElementRow);
+ let value = null;
+ if (eventListener.onWindow)
+ value = WI.unlocalizedString("window");
+ else if (eventListener.node)
+ value = WI.linkifyNodeReference(eventListener.node);
+ if (value)
+ rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Target"), value));
}
this._pauseReasonGroup.rows = rows;
@@ -1388,6 +1416,9 @@
|| treeElement instanceof WI.URLBreakpointTreeElement)
return;
+ if (treeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject)
+ return;
+
if (treeElement instanceof WI.FolderTreeElement
|| treeElement instanceof WI.ResourceTreeElement
|| treeElement instanceof WI.ScriptTreeElement