From 79207867b53f1d8fce379c3cdfdb89cc7f273820 Mon Sep 17 00:00:00 2001 From: Hayato Ito Date: Fri, 14 Sep 2018 00:36:02 -0700 Subject: [PATCH] Call capture event listeners in capturing phase at shadow hosts Chromestatus entry is here: https://www.chromestatus.com/feature/5636327009681408 Per the discussion of https://github.com/whatwg/dom/issues/685, Blink will try to align the event dispatch behavior with other browsers; Call capture event listeners in capturing phase at shadow hosts. So far, Blink and WebKit call capture event listeners in *bubbling* phase, instead of *capturing* phase, at shadow hosts. Other browsers: - Safari: Will try to change the behavior in the next Safari Technical Preview. - Firefox: Already implemented the new behavior - Edge: Strong public support for the new behavior. This change is guard by CallCaptureListenersAtCapturePhaseAtShadowHosts flag, which is disabled at this moment, to confirm that this CL doesn't cause any behavior change when the flag is disabled. This CL adds a wpt for new behavior, which is now marked as [Failure] in Blink. After this CL lands, I will flip the flag in a follow-up CL, with rebasing a very few existing tests. BUG=883650 Change-Id: I29938840aed4f3430d8b749cd4843176b8668b5d --- .../event-dispatch-order.tentative.html | 30 ++++++++++++ shadow-dom/resources/shadow-dom.js | 49 +++++++++++++++---- 2 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 shadow-dom/event-dispatch-order.tentative.html diff --git a/shadow-dom/event-dispatch-order.tentative.html b/shadow-dom/event-dispatch-order.tentative.html new file mode 100644 index 00000000000000..1e88740f53a2dc --- /dev/null +++ b/shadow-dom/event-dispatch-order.tentative.html @@ -0,0 +1,30 @@ + +Shadow DOM: event dispatch order for capture and non-capture listerns at a shadow host + + + + + + +
+ +
+ diff --git a/shadow-dom/resources/shadow-dom.js b/shadow-dom/resources/shadow-dom.js index 3e55684dac1c4f..1c1835d82f5655 100644 --- a/shadow-dom/resources/shadow-dom.js +++ b/shadow-dom/resources/shadow-dom.js @@ -53,7 +53,9 @@ function createTestTree(node) { return ids; } -function dispatchEventWithLog(nodes, target, event) { +// TODO(hayato): Refactor this so that only interested results are recorded. +// Callers of this function would not be interested in every results. +function dispatchEventWithLog(nodes, target, event, options) { function labelFor(e) { return e.id || e.tagName; @@ -70,15 +72,40 @@ function dispatchEventWithLog(nodes, target, event) { if (!id) continue; attachedNodes.push(node); - node.addEventListener(event.type, (e) => { + if (options && options.capture) { + // Record [currentTarget, target, relatedTarget, composedPath(), 'capture' | 'non-capture'] + // TODO(hayato): Support register listeners in different orders. + // e.g. Register non-capture listener at first, then register capture listener. + node.addEventListener(event.type, (e) => { + log.push([id, + labelFor(e.target), + e.relatedTarget ? labelFor(e.relatedTarget) : null, + e.composedPath().map((n) => { + return labelFor(n); + }), + 'capture']); + }, true); + node.addEventListener(event.type, (e) => { + log.push([id, + labelFor(e.target), + e.relatedTarget ? labelFor(e.relatedTarget) : null, + e.composedPath().map((n) => { + return labelFor(n); + }), + 'non-capture']); + }); + } else { // Record [currentTarget, target, relatedTarget, composedPath()] - log.push([id, - labelFor(e.target), - e.relatedTarget ? labelFor(e.relatedTarget) : null, - e.composedPath().map((n) => { - return labelFor(n); - })]); - }); + node.addEventListener(event.type, (e) => { + log.push([id, + labelFor(e.target), + e.relatedTarget ? labelFor(e.relatedTarget) : null, + e.composedPath().map((n) => { + return labelFor(n); + })] + ); + }); + } } } target.dispatchEvent(event); @@ -122,9 +149,13 @@ function dispatchUAEventWithLog(nodes, target, eventType, callback) { function assert_event_path_equals(actual, expected) { assert_equals(actual.length, expected.length); for (let i = 0; i < actual.length; ++i) { + assert_equals(actual[i].length, expected[i].length); assert_equals(actual[i][0], expected[i][0], 'currentTarget at ' + i + ' should be same'); assert_equals(actual[i][1], expected[i][1], 'target at ' + i + ' should be same'); assert_equals(actual[i][2], expected[i][2], 'relatedTarget at ' + i + ' should be same'); assert_array_equals(actual[i][3], expected[i][3], 'composedPath at ' + i + ' should be same'); + if (actual[i][4]) { + assert_equals(actual[i][4], expected[i][4], 'listener type should be same at ' + i); + } } }