Diff
Modified: trunk/LayoutTests/ChangeLog (246060 => 246061)
--- trunk/LayoutTests/ChangeLog 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/ChangeLog 2019-06-04 14:34:11 UTC (rev 246061)
@@ -1,3 +1,26 @@
+2019-06-04 Antoine Quint <[email protected]>
+
+ The "mouseenter" and "pointerenter" events are fired from the bottom up
+ https://bugs.webkit.org/show_bug.cgi?id=198036
+ <rdar://problem/50940350>
+
+ Reviewed by Darin Adler.
+
+ * fast/events/mouseenter-mouseleave-capture-expected.txt:
+ * fast/events/mouseenter-mouseleave-expected.txt:
+ * fast/events/mouseenterleave-on-subframe-expected.txt:
+ * fast/events/shadow-event-path-expected.txt:
+ * fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary-expected.txt:
+ * fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree-expected.txt:
+ * fast/shadow-dom/mouseenter-mouseleave-on-slot-parent-expected.txt:
+ * platform/mac-wk1/TestExpectations:
+ * platform/mac-wk2/fast/events/shadow-event-path-expected.txt:
+ * platform/mac/fast/events/shadow-event-path-2-expected.txt:
+ * pointerevents/ios/enter-leave-order-expected.txt: Added.
+ * pointerevents/ios/enter-leave-order.html: Added.
+ * pointerevents/mouse/enter-leave-order-expected.txt: Added.
+ * pointerevents/mouse/enter-leave-order.html: Added.
+
2019-06-04 Cathie Chen <[email protected]>
JS wrapper of target in ResizeObserverEntry/ResizeObserver shouldn't get collected ahead
Modified: trunk/LayoutTests/fast/events/mouseenter-mouseleave-capture-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/events/mouseenter-mouseleave-capture-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/events/mouseenter-mouseleave-capture-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -8,8 +8,8 @@
mouseMoveTo(110,140)
mouseout on html
mouseover on outer1
+mouseenter on body
mouseenter on outer1
-mouseenter on body
mousemove on outer1
mouseMoveTo(130,140)
@@ -22,8 +22,8 @@
mouseout on inner1
mouseleave on inner1
mouseover on inner3
+mouseenter on inner2
mouseenter on inner3
-mouseenter on inner2
mousemove on inner3
mouseMoveTo(180,140)
Modified: trunk/LayoutTests/fast/events/mouseenter-mouseleave-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/events/mouseenter-mouseleave-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/events/mouseenter-mouseleave-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -9,8 +9,8 @@
mouseMoveTo(110,140)
mouseout on html
mouseover on outer1
+mouseenter on body
mouseenter on outer1
-mouseenter on body
mousemove on outer1
mouseMoveTo(130,140)
@@ -23,8 +23,8 @@
mouseout on inner1
mouseleave on inner1
mouseover on inner3
+mouseenter on inner2
mouseenter on inner3
-mouseenter on inner2
mousemove on inner3
mouseMoveTo(180,140)
Modified: trunk/LayoutTests/fast/events/mouseenterleave-on-subframe-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/events/mouseenterleave-on-subframe-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/events/mouseenterleave-on-subframe-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -1,9 +1,9 @@
This is a test of a mouseleave events in an inner-document. The test is success if we get matching mouseleave events for every mouseenter event, and if the logged nodeNames of event targets does not include '#document'.
+mouseenter on HTML
+mouseenter on BODY
mouseenter on DIV
-mouseenter on BODY
-mouseenter on HTML
mouseleave on DIV
mouseleave on BODY
mouseleave on HTML
Modified: trunk/LayoutTests/fast/events/shadow-event-path-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/events/shadow-event-path-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/events/shadow-event-path-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -39,16 +39,16 @@
target:input#target
relatedTarget:null
-mouseenter@input#target
- target:input#target
+mouseenter@html
+ target:html
relatedTarget:null
-mouseenter@div#divInsideSummary
- target:div#divInsideSummary
+mouseenter@body
+ target:body
relatedTarget:null
-mouseenter@summary
- target:summary
+mouseenter@div#detailsContainer
+ target:div#detailsContainer
relatedTarget:null
mouseenter@details
@@ -55,16 +55,16 @@
target:details
relatedTarget:null
-mouseenter@div#detailsContainer
- target:div#detailsContainer
+mouseenter@summary
+ target:summary
relatedTarget:null
-mouseenter@body
- target:body
+mouseenter@div#divInsideSummary
+ target:div#divInsideSummary
relatedTarget:null
-mouseenter@html
- target:html
+mouseenter@input#target
+ target:input#target
relatedTarget:null
mousemove@input#target
Modified: trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-across-shadow-boundary-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -14,8 +14,8 @@
mouseenter on slot
==Entering slotted element==
+mouseenter on targetParent
mouseenter on target
-mouseenter on targetParent
==Leaving slotted element==
mouseleave on target
Modified: trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-inside-shadow-tree-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -4,10 +4,10 @@
==Entering target==
+mouseenter on hostParent
+mouseenter on host
+mouseenter on container
mouseenter on target
-mouseenter on container
-mouseenter on host
-mouseenter on hostParent
==Leaving target==
mouseleave on target
Modified: trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-on-slot-parent-expected.txt (246060 => 246061)
--- trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-on-slot-parent-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/fast/shadow-dom/mouseenter-mouseleave-on-slot-parent-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -4,9 +4,9 @@
==Entering target==
+mouseenter on slotContainer
+mouseenter on slot
mouseenter on target
-mouseenter on slot
-mouseenter on slotContainer
==Leaving target==
mouseleave on target
Modified: trunk/LayoutTests/platform/mac/fast/events/shadow-event-path-2-expected.txt (246060 => 246061)
--- trunk/LayoutTests/platform/mac/fast/events/shadow-event-path-2-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/platform/mac/fast/events/shadow-event-path-2-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -67,8 +67,8 @@
target:input#target
relatedTarget:html
-mouseenter@input#target
- target:input#target
+mouseenter@body
+ target:body
relatedTarget:html
mouseenter@div#detailsContainer
@@ -75,8 +75,8 @@
target:div#detailsContainer
relatedTarget:html
-mouseenter@body
- target:body
+mouseenter@input#target
+ target:input#target
relatedTarget:html
mousemove@input#target
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (246060 => 246061)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-06-04 14:34:11 UTC (rev 246061)
@@ -689,6 +689,7 @@
webkit.org/b/194309 media/modern-media-controls/compact-media-controls/compact-media-controls-layout.html [ Pass Failure ]
+webkit.org/b/195098 pointerevents/mouse/enter-leave-order.html [ Failure ]
webkit.org/b/195098 pointerevents/mouse/over-enter-out-leave.html [ Failure ]
webkit.org/b/195098 pointerevents/mouse/pointer-capture.html [ Failure ]
webkit.org/b/195098 pointerevents/mouse/pointer-events-before-mouse-events.html [ Failure ]
Modified: trunk/LayoutTests/platform/mac-wk2/fast/events/shadow-event-path-expected.txt (246060 => 246061)
--- trunk/LayoutTests/platform/mac-wk2/fast/events/shadow-event-path-expected.txt 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/LayoutTests/platform/mac-wk2/fast/events/shadow-event-path-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -39,16 +39,16 @@
target:input#target
relatedTarget:null
-mouseenter@input#target
- target:input#target
+mouseenter@html
+ target:html
relatedTarget:null
-mouseenter@div#divInsideSummary
- target:div#divInsideSummary
+mouseenter@body
+ target:body
relatedTarget:null
-mouseenter@summary
- target:summary
+mouseenter@div#detailsContainer
+ target:div#detailsContainer
relatedTarget:null
mouseenter@details
@@ -55,16 +55,16 @@
target:details
relatedTarget:null
-mouseenter@div#detailsContainer
- target:div#detailsContainer
+mouseenter@summary
+ target:summary
relatedTarget:null
-mouseenter@body
- target:body
+mouseenter@div#divInsideSummary
+ target:div#divInsideSummary
relatedTarget:null
-mouseenter@html
- target:html
+mouseenter@input#target
+ target:input#target
relatedTarget:null
mousemove@input#target
Added: trunk/LayoutTests/pointerevents/ios/enter-leave-order-expected.txt (0 => 246061)
--- trunk/LayoutTests/pointerevents/ios/enter-leave-order-expected.txt (rev 0)
+++ trunk/LayoutTests/pointerevents/ios/enter-leave-order-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -0,0 +1,3 @@
+
+PASS Testing that "pointerenter" events are dispatched from top to bottom and "pointerleave" events are dispatched bottom to top.
+
Added: trunk/LayoutTests/pointerevents/ios/enter-leave-order.html (0 => 246061)
--- trunk/LayoutTests/pointerevents/ios/enter-leave-order.html (rev 0)
+++ trunk/LayoutTests/pointerevents/ios/enter-leave-order.html 2019-06-04 14:34:11 UTC (rev 246061)
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+
+div.test-container {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100px;
+ height: 100px;
+}
+
+#top {
+ left: 50px;
+ top: 50px;
+}
+
+</style>
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script>
+
+'use strict';
+
+const events = [];
+
+function logEvent(event)
+{
+ events.push(`${event.type}@${event.target.id}`);
+}
+
+function makeDiv(id)
+{
+ const div = document.createElement("div");
+ div.addEventListener("pointerenter", logEvent);
+ div.addEventListener("pointerleave", logEvent);
+ div.className = "test-container";
+ div.id = id;
+ return div;
+}
+
+document.body.appendChild(makeDiv("top")).appendChild(makeDiv("middle")).appendChild(makeDiv("bottom"));
+
+async_test(test => {
+ const tapped = ui.tap({ x: 100, y: 100 }).then(() => {
+ assert_array_equals(events, [
+ "pointerenter@top",
+ "pointerenter@middle",
+ "pointerenter@bottom",
+ "pointerleave@bottom",
+ "pointerleave@middle",
+ "pointerleave@top"
+ ]);
+ test.done();
+ });
+}, `Testing that "pointerenter" events are dispatched from top to bottom and "pointerleave" events are dispatched bottom to top.`);
+
+</script>
+</body>
+</html>
\ No newline at end of file
Added: trunk/LayoutTests/pointerevents/mouse/enter-leave-order-expected.txt (0 => 246061)
--- trunk/LayoutTests/pointerevents/mouse/enter-leave-order-expected.txt (rev 0)
+++ trunk/LayoutTests/pointerevents/mouse/enter-leave-order-expected.txt 2019-06-04 14:34:11 UTC (rev 246061)
@@ -0,0 +1,3 @@
+
+PASS Testing that "pointerenter" events are dispatched from top to bottom and "pointerleave" events are dispatched bottom to top.
+
Added: trunk/LayoutTests/pointerevents/mouse/enter-leave-order.html (0 => 246061)
--- trunk/LayoutTests/pointerevents/mouse/enter-leave-order.html (rev 0)
+++ trunk/LayoutTests/pointerevents/mouse/enter-leave-order.html 2019-06-04 14:34:11 UTC (rev 246061)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style>
+
+div.test-container {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100px;
+ height: 100px;
+}
+
+#top {
+ left: 50px;
+ top: 50px;
+}
+
+</style>
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script>
+
+'use strict';
+
+const events = [];
+
+function logEvent(event)
+{
+ events.push(`${event.type}@${event.target.id}`);
+}
+
+function makeDiv(id)
+{
+ const div = document.createElement("div");
+ div.addEventListener("pointerenter", logEvent);
+ div.addEventListener("pointerleave", logEvent);
+ div.className = "test-container";
+ div.id = id;
+ return div;
+}
+
+// Add three nested and fully overlapping elements.
+document.body.appendChild(makeDiv("top")).appendChild(makeDiv("middle")).appendChild(makeDiv("bottom"));
+
+// mouse over and out of the elements.
+eventSender.mouseMoveTo(75, 75);
+eventSender.mouseMoveTo(25, 25);
+
+test(() => {
+ assert_array_equals(events, [
+ "pointerenter@top",
+ "pointerenter@middle",
+ "pointerenter@bottom",
+ "pointerleave@bottom",
+ "pointerleave@middle",
+ "pointerleave@top"
+ ]);
+}, `Testing that "pointerenter" events are dispatched from top to bottom and "pointerleave" events are dispatched bottom to top.`);
+
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (246060 => 246061)
--- trunk/Source/WebCore/ChangeLog 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/Source/WebCore/ChangeLog 2019-06-04 14:34:11 UTC (rev 246061)
@@ -1,3 +1,27 @@
+2019-06-04 Antoine Quint <[email protected]>
+
+ The "mouseenter" and "pointerenter" events are fired from the bottom up
+ https://bugs.webkit.org/show_bug.cgi?id=198036
+ <rdar://problem/50940350>
+
+ Reviewed by Darin Adler.
+
+ Ensure "mouseenter" and "pointerenter" events are dispatched from the bottom up to match the UI Events spec
+ at https://w3c.github.io/uievents/#events-mouseevent-event-order. We also fix the issue where "pointerevent"
+ and "pointerleave" events were dispatched as bubbling events on iOS which is not correct and was caught by the
+ new iOS test.
+
+ Tests: pointerevents/ios/enter-leave-order.html
+ pointerevents/mouse/enter-leave-order.html
+
+ * dom/ios/PointerEventIOS.cpp:
+ (WebCore::typeCanBubble):
+ (WebCore::PointerEvent::PointerEvent):
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::updateMouseEventTargetNode):
+ * page/PointerCaptureController.cpp:
+ (WebCore::PointerCaptureController::dispatchEventForTouchAtIndex):
+
2019-06-04 Cathie Chen <[email protected]>
JS wrapper of target in ResizeObserverEntry/ResizeObserver shouldn't get collected ahead
Modified: trunk/Source/WebCore/dom/ios/PointerEventIOS.cpp (246060 => 246061)
--- trunk/Source/WebCore/dom/ios/PointerEventIOS.cpp 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/Source/WebCore/dom/ios/PointerEventIOS.cpp 2019-06-04 14:34:11 UTC (rev 246061)
@@ -57,6 +57,11 @@
return PointerEvent::IsCancelable::Yes;
}
+static Event::CanBubble typeCanBubble(const AtomicString& type)
+{
+ return (type == eventNames().pointerenterEvent || type == eventNames().pointerleaveEvent) ? Event::CanBubble::No : Event::CanBubble::Yes;
+}
+
Ref<PointerEvent> PointerEvent::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
{
auto phase = event.touchPhaseAtIndex(index);
@@ -69,7 +74,7 @@
}
PointerEvent::PointerEvent(const AtomicString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
- : MouseEvent(type, CanBubble::Yes, isCancelable, IsComposed::Yes, event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, event.touchLocationAtIndex(index), event.touchLocationAtIndex(index), { }, event.modifiers(), 0, 0, nullptr, 0, 0, nullptr, IsSimulated::No, IsTrusted::Yes)
+ : MouseEvent(type, typeCanBubble(type), isCancelable, IsComposed::Yes, event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, event.touchLocationAtIndex(index), event.touchLocationAtIndex(index), { }, event.modifiers(), 0, 0, nullptr, 0, 0, nullptr, IsSimulated::No, IsTrusted::Yes)
, m_pointerId(event.touchIdentifierAtIndex(index))
, m_width(2 * event.radiusXAtIndex(index))
, m_height(2 * event.radiusYAtIndex(index))
Modified: trunk/Source/WebCore/page/EventHandler.cpp (246060 => 246061)
--- trunk/Source/WebCore/page/EventHandler.cpp 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/Source/WebCore/page/EventHandler.cpp 2019-06-04 14:34:11 UTC (rev 246061)
@@ -2594,7 +2594,7 @@
if (m_elementUnderMouse)
m_elementUnderMouse->dispatchMouseEvent(platformMouseEvent, eventNames().mouseoverEvent, 0, m_lastElementUnderMouse.get());
- for (auto& chain : enteredElementsChain) {
+ for (auto& chain : WTF::makeReversedRange(enteredElementsChain)) {
if (hasCapturingMouseEnterListener || chain->hasEventListeners(eventNames().pointerenterEvent) || chain->hasEventListeners(eventNames().mouseenterEvent))
chain->dispatchMouseEvent(platformMouseEvent, eventNames().mouseenterEvent, 0, m_lastElementUnderMouse.get());
}
Modified: trunk/Source/WebCore/page/PointerCaptureController.cpp (246060 => 246061)
--- trunk/Source/WebCore/page/PointerCaptureController.cpp 2019-06-04 11:14:10 UTC (rev 246060)
+++ trunk/Source/WebCore/page/PointerCaptureController.cpp 2019-06-04 14:34:11 UTC (rev 246061)
@@ -190,9 +190,18 @@
}
}
- for (Element* element = &downcast<Element>(target); element; element = element->parentElementInComposedTree()) {
+ Vector<Ref<Element>, 32> targetChain;
+ for (Element* element = targetElement; element; element = element->parentElementInComposedTree()) {
if (hasCapturingListenerInHierarchy || element->hasEventListeners(type))
+ targetChain.append(*element);
+ }
+
+ if (type == eventNames().pointerenterEvent) {
+ for (auto& element : WTF::makeReversedRange(targetChain))
element->dispatchEvent(PointerEvent::create(type, platformTouchEvent, index, isPrimary, view));
+ } else {
+ for (auto& element : targetChain)
+ element->dispatchEvent(PointerEvent::create(type, platformTouchEvent, index, isPrimary, view));
}
};