summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-08-28 13:42:07 +0200
committerAndreas Kling <kling@serenityos.org>2022-09-06 00:27:09 +0200
commit6f433c86564c24d47d520cb5bdcc2209d724ac96 (patch)
tree886a2f727782e466e99c61c628637872c1b7403f /Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp
parentbb547ce1c4251e3689287eac845593398a379ca5 (diff)
downloadserenity-6f433c86564c24d47d520cb5bdcc2209d724ac96.zip
LibWeb+LibJS: Make the EventTarget hierarchy (incl. DOM) GC-allocated
This is a monster patch that turns all EventTargets into GC-allocated PlatformObjects. Their C++ wrapper classes are removed, and the LibJS garbage collector is now responsible for their lifetimes. There's a fair amount of hacks and band-aids in this patch, and we'll have a lot of cleanup to do after this.
Diffstat (limited to 'Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp')
-rw-r--r--Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp39
1 files changed, 18 insertions, 21 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp
index 5112681d92..19a9bb9da3 100644
--- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp
+++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp
@@ -8,10 +8,7 @@
#include <AK/TypeCasts.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/FunctionObject.h>
-#include <LibWeb/Bindings/EventTargetWrapper.h>
-#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
#include <LibWeb/Bindings/IDLAbstractOperations.h>
-#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/DOM/AbortSignal.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Event.h>
@@ -93,8 +90,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent
Event* current_event = nullptr;
// 8. If global is a Window object, then:
- if (is<Bindings::WindowObject>(global)) {
- auto& bindings_window_global = verify_cast<Bindings::WindowObject>(global);
+ if (is<HTML::Window>(global)) {
+ auto& bindings_window_global = verify_cast<HTML::Window>(global);
auto& window_impl = bindings_window_global.impl();
// 1. Set currentEvent to global’s current event.
@@ -111,8 +108,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent
// 10. Call a user object’s operation with listener’s callback, "handleEvent", « event », and event’s currentTarget attribute value. If this throws an exception, then:
// FIXME: These should be wrapped for us in call_user_object_operation, but it currently doesn't do that.
- auto* this_value = Bindings::wrap(realm, *event.current_target());
- auto* wrapped_event = Bindings::wrap(realm, event);
+ auto* this_value = event.current_target().ptr();
+ auto* wrapped_event = &event;
auto result = Bindings::IDL::call_user_object_operation(callback, "handleEvent", this_value, wrapped_event);
// If this throws an exception, then:
@@ -127,8 +124,8 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent
event.set_in_passive_listener(false);
// 12. If global is a Window object, then set global’s current event to currentEvent.
- if (is<Bindings::WindowObject>(global)) {
- auto& bindings_window_global = verify_cast<Bindings::WindowObject>(global);
+ if (is<HTML::Window>(global)) {
+ auto& bindings_window_global = verify_cast<HTML::Window>(global);
auto& window_impl = bindings_window_global.impl();
window_impl.set_current_event(current_event);
}
@@ -146,17 +143,17 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent
void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Phase phase)
{
auto last_valid_shadow_adjusted_target = event.path().last_matching([&struct_](auto& entry) {
- return entry.index <= struct_.index && !entry.shadow_adjusted_target.is_null();
+ return entry.index <= struct_.index && entry.shadow_adjusted_target;
});
VERIFY(last_valid_shadow_adjusted_target.has_value());
// 1. Set event’s target to the shadow-adjusted target of the last struct in event’s path,
// that is either struct or preceding struct, whose shadow-adjusted target is non-null.
- event.set_target(last_valid_shadow_adjusted_target.value().shadow_adjusted_target);
+ event.set_target(last_valid_shadow_adjusted_target.value().shadow_adjusted_target.ptr());
// 2. Set event’s relatedTarget to struct’s relatedTarget.
- event.set_related_target(struct_.related_target);
+ event.set_related_target(struct_.related_target.ptr());
// 3. Set event’s touch target list to struct’s touch target list.
event.set_touch_target_list(struct_.touch_target_list);
@@ -166,7 +163,7 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha
return;
// 5. Initialize event’s currentTarget attribute to struct’s invocation target.
- event.set_current_target(struct_.invocation_target);
+ event.set_current_target(struct_.invocation_target.ptr());
// 6. Let listeners be a clone of event’s currentTarget attribute value’s event listener list.
// NOTE: This avoids event listeners added after this point from being run. Note that removal still has an effect due to the removed field.
@@ -205,25 +202,25 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha
}
// https://dom.spec.whatwg.org/#concept-event-dispatch
-bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event, bool legacy_target_override)
+bool EventDispatcher::dispatch(JS::NonnullGCPtr<EventTarget> target, Event& event, bool legacy_target_override)
{
// 1. Set event’s dispatch flag.
event.set_dispatched(true);
// 2. Let targetOverride be target, if legacy target override flag is not given, and target’s associated Document otherwise. [HTML]
// NOTE: legacy target override flag is only used by HTML and only when target is a Window object.
- RefPtr<EventTarget> target_override;
+ JS::GCPtr<EventTarget> target_override;
if (!legacy_target_override) {
target_override = target;
} else {
- target_override = verify_cast<HTML::Window>(*target).associated_document();
+ target_override = &verify_cast<HTML::Window>(*target).associated_document();
}
// 3. Let activationTarget be null.
- RefPtr<EventTarget> activation_target;
+ JS::GCPtr<EventTarget> activation_target;
// 4. Let relatedTarget be the result of retargeting event’s relatedTarget against target.
- RefPtr<EventTarget> related_target = retarget(event.related_target(), target);
+ JS::GCPtr<EventTarget> related_target = retarget(event.related_target(), target);
bool clear_targets = false;
// 5. If target is not relatedTarget or target is event’s relatedTarget, then:
@@ -285,12 +282,12 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event,
}
// 7. Otherwise, if parent is relatedTarget, then set parent to null.
- else if (related_target == parent) {
+ else if (related_target.ptr() == parent) {
parent = nullptr;
}
// 8. Otherwise, set target to parent and then:
else {
- target = *parent;
+ target = parent;
// 1. If isActivationEvent is true, activationTarget is null, and target has activation behavior, then set activationTarget to target.
if (is_activation_event && !activation_target && target->activation_behavior)
@@ -311,7 +308,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event,
// 10. Let clearTargetsStruct be the last struct in event’s path whose shadow-adjusted target is non-null.
auto clear_targets_struct = event.path().last_matching([](auto& entry) {
- return !entry.shadow_adjusted_target.is_null();
+ return entry.shadow_adjusted_target;
});
VERIFY(clear_targets_struct.has_value());