Web Inspector: Timeline should show when events preventDefault() was called on an...
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2019 00:55:40 +0000 (00:55 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2019 00:55:40 +0000 (00:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=176824
<rdar://problem/34290931>

Reviewed by Timothy Hatcher.

Original patch by Joseph Pecoraro <pecoraro@apple.com>.

Source/WebCore:

Tests: inspector/timeline/timeline-event-CancelAnimationFrame.html
       inspector/timeline/timeline-event-EventDispatch.html
       inspector/timeline/timeline-event-FireAnimationFrame.html
       inspector/timeline/timeline-event-RequestAnimationFrame.html
       inspector/timeline/timeline-event-TimerFire.html
       inspector/timeline/timeline-event-TimerInstall.html
       inspector/timeline/timeline-event-TimerRemove.html

* dom/EventTarget.cpp:
(WebCore::EventTarget::innerInvokeEventListeners):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::dispatchEvent):
Include `defaultPrevented` when notifying inspector.

* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::didDispatchEvent):
(WebCore::InspectorInstrumentation::didDispatchEventOnWindow):
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::didDispatchEventImpl):
(WebCore::InspectorInstrumentation::didDispatchEventOnWindowImpl):
Pass `defaultPrevented` on to agent.

* inspector/agents/InspectorTimelineAgent.h:
* inspector/agents/InspectorTimelineAgent.cpp:
(WebCore::InspectorTimelineAgent::didDispatchEvent):
Append a boolean `defaultPrevented` property on the `EventDispatch` timeline record's data.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:
New string.

* UserInterface/Controllers/TimelineManager.js:
(WI.TimelineManager.prototype._processRecord):
Include the whole data object as extra details.

* UserInterface/Models/ScriptTimelineRecord.js:
(WI.ScriptTimelineRecord):
(WI.ScriptTimelineRecord.prototype.get eventType):
Wholesale copy of the extra data instead of just a single property.

* UserInterface/Views/ScriptDetailsTimelineView.js:
(WI.ScriptDetailsTimelineView):
Give the name column more initial space, there is still extra space
after this adjustment but name is comfortably larger (and the most
likely to be expanded).

* UserInterface/Views/ScriptTimelineDataGridNode.js:
(WI.ScriptTimelineDataGridNode.prototype.get subtitle):
Include "default prevented" as the event's subtitle if it was prevented.

LayoutTests:

* inspector/timeline/resources/timeline-event-utilities.js: Added.
(finishRecording):
(TestPage.registerInitializer.InspectorTest.TimelineEvent.captureTimelineWithScript):
(TestPage.registerInitializer):
Helper code for creating a recording from a function.

* inspector/timeline/timeline-event-CancelAnimationFrame.html: Added.
* inspector/timeline/timeline-event-CancelAnimationFrame-expected.txt: Added.
* inspector/timeline/timeline-event-EventDispatch.html: Added.
* inspector/timeline/timeline-event-EventDispatch-expected.txt: Added.
* inspector/timeline/timeline-event-FireAnimationFrame.html: Added.
* inspector/timeline/timeline-event-FireAnimationFrame-expected.txt: Added.
* inspector/timeline/timeline-event-RequestAnimationFrame.html: Added.
* inspector/timeline/timeline-event-RequestAnimationFrame-expected.txt: Added.
* inspector/timeline/timeline-event-TimerFire.html: Added.
* inspector/timeline/timeline-event-TimerFire-expected.txt: Added.
* inspector/timeline/timeline-event-TimerInstall.html: Added.
* inspector/timeline/timeline-event-TimerInstall-expected.txt: Added.
* inspector/timeline/timeline-event-TimerRemove.html: Added.
* inspector/timeline/timeline-event-TimerRemove-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243269 268f45cc-cd09-0410-ab3c-d52691b4dbfc

29 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/timeline/resources/timeline-event-utilities.js [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-CancelAnimationFrame-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-CancelAnimationFrame.html [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-EventDispatch-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-EventDispatch.html [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-FireAnimationFrame-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-FireAnimationFrame.html [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-RequestAnimationFrame-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-RequestAnimationFrame.html [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-TimerFire-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-TimerFire.html [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-TimerInstall-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-TimerInstall.html [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-TimerRemove-expected.txt [new file with mode: 0644]
LayoutTests/inspector/timeline/timeline-event-TimerRemove.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/EventTarget.cpp
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/agents/InspectorTimelineAgent.cpp
Source/WebCore/inspector/agents/InspectorTimelineAgent.h
Source/WebCore/page/DOMWindow.cpp
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js
Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js
Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js

index fbcbe84..39e321a 100644 (file)
@@ -1,5 +1,36 @@
 2019-03-20  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Timeline should show when events preventDefault() was called on an event or not
+        https://bugs.webkit.org/show_bug.cgi?id=176824
+        <rdar://problem/34290931>
+
+        Reviewed by Timothy Hatcher.
+
+        Original patch by Joseph Pecoraro <pecoraro@apple.com>.
+
+        * inspector/timeline/resources/timeline-event-utilities.js: Added.
+        (finishRecording):
+        (TestPage.registerInitializer.InspectorTest.TimelineEvent.captureTimelineWithScript):
+        (TestPage.registerInitializer):
+        Helper code for creating a recording from a function.
+
+        * inspector/timeline/timeline-event-CancelAnimationFrame.html: Added.
+        * inspector/timeline/timeline-event-CancelAnimationFrame-expected.txt: Added.
+        * inspector/timeline/timeline-event-EventDispatch.html: Added.
+        * inspector/timeline/timeline-event-EventDispatch-expected.txt: Added.
+        * inspector/timeline/timeline-event-FireAnimationFrame.html: Added.
+        * inspector/timeline/timeline-event-FireAnimationFrame-expected.txt: Added.
+        * inspector/timeline/timeline-event-RequestAnimationFrame.html: Added.
+        * inspector/timeline/timeline-event-RequestAnimationFrame-expected.txt: Added.
+        * inspector/timeline/timeline-event-TimerFire.html: Added.
+        * inspector/timeline/timeline-event-TimerFire-expected.txt: Added.
+        * inspector/timeline/timeline-event-TimerInstall.html: Added.
+        * inspector/timeline/timeline-event-TimerInstall-expected.txt: Added.
+        * inspector/timeline/timeline-event-TimerRemove.html: Added.
+        * inspector/timeline/timeline-event-TimerRemove-expected.txt: Added.
+
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: Styles Redesign: Editing selector should not hide the rule
         https://bugs.webkit.org/show_bug.cgi?id=178489
         <rdar://problem/35062434>
diff --git a/LayoutTests/inspector/timeline/resources/timeline-event-utilities.js b/LayoutTests/inspector/timeline/resources/timeline-event-utilities.js
new file mode 100644 (file)
index 0000000..8e2e103
--- /dev/null
@@ -0,0 +1,31 @@
+function finishRecording(data) {
+    TestPage.addResult("Finish recording...");
+    TestPage.dispatchEventToFrontend("FinishRecording", data);
+}
+
+TestPage.registerInitializer(() => {
+    InspectorTest.TimelineEvent = {};
+
+    InspectorTest.TimelineEvent.captureTimelineWithScript = function(expression) {
+        let pageRecordingData = null;
+
+        InspectorTest.log("Starting Capture...");
+        const newRecording = true;
+        WI.timelineManager.startCapturing(newRecording);
+
+        let promises = [];
+
+        promises.push(WI.timelineManager.awaitEvent(WI.TimelineManager.Event.CapturingStopped));
+
+        promises.push(InspectorTest.awaitEvent("FinishRecording").then((event) => {
+            InspectorTest.log("Stopping Capture...");
+            pageRecordingData = event.data;
+            WI.timelineManager.stopCapturing();
+        }));
+
+        InspectorTest.log("Evaluating...");
+        promises.push(InspectorTest.evaluateInPage(expression));
+
+        return Promise.all(promises).then(() => pageRecordingData);
+    }
+});
diff --git a/LayoutTests/inspector/timeline/timeline-event-CancelAnimationFrame-expected.txt b/LayoutTests/inspector/timeline/timeline-event-CancelAnimationFrame-expected.txt
new file mode 100644 (file)
index 0000000..808240b
--- /dev/null
@@ -0,0 +1,13 @@
+Tests 'CancelAnimationFrame' Timeline event records.
+
+
+== Running test suite: TimelineEvent.CancelAnimationFrame
+-- Running test case: TimelineEvent.CancelAnimationFrame.requestAnimationFrame
+Starting Capture...
+Evaluating...
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 AnimationFrameCanceled record.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the requestAnimationFrame identifier.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-CancelAnimationFrame.html b/LayoutTests/inspector/timeline/timeline-event-CancelAnimationFrame.html
new file mode 100644 (file)
index 0000000..c475af3
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testRequestAnimationFrame() {
+    let requestAnimationFrameIdentifier = requestAnimationFrame(() => {
+        TestPage.addResult("FAIL: requestAnimationFrame fired");
+    });
+
+    cancelAnimationFrame(requestAnimationFrameIdentifier);
+
+    setTimeout(() => {
+        finishRecording({requestAnimationFrameIdentifier});
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.CancelAnimationFrame");
+
+    suite.addTestCase({
+        name: "TimelineEvent.CancelAnimationFrame.requestAnimationFrame",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testRequestAnimationFrame()`);
+
+            InspectorTest.assert(typeof pageRecordingData.requestAnimationFrameIdentifier === "number");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.AnimationFrameCanceled);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 AnimationFrameCanceled record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, pageRecordingData.requestAnimationFrameIdentifier, "ScriptTimelineRecord details should be the requestAnimationFrame identifier.");
+            }
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'CancelAnimationFrame' Timeline event records.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/timeline/timeline-event-EventDispatch-expected.txt b/LayoutTests/inspector/timeline/timeline-event-EventDispatch-expected.txt
new file mode 100644 (file)
index 0000000..218bb02
--- /dev/null
@@ -0,0 +1,45 @@
+Tests 'EventDispatch' Timeline event records.
+
+  
+
+== Running test suite: TimelineEvent.EventDispatch
+-- Running test case: TimelineEvent.EventDispatch.Handler.Regular
+Starting Capture...
+Evaluating...
+PASS: click handler fired
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 EventDispatched record.
+DETAILS: {"type":"click","defaultPrevented":false}
+PASS: ScriptTimelineRecord extraDetails should show default was not prevented.
+
+-- Running test case: TimelineEvent.EventDispatch.Handler.DefaultPrevented
+Starting Capture...
+Evaluating...
+PASS: click handler fired, will prevent default
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 EventDispatched record.
+DETAILS: {"type":"click","defaultPrevented":true}
+PASS: ScriptTimelineRecord extraDetails should show default was prevented.
+
+-- Running test case: TimelineEvent.EventDispatch.AttributeHandler.Regular
+Starting Capture...
+Evaluating...
+PASS: b1 onclick attribute handler fired
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 EventDispatched record.
+DETAILS: {"type":"click","defaultPrevented":false}
+PASS: ScriptTimelineRecord extraDetails should show default was not prevented.
+
+-- Running test case: TimelineEvent.EventDispatch.AttributeHandler.DefaultPrevented
+Starting Capture...
+Evaluating...
+PASS: b2 onclick attribute handler fired, will prevent default
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 EventDispatched record.
+DETAILS: {"type":"click","defaultPrevented":true}
+PASS: ScriptTimelineRecord extraDetails should show default was prevented.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-EventDispatch.html b/LayoutTests/inspector/timeline/timeline-event-EventDispatch.html
new file mode 100644 (file)
index 0000000..a2a3a7c
--- /dev/null
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testClickEventHandler({preventDefault}) {
+    let button = document.body.appendChild(document.createElement("button"));
+    button.addEventListener("click", (event) => {
+        TestPage.addResult("PASS: click handler fired" + (preventDefault ? ", will prevent default" : ""));
+
+        if (preventDefault)
+            event.preventDefault();
+
+        setTimeout(() => {
+            finishRecording({preventDefault});
+        });
+    });
+    button.dispatchEvent(new MouseEvent("click", {bubbles: true, cancelable: true}));
+}
+
+function testClickEventAttributeHandler(id, {preventDefault}) {
+    let button = document.getElementById(id);
+    button.dispatchEvent(new MouseEvent("click", {bubbles: true, cancelable: true}));
+
+    setTimeout(() => {
+        finishRecording({preventDefault});
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.EventDispatch");
+
+    suite.addTestCase({
+        name: "TimelineEvent.EventDispatch.Handler.Regular",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testClickEventHandler({preventDefault: false})`);
+
+            InspectorTest.assert(typeof pageRecordingData.preventDefault === "boolean");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 EventDispatched record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + JSON.stringify(record.extraDetails));
+                InspectorTest.expectEqual(record.extraDetails.defaultPrevented, pageRecordingData.preventDefault, "ScriptTimelineRecord extraDetails should show default was not prevented.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TimelineEvent.EventDispatch.Handler.DefaultPrevented",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testClickEventHandler({preventDefault: true})`);
+
+            InspectorTest.assert(typeof pageRecordingData.preventDefault === "boolean");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 EventDispatched record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + JSON.stringify(record.extraDetails));
+                InspectorTest.expectEqual(record.extraDetails.defaultPrevented, pageRecordingData.preventDefault, "ScriptTimelineRecord extraDetails should show default was prevented.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TimelineEvent.EventDispatch.AttributeHandler.Regular",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testClickEventAttributeHandler("b1", {preventDefault: false})`);
+
+            InspectorTest.assert(typeof pageRecordingData.preventDefault === "boolean");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 EventDispatched record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + JSON.stringify(record.extraDetails));
+                InspectorTest.expectEqual(record.extraDetails.defaultPrevented, pageRecordingData.preventDefault, "ScriptTimelineRecord extraDetails should show default was not prevented.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TimelineEvent.EventDispatch.AttributeHandler.DefaultPrevented",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testClickEventAttributeHandler("b2", {preventDefault: true})`);
+
+            InspectorTest.assert(typeof pageRecordingData.preventDefault === "boolean");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 EventDispatched record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + JSON.stringify(record.extraDetails));
+                InspectorTest.expectEqual(record.extraDetails.defaultPrevented, pageRecordingData.preventDefault, "ScriptTimelineRecord extraDetails should show default was prevented.");
+            }
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'EventDispatch' Timeline event records.</p>
+    <button id="b1" onclick="TestPage.addResult('PASS: b1 onclick attribute handler fired'); return true"></button>
+    <button id="b2" onclick="TestPage.addResult('PASS: b2 onclick attribute handler fired, will prevent default'); return false"></button>
+</body>
+</html>
diff --git a/LayoutTests/inspector/timeline/timeline-event-FireAnimationFrame-expected.txt b/LayoutTests/inspector/timeline/timeline-event-FireAnimationFrame-expected.txt
new file mode 100644 (file)
index 0000000..41995da
--- /dev/null
@@ -0,0 +1,14 @@
+Tests 'FireAnimationFrame' Timeline event records.
+
+
+== Running test suite: TimelineEvent.FireAnimationFrame
+-- Running test case: TimelineEvent.FireAnimationFrame.requestAnimationFrame
+Starting Capture...
+Evaluating...
+PASS: requestAnimationFrame fired
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 AnimationFrameFired record.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the requestAnimationFrame identifier.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-FireAnimationFrame.html b/LayoutTests/inspector/timeline/timeline-event-FireAnimationFrame.html
new file mode 100644 (file)
index 0000000..a7a8fe3
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testRequestAnimationFrame() {
+    let requestAnimationFrameIdentifier = requestAnimationFrame(() => {
+        TestPage.addResult("PASS: requestAnimationFrame fired");
+
+        setTimeout(() => {
+            finishRecording({requestAnimationFrameIdentifier});
+        });
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.FireAnimationFrame");
+
+    suite.addTestCase({
+        name: "TimelineEvent.FireAnimationFrame.requestAnimationFrame",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testRequestAnimationFrame()`);
+
+            InspectorTest.assert(typeof pageRecordingData.requestAnimationFrameIdentifier === "number");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.AnimationFrameFired);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 AnimationFrameFired record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, pageRecordingData.requestAnimationFrameIdentifier, "ScriptTimelineRecord details should be the requestAnimationFrame identifier.");
+            }
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'FireAnimationFrame' Timeline event records.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/timeline/timeline-event-RequestAnimationFrame-expected.txt b/LayoutTests/inspector/timeline/timeline-event-RequestAnimationFrame-expected.txt
new file mode 100644 (file)
index 0000000..04713ad
--- /dev/null
@@ -0,0 +1,14 @@
+Tests 'RequestAnimationFrame' Timeline event records.
+
+
+== Running test suite: TimelineEvent.RequestAnimationFrame
+-- Running test case: TimelineEvent.RequestAnimationFrame.requestAnimationFrame
+Starting Capture...
+Evaluating...
+PASS: requestAnimationFrame fired
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 AnimationFrameRequested record.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the requestAnimationFrame identifier.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-RequestAnimationFrame.html b/LayoutTests/inspector/timeline/timeline-event-RequestAnimationFrame.html
new file mode 100644 (file)
index 0000000..7b44f40
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testRequestAnimationFrame() {
+    let requestAnimationFrameIdentifier = requestAnimationFrame(() => {
+        TestPage.addResult("PASS: requestAnimationFrame fired");
+
+        setTimeout(() => {
+            finishRecording({requestAnimationFrameIdentifier});
+        });
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.RequestAnimationFrame");
+
+    suite.addTestCase({
+        name: "TimelineEvent.RequestAnimationFrame.requestAnimationFrame",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testRequestAnimationFrame()`);
+
+            InspectorTest.assert(typeof pageRecordingData.requestAnimationFrameIdentifier === "number");
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.AnimationFrameRequested);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 AnimationFrameRequested record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, pageRecordingData.requestAnimationFrameIdentifier, "ScriptTimelineRecord details should be the requestAnimationFrame identifier.");
+            }
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'RequestAnimationFrame' Timeline event records.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/timeline/timeline-event-TimerFire-expected.txt b/LayoutTests/inspector/timeline/timeline-event-TimerFire-expected.txt
new file mode 100644 (file)
index 0000000..ee3451b
--- /dev/null
@@ -0,0 +1,33 @@
+Tests 'TimerFire' Timeline event records.
+
+
+== Running test suite: TimelineEvent.TimerFire
+-- Running test case: TimelineEvent.TimerFire.setTimeout
+Starting Capture...
+Evaluating...
+PASS: setTimeout fired
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 TimerFired record.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the setTimeout identifier.
+
+-- Running test case: TimelineEvent.TimerFire.setInterval
+Starting Capture...
+Evaluating...
+PASS: setInterval fired: 1
+PASS: setInterval fired: 2
+PASS: setInterval fired: 3
+Finish recording...
+Stopping Capture...
+PASS: Should be 3 TimerFired records.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the setInterval identifier.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the setInterval identifier.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the setInterval identifier.
+
+-- Running test case: SanityCheck
+PASS: The setTimeout identifier and setInterval identifiers should be different.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-TimerFire.html b/LayoutTests/inspector/timeline/timeline-event-TimerFire.html
new file mode 100644 (file)
index 0000000..075f0a1
--- /dev/null
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testSetTimeout() {
+    let setTimeoutIdentifier = setTimeout(() => {
+        TestPage.addResult("PASS: setTimeout fired");
+
+        requestAnimationFrame(() => {
+            finishRecording({setTimeoutIdentifier});
+        });
+    });
+}
+
+function testSetInterval() {
+    let count = 0;
+
+    let setIntervalIdentifier = setInterval(() => {
+        count++;
+
+        TestPage.addResult("PASS: setInterval fired: " + count);
+
+        if (count === 3) {
+            clearInterval(setIntervalIdentifier);
+
+            requestAnimationFrame(() => {
+                finishRecording({setIntervalIdentifier});
+            });
+        }
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.TimerFire");
+
+    let timeoutIdentifier = undefined;
+    let intervalIdentifier = undefined;
+
+    suite.addTestCase({
+        name: "TimelineEvent.TimerFire.setTimeout",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testSetTimeout()`);
+
+            InspectorTest.assert(typeof pageRecordingData.setTimeoutIdentifier === "number");
+            timeoutIdentifier = pageRecordingData.setTimeoutIdentifier;
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.TimerFired);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 TimerFired record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, timeoutIdentifier, "ScriptTimelineRecord details should be the setTimeout identifier.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TimelineEvent.TimerFire.setInterval",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testSetInterval()`);
+
+            InspectorTest.assert(typeof pageRecordingData.setIntervalIdentifier === "number");
+            intervalIdentifier = pageRecordingData.setIntervalIdentifier;
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.TimerFired);
+            InspectorTest.expectEqual(records.length, 3, "Should be 3 TimerFired records.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, pageRecordingData.setIntervalIdentifier, "ScriptTimelineRecord details should be the setInterval identifier.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "SanityCheck",
+        async test() {
+            InspectorTest.expectThat(timeoutIdentifier !== intervalIdentifier, "The setTimeout identifier and setInterval identifiers should be different.");
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'TimerFire' Timeline event records.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/timeline/timeline-event-TimerInstall-expected.txt b/LayoutTests/inspector/timeline/timeline-event-TimerInstall-expected.txt
new file mode 100644 (file)
index 0000000..c039ee5
--- /dev/null
@@ -0,0 +1,29 @@
+Tests 'TimerInstall' Timeline event records.
+
+
+== Running test suite: TimelineEvent.TimerInstall
+-- Running test case: TimelineEvent.TimerInstall.setTimeout
+Starting Capture...
+Evaluating...
+PASS: setTimeout fired
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 TimerInstalled record.
+DETAILS: {"timerId":"<filtered>","timeout":10,"repeating":false}
+PASS: ScriptTimelineRecord details should be the setTimeout identifier.
+
+-- Running test case: TimelineEvent.TimerInstall.setInterval
+Starting Capture...
+Evaluating...
+PASS: setInterval fired: 1
+PASS: setInterval fired: 2
+PASS: setInterval fired: 3
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 TimerInstalled record.
+DETAILS: {"timerId":"<filtered>","timeout":5,"repeating":true}
+PASS: ScriptTimelineRecord details should be the setInterval identifier.
+
+-- Running test case: SanityCheck
+PASS: The setTimeout identifier and setInterval identifiers should be different.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-TimerInstall.html b/LayoutTests/inspector/timeline/timeline-event-TimerInstall.html
new file mode 100644 (file)
index 0000000..e0694df
--- /dev/null
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testSetTimeout() {
+    let setTimeoutIdentifier = setTimeout(() => {
+        TestPage.addResult("PASS: setTimeout fired");
+
+        requestAnimationFrame(() => {
+            finishRecording({setTimeoutIdentifier});
+        });
+    }, 10);
+}
+
+function testSetInterval() {
+    let count = 0;
+
+    let setIntervalIdentifier = setInterval(() => {
+        count++;
+
+        TestPage.addResult("PASS: setInterval fired: " + count);
+
+        if (count === 3) {
+            clearInterval(setIntervalIdentifier);
+
+            requestAnimationFrame(() => {
+                finishRecording({setIntervalIdentifier});
+            });
+        }
+    }, 5);
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.TimerInstall");
+
+    let timeoutIdentifier = undefined;
+    let intervalIdentifier = undefined;
+
+    function jsonFilter(key, value) {
+        if (key === "timerId")
+            return "<filtered>";
+        return value;
+    }
+
+    suite.addTestCase({
+        name: "TimelineEvent.TimerInstall.setTimeout",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testSetTimeout()`);
+
+            InspectorTest.assert(typeof pageRecordingData.setTimeoutIdentifier === "number");
+            timeoutIdentifier = pageRecordingData.setTimeoutIdentifier;
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.TimerInstalled);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 TimerInstalled record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + JSON.stringify(record.details, jsonFilter));
+                InspectorTest.expectEqual(record.details.timerId, timeoutIdentifier, "ScriptTimelineRecord details should be the setTimeout identifier.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TimelineEvent.TimerInstall.setInterval",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testSetInterval()`);
+
+            InspectorTest.assert(typeof pageRecordingData.setIntervalIdentifier === "number");
+            intervalIdentifier = pageRecordingData.setIntervalIdentifier;
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.TimerInstalled);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 TimerInstalled record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + JSON.stringify(record.details, jsonFilter));
+                InspectorTest.expectEqual(record.details.timerId, pageRecordingData.setIntervalIdentifier, "ScriptTimelineRecord details should be the setInterval identifier.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "SanityCheck",
+        async test() {
+            InspectorTest.expectThat(timeoutIdentifier !== intervalIdentifier, "The setTimeout identifier and setInterval identifiers should be different.");
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'TimerInstall' Timeline event records.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/timeline/timeline-event-TimerRemove-expected.txt b/LayoutTests/inspector/timeline/timeline-event-TimerRemove-expected.txt
new file mode 100644 (file)
index 0000000..64fb973
--- /dev/null
@@ -0,0 +1,28 @@
+Tests 'TimerRemove' Timeline event records.
+
+
+== Running test suite: TimelineEvent.TimerRemove
+-- Running test case: TimelineEvent.TimerRemove.setTimeout
+Starting Capture...
+Evaluating...
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 TimerRemoved record.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the setTimeout identifier.
+
+-- Running test case: TimelineEvent.TimerRemove.setInterval
+Starting Capture...
+Evaluating...
+PASS: setInterval fired: 1
+PASS: setInterval fired: 2
+PASS: setInterval fired: 3
+Finish recording...
+Stopping Capture...
+PASS: Should be 1 TimerRemoved record.
+DETAILS: number
+PASS: ScriptTimelineRecord details should be the setInterval identifier.
+
+-- Running test case: SanityCheck
+PASS: The setTimeout identifier and setInterval identifiers should be different.
+
diff --git a/LayoutTests/inspector/timeline/timeline-event-TimerRemove.html b/LayoutTests/inspector/timeline/timeline-event-TimerRemove.html
new file mode 100644 (file)
index 0000000..6c765fd
--- /dev/null
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script src="./resources/timeline-event-utilities.js"></script>
+<script>
+
+function testSetTimeout() {
+    let setTimeoutIdentifier = setTimeout(() => {
+        TestPage.addResult("FAIL: setTimeout fired");
+    });
+
+    clearTimeout(setTimeoutIdentifier);
+
+    requestAnimationFrame(() => {
+        finishRecording({setTimeoutIdentifier});
+    });
+}
+
+function testSetInterval() {
+    let count = 0;
+
+    let setIntervalIdentifier = setInterval(() => {
+        count++;
+
+        TestPage.addResult("PASS: setInterval fired: " + count);
+
+        if (count === 3) {
+            clearInterval(setIntervalIdentifier);
+
+            requestAnimationFrame(() => {
+                finishRecording({setIntervalIdentifier});
+            });
+        }
+    });
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite("TimelineEvent.TimerRemove");
+
+    let timeoutIdentifier = undefined;
+    let intervalIdentifier = undefined;
+
+    suite.addTestCase({
+        name: "TimelineEvent.TimerRemove.setTimeout",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testSetTimeout()`);
+
+            InspectorTest.assert(typeof pageRecordingData.setTimeoutIdentifier === "number");
+            timeoutIdentifier = pageRecordingData.setTimeoutIdentifier;
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.TimerRemoved);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 TimerRemoved record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, timeoutIdentifier, "ScriptTimelineRecord details should be the setTimeout identifier.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TimelineEvent.TimerRemove.setInterval",
+        async test() {
+            let pageRecordingData = await InspectorTest.TimelineEvent.captureTimelineWithScript(`testSetInterval()`);
+
+            InspectorTest.assert(typeof pageRecordingData.setIntervalIdentifier === "number");
+            intervalIdentifier = pageRecordingData.setIntervalIdentifier;
+
+            let recording = WI.timelineManager.activeRecording;
+            let scriptTimeline = recording.timelines.get(WI.TimelineRecord.Type.Script);
+            let records = scriptTimeline.records.filter((x) => x.eventType === WI.ScriptTimelineRecord.EventType.TimerRemoved);
+            InspectorTest.expectEqual(records.length, 1, "Should be 1 TimerRemoved record.");
+            for (let record of records) {
+                InspectorTest.log("DETAILS: " + typeof record.details);
+                InspectorTest.expectEqual(record.details, pageRecordingData.setIntervalIdentifier, "ScriptTimelineRecord details should be the setInterval identifier.");
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "SanityCheck",
+        async test() {
+            InspectorTest.expectThat(timeoutIdentifier !== intervalIdentifier, "The setTimeout identifier and setInterval identifiers should be different.");
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests 'TimerRemove' Timeline event records.</p>
+</body>
+</html>
index 30e0677..44c7449 100644 (file)
@@ -1,3 +1,40 @@
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Timeline should show when events preventDefault() was called on an event or not
+        https://bugs.webkit.org/show_bug.cgi?id=176824
+        <rdar://problem/34290931>
+
+        Reviewed by Timothy Hatcher.
+
+        Original patch by Joseph Pecoraro <pecoraro@apple.com>.
+
+        Tests: inspector/timeline/timeline-event-CancelAnimationFrame.html
+               inspector/timeline/timeline-event-EventDispatch.html
+               inspector/timeline/timeline-event-FireAnimationFrame.html
+               inspector/timeline/timeline-event-RequestAnimationFrame.html
+               inspector/timeline/timeline-event-TimerFire.html
+               inspector/timeline/timeline-event-TimerInstall.html
+               inspector/timeline/timeline-event-TimerRemove.html
+
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::innerInvokeEventListeners):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::dispatchEvent):
+        Include `defaultPrevented` when notifying inspector.
+
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::didDispatchEvent):
+        (WebCore::InspectorInstrumentation::didDispatchEventOnWindow):
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::didDispatchEventImpl):
+        (WebCore::InspectorInstrumentation::didDispatchEventOnWindowImpl):
+        Pass `defaultPrevented` on to agent.
+
+        * inspector/agents/InspectorTimelineAgent.h:
+        * inspector/agents/InspectorTimelineAgent.cpp:
+        (WebCore::InspectorTimelineAgent::didDispatchEvent):
+        Append a boolean `defaultPrevented` property on the `EventDispatch` timeline record's data.
+
 2019-03-20  Antoine Quint  <graouts@apple.com>
 
         DumpRenderTree crashes under WebAnimation::isRelevant when running imported/mozilla/css-transitions/test_document-get-animations.html in GuardMalloc
index 9ebe1dd..46886de 100644 (file)
@@ -316,7 +316,7 @@ void EventTarget::innerInvokeEventListeners(Event& event, EventListenerVector li
     }
 
     if (contextIsDocument)
-        InspectorInstrumentation::didDispatchEvent(willDispatchEventCookie);
+        InspectorInstrumentation::didDispatchEvent(willDispatchEventCookie, event.defaultPrevented());
 }
 
 Vector<AtomicString> EventTarget::eventTypes()
index 758add0..a53a910 100644 (file)
@@ -413,10 +413,10 @@ void InspectorInstrumentation::didHandleEventImpl(InstrumentingAgents& instrumen
         domDebuggerAgent->didHandleEvent();
 }
 
-void InspectorInstrumentation::didDispatchEventImpl(const InspectorInstrumentationCookie& cookie)
+void InspectorInstrumentation::didDispatchEventImpl(const InspectorInstrumentationCookie& cookie, bool defaultPrevented)
 {
     if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
-        timelineAgent->didDispatchEvent();
+        timelineAgent->didDispatchEvent(defaultPrevented);
 }
 
 InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventOnWindowImpl(InstrumentingAgents& instrumentingAgents, const Event& event, DOMWindow& window)
@@ -431,10 +431,10 @@ InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventOnWind
     return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
 }
 
-void InspectorInstrumentation::didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie& cookie)
+void InspectorInstrumentation::didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie& cookie, bool defaultPrevented)
 {
     if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
-        timelineAgent->didDispatchEvent();
+        timelineAgent->didDispatchEvent(defaultPrevented);
 }
 
 void InspectorInstrumentation::eventDidResetAfterDispatchImpl(InstrumentingAgents& instrumentingAgents, const Event& event)
index fd9ed0d..3ce6e14 100644 (file)
@@ -152,11 +152,11 @@ public:
     static void willRemoveEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     static bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture);
     static InspectorInstrumentationCookie willDispatchEvent(Document&, const Event&, bool hasEventListeners);
-    static void didDispatchEvent(const InspectorInstrumentationCookie&);
+    static void didDispatchEvent(const InspectorInstrumentationCookie&, bool defaultPrevented);
     static void willHandleEvent(ScriptExecutionContext&, Event&, const RegisteredEventListener&);
     static void didHandleEvent(ScriptExecutionContext&);
     static InspectorInstrumentationCookie willDispatchEventOnWindow(Frame*, const Event&, DOMWindow&);
-    static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&);
+    static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&, bool defaultPrevented);
     static void eventDidResetAfterDispatch(const Event&);
     static InspectorInstrumentationCookie willEvaluateScript(Frame&, const String& url, int lineNumber, int columnNumber);
     static void didEvaluateScript(const InspectorInstrumentationCookie&, Frame&);
@@ -347,9 +347,9 @@ private:
     static InspectorInstrumentationCookie willDispatchEventImpl(InstrumentingAgents&, Document&, const Event&, bool hasEventListeners);
     static void willHandleEventImpl(InstrumentingAgents&, Event&, const RegisteredEventListener&);
     static void didHandleEventImpl(InstrumentingAgents&);
-    static void didDispatchEventImpl(const InspectorInstrumentationCookie&);
+    static void didDispatchEventImpl(const InspectorInstrumentationCookie&, bool defaultPrevented);
     static InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InstrumentingAgents&, const Event&, DOMWindow&);
-    static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&);
+    static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&, bool defaultPrevented);
     static void eventDidResetAfterDispatchImpl(InstrumentingAgents&, const Event&);
     static InspectorInstrumentationCookie willEvaluateScriptImpl(InstrumentingAgents&, Frame&, const String& url, int lineNumber, int columnNumber);
     static void didEvaluateScriptImpl(const InspectorInstrumentationCookie&, Frame&);
@@ -793,11 +793,11 @@ inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEven
     return InspectorInstrumentationCookie();
 }
 
-inline void InspectorInstrumentation::didDispatchEvent(const InspectorInstrumentationCookie& cookie)
+inline void InspectorInstrumentation::didDispatchEvent(const InspectorInstrumentationCookie& cookie, bool defaultPrevented)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
     if (cookie.isValid())
-        didDispatchEventImpl(cookie);
+        didDispatchEventImpl(cookie, defaultPrevented);
 }
 
 inline void InspectorInstrumentation::willHandleEvent(ScriptExecutionContext& context, Event& event, const RegisteredEventListener& listener)
@@ -822,11 +822,11 @@ inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEven
     return InspectorInstrumentationCookie();
 }
 
-inline void InspectorInstrumentation::didDispatchEventOnWindow(const InspectorInstrumentationCookie& cookie)
+inline void InspectorInstrumentation::didDispatchEventOnWindow(const InspectorInstrumentationCookie& cookie, bool defaultPrevented)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
     if (cookie.isValid())
-        didDispatchEventOnWindowImpl(cookie);
+        didDispatchEventOnWindowImpl(cookie, defaultPrevented);
 }
 
 inline void InspectorInstrumentation::eventDidResetAfterDispatch(const Event& event)
index 6b2b56a..81dedce 100644 (file)
@@ -306,8 +306,12 @@ void InspectorTimelineAgent::willDispatchEvent(const Event& event, Frame* frame)
     pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(event), TimelineRecordType::EventDispatch, false, frame);
 }
 
-void InspectorTimelineAgent::didDispatchEvent()
+void InspectorTimelineAgent::didDispatchEvent(bool defaultPrevented)
 {
+    auto& entry = m_recordStack.last();
+    ASSERT(entry.type == TimelineRecordType::EventDispatch);
+    entry.data->setBoolean("defaultPrevented"_s, defaultPrevented);
+
     didCompleteCurrentRecord(TimelineRecordType::EventDispatch);
 }
 
index 90a396f..aac38ff 100644 (file)
@@ -115,7 +115,7 @@ public:
     void willCallFunction(const String& scriptName, int scriptLine, int scriptColumn, Frame*);
     void didCallFunction(Frame*);
     void willDispatchEvent(const Event&, Frame*);
-    void didDispatchEvent();
+    void didDispatchEvent(bool defaultPrevented);
     void willEvaluateScript(const String&, int lineNumber, int columnNumber, Frame&);
     void didEvaluateScript(Frame&);
     void didInvalidateLayout(Frame&);
index d0be79c..f10aae8 100644 (file)
@@ -2109,7 +2109,7 @@ void DOMWindow::dispatchEvent(Event& event, EventTarget* target)
     // FIXME: We should use EventDispatcher everywhere.
     fireEventListeners(event, EventInvokePhase::Capturing);
     fireEventListeners(event, EventInvokePhase::Bubbling);
-    InspectorInstrumentation::didDispatchEventOnWindow(cookie);
+    InspectorInstrumentation::didDispatchEventOnWindow(cookie, event.defaultPrevented());
     event.resetAfterDispatch();
 }
 
index 0fb96d0..b5ab3ff 100644 (file)
@@ -1,5 +1,37 @@
 2019-03-20  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Timeline should show when events preventDefault() was called on an event or not
+        https://bugs.webkit.org/show_bug.cgi?id=176824
+        <rdar://problem/34290931>
+
+        Reviewed by Timothy Hatcher.
+
+        Original patch by Joseph Pecoraro <pecoraro@apple.com>.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        New string.
+
+        * UserInterface/Controllers/TimelineManager.js:
+        (WI.TimelineManager.prototype._processRecord):
+        Include the whole data object as extra details.
+
+        * UserInterface/Models/ScriptTimelineRecord.js:
+        (WI.ScriptTimelineRecord):
+        (WI.ScriptTimelineRecord.prototype.get eventType):
+        Wholesale copy of the extra data instead of just a single property.
+
+        * UserInterface/Views/ScriptDetailsTimelineView.js:
+        (WI.ScriptDetailsTimelineView):
+        Give the name column more initial space, there is still extra space
+        after this adjustment but name is comfortably larger (and the most
+        likely to be expanded).
+
+        * UserInterface/Views/ScriptTimelineDataGridNode.js:
+        (WI.ScriptTimelineDataGridNode.prototype.get subtitle):
+        Include "default prevented" as the event's subtitle if it was prevented.
+
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: Styles Redesign: Editing selector should not hide the rule
         https://bugs.webkit.org/show_bug.cgi?id=178489
         <rdar://problem/35062434>
index 135eae9..4e9b0ce 100644 (file)
@@ -1180,6 +1180,7 @@ localizedStrings["\u201C%s\u201D Event Fired"] = "\u201C%s\u201D Event Fired";
 localizedStrings["\u201C%s\u201D Profile Recorded"] = "\u201C%s\u201D Profile Recorded";
 localizedStrings["computed"] = "computed";
 localizedStrings["default"] = "default";
+localizedStrings["default prevented"] = "default prevented";
 localizedStrings["for changes to take effect"] = "for changes to take effect";
 localizedStrings["invalid HAR"] = "invalid HAR";
 localizedStrings["invalid JSON"] = "invalid JSON";
index d8a5389..e4b72ec 100644 (file)
@@ -697,7 +697,7 @@ WI.TimelineManager = class TimelineManager extends WI.Object
                 record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.TimerFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.timerId, profileData);
                 break;
             case TimelineAgent.EventType.EventDispatch:
-                record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.EventDispatched, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type, profileData);
+                record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.EventDispatched, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type, profileData, parentRecordPayload.data);
                 break;
             case TimelineAgent.EventType.ObserverCallback:
                 record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.ObserverCallback, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type, profileData);
index 77bca00..1b328f3 100644 (file)
@@ -25,7 +25,7 @@
 
 WI.ScriptTimelineRecord = class ScriptTimelineRecord extends WI.TimelineRecord
 {
-    constructor(eventType, startTime, endTime, callFrames, sourceCodeLocation, details, profilePayload)
+    constructor(eventType, startTime, endTime, callFrames, sourceCodeLocation, details, profilePayload, extraDetails)
     {
         super(WI.TimelineRecord.Type.Script, startTime, endTime, callFrames, sourceCodeLocation);
 
@@ -38,6 +38,7 @@ WI.ScriptTimelineRecord = class ScriptTimelineRecord extends WI.TimelineRecord
         this._details = details || "";
         this._profilePayload = profilePayload || null;
         this._profile = null;
+        this._extraDetails = extraDetails || null;
 
         // COMPATIBILITY(iOS 9): Before the ScriptProfilerAgent we did not have sample data. Return NaN to match old behavior.
         if (!window.ScriptProfilerAgent)
@@ -76,15 +77,10 @@ WI.ScriptTimelineRecord = class ScriptTimelineRecord extends WI.TimelineRecord
 
     // Public
 
-    get eventType()
-    {
-        return this._eventType;
-    }
-
-    get details()
-    {
-        return this._details;
-    }
+    get eventType() { return this._eventType; }
+    get details() { return this._details; }
+    get extraDetails() { return this._extraDetails; }
+    get callCountOrSamples() { return this._callCountOrSamples; }
 
     get profile()
     {
@@ -92,11 +88,6 @@ WI.ScriptTimelineRecord = class ScriptTimelineRecord extends WI.TimelineRecord
         return this._profile;
     }
 
-    get callCountOrSamples()
-    {
-        return this._callCountOrSamples;
-    }
-
     isGarbageCollection()
     {
         return this._eventType === WI.ScriptTimelineRecord.EventType.GarbageCollected;
index 6d8db3a..c2c0924 100644 (file)
@@ -34,7 +34,7 @@ WI.ScriptDetailsTimelineView = class ScriptDetailsTimelineView extends WI.Timeli
         let columns = {name: {}, location: {}, callCount: {}, startTime: {}, totalTime: {}, selfTime: {}, averageTime: {}};
 
         columns.name.title = WI.UIString("Name");
-        columns.name.width = "10%";
+        columns.name.width = "30%";
         columns.name.icon = true;
         columns.name.disclosure = true;
         columns.name.locked = true;
index 4565bee..96896f4 100644 (file)
@@ -86,6 +86,9 @@ WI.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode extends WI.Time
                 this._subtitle = WI.UIString("%s interval").format(timeoutString);
             else
                 this._subtitle = WI.UIString("%s delay").format(timeoutString);
+        } else if (this._record.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched) {
+            if (this._record.extraDetails && this._record.extraDetails.defaultPrevented)
+                this._subtitle = WI.UIString("default prevented");
         }
 
         return this._subtitle;