mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 21:27:45 +00:00
LibWeb: Make DOM::Event and all its subclasses GC-allocated
This commit is contained in:
parent
a4ddb0ef87
commit
7c3db526b0
76 changed files with 892 additions and 565 deletions
|
@ -60,7 +60,7 @@ void AbortSignal::signal_abort(JS::Value reason)
|
|||
m_abort_algorithms.clear();
|
||||
|
||||
// 5. Fire an event named abort at signal.
|
||||
dispatch_event(Event::create(HTML::EventNames::abort));
|
||||
dispatch_event(*Event::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), HTML::EventNames::abort));
|
||||
}
|
||||
|
||||
void AbortSignal::set_onabort(Bindings::CallbackType* event_handler)
|
||||
|
|
|
@ -1,15 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/CustomEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/CustomEvent.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
CustomEvent* CustomEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<CustomEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
CustomEvent* CustomEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name)
|
||||
: Event(window_object, event_name)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::CustomEventPrototype>("CustomEvent"));
|
||||
}
|
||||
|
||||
CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
: Event(window_object, event_name, event_init)
|
||||
, m_detail(event_init.detail)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::CustomEventPrototype>("CustomEvent"));
|
||||
}
|
||||
|
||||
CustomEvent::~CustomEvent() = default;
|
||||
|
||||
void CustomEvent::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_detail);
|
||||
}
|
||||
|
||||
|
@ -21,7 +50,7 @@ void CustomEvent::init_custom_event(String const& type, bool bubbles, bool cance
|
|||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize(type, bubbles, cancelable);
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// 3. Set this’s detail attribute to detail.
|
||||
m_detail = detail;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -16,41 +17,34 @@ struct CustomEventInit : public EventInit {
|
|||
|
||||
// https://dom.spec.whatwg.org/#customevent
|
||||
class CustomEvent : public Event {
|
||||
JS_OBJECT(CustomEvent, Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::CustomEventWrapper;
|
||||
static CustomEvent* create(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init = {});
|
||||
static CustomEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<CustomEvent> create(FlyString const& event_name, CustomEventInit const& event_init = {})
|
||||
{
|
||||
return adopt_ref(*new CustomEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<CustomEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
{
|
||||
return CustomEvent::create(event_name, event_init);
|
||||
}
|
||||
CustomEvent(Bindings::WindowObject&, FlyString const& event_name);
|
||||
CustomEvent(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init);
|
||||
|
||||
virtual ~CustomEvent() override = default;
|
||||
virtual ~CustomEvent() override;
|
||||
|
||||
CustomEvent& impl() { return *this; }
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-customevent-detail
|
||||
JS::Value detail() const { return m_detail; }
|
||||
|
||||
void visit_edges(JS::Cell::Visitor&);
|
||||
virtual void visit_edges(JS::Cell::Visitor&) override;
|
||||
|
||||
void init_custom_event(String const& type, bool bubbles, bool cancelable, JS::Value detail);
|
||||
|
||||
private:
|
||||
explicit CustomEvent(FlyString const& event_name)
|
||||
: Event(event_name)
|
||||
{
|
||||
}
|
||||
|
||||
CustomEvent(FlyString const& event_name, CustomEventInit const& event_init)
|
||||
: Event(event_name, event_init)
|
||||
, m_detail(event_init.detail)
|
||||
{
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent-type-bubbles-cancelable-detail-detail
|
||||
JS::Value m_detail { JS::js_null() };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::CustomEvent& object) { return &object; }
|
||||
using CustomEventWrapper = Web::DOM::CustomEvent;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#import <DOM/Event.idl>
|
||||
|
||||
[Exposed=(Window,Worker), CustomVisit]
|
||||
[Exposed=(Window,Worker), NoInstanceWrapper]
|
||||
interface CustomEvent : Event {
|
||||
constructor(DOMString type, optional CustomEventInit eventInitDict = {});
|
||||
|
||||
|
|
|
@ -1160,51 +1160,53 @@ NonnullRefPtr<Range> Document::create_range()
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createevent
|
||||
DOM::ExceptionOr<NonnullRefPtr<Event>> Document::create_event(String const& interface)
|
||||
DOM::ExceptionOr<JS::NonnullGCPtr<Event>> Document::create_event(String const& interface)
|
||||
{
|
||||
auto& window_object = preferred_window_object();
|
||||
|
||||
// NOTE: This is named event here, since we do step 5 and 6 as soon as possible for each case.
|
||||
// 1. Let constructor be null.
|
||||
RefPtr<Event> event;
|
||||
JS::GCPtr<Event> event;
|
||||
|
||||
// 2. If interface is an ASCII case-insensitive match for any of the strings in the first column in the following table,
|
||||
// then set constructor to the interface in the second column on the same row as the matching string:
|
||||
auto interface_lowercase = interface.to_lowercase();
|
||||
if (interface_lowercase == "beforeunloadevent") {
|
||||
event = Event::create(""); // FIXME: Create BeforeUnloadEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create BeforeUnloadEvent
|
||||
} else if (interface_lowercase == "compositionevent") {
|
||||
event = Event::create(""); // FIXME: Create CompositionEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
|
||||
} else if (interface_lowercase == "customevent") {
|
||||
event = CustomEvent::create("");
|
||||
event = CustomEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "devicemotionevent") {
|
||||
event = Event::create(""); // FIXME: Create DeviceMotionEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create DeviceMotionEvent
|
||||
} else if (interface_lowercase == "deviceorientationevent") {
|
||||
event = Event::create(""); // FIXME: Create DeviceOrientationEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create DeviceOrientationEvent
|
||||
} else if (interface_lowercase == "dragevent") {
|
||||
event = Event::create(""); // FIXME: Create DragEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create DragEvent
|
||||
} else if (interface_lowercase.is_one_of("event", "events")) {
|
||||
event = Event::create("");
|
||||
event = Event::create(window_object, "");
|
||||
} else if (interface_lowercase == "focusevent") {
|
||||
event = UIEvents::FocusEvent::create("");
|
||||
event = UIEvents::FocusEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "hashchangeevent") {
|
||||
event = Event::create(""); // FIXME: Create HashChangeEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create HashChangeEvent
|
||||
} else if (interface_lowercase == "htmlevents") {
|
||||
event = Event::create("");
|
||||
event = Event::create(window_object, "");
|
||||
} else if (interface_lowercase == "keyboardevent") {
|
||||
event = UIEvents::KeyboardEvent::create("");
|
||||
event = UIEvents::KeyboardEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "messageevent") {
|
||||
event = HTML::MessageEvent::create("");
|
||||
event = HTML::MessageEvent::create(window_object, "");
|
||||
} else if (interface_lowercase.is_one_of("mouseevent", "mouseevents")) {
|
||||
event = UIEvents::MouseEvent::create("");
|
||||
event = UIEvents::MouseEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "storageevent") {
|
||||
event = Event::create(""); // FIXME: Create StorageEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create StorageEvent
|
||||
} else if (interface_lowercase == "svgevents") {
|
||||
event = Event::create("");
|
||||
event = Event::create(window_object, "");
|
||||
} else if (interface_lowercase == "textevent") {
|
||||
event = Event::create(""); // FIXME: Create CompositionEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
|
||||
} else if (interface_lowercase == "touchevent") {
|
||||
event = Event::create(""); // FIXME: Create TouchEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create TouchEvent
|
||||
} else if (interface_lowercase.is_one_of("uievent", "uievents")) {
|
||||
event = UIEvents::UIEvent::create("");
|
||||
event = UIEvents::UIEvent::create(window_object, "");
|
||||
}
|
||||
|
||||
// 3. If constructor is null, then throw a "NotSupportedError" DOMException.
|
||||
|
@ -1228,7 +1230,7 @@ DOM::ExceptionOr<NonnullRefPtr<Event>> Document::create_event(String const& inte
|
|||
event->set_initialized(false);
|
||||
|
||||
// 10. Return event.
|
||||
return event.release_nonnull();
|
||||
return JS::NonnullGCPtr(*event);
|
||||
}
|
||||
|
||||
void Document::set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement* script)
|
||||
|
@ -1408,7 +1410,7 @@ void Document::update_readiness(HTML::DocumentReadyState readiness_value)
|
|||
// FIXME: 3. Otherwise, if readinessValue is "interactive", and document's load timing info's DOM interactive time is 0, then set document's load timing info's DOM interactive time to now.
|
||||
|
||||
// 3. Fire an event named readystatechange at document.
|
||||
dispatch_event(Event::create(HTML::EventNames::readystatechange));
|
||||
dispatch_event(*Event::create(preferred_window_object(), HTML::EventNames::readystatechange));
|
||||
}
|
||||
|
||||
Page* Document::page()
|
||||
|
@ -1448,8 +1450,8 @@ void Document::completely_finish_loading()
|
|||
}
|
||||
// Otherwise, if container is non-null, then queue an element task on the DOM manipulation task source given container to fire an event named load at container.
|
||||
else if (container) {
|
||||
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container]() mutable {
|
||||
container->dispatch_event(DOM::Event::create(HTML::EventNames::load));
|
||||
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container, this]() mutable {
|
||||
container->dispatch_event(*DOM::Event::create(preferred_window_object(), HTML::EventNames::load));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1560,7 +1562,7 @@ void Document::run_the_resize_steps()
|
|||
return;
|
||||
m_last_viewport_size = viewport_size;
|
||||
|
||||
window().dispatch_event(DOM::Event::create(UIEvents::EventNames::resize));
|
||||
window().dispatch_event(*DOM::Event::create(preferred_window_object(), UIEvents::EventNames::resize));
|
||||
|
||||
update_layout();
|
||||
}
|
||||
|
@ -1596,9 +1598,9 @@ void Document::evaluate_media_queries_and_report_changes()
|
|||
CSS::MediaQueryListEventInit init;
|
||||
init.media = media_query_list->media();
|
||||
init.matches = now_matches;
|
||||
auto event = CSS::MediaQueryListEvent::create(HTML::EventNames::change, init);
|
||||
auto event = CSS::MediaQueryListEvent::create(preferred_window_object(), HTML::EventNames::change, init);
|
||||
event->set_is_trusted(true);
|
||||
media_query_list->dispatch_event(event);
|
||||
media_query_list->dispatch_event(*event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ public:
|
|||
NonnullRefPtr<Text> create_text_node(String const& data);
|
||||
NonnullRefPtr<Comment> create_comment(String const& data);
|
||||
NonnullRefPtr<Range> create_range();
|
||||
ExceptionOr<NonnullRefPtr<Event>> create_event(String const& interface);
|
||||
ExceptionOr<JS::NonnullGCPtr<Event>> create_event(String const& interface);
|
||||
|
||||
void set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement*);
|
||||
HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; }
|
||||
|
|
|
@ -1,17 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWeb/Bindings/EventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
#include <LibWeb/DOM/Node.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
JS::NonnullGCPtr<Event> Event::create(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init)
|
||||
{
|
||||
return *window_object.heap().allocate<Event>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<Event> Event::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
Event::Event(Bindings::WindowObject& window_object, FlyString const& type)
|
||||
: PlatformObject(window_object.ensure_web_prototype<Bindings::EventPrototype>("Event"))
|
||||
, m_type(type)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
|
||||
Event::Event(Bindings::WindowObject& window_object, FlyString const& type, EventInit const& event_init)
|
||||
: PlatformObject(window_object.ensure_web_prototype<Bindings::EventPrototype>("Event"))
|
||||
, m_type(type)
|
||||
, m_bubbles(event_init.bubbles)
|
||||
, m_cancelable(event_init.cancelable)
|
||||
, m_composed(event_init.composed)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-path-append
|
||||
void Event::append_to_path(EventTarget& invocation_target, RefPtr<EventTarget> shadow_adjusted_target, RefPtr<EventTarget> related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree)
|
||||
{
|
||||
|
@ -46,7 +76,7 @@ void Event::set_cancelled_flag()
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-initialize
|
||||
void Event::initialize(String const& type, bool bubbles, bool cancelable)
|
||||
void Event::initialize_event(String const& type, bool bubbles, bool cancelable)
|
||||
{
|
||||
// 1. Set event’s initialized flag.
|
||||
m_initialized = true;
|
||||
|
@ -80,7 +110,7 @@ void Event::init_event(String const& type, bool bubbles, bool cancelable)
|
|||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize(type, bubbles, cancelable);
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-timestamp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -7,8 +7,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/Bindings/Wrappable.h>
|
||||
#include <LibWeb/DOM/EventTarget.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
@ -19,12 +19,10 @@ struct EventInit {
|
|||
bool composed { false };
|
||||
};
|
||||
|
||||
class Event
|
||||
: public RefCounted<Event>
|
||||
, public Bindings::Wrappable {
|
||||
public:
|
||||
using WrapperType = Bindings::EventWrapper;
|
||||
class Event : public Bindings::PlatformObject {
|
||||
JS_OBJECT(Event, Bindings::PlatformObject);
|
||||
|
||||
public:
|
||||
enum Phase : u16 {
|
||||
None = 0,
|
||||
CapturingPhase = 1,
|
||||
|
@ -47,17 +45,16 @@ public:
|
|||
|
||||
using Path = Vector<PathEntry>;
|
||||
|
||||
static NonnullRefPtr<Event> create(FlyString const& event_name, EventInit const& event_init = {})
|
||||
{
|
||||
return adopt_ref(*new Event(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<Event> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init)
|
||||
{
|
||||
return Event::create(event_name, event_init);
|
||||
}
|
||||
static JS::NonnullGCPtr<Event> create(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init = {});
|
||||
static JS::NonnullGCPtr<Event> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init);
|
||||
|
||||
Event(Bindings::WindowObject&, FlyString const& type);
|
||||
Event(Bindings::WindowObject&, FlyString const& type, EventInit const& event_init);
|
||||
|
||||
virtual ~Event() = default;
|
||||
|
||||
Event& impl() { return *this; }
|
||||
|
||||
double time_stamp() const;
|
||||
|
||||
FlyString const& type() const { return m_type; }
|
||||
|
@ -149,21 +146,7 @@ public:
|
|||
NonnullRefPtrVector<EventTarget> composed_path() const;
|
||||
|
||||
protected:
|
||||
explicit Event(FlyString const& type)
|
||||
: m_type(type)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
Event(FlyString const& type, EventInit const& event_init)
|
||||
: m_type(type)
|
||||
, m_bubbles(event_init.bubbles)
|
||||
, m_cancelable(event_init.cancelable)
|
||||
, m_composed(event_init.composed)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
|
||||
void initialize(String const&, bool, bool);
|
||||
void initialize_event(String const&, bool, bool);
|
||||
|
||||
private:
|
||||
FlyString m_type;
|
||||
|
@ -195,3 +178,8 @@ private:
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::Event& object) { return &object; }
|
||||
using EventWrapper = Web::DOM::Event;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#import <DOM/EventTarget.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface Event {
|
||||
|
||||
constructor(DOMString type, optional EventInit eventInitDict = {});
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibWeb/Bindings/EventTargetWrapper.h>
|
||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/EventWrapper.h>
|
||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/AbortSignal.h>
|
||||
|
@ -92,7 +90,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent
|
|||
auto& global = realm.global_object();
|
||||
|
||||
// 7. Let currentEvent be undefined.
|
||||
RefPtr<Event> current_event;
|
||||
Event* current_event = nullptr;
|
||||
|
||||
// 8. If global is a Window object, then:
|
||||
if (is<Bindings::WindowObject>(global)) {
|
||||
|
@ -207,10 +205,10 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-dispatch
|
||||
bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<Event> event, bool legacy_target_override)
|
||||
bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event, bool legacy_target_override)
|
||||
{
|
||||
// 1. Set event’s dispatch flag.
|
||||
event->set_dispatched(true);
|
||||
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.
|
||||
|
@ -225,24 +223,24 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
RefPtr<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);
|
||||
RefPtr<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:
|
||||
if (related_target != target || event->related_target() == target) {
|
||||
if (related_target != target || event.related_target() == target) {
|
||||
// 1. Let touchTargets be a new list.
|
||||
Event::TouchTargetList touch_targets;
|
||||
|
||||
// 2. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against target to touchTargets.
|
||||
for (auto& touch_target : event->touch_target_list()) {
|
||||
for (auto& touch_target : event.touch_target_list()) {
|
||||
touch_targets.append(retarget(touch_target, target));
|
||||
}
|
||||
|
||||
// 3. Append to an event path with event, target, targetOverride, relatedTarget, touchTargets, and false.
|
||||
event->append_to_path(*target, target_override, related_target, touch_targets, false);
|
||||
event.append_to_path(*target, target_override, related_target, touch_targets, false);
|
||||
|
||||
// 4. Let isActivationEvent be true, if event is a MouseEvent object and event’s type attribute is "click"; otherwise false.
|
||||
bool is_activation_event = is<UIEvents::MouseEvent>(*event) && event->type() == HTML::EventNames::click;
|
||||
bool is_activation_event = is<UIEvents::MouseEvent>(event) && event.type() == HTML::EventNames::click;
|
||||
|
||||
// 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target.
|
||||
if (is_activation_event && target->activation_behavior)
|
||||
|
@ -265,13 +263,13 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
// FIXME: 2. If parent is a slottable and is assigned, then set slottable to 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);
|
||||
|
||||
// 4. Let touchTargets be a new list.
|
||||
touch_targets.clear();
|
||||
|
||||
// 5. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against parent to touchTargets.
|
||||
for (auto& touch_target : event->touch_target_list()) {
|
||||
for (auto& touch_target : event.touch_target_list()) {
|
||||
touch_targets.append(retarget(touch_target, parent));
|
||||
}
|
||||
|
||||
|
@ -279,11 +277,11 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
if (is<HTML::Window>(parent)
|
||||
|| (is<Node>(parent) && verify_cast<Node>(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*parent)))) {
|
||||
// 1. If isActivationEvent is true, event’s bubbles attribute is true, activationTarget is null, and parent has activation behavior, then set activationTarget to parent.
|
||||
if (is_activation_event && event->bubbles() && !activation_target && parent->activation_behavior)
|
||||
if (is_activation_event && event.bubbles() && !activation_target && parent->activation_behavior)
|
||||
activation_target = parent;
|
||||
|
||||
// 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree.
|
||||
event->append_to_path(*parent, nullptr, related_target, touch_targets, slot_in_closed_tree);
|
||||
event.append_to_path(*parent, nullptr, related_target, touch_targets, slot_in_closed_tree);
|
||||
|
||||
}
|
||||
// 7. Otherwise, if parent is relatedTarget, then set parent to null.
|
||||
|
@ -299,7 +297,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
activation_target = target;
|
||||
|
||||
// 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree.
|
||||
event->append_to_path(*parent, target, related_target, touch_targets, slot_in_closed_tree);
|
||||
event.append_to_path(*parent, target, related_target, touch_targets, slot_in_closed_tree);
|
||||
}
|
||||
|
||||
// 9. If parent is non-null, then set parent to the result of invoking parent’s get the parent with event.
|
||||
|
@ -312,7 +310,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
}
|
||||
|
||||
// 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) {
|
||||
auto clear_targets_struct = event.path().last_matching([](auto& entry) {
|
||||
return !entry.shadow_adjusted_target.is_null();
|
||||
});
|
||||
|
||||
|
@ -349,32 +347,32 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
activation_target->legacy_pre_activation_behavior();
|
||||
|
||||
// 13. For each struct in event’s path, in reverse order:
|
||||
for (auto& entry : event->path().in_reverse()) {
|
||||
for (auto& entry : event.path().in_reverse()) {
|
||||
// 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET.
|
||||
if (entry.shadow_adjusted_target)
|
||||
event->set_phase(Event::Phase::AtTarget);
|
||||
event.set_phase(Event::Phase::AtTarget);
|
||||
// 2. Otherwise, set event’s eventPhase attribute to CAPTURING_PHASE.
|
||||
else
|
||||
event->set_phase(Event::Phase::CapturingPhase);
|
||||
event.set_phase(Event::Phase::CapturingPhase);
|
||||
|
||||
// 3. Invoke with struct, event, "capturing", and legacyOutputDidListenersThrowFlag if given.
|
||||
invoke(entry, event, Event::Phase::CapturingPhase);
|
||||
}
|
||||
|
||||
// 14. For each struct in event’s path:
|
||||
for (auto& entry : event->path()) {
|
||||
for (auto& entry : event.path()) {
|
||||
// 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET.
|
||||
if (entry.shadow_adjusted_target) {
|
||||
event->set_phase(Event::Phase::AtTarget);
|
||||
event.set_phase(Event::Phase::AtTarget);
|
||||
}
|
||||
// 2. Otherwise:
|
||||
else {
|
||||
// 1. If event’s bubbles attribute is false, then continue.
|
||||
if (!event->bubbles())
|
||||
if (!event.bubbles())
|
||||
continue;
|
||||
|
||||
// 2. Set event’s eventPhase attribute to BUBBLING_PHASE.
|
||||
event->set_phase(Event::Phase::BubblingPhase);
|
||||
event.set_phase(Event::Phase::BubblingPhase);
|
||||
}
|
||||
|
||||
// 3. Invoke with struct, event, "bubbling", and legacyOutputDidListenersThrowFlag if given.
|
||||
|
@ -383,35 +381,35 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
}
|
||||
|
||||
// 6. Set event’s eventPhase attribute to NONE.
|
||||
event->set_phase(Event::Phase::None);
|
||||
event.set_phase(Event::Phase::None);
|
||||
|
||||
// 7. Set event’s currentTarget attribute to null.
|
||||
event->set_current_target(nullptr);
|
||||
event.set_current_target(nullptr);
|
||||
|
||||
// 8. Set event’s path to the empty list.
|
||||
event->clear_path();
|
||||
event.clear_path();
|
||||
|
||||
// 9. Unset event’s 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);
|
||||
event.set_dispatched(false);
|
||||
event.set_stop_propagation(false);
|
||||
event.set_stop_immediate_propagation(false);
|
||||
|
||||
// 10. If clearTargets, then:
|
||||
if (clear_targets) {
|
||||
// 1. Set event’s target to null.
|
||||
event->set_target(nullptr);
|
||||
event.set_target(nullptr);
|
||||
|
||||
// 2. Set event’s relatedTarget to null.
|
||||
event->set_related_target(nullptr);
|
||||
event.set_related_target(nullptr);
|
||||
|
||||
// 3. Set event’s touch target list to the empty list.
|
||||
event->clear_touch_target_list();
|
||||
event.clear_touch_target_list();
|
||||
}
|
||||
|
||||
// 11. If activationTarget is non-null, then:
|
||||
if (activation_target) {
|
||||
// 1. If event’s canceled flag is unset, then run activationTarget’s activation behavior with event.
|
||||
if (!event->cancelled()) {
|
||||
if (!event.cancelled()) {
|
||||
activation_target->activation_behavior(event);
|
||||
activation_target->legacy_cancelled_activation_behavior_was_not_called();
|
||||
}
|
||||
|
@ -422,7 +420,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
|||
}
|
||||
|
||||
// 12. Return false if event’s canceled flag is set; otherwise true.
|
||||
return !event->cancelled();
|
||||
return !event.cancelled();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Web::DOM {
|
|||
|
||||
class EventDispatcher {
|
||||
public:
|
||||
static bool dispatch(NonnullRefPtr<EventTarget>, NonnullRefPtr<Event>, bool legacy_target_override = false);
|
||||
static bool dispatch(NonnullRefPtr<EventTarget>, Event&, bool legacy_target_override = false);
|
||||
|
||||
private:
|
||||
static void invoke(Event::PathEntry&, Event&, Event::Phase);
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibWeb/Bindings/DocumentWrapper.h>
|
||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/EventWrapper.h>
|
||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/DOM/AbortSignal.h>
|
||||
|
@ -204,17 +202,17 @@ void EventTarget::remove_from_event_listener_list(DOMEventListener& listener)
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent
|
||||
ExceptionOr<bool> EventTarget::dispatch_event_binding(NonnullRefPtr<Event> event)
|
||||
ExceptionOr<bool> EventTarget::dispatch_event_binding(Event& event)
|
||||
{
|
||||
// 1. If event’s dispatch flag is set, or if its initialized flag is not set, then throw an "InvalidStateError" DOMException.
|
||||
if (event->dispatched())
|
||||
if (event.dispatched())
|
||||
return DOM::InvalidStateError::create("The event is already being dispatched.");
|
||||
|
||||
if (!event->initialized())
|
||||
if (!event.initialized())
|
||||
return DOM::InvalidStateError::create("Cannot dispatch an uninitialized event.");
|
||||
|
||||
// 2. Initialize event’s isTrusted attribute to false.
|
||||
event->set_is_trusted(false);
|
||||
event.set_is_trusted(false);
|
||||
|
||||
// 3. Return the result of dispatching event to this.
|
||||
return dispatch_event(event);
|
||||
|
@ -736,9 +734,9 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local
|
|||
event_target->activate_event_handler(local_name, *event_handler);
|
||||
}
|
||||
|
||||
bool EventTarget::dispatch_event(NonnullRefPtr<Event> event)
|
||||
bool EventTarget::dispatch_event(Event& event)
|
||||
{
|
||||
return EventDispatcher::dispatch(*this, move(event));
|
||||
return EventDispatcher::dispatch(*this, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ public:
|
|||
void add_event_listener_without_options(FlyString const& type, IDLEventListener& callback);
|
||||
void remove_event_listener_without_options(FlyString const& type, IDLEventListener& callback);
|
||||
|
||||
virtual bool dispatch_event(NonnullRefPtr<Event>);
|
||||
ExceptionOr<bool> dispatch_event_binding(NonnullRefPtr<Event>);
|
||||
virtual bool dispatch_event(Event&);
|
||||
ExceptionOr<bool> dispatch_event_binding(Event&);
|
||||
|
||||
virtual JS::Object* create_wrapper(JS::Realm&) = 0;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibWeb/Bindings/EventWrapper.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/Bindings/NodeWrapper.h>
|
||||
#include <LibWeb/Bindings/NodeWrapperFactory.h>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue