Commit c8804494 authored by Rakina Zata Amni's avatar Rakina Zata Amni Committed by Commit Bot

Set relatedTarget to null if target is null in DispatchEventPostProcess

In some cases, relatedTarget kept its value after event dispatch has
finished even though target is set to null. See test file for the cases.

This change adds a check so that when target is set to null in the
post-processing phase, the change is also reflected in relatedTarget.

Bug: 771580
Change-Id: Idda5d00c1a793b2669be66e76439851d1f66459c
Reviewed-on: https://chromium-review.googlesource.com/720897Reviewed-by: default avatarHayato Ito <hayato@chromium.org>
Reviewed-by: default avatarTakayoshi Kochi <kochi@chromium.org>
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
Cr-Commit-Position: refs/heads/master@{#509710}
parent 69bf5cae
This is a testharness.js-based test.
PASS Event properties post dispatch without ShadowRoots (composed: true).
PASS Event properties post dispatch without ShadowRoots (composed: false).
PASS Event properties post dispatch with an open ShadowRoot (composed: true).
PASS Event properties post dispatch with an open ShadowRoot (composed: false).
PASS Event properties post dispatch with a closed ShadowRoot (composed: true).
PASS Event properties post dispatch with a closed ShadowRoot (composed: false).
PASS Event properties post dispatch with nested ShadowRoots (composed: true).
PASS Event properties post dispatch with nested ShadowRoots (composed: false).
FAIL Event properties post dispatch with relatedTarget in the same shadow tree. (composed: true) assert_equals: expected null but got Element node <div id="relatedTarget">\n <div id="target"></div>\n...
FAIL Event properties post dispatch with relatedTarget in the same shadow tree. (composed: false) assert_equals: expected null but got Element node <div id="relatedTarget">\n <div id="target"></div>\n...
PASS Event properties post dispatch with relatedTarget in the document tree and the shadow tree. (composed: true)
FAIL Event properties post dispatch with relatedTarget in the document tree and the shadow tree. (composed: false) assert_equals: expected null but got Element node <div id="relatedTarget"></div>
FAIL Event properties post dispatch with relatedTarget in the different shadow trees. (composed: true) assert_equals: expected Element node <div id="host1">\n \n </div> but got null
FAIL Event properties post dispatch with relatedTarget in the different shadow trees. (composed: false) assert_equals: expected null but got Element node <div id="host2">\n \n </div>
Harness: the test ran to completion.
...@@ -206,7 +206,7 @@ document.body.removeChild(n6.test6); ...@@ -206,7 +206,7 @@ document.body.removeChild(n6.test6);
let n7 = createTestTree(test7); let n7 = createTestTree(test7);
document.body.appendChild(n7.test7); document.body.appendChild(n7.test7);
test(() => { test(() => {
let log = dispatchEventWithEventLog(n7, n7.target, new MouseEvent('my-event', {bubbles: true, compoesed: true, relatedTarget: n7.relatedTarget})); let log = dispatchEventWithEventLog(n7, n7.target, new MouseEvent('my-event', {bubbles: true, composed: true, relatedTarget: n7.relatedTarget}));
assert_equals(log.event.target, n7.host1); assert_equals(log.event.target, n7.host1);
assert_equals(log.event.relatedTarget, n7.host2); assert_equals(log.event.relatedTarget, n7.host2);
assert_equals(log.event.eventPhase, 0); assert_equals(log.event.eventPhase, 0);
...@@ -215,7 +215,7 @@ test(() => { ...@@ -215,7 +215,7 @@ test(() => {
}, 'Event properties post dispatch with relatedTarget in the different shadow trees. (composed: true)'); }, 'Event properties post dispatch with relatedTarget in the different shadow trees. (composed: true)');
test(() => { test(() => {
let log = dispatchEventWithEventLog(n7, n7.target, new MouseEvent('my-event', {bubbles: true, compoesed: false, relatedTarget: n7.relatedTarget})); let log = dispatchEventWithEventLog(n7, n7.target, new MouseEvent('my-event', {bubbles: true, composed: false, relatedTarget: n7.relatedTarget}));
assert_equals(log.event.target, null); assert_equals(log.event.target, null);
assert_equals(log.event.relatedTarget, null); assert_equals(log.event.relatedTarget, null);
assert_equals(log.event.eventPhase, 0); assert_equals(log.event.eventPhase, 0);
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#include "core/dom/StaticNodeList.h" #include "core/dom/StaticNodeList.h"
#include "core/dom/events/EventDispatchMediator.h" #include "core/dom/events/EventDispatchMediator.h"
#include "core/dom/events/EventTarget.h" #include "core/dom/events/EventTarget.h"
#include "core/events/FocusEvent.h"
#include "core/events/MouseEvent.h"
#include "core/events/PointerEvent.h"
#include "core/frame/HostsUsingFeatures.h" #include "core/frame/HostsUsingFeatures.h"
#include "core/frame/UseCounter.h" #include "core/frame/UseCounter.h"
#include "core/svg/SVGElement.h" #include "core/svg/SVGElement.h"
...@@ -254,6 +257,16 @@ void Event::SetTarget(EventTarget* target) { ...@@ -254,6 +257,16 @@ void Event::SetTarget(EventTarget* target) {
ReceivedTarget(); ReceivedTarget();
} }
void Event::SetRelatedTargetIfExists(EventTarget* related_target) {
if (IsMouseEvent()) {
ToMouseEvent(this)->SetRelatedTarget(related_target);
} else if (IsPointerEvent()) {
ToPointerEvent(this)->SetRelatedTarget(related_target);
} else if (IsFocusEvent()) {
ToFocusEvent(this)->SetRelatedTarget(related_target);
}
}
void Event::ReceivedTarget() {} void Event::ReceivedTarget() {}
void Event::SetUnderlyingEvent(Event* ue) { void Event::SetUnderlyingEvent(Event* ue) {
......
...@@ -123,6 +123,8 @@ class CORE_EXPORT Event : public GarbageCollectedFinalized<Event>, ...@@ -123,6 +123,8 @@ class CORE_EXPORT Event : public GarbageCollectedFinalized<Event>,
// is dangerous. // is dangerous.
virtual void DoneDispatchingEventAtCurrentTarget() {} virtual void DoneDispatchingEventAtCurrentTarget() {}
void SetRelatedTargetIfExists(EventTarget* related_target);
unsigned short eventPhase() const { return event_phase_; } unsigned short eventPhase() const { return event_phase_; }
void SetEventPhase(unsigned short event_phase) { event_phase_ = event_phase; } void SetEventPhase(unsigned short event_phase) { event_phase_ = event_phase; }
......
...@@ -186,12 +186,6 @@ DispatchEventResult EventDispatcher::Dispatch() { ...@@ -186,12 +186,6 @@ DispatchEventResult EventDispatcher::Dispatch() {
} }
DispatchEventPostProcess(activation_target, DispatchEventPostProcess(activation_target,
pre_dispatch_event_handler_result); pre_dispatch_event_handler_result);
// Ensure that after event dispatch, the event's target object is the
// outermost shadow DOM boundary.
event_->SetTarget(event_->GetEventPath().GetWindowEventContext().Target());
event_->SetCurrentTarget(nullptr);
return EventTarget::GetDispatchEventResult(*event_); return EventTarget::GetDispatchEventResult(*event_);
} }
...@@ -272,7 +266,8 @@ inline void EventDispatcher::DispatchEventPostProcess( ...@@ -272,7 +266,8 @@ inline void EventDispatcher::DispatchEventPostProcess(
event_->SetStopImmediatePropagation(false); event_->SetStopImmediatePropagation(false);
// 15. Set event’s eventPhase attribute to NONE. // 15. Set event’s eventPhase attribute to NONE.
event_->SetEventPhase(0); event_->SetEventPhase(0);
// 16. Set event’s currentTarget attribute to null. // TODO(rakina): investigate this and move it to the bottom of step 16
// 17. Set event’s currentTarget attribute to null.
event_->SetCurrentTarget(nullptr); event_->SetCurrentTarget(nullptr);
bool is_click = event_->IsMouseEvent() && bool is_click = event_->IsMouseEvent() &&
...@@ -346,6 +341,11 @@ inline void EventDispatcher::DispatchEventPostProcess( ...@@ -346,6 +341,11 @@ inline void EventDispatcher::DispatchEventPostProcess(
UseCounter::Count(node_->GetDocument(), UseCounter::Count(node_->GetDocument(),
WebFeature::kUntrustedMouseDownEventDispatchedToSelect); WebFeature::kUntrustedMouseDownEventDispatchedToSelect);
} }
// 16. If target's root is a shadow root, then set event's target attribute
// and event's relatedTarget to null.
event_->SetTarget(event_->GetEventPath().GetWindowEventContext().Target());
if (!event_->target())
event_->SetRelatedTargetIfExists(nullptr);
} }
} // namespace blink } // namespace blink
...@@ -50,13 +50,7 @@ void NodeEventContext::HandleLocalEvents(Event& event) const { ...@@ -50,13 +50,7 @@ void NodeEventContext::HandleLocalEvents(Event& event) const {
if (TouchEventContext* touch_context = GetTouchEventContext()) { if (TouchEventContext* touch_context = GetTouchEventContext()) {
touch_context->HandleLocalEvents(event); touch_context->HandleLocalEvents(event);
} else if (RelatedTarget()) { } else if (RelatedTarget()) {
if (event.IsMouseEvent()) { event.SetRelatedTargetIfExists(RelatedTarget());
ToMouseEvent(event).SetRelatedTarget(RelatedTarget());
} else if (event.IsPointerEvent()) {
ToPointerEvent(event).SetRelatedTarget(RelatedTarget());
} else if (event.IsFocusEvent()) {
ToFocusEvent(event).SetRelatedTarget(RelatedTarget());
}
} }
event.SetTarget(Target()); event.SetTarget(Target());
event.SetCurrentTarget(current_target_.Get()); event.SetCurrentTarget(current_target_.Get());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment