What happens on a click
// actual differences (in chrome, IE, Firefox, Safari an Edge are all different) are: | |
// - behavior in disabled 'form' controls | |
// - phoning to home base (not here, it's defined elsewhere, can dig it up) | |
// - dealing with clicks dispatching clicks 'recursively' | |
// this is HTMLElement::click | |
void HTMLElement::click() { | |
DispatchSimulatedClick(nullptr, kSendNoEvents, | |
SimulatedClickCreationScope::kFromScript); | |
} | |
// this is the DispatchSimulatedClick method in event_dispatcher.cc the "heart" of the difference | |
void EventDispatcher::DispatchSimulatedClick( | |
Node& node, | |
Event* underlying_event, | |
SimulatedClickMouseEventOptions mouse_event_options, | |
SimulatedClickCreationScope creation_scope) { | |
// This persistent vector doesn't cause leaks, because added Nodes are removed | |
// before dispatchSimulatedClick() returns. This vector is here just to | |
// prevent the code from running into an infinite recursion of | |
// dispatchSimulatedClick(). | |
DEFINE_STATIC_LOCAL(Persistent<HeapHashSet<Member<Node>>>, | |
nodes_dispatching_simulated_clicks, | |
(MakeGarbageCollected<HeapHashSet<Member<Node>>>())); | |
if (IsDisabledFormControl(&node)) | |
return; | |
if (nodes_dispatching_simulated_clicks->Contains(&node)) | |
return; | |
nodes_dispatching_simulated_clicks->insert(&node); | |
if (mouse_event_options == kSendMouseOverUpDownEvents) | |
EventDispatcher(node, *MouseEvent::Create(event_type_names::kMouseover, | |
node.GetDocument().domWindow(), | |
underlying_event, creation_scope)) | |
.Dispatch(); | |
if (mouse_event_options != kSendNoEvents) { | |
EventDispatcher(node, *MouseEvent::Create(event_type_names::kMousedown, | |
node.GetDocument().domWindow(), | |
underlying_event, creation_scope)) | |
.Dispatch(); | |
node.SetActive(true); | |
EventDispatcher(node, *MouseEvent::Create(event_type_names::kMouseup, | |
node.GetDocument().domWindow(), | |
underlying_event, creation_scope)) | |
.Dispatch(); | |
} | |
// Some elements (e.g. the color picker) may set active state to true before | |
// calling this method and expect the state to be reset during the call. | |
node.SetActive(false); | |
// always send click | |
EventDispatcher(node, *MouseEvent::Create(event_type_names::kClick, | |
node.GetDocument().domWindow(), | |
underlying_event, creation_scope)) | |
.Dispatch(); | |
nodes_dispatching_simulated_clicks->erase(&node); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
And there is a separate path for 'real' clicks as well as clicks through the debugger (Input.dispatchMouseEvent which is essentially what Selenium calls).
This is part of why automation is hard.