mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 12:17:34 +00:00
LibWeb: Ensure DOM events on slottables are properly propagated
Most events on a slottable are composed, meaning they propagate from the slottable and through its shadow tree before bubbling up to the parent of the slottable.
This commit is contained in:
parent
d67d93f870
commit
e4d3a9aa68
2 changed files with 32 additions and 7 deletions
|
@ -10,13 +10,17 @@
|
||||||
#include <LibJS/Runtime/FunctionObject.h>
|
#include <LibJS/Runtime/FunctionObject.h>
|
||||||
#include <LibWeb/DOM/AbortSignal.h>
|
#include <LibWeb/DOM/AbortSignal.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
#include <LibWeb/DOM/Element.h>
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
#include <LibWeb/DOM/EventDispatcher.h>
|
#include <LibWeb/DOM/EventDispatcher.h>
|
||||||
#include <LibWeb/DOM/EventTarget.h>
|
#include <LibWeb/DOM/EventTarget.h>
|
||||||
#include <LibWeb/DOM/IDLEventListener.h>
|
#include <LibWeb/DOM/IDLEventListener.h>
|
||||||
#include <LibWeb/DOM/Node.h>
|
#include <LibWeb/DOM/Node.h>
|
||||||
#include <LibWeb/DOM/ShadowRoot.h>
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
|
#include <LibWeb/DOM/Slottable.h>
|
||||||
|
#include <LibWeb/DOM/Text.h>
|
||||||
#include <LibWeb/HTML/EventNames.h>
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
|
#include <LibWeb/HTML/HTMLSlotElement.h>
|
||||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <LibWeb/UIEvents/MouseEvent.h>
|
#include <LibWeb/UIEvents/MouseEvent.h>
|
||||||
|
@ -241,7 +245,11 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> target, Event& even
|
||||||
if (is_activation_event && target->activation_behavior)
|
if (is_activation_event && target->activation_behavior)
|
||||||
activation_target = target;
|
activation_target = target;
|
||||||
|
|
||||||
// FIXME: 6. Let slottable be target, if target is a slottable and is assigned, and null otherwise.
|
// 6. Let slottable be target, if target is a slottable and is assigned, and null otherwise.
|
||||||
|
JS::GCPtr<EventTarget> slottable;
|
||||||
|
|
||||||
|
if (is<Node>(*target) && is_an_assigned_slottable(static_cast<Node&>(*target)))
|
||||||
|
slottable = target;
|
||||||
|
|
||||||
// 7. Let slot-in-closed-tree be false
|
// 7. Let slot-in-closed-tree be false
|
||||||
bool slot_in_closed_tree = false;
|
bool slot_in_closed_tree = false;
|
||||||
|
@ -251,11 +259,24 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> target, Event& even
|
||||||
|
|
||||||
// 9. While parent is non-null:
|
// 9. While parent is non-null:
|
||||||
while (parent) {
|
while (parent) {
|
||||||
// FIXME: 1. If slottable is non-null:
|
// 1. If slottable is non-null:
|
||||||
// 1. Assert: parent is a slot.
|
if (slottable != nullptr) {
|
||||||
// 2. Set slottable to null.
|
// 1. Assert: parent is a slot.
|
||||||
// 3. If parent’s root is a shadow root whose mode is "closed", then set slot-in-closed-tree to true.
|
VERIFY(is<HTML::HTMLSlotElement>(parent));
|
||||||
// FIXME: 2. If parent is a slottable and is assigned, then set slottable to parent.
|
|
||||||
|
// 2. Set slottable to null.
|
||||||
|
slottable = nullptr;
|
||||||
|
|
||||||
|
// 3. If parent’s root is a shadow root whose mode is "closed", then set slot-in-closed-tree to true.
|
||||||
|
auto& parent_root = static_cast<Node&>(*parent).root();
|
||||||
|
|
||||||
|
if (parent_root.is_shadow_root() && static_cast<ShadowRoot&>(parent_root).mode() == Bindings::ShadowRootMode::Closed)
|
||||||
|
slot_in_closed_tree = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. If parent is a slottable and is assigned, then set slottable to parent.
|
||||||
|
if (is<Node>(*parent) && is_an_assigned_slottable(static_cast<Node&>(*parent)))
|
||||||
|
slottable = parent;
|
||||||
|
|
||||||
// 3. Let relatedTarget be the result of retargeting event’s relatedTarget against parent.
|
// 3. Let relatedTarget be the result of retargeting event’s relatedTarget against parent.
|
||||||
related_target = retarget(event.related_target(), parent);
|
related_target = retarget(event.related_target(), parent);
|
||||||
|
|
|
@ -929,7 +929,11 @@ void Node::detach_layout_node(Badge<Layout::TreeBuilder>)
|
||||||
|
|
||||||
EventTarget* Node::get_parent(Event const&)
|
EventTarget* Node::get_parent(Event const&)
|
||||||
{
|
{
|
||||||
// FIXME: returns the node’s assigned slot, if node is assigned, and node’s parent otherwise.
|
// A node’s get the parent algorithm, given an event, returns the node’s assigned slot, if node is assigned;
|
||||||
|
// otherwise node’s parent.
|
||||||
|
if (auto assigned_slot = assigned_slot_for_node(*this))
|
||||||
|
return assigned_slot.ptr();
|
||||||
|
|
||||||
return parent();
|
return parent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue