Diff
Modified: trunk/LayoutTests/ChangeLog (241109 => 241110)
--- trunk/LayoutTests/ChangeLog 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/LayoutTests/ChangeLog 2019-02-07 00:31:56 UTC (rev 241110)
@@ -1,3 +1,14 @@
+2019-02-06 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: DOM: don't send the entire function string with each event listener
+ https://bugs.webkit.org/show_bug.cgi?id=194293
+ <rdar://problem/47822809>
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/dom/getEventListenersForNode.html:
+ * inspector/dom/getEventListenersForNode-expected.txt:
+
2019-02-06 Andy Estes <aes...@apple.com>
[Payment Request] It should be possible to require a phonetic name for shipping contacts
Modified: trunk/LayoutTests/inspector/dom/getEventListenersForNode-expected.txt (241109 => 241110)
--- trunk/LayoutTests/inspector/dom/getEventListenersForNode-expected.txt 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/LayoutTests/inspector/dom/getEventListenersForNode-expected.txt 2019-02-07 00:31:56 UTC (rev 241110)
@@ -3,34 +3,74 @@
== Running test suite: DOM.getEventListenersForNode
-- Running test case: DOM.getEventListenersForNode.Basic
-Event: alpha
+Event: A
Node: body
Capture: true
Attribute: false
+Handler Name: bodyA
PASS: The Event Listener has a source location.
-PASS: The Event Listener has a function.
-Event: beta
+Event: B
+Node: body
+Capture: true
+Attribute: false
+PASS: The Event Listener has a source location.
+
+Event: E
Node: div#x
Capture: false
Attribute: false
+Handler Name: ObjectEventHandler
+PASS: The Event Listener has a source location.
+
+Event: D
+Node: div#x
+Capture: false
+Attribute: false
+Handler Name: handleEvent
+PASS: The Event Listener has a source location.
+
+Event: C
+Node: div#x
+Capture: false
+Attribute: false
+PASS: The Event Listener has a source location.
+
+Event: B
+Node: div#x
+Capture: false
+Attribute: false
+Handler Name: xB
Once: true
PASS: The Event Listener has a source location.
-PASS: The Event Listener has a function.
-Event: alpha
+Event: A
Node: div#x
Capture: false
Attribute: false
+Handler Name: xA
PASS: The Event Listener has a source location.
-PASS: The Event Listener has a function.
-Event: alpha
+Event: click
+Node: div#x
+Capture: false
+Attribute: true
+Handler Name: onclick
+PASS: The Event Listener has a source location.
+
+Event: B
Node: #document
Capture: false
Attribute: false
Passive: true
PASS: The Event Listener has a source location.
-PASS: The Event Listener has a function.
+Event: A
+Node: #document
+Capture: false
+Attribute: false
+Handler Name: documentA
+Passive: true
+PASS: The Event Listener has a source location.
+
Modified: trunk/LayoutTests/inspector/dom/getEventListenersForNode.html (241109 => 241110)
--- trunk/LayoutTests/inspector/dom/getEventListenersForNode.html 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/LayoutTests/inspector/dom/getEventListenersForNode.html 2019-02-07 00:31:56 UTC (rev 241110)
@@ -27,6 +27,8 @@
InspectorTest.log(`Capture: ${eventListener.useCapture}`);
InspectorTest.log(`Attribute: ${eventListener.isAttribute}`);
+ if (eventListener.handlerName)
+ InspectorTest.log(`Handler Name: ${eventListener.handlerName}`);
if (eventListener.passive)
InspectorTest.log(`Passive: ${eventListener.passive}`);
if (eventListener.once)
@@ -33,7 +35,6 @@
InspectorTest.log(`Once: ${eventListener.once}`);
InspectorTest.expectThat(eventListener.location, "The Event Listener has a source location.");
- InspectorTest.expectThat(eventListener.handlerBody, "The Event Listener has a function.");
InspectorTest.log("");
}
@@ -62,15 +63,24 @@
<body _onload_="runTest()">
<p>Testing DOMAgent.getEventListenersForNode.</p>
- <div id="x"></div>
+ <div id="x" _onclick_="(function xClick(event) { })()"></div>
<script>
+ class ObjectEventHandler {
+ handleEvent(event) { }
+ }
+
let element = document.getElementById("x");
- element.addEventListener("alpha", (event) => {});
- element.addEventListener("beta", (event) => {}, {once: true});
+ element.addEventListener("A", function xA(event) { });
+ element.addEventListener("B", function xB(event) { }, {once: true});
+ element.addEventListener("C", (event) => { });
+ element.addEventListener("D", { handleEvent(event) { } });
+ element.addEventListener("E", new ObjectEventHandler);
- document.body.addEventListener("alpha", (event) => {}, true);
+ document.body.addEventListener("A", function bodyA(event) { }, true);
+ document.body.addEventListener("B", (event) => {}, true);
- document.addEventListener("alpha", (event) => {}, {passive: true});
+ document.addEventListener("A", function documentA(event) { }, {passive: true});
+ document.addEventListener("B", (event) => {}, {passive: true});
</script>
</body>
</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (241109 => 241110)
--- trunk/Source/_javascript_Core/ChangeLog 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-02-07 00:31:56 UTC (rev 241110)
@@ -1,3 +1,16 @@
+2019-02-06 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: DOM: don't send the entire function string with each event listener
+ https://bugs.webkit.org/show_bug.cgi?id=194293
+ <rdar://problem/47822809>
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/protocol/DOM.json:
+
+ * runtime/JSFunction.h:
+ Export `calculatedDisplayName`.
+
2019-02-06 Yusuke Suzuki <ysuz...@apple.com>
[JSC] PrivateName to PublicName hash table is wasteful
Modified: trunk/Source/_javascript_Core/inspector/protocol/DOM.json (241109 => 241110)
--- trunk/Source/_javascript_Core/inspector/protocol/DOM.json 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/_javascript_Core/inspector/protocol/DOM.json 2019-02-07 00:31:56 UTC (rev 241110)
@@ -79,10 +79,9 @@
{ "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": "handlerBody", "type": "string", "description": "Event handler function body." },
{ "name": "location", "$ref": "Debugger.Location", "optional": true, "description": "Handler code location." },
- { "name": "sourceName", "type": "string", "optional": true, "description": "Source script URL." },
- { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." },
+ { "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 },
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (241109 => 241110)
--- trunk/Source/_javascript_Core/runtime/JSFunction.h 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h 2019-02-07 00:31:56 UTC (rev 241110)
@@ -88,7 +88,7 @@
JS_EXPORT_PRIVATE String name(VM&);
JS_EXPORT_PRIVATE String displayName(VM&);
- const String calculatedDisplayName(VM&);
+ JS_EXPORT_PRIVATE const String calculatedDisplayName(VM&);
ExecutableBase* executable() const { return m_executable.get(); }
Modified: trunk/Source/WebCore/ChangeLog (241109 => 241110)
--- trunk/Source/WebCore/ChangeLog 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/WebCore/ChangeLog 2019-02-07 00:31:56 UTC (rev 241110)
@@ -1,3 +1,16 @@
+2019-02-06 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: DOM: don't send the entire function string with each event listener
+ https://bugs.webkit.org/show_bug.cgi?id=194293
+ <rdar://problem/47822809>
+
+ Reviewed by Joseph Pecoraro.
+
+ Test: inspector/dom/getEventListenersForNode.html
+
+ * inspector/agents/InspectorDOMAgent.cpp:
+ (WebCore::InspectorDOMAgent::buildObjectForEventListener):
+
2019-02-06 Andy Estes <aes...@apple.com>
[Payment Request] It should be possible to require a phonetic name for shipping contacts
Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp (241109 => 241110)
--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2019-02-07 00:31:56 UTC (rev 241110)
@@ -1663,28 +1663,48 @@
{
Ref<EventListener> eventListener = registeredEventListener.callback();
- JSC::ExecState* state = nullptr;
- JSC::JSObject* handler = nullptr;
- String body;
+ JSC::ExecState* exec = nullptr;
+ JSC::JSObject* handlerObject = nullptr;
+ JSC::JSFunction* handlerFunction = nullptr;
+ String handlerName;
int lineNumber = 0;
int columnNumber = 0;
String scriptID;
- String sourceName;
if (is<JSEventListener>(eventListener.get())) {
auto& scriptListener = downcast<JSEventListener>(eventListener.get());
+
JSC::JSLockHolder lock(scriptListener.isolatedWorld().vm());
- state = execStateFromNode(scriptListener.isolatedWorld(), &node->document());
- handler = scriptListener.jsFunction(node->document());
- if (handler && state) {
- body = handler->toString(state)->value(state);
- if (auto function = JSC::jsDynamicCast<JSC::JSFunction*>(state->vm(), handler)) {
- if (!function->isHostOrBuiltinFunction()) {
- if (auto executable = function->jsExecutable()) {
- lineNumber = executable->firstLine() - 1;
- columnNumber = executable->startColumn() - 1;
- scriptID = executable->sourceID() == JSC::SourceProvider::nullID ? emptyString() : String::number(executable->sourceID());
- sourceName = executable->sourceURL();
- }
+
+ exec = execStateFromNode(scriptListener.isolatedWorld(), &node->document());
+ handlerObject = scriptListener.jsFunction(node->document());
+ if (handlerObject && exec) {
+ handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(exec->vm(), handlerObject);
+
+ if (!handlerFunction) {
+ auto scope = DECLARE_CATCH_SCOPE(exec->vm());
+
+ // If the handler is not actually a function, see if it implements the EventListener interface and use that.
+ auto handleEventValue = handlerObject->get(exec, JSC::Identifier::fromString(exec, "handleEvent"));
+
+ if (UNLIKELY(scope.exception()))
+ scope.clearException();
+
+ if (handleEventValue)
+ handlerFunction = JSC::jsDynamicCast<JSC::JSFunction*>(exec->vm(), handleEventValue);
+ }
+
+ if (handlerFunction && !handlerFunction->isHostOrBuiltinFunction()) {
+ // If the listener implements the EventListener interface, use the class name instead of
+ // "handleEvent", unless it is a plain object.
+ if (handlerFunction != handlerObject)
+ handlerName = JSC::JSObject::calculatedClassName(handlerObject);
+ if (handlerName.isEmpty() || handlerName == "Object"_s)
+ handlerName = handlerFunction->calculatedDisplayName(exec->vm());
+
+ if (auto executable = handlerFunction->jsExecutable()) {
+ lineNumber = executable->firstLine() - 1;
+ columnNumber = executable->startColumn() - 1;
+ scriptID = executable->sourceID() == JSC::SourceProvider::nullID ? emptyString() : String::number(executable->sourceID());
}
}
}
@@ -1696,12 +1716,11 @@
.setUseCapture(registeredEventListener.useCapture())
.setIsAttribute(eventListener->isAttribute())
.setNodeId(pushNodePathToFrontend(node))
- .setHandlerBody(body)
.release();
- if (objectGroupId && handler && state) {
- InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(state);
+ if (objectGroupId && handlerObject && exec) {
+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptFor(exec);
if (!injectedScript.hasNoValue())
- value->setHandler(injectedScript.wrapObject(handler, *objectGroupId));
+ value->setHandlerObject(injectedScript.wrapObject(handlerObject, *objectGroupId));
}
if (!scriptID.isNull()) {
auto location = Inspector::Protocol::Debugger::Location::create()
@@ -1710,9 +1729,9 @@
.release();
location->setColumnNumber(columnNumber);
value->setLocation(WTFMove(location));
- if (!sourceName.isEmpty())
- value->setSourceName(sourceName);
}
+ if (!handlerName.isEmpty())
+ value->setHandlerName(handlerName);
if (registeredEventListener.isPassive())
value->setPassive(true);
if (registeredEventListener.isOnce())
Modified: trunk/Source/WebInspectorUI/ChangeLog (241109 => 241110)
--- trunk/Source/WebInspectorUI/ChangeLog 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/WebInspectorUI/ChangeLog 2019-02-07 00:31:56 UTC (rev 241110)
@@ -1,3 +1,14 @@
+2019-02-06 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: DOM: don't send the entire function string with each event listener
+ https://bugs.webkit.org/show_bug.cgi?id=194293
+ <rdar://problem/47822809>
+
+ Reviewed by Joseph Pecoraro.
+
+ * UserInterface/Views/EventListenerSectionGroup.js:
+ (WI.EventListenerSectionGroup.prototype._functionTextOrLink):
+
2019-02-06 Joseph Pecoraro <pecor...@apple.com>
Web Inspector: "Worker not found" uncaught protocol errors
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js (241109 => 241110)
--- trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js 2019-02-07 00:23:21 UTC (rev 241109)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/EventListenerSectionGroup.js 2019-02-07 00:31:56 UTC (rev 241110)
@@ -80,15 +80,21 @@
_functionTextOrLink()
{
- var match = this._eventListener.handlerBody.match(/function ([^\(]+?)\(/);
- if (match) {
- var anonymous = false;
- var functionName = match[1];
- } else {
- var anonymous = true;
- var functionName = WI.UIString("(anonymous function)");
+ let anonymous = false;
+ let functionName = this._eventListener.handlerName;
+
+ // COMPATIBILITY (iOS 12.2): DOM.EventListener.handlerBody was replaced by DOM.EventListener.handlerName.
+ if (!functionName && this._eventListener.handlerBody) {
+ let match = this._eventListener.handlerBody.match(/function ([^\(]+?)\(/);
+ if (match)
+ functionName = match[1];
}
+ if (!functionName) {
+ anonymous = true;
+ functionName = WI.UIString("(anonymous function)");
+ }
+
if (!this._eventListener.location)
return functionName;