LibWeb: Initialize clearTargets in event dispatch correctly

Corresponds to https://github.com/whatwg/dom/pull/1347
This commit is contained in:
Sam Atkins 2025-01-29 12:05:43 +00:00 committed by Jelle Raaijmakers
parent 3775f3399c
commit a5be7cb6fb
Notes: github-actions[bot] 2025-01-30 16:15:47 +00:00
4 changed files with 24 additions and 21 deletions

View file

@ -118,13 +118,13 @@ bool DOMTokenList::contains(String const& token)
// https://dom.spec.whatwg.org/#dom-domtokenlist-add
WebIDL::ExceptionOr<void> DOMTokenList::add(Vector<String> const& tokens)
{
// 1. For each token in tokens:
// 1. For each token of tokens:
for (auto const& token : tokens) {
// a. If token is the empty string, then throw a "SyntaxError" DOMException.
// b. If token contains any ASCII whitespace, then throw an "InvalidCharacterError" DOMException.
TRY(validate_token(token));
// 2. For each token in tokens, append token to thiss token set.
// 2. For each token of tokens, append token to thiss token set.
append_to_ordered_set(m_token_set, token);
}
@ -136,13 +136,13 @@ WebIDL::ExceptionOr<void> DOMTokenList::add(Vector<String> const& tokens)
// https://dom.spec.whatwg.org/#dom-domtokenlist-remove
WebIDL::ExceptionOr<void> DOMTokenList::remove(Vector<String> const& tokens)
{
// 1. For each token in tokens:
// 1. For each token of tokens:
for (auto const& token : tokens) {
// a. If token is the empty string, then throw a "SyntaxError" DOMException.
// b. If token contains any ASCII whitespace, then throw an "InvalidCharacterError" DOMException.
TRY(validate_token(token));
// 2. For each token in tokens, remove token from thiss token set.
// 2. For each token of tokens, remove token from thiss token set.
remove_from_ordered_set(m_token_set, token);
}

View file

@ -37,7 +37,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<GC::Root<DOM::DOMEventLi
// 1. Let found be false.
bool found = false;
// 2. For each listener in listeners, whose removed is false:
// 2. For each listener of listeners, whose removed is false:
for (auto& listener : listeners) {
if (listener->removed)
continue;
@ -212,8 +212,10 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
// 4. Let relatedTarget be the result of retargeting events relatedTarget against target.
GC::Ptr<EventTarget> related_target = retarget(event.related_target(), target);
// 5. Let clearTargets be false.
bool clear_targets = false;
// 5. If target is not relatedTarget or target is events relatedTarget, then:
// 6. If target is not relatedTarget or target is events relatedTarget, then:
if (related_target != target || event.related_target() == target) {
// 1. Let touchTargets be a new list.
Event::TouchTargetList touch_targets;
@ -320,8 +322,9 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
VERIFY(clear_targets_struct.has_value());
// 11. Let clearTargets be true if clearTargetsStructs shadow-adjusted target, clearTargetsStructs relatedTarget,
// or an EventTarget object in clearTargetsStructs touch target list is a node and its root is a shadow root; otherwise false.
// 11. If clearTargetsStructs shadow-adjusted target, clearTargetsStructs relatedTarget, or an EventTarget
// object in clearTargetsStructs touch target list is a node whose root is a shadow root:
// set clearTargets to true.
if (is<Node>(clear_targets_struct.value().shadow_adjusted_target.ptr())) {
auto& shadow_adjusted_target_node = as<Node>(*clear_targets_struct.value().shadow_adjusted_target);
if (is<ShadowRoot>(shadow_adjusted_target_node.root()))
@ -350,7 +353,7 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
if (activation_target)
activation_target->legacy_pre_activation_behavior();
// 13. For each struct in events path, in reverse order:
// 13. For each struct of events path, in reverse order:
for (auto& entry : event.path().in_reverse()) {
// 1. If structs shadow-adjusted target is non-null, then set events eventPhase attribute to AT_TARGET.
if (entry.shadow_adjusted_target)
@ -363,7 +366,7 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
invoke(entry, event, Event::Phase::CapturingPhase, legacy_output_did_listeners_throw);
}
// 14. For each struct in events path:
// 14. For each struct of events path:
for (auto& entry : event.path()) {
// 1. If structs shadow-adjusted target is non-null, then set events eventPhase attribute to AT_TARGET.
if (entry.shadow_adjusted_target) {
@ -384,21 +387,21 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
}
}
// 6. Set events eventPhase attribute to NONE.
// 7. Set events eventPhase attribute to NONE.
event.set_phase(Event::Phase::None);
// 7. Set events currentTarget attribute to null.
// 8. Set events currentTarget attribute to null.
event.set_current_target(nullptr);
// 8. Set events path to the empty list.
// 9. Set events path to the empty list.
event.clear_path();
// 9. Unset events dispatch flag, stop propagation flag, and stop immediate propagation flag.
// 10. Unset events dispatch flag, stop propagation flag, and stop immediate propagation flag.
event.set_dispatched(false);
event.set_stop_propagation(false);
event.set_stop_immediate_propagation(false);
// 10. If clearTargets, then:
// 11. If clearTargets, then:
if (clear_targets) {
// 1. Set events target to null.
event.set_target(nullptr);
@ -410,7 +413,7 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
event.clear_touch_target_list();
}
// 11. If activationTarget is non-null, then:
// 12. If activationTarget is non-null, then:
if (activation_target) {
// 1. If events canceled flag is unset, then run activationTargets activation behavior with event.
if (!event.cancelled()) {
@ -423,7 +426,7 @@ bool EventDispatcher::dispatch(GC::Ref<EventTarget> target, Event& event, bool l
}
}
// 12. Return false if events canceled flag is set; otherwise true.
// 13. Return false if events canceled flag is set; otherwise true.
return !event.cancelled();
}

View file

@ -60,7 +60,7 @@ Vector<FlyString> NamedNodeMap::supported_property_names() const
names.append(attribute_name.to_string());
}
// 2. If this NamedNodeMap objects element is in the HTML namespace and its node document is an HTML document, then for each name in names:
// 2. If this NamedNodeMap objects element is in the HTML namespace and its node document is an HTML document, then for each name of names:
if (associated_element().namespace_uri() == Namespace::HTML && associated_element().document().is_html_document()) {
// 1. Let lowercaseName be name, in ASCII lowercase.
// 2. If lowercaseName is not equal to name, remove name from names.

View file

@ -1502,18 +1502,18 @@ u16 Node::compare_document_position(GC::Ptr<Node> other)
// 4. If node1 is an attribute, then set attr1 to node1 and node1 to attr1s element.
if (is<Attr>(node1)) {
attr1 = as<Attr>(node1);
node1 = const_cast<Element*>(attr1->owner_element());
node1 = attr1->owner_element();
}
// 5. If node2 is an attribute, then:
if (is<Attr>(node2)) {
// 1. Set attr2 to node2 and node2 to attr2s element.
attr2 = as<Attr>(node2);
node2 = const_cast<Element*>(attr2->owner_element());
node2 = attr2->owner_element();
// 2. If attr1 and node1 are non-null, and node2 is node1, then:
if (attr1 && node1 && node2 == node1) {
// FIXME: 1. For each attr in node2s attribute list:
// FIXME: 1. For each attr of node2s attribute list:
// 1. If attr equals attr1, then return the result of adding DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC and DOCUMENT_POSITION_PRECEDING.
// 2. If attr equals attr2, then return the result of adding DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC and DOCUMENT_POSITION_FOLLOWING.
}