LibWeb: Make DOM::Event and all its subclasses GC-allocated

This commit is contained in:
Andreas Kling 2022-08-08 22:29:40 +02:00
parent a4ddb0ef87
commit 7c3db526b0
Notes: sideshowbarker 2024-07-17 07:28:23 +09:00
76 changed files with 892 additions and 565 deletions

View file

@ -39,7 +39,6 @@ interface CSSRule {
- It must have a public `using WrapperType = Bindings::HTMLDetailsElementWrapper;`
7. Depending on what kind of thing your interface is, you may need to add it to the `WrapperFactory` of that kind:
- Events: [`LibWeb/Bindings/EventWrapperFactory.cpp`](../../Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp)
- Elements: [`LibWeb/Bindings/NodeWrapperFactory.cpp`](../../Userland/Libraries/LibWeb/Bindings/NodeWrapperFactory.cpp)
Open the relevant wrapper factory file, and add `#include` directives and an `if` statement for your new type.

View file

@ -300,8 +300,6 @@ static void emit_includes_for_all_imports(auto& interface, auto& generator, bool
static bool should_emit_wrapper_factory(IDL::Interface const& interface)
{
// FIXME: This is very hackish.
if (interface.name == "Event")
return false;
if (interface.name == "EventTarget")
return false;
if (interface.name == "Node")
@ -2042,6 +2040,7 @@ using namespace Web::IntersectionObserver;
using namespace Web::RequestIdleCallback;
using namespace Web::ResizeObserver;
using namespace Web::Selection;
using namespace Web::UIEvents;
using namespace Web::WebGL;
namespace Web::Bindings {
@ -2904,7 +2903,6 @@ void generate_constructor_implementation(IDL::Interface const& interface)
#include <LibWeb/Bindings/@wrapper_class@.h>
#endif
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
#include <LibWeb/Bindings/EventWrapperFactory.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/NodeWrapper.h>
#include <LibWeb/Bindings/NodeWrapperFactory.h>
@ -3208,8 +3206,6 @@ void generate_prototype_implementation(IDL::Interface const& interface)
#if __has_include(<LibWeb/Bindings/@wrapper_class@.h>)
#include <LibWeb/Bindings/@wrapper_class@.h>
#endif
#include <LibWeb/Bindings/EventWrapper.h>
#include <LibWeb/Bindings/EventWrapperFactory.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/WindowObject.h>
@ -3253,6 +3249,7 @@ using namespace Web::RequestIdleCallback;
using namespace Web::ResizeObserver;
using namespace Web::Selection;
using namespace Web::SVG;
using namespace Web::UIEvents;
using namespace Web::URL;
using namespace Web::WebSockets;
using namespace Web::XHR;
@ -3712,6 +3709,7 @@ using namespace Web::IntersectionObserver;
using namespace Web::RequestIdleCallback;
using namespace Web::ResizeObserver;
using namespace Web::Selection;
using namespace Web::UIEvents;
using namespace Web::WebGL;
namespace Web::Bindings {
@ -3830,6 +3828,7 @@ using namespace Web::RequestIdleCallback;
using namespace Web::ResizeObserver;
using namespace Web::Selection;
using namespace Web::XHR;
using namespace Web::UIEvents;
using namespace Web::URL;
using namespace Web::WebGL;

View file

@ -1,56 +0,0 @@
/*
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CloseEventWrapper.h>
#include <LibWeb/Bindings/CustomEventWrapper.h>
#include <LibWeb/Bindings/EventWrapper.h>
#include <LibWeb/Bindings/EventWrapperFactory.h>
#include <LibWeb/Bindings/KeyboardEventWrapper.h>
#include <LibWeb/Bindings/MediaQueryListEventWrapper.h>
#include <LibWeb/Bindings/MessageEventWrapper.h>
#include <LibWeb/Bindings/MouseEventWrapper.h>
#include <LibWeb/Bindings/PageTransitionEventWrapper.h>
#include <LibWeb/Bindings/ProgressEventWrapper.h>
#include <LibWeb/Bindings/PromiseRejectionEventWrapper.h>
#include <LibWeb/Bindings/SubmitEventWrapper.h>
#include <LibWeb/Bindings/WebGLContextEventWrapper.h>
namespace Web::Bindings {
EventWrapper* wrap(JS::Realm& realm, DOM::Event& event)
{
if (event.wrapper())
return static_cast<EventWrapper*>(event.wrapper());
if (is<DOM::CustomEvent>(event))
return static_cast<CustomEventWrapper*>(wrap_impl(realm, static_cast<DOM::CustomEvent&>(event)));
if (is<CSS::MediaQueryListEvent>(event))
return static_cast<MediaQueryListEventWrapper*>(wrap_impl(realm, static_cast<CSS::MediaQueryListEvent&>(event)));
if (is<HTML::CloseEvent>(event))
return static_cast<CloseEventWrapper*>(wrap_impl(realm, static_cast<HTML::CloseEvent&>(event)));
if (is<HTML::MessageEvent>(event))
return static_cast<MessageEventWrapper*>(wrap_impl(realm, static_cast<HTML::MessageEvent&>(event)));
if (is<HTML::PageTransitionEvent>(event))
return static_cast<PageTransitionEventWrapper*>(wrap_impl(realm, static_cast<HTML::PageTransitionEvent&>(event)));
if (is<HTML::PromiseRejectionEvent>(event))
return static_cast<PromiseRejectionEventWrapper*>(wrap_impl(realm, static_cast<HTML::PromiseRejectionEvent&>(event)));
if (is<HTML::SubmitEvent>(event))
return static_cast<SubmitEventWrapper*>(wrap_impl(realm, static_cast<HTML::SubmitEvent&>(event)));
if (is<UIEvents::KeyboardEvent>(event))
return static_cast<KeyboardEventWrapper*>(wrap_impl(realm, static_cast<UIEvents::KeyboardEvent&>(event)));
if (is<UIEvents::MouseEvent>(event))
return static_cast<MouseEventWrapper*>(wrap_impl(realm, static_cast<UIEvents::MouseEvent&>(event)));
if (is<XHR::ProgressEvent>(event))
return static_cast<ProgressEventWrapper*>(wrap_impl(realm, static_cast<XHR::ProgressEvent&>(event)));
if (is<UIEvents::UIEvent>(event))
return static_cast<UIEventWrapper*>(wrap_impl(realm, static_cast<UIEvents::UIEvent&>(event)));
if (is<WebGL::WebGLContextEvent>(event))
return static_cast<WebGLContextEventWrapper*>(wrap_impl(realm, static_cast<WebGL::WebGLContextEvent&>(event)));
return static_cast<EventWrapper*>(wrap_impl(realm, event));
}
}

View file

@ -1,16 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Forward.h>
#include <LibWeb/Forward.h>
namespace Web::Bindings {
EventWrapper* wrap(JS::Realm&, DOM::Event&);
}

View file

@ -134,8 +134,8 @@ JS::VM& main_thread_vm()
/* .promise = */ promise,
/* .reason = */ promise.cell()->result(),
};
auto promise_rejection_event = HTML::PromiseRejectionEvent::create(HTML::EventNames::rejectionhandled, event_init);
window.impl().dispatch_event(move(promise_rejection_event));
auto promise_rejection_event = HTML::PromiseRejectionEvent::create(window, HTML::EventNames::rejectionhandled, event_init);
window.impl().dispatch_event(*promise_rejection_event);
});
break;
}

View file

@ -19,8 +19,6 @@
#include <LibWeb/Bindings/ElementWrapper.h>
#include <LibWeb/Bindings/EventTargetConstructor.h>
#include <LibWeb/Bindings/EventTargetPrototype.h>
#include <LibWeb/Bindings/EventWrapper.h>
#include <LibWeb/Bindings/EventWrapperFactory.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/HistoryWrapper.h>
#include <LibWeb/Bindings/LocationObject.h>

View file

@ -6,7 +6,6 @@ set(SOURCES
Bindings/CallbackType.cpp
Bindings/CrossOriginAbstractOperations.cpp
Bindings/EventTargetWrapperFactory.cpp
Bindings/EventWrapperFactory.cpp
Bindings/IDLAbstractOperations.cpp
Bindings/ImageConstructor.cpp
Bindings/LegacyPlatformObject.cpp
@ -47,6 +46,7 @@ set(SOURCES
CSS/MediaList.cpp
CSS/MediaQuery.cpp
CSS/MediaQueryList.cpp
CSS/MediaQueryListEvent.cpp
CSS/Parser/Block.cpp
CSS/Parser/ComponentValue.cpp
CSS/Parser/Declaration.cpp
@ -145,9 +145,11 @@ set(SOURCES
HTML/Canvas/CanvasState.cpp
HTML/CanvasGradient.cpp
HTML/CanvasRenderingContext2D.cpp
HTML/CloseEvent.cpp
HTML/CrossOrigin/Reporting.cpp
HTML/DOMParser.cpp
HTML/DOMStringMap.cpp
HTML/ErrorEvent.cpp
HTML/EventHandler.cpp
HTML/EventLoop/EventLoop.cpp
HTML/EventLoop/Task.cpp
@ -232,7 +234,9 @@ set(SOURCES
HTML/HTMLVideoElement.cpp
HTML/ImageData.cpp
HTML/MessageChannel.cpp
HTML/MessageEvent.cpp
HTML/MessagePort.cpp
HTML/PageTransitionEvent.cpp
HTML/Parser/Entities.cpp
HTML/Parser/HTMLEncodingDetection.cpp
HTML/Parser/HTMLParser.cpp
@ -241,12 +245,14 @@ set(SOURCES
HTML/Parser/ListOfActiveFormattingElements.cpp
HTML/Parser/StackOfOpenElements.cpp
HTML/Path2D.cpp
HTML/PromiseRejectionEvent.cpp
HTML/Scripting/ClassicScript.cpp
HTML/Scripting/Environments.cpp
HTML/Scripting/ExceptionReporter.cpp
HTML/Scripting/Script.cpp
HTML/Scripting/WindowEnvironmentSettingsObject.cpp
HTML/Storage.cpp
HTML/SubmitEvent.cpp
HTML/SyntaxHighlighter/SyntaxHighlighter.cpp
HTML/TagNames.cpp
HTML/TextMetrics.cpp
@ -371,6 +377,7 @@ set(SOURCES
UIEvents/FocusEvent.cpp
UIEvents/KeyboardEvent.cpp
UIEvents/MouseEvent.cpp
UIEvents/UIEvent.cpp
URL/URL.cpp
URL/URLSearchParams.cpp
URL/URLSearchParamsIterator.cpp
@ -386,10 +393,12 @@ set(SOURCES
WebAssembly/WebAssemblyTableObject.cpp
WebAssembly/WebAssemblyTablePrototype.cpp
WebGL/WebGLContextAttributes.cpp
WebGL/WebGLContextEvent.cpp
WebGL/WebGLRenderingContext.cpp
WebGL/WebGLRenderingContextBase.cpp
WebSockets/WebSocket.cpp
XHR/EventNames.cpp
XHR/ProgressEvent.cpp
XHR/XMLHttpRequest.cpp
XHR/XMLHttpRequestEventTarget.cpp
XML/XMLDocumentBuilder.cpp

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/MediaQueryListEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/CSS/MediaQueryListEvent.h>
namespace Web::CSS {
MediaQueryListEvent* MediaQueryListEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init)
{
return window_object.heap().allocate<MediaQueryListEvent>(window_object.realm(), window_object, event_name, event_init);
}
MediaQueryListEvent* MediaQueryListEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
MediaQueryListEvent::MediaQueryListEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init)
: DOM::Event(window_object, event_name, event_init)
, m_media(event_init.media)
, m_matches(event_init.matches)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::MediaQueryListEventPrototype>("MediaQueryListEvent"));
}
MediaQueryListEvent::~MediaQueryListEvent() = default;
}

View file

@ -15,33 +15,28 @@ struct MediaQueryListEventInit : public DOM::EventInit {
bool matches { false };
};
class MediaQueryListEvent : public DOM::Event {
class MediaQueryListEvent final : public DOM::Event {
JS_OBJECT(MediaQueryListEvent, DOM::Event);
public:
using WrapperType = Bindings::MediaQueryListEventWrapper;
static MediaQueryListEvent* create(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init = {});
static MediaQueryListEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init);
static NonnullRefPtr<MediaQueryListEvent> create(FlyString const& event_name, MediaQueryListEventInit const& event_init = {})
{
return adopt_ref(*new MediaQueryListEvent(event_name, event_init));
}
static NonnullRefPtr<MediaQueryListEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init)
{
return MediaQueryListEvent::create(event_name, event_init);
}
MediaQueryListEvent(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init);
virtual ~MediaQueryListEvent() override;
virtual ~MediaQueryListEvent() override = default;
MediaQueryListEvent& impl() { return *this; }
String const& media() const { return m_media; }
bool matches() const { return m_matches; }
protected:
MediaQueryListEvent(FlyString const& event_name, MediaQueryListEventInit const& event_init)
: DOM::Event(event_name, event_init)
, m_media(event_init.media)
, m_matches(event_init.matches)
{
}
private:
String m_media;
bool m_matches;
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::CSS::MediaQueryListEvent& object) { return &object; }
using MediaQueryListEventWrapper = Web::CSS::MediaQueryListEvent;
}

View file

@ -1,5 +1,6 @@
#import <DOM/Event.idl>
[NoInstanceWrapper]
interface MediaQueryListEvent : Event {
constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {});

View file

@ -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)

View file

@ -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 thiss detail attribute to detail.
m_detail = detail;

View file

@ -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;
}

View file

@ -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 = {});

View file

@ -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);
}
}

View file

@ -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; }

View file

@ -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 events 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

View file

@ -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;
}

View file

@ -1,5 +1,6 @@
#import <DOM/EventTarget.idl>
[NoInstanceWrapper]
interface Event {
constructor(DOMString type, optional EventInit eventInitDict = {});

View file

@ -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 events dispatch flag.
event->set_dispatched(true);
event.set_dispatched(true);
// 2. Let targetOverride be target, if legacy target override flag is not given, and targets 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 events 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 events 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 events 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 events 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 events 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 events 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, events 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 parents get the parent with event.
@ -312,7 +310,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
}
// 10. Let clearTargetsStruct be the last struct in events 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 events path, in reverse order:
for (auto& entry : event->path().in_reverse()) {
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)
event->set_phase(Event::Phase::AtTarget);
event.set_phase(Event::Phase::AtTarget);
// 2. Otherwise, set events 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 events path:
for (auto& entry : event->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) {
event->set_phase(Event::Phase::AtTarget);
event.set_phase(Event::Phase::AtTarget);
}
// 2. Otherwise:
else {
// 1. If events bubbles attribute is false, then continue.
if (!event->bubbles())
if (!event.bubbles())
continue;
// 2. Set events 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 events eventPhase attribute to NONE.
event->set_phase(Event::Phase::None);
event.set_phase(Event::Phase::None);
// 7. Set events currentTarget attribute to null.
event->set_current_target(nullptr);
event.set_current_target(nullptr);
// 8. Set events path to the empty list.
event->clear_path();
event.clear_path();
// 9. 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);
event.set_dispatched(false);
event.set_stop_propagation(false);
event.set_stop_immediate_propagation(false);
// 10. If clearTargets, then:
if (clear_targets) {
// 1. Set events target to null.
event->set_target(nullptr);
event.set_target(nullptr);
// 2. Set events relatedTarget to null.
event->set_related_target(nullptr);
event.set_related_target(nullptr);
// 3. Set events 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 events canceled flag is unset, then run activationTargets 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 events canceled flag is set; otherwise true.
return !event->cancelled();
return !event.cancelled();
}
}

View file

@ -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);

View file

@ -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 events 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 events 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);
}
}

View file

@ -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;

View file

@ -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>

View file

@ -455,10 +455,8 @@ class CanvasGradientWrapper;
class CanvasRenderingContext2DWrapper;
class CDATASectionWrapper;
class CharacterDataWrapper;
class CloseEventWrapper;
class CommentWrapper;
class CryptoWrapper;
class CustomEventWrapper;
class DocumentFragmentWrapper;
class DocumentTypeWrapper;
class DocumentWrapper;
@ -470,11 +468,8 @@ class DOMRectListWrapper;
class DOMRectReadOnlyWrapper;
class DOMRectWrapper;
class ElementWrapper;
class ErrorEventWrapper;
class EventTargetWrapper;
class EventWrapper;
class FileWrapper;
class FocusEventWrapper;
class HeadersWrapper;
class HeadersIteratorWrapper;
class HistoryWrapper;
@ -554,26 +549,19 @@ class HTMLVideoElementWrapper;
class IdleDeadlineWrapper;
class ImageDataWrapper;
class IntersectionObserverWrapper;
class KeyboardEventWrapper;
class LocationObject;
class MediaQueryListEventWrapper;
class MediaQueryListWrapper;
class MessageChannelWrapper;
class MessageEventWrapper;
class MessagePortWrapper;
class MouseEventWrapper;
class MutationObserverWrapper;
class MutationRecordWrapper;
class NodeListWrapper;
class NodeWrapper;
class OptionConstructor;
class PageTransitionEventWrapper;
class Path2DWrapper;
class PerformanceTimingWrapper;
class PerformanceWrapper;
class ProcessingInstructionWrapper;
class ProgressEventWrapper;
class PromiseRejectionEventWrapper;
class RangeConstructor;
class RangePrototype;
class RangeWrapper;
@ -582,7 +570,6 @@ class ScreenWrapper;
class SelectionWrapper;
class StaticRangeWrapper;
class StorageWrapper;
class SubmitEventWrapper;
class SubtleCryptoWrapper;
class SVGAnimatedLengthWrapper;
class SVGCircleElementWrapper;
@ -604,7 +591,6 @@ class TextDecoderWrapper;
class TextEncoderWrapper;
class TextMetricsWrapper;
class TextWrapper;
class UIEventWrapper;
class URLConstructor;
class URLPrototype;
class URLSearchParamsConstructor;
@ -613,7 +599,6 @@ class URLSearchParamsIteratorWrapper;
class URLSearchParamsPrototype;
class URLSearchParamsWrapper;
class URLWrapper;
class WebGLContextEventWrapper;
class WebGLRenderingContextWrapper;
class WebSocketWrapper;
class WindowObject;

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/CloseEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/CloseEvent.h>
namespace Web::HTML {
CloseEvent* CloseEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init)
{
return window_object.heap().allocate<CloseEvent>(window_object.realm(), window_object, event_name, event_init);
}
CloseEvent* CloseEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
CloseEvent::CloseEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init)
: DOM::Event(window_object, event_name, event_init)
, m_was_clean(event_init.was_clean)
, m_code(event_init.code)
, m_reason(event_init.reason)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::CloseEventPrototype>("CloseEvent"));
}
CloseEvent::~CloseEvent() = default;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Dex <dexes.ttp@gmail.com>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -17,36 +18,31 @@ struct CloseEventInit : public DOM::EventInit {
};
class CloseEvent : public DOM::Event {
JS_OBJECT(CloseEvent, DOM::Event);
public:
using WrapperType = Bindings::CloseEventWrapper;
static CloseEvent* create(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init = {});
static CloseEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init);
static NonnullRefPtr<CloseEvent> create(FlyString const& event_name, CloseEventInit const& event_init = {})
{
return adopt_ref(*new CloseEvent(event_name, event_init));
}
static NonnullRefPtr<CloseEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init)
{
return CloseEvent::create(event_name, event_init);
}
CloseEvent(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init);
virtual ~CloseEvent() override = default;
virtual ~CloseEvent() override;
CloseEvent& impl() { return *this; }
bool was_clean() const { return m_was_clean; }
u16 code() const { return m_code; }
String reason() const { return m_reason; }
protected:
CloseEvent(FlyString const& event_name, CloseEventInit const& event_init)
: DOM::Event(event_name, event_init)
, m_was_clean(event_init.was_clean)
, m_code(event_init.code)
, m_reason(event_init.reason)
{
}
private:
bool m_was_clean { false };
u16 m_code { 0 };
String m_reason;
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::HTML::CloseEvent& object) { return &object; }
using CloseEventWrapper = Web::HTML::CloseEvent;
}

View file

@ -1,5 +1,6 @@
#import <DOM/Event.idl>
[NoInstanceWrapper]
interface CloseEvent : Event {
constructor(DOMString type, optional CloseEventInit eventInitDict = {});

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/ErrorEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/ErrorEvent.h>
namespace Web::HTML {
ErrorEvent* ErrorEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init)
{
return window_object.heap().allocate<ErrorEvent>(window_object.realm(), window_object, event_name, event_init);
}
ErrorEvent* ErrorEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
ErrorEvent::ErrorEvent(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init)
: DOM::Event(window_object, event_name)
, m_message(event_init.message)
, m_filename(event_init.filename)
, m_lineno(event_init.lineno)
, m_colno(event_init.colno)
, m_error(event_init.error)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::ErrorEventPrototype>("ErrorEvent"));
}
ErrorEvent::~ErrorEvent() = default;
void ErrorEvent::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_error);
}
}

View file

@ -21,20 +21,17 @@ struct ErrorEventInit : public DOM::EventInit {
// https://html.spec.whatwg.org/multipage/webappapis.html#errorevent
class ErrorEvent final : public DOM::Event {
JS_OBJECT(ErrorEvent, DOM::Event);
public:
using WrapperType = Bindings::ErrorEventWrapper;
static ErrorEvent* create(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init = {});
static ErrorEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init);
static NonnullRefPtr<ErrorEvent> create(FlyString const& event_name, ErrorEventInit const& event_init = {})
{
return adopt_ref(*new ErrorEvent(event_name, event_init));
}
ErrorEvent(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init);
static NonnullRefPtr<ErrorEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init)
{
return ErrorEvent::create(event_name, event_init);
}
virtual ~ErrorEvent() override;
virtual ~ErrorEvent() override = default;
ErrorEvent& impl() { return *this; }
// https://html.spec.whatwg.org/multipage/webappapis.html#dom-errorevent-message
String const& message() const { return m_message; }
@ -49,24 +46,21 @@ public:
u32 colno() const { return m_colno; }
// https://html.spec.whatwg.org/multipage/webappapis.html#dom-errorevent-error
JS::Value error() const { return m_error.value(); }
JS::Value error() const { return m_error; }
private:
ErrorEvent(FlyString const& event_name, ErrorEventInit const& event_init)
: DOM::Event(event_name)
, m_message(event_init.message)
, m_filename(event_init.filename)
, m_lineno(event_init.lineno)
, m_colno(event_init.colno)
, m_error(JS::make_handle(event_init.error))
{
}
virtual void visit_edges(Cell::Visitor&) override;
String m_message { "" };
String m_filename { "" }; // FIXME: This should be a USVString.
u32 m_lineno { 0 };
u32 m_colno { 0 };
JS::Handle<JS::Value> m_error;
JS::Value m_error;
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::HTML::ErrorEvent& object) { return &object; }
using ErrorEventWrapper = Web::HTML::ErrorEvent;
}

View file

@ -247,9 +247,9 @@ static void run_focus_update_steps(NonnullRefPtrVector<DOM::Node> old_chain, Non
// with related blur target as the related target.
if (blur_event_target) {
// FIXME: Implement the "fire a focus event" spec operation.
auto blur_event = UIEvents::FocusEvent::create(HTML::EventNames::blur);
auto blur_event = UIEvents::FocusEvent::create(verify_cast<DOM::Node>(*blur_event_target).document().preferred_window_object(), HTML::EventNames::blur);
blur_event->set_related_target(related_blur_target);
blur_event_target->dispatch_event(move(blur_event));
blur_event_target->dispatch_event(*blur_event);
}
}
@ -290,9 +290,9 @@ static void run_focus_update_steps(NonnullRefPtrVector<DOM::Node> old_chain, Non
// with related focus target as the related target.
if (focus_event_target) {
// FIXME: Implement the "fire a focus event" spec operation.
auto focus_event = UIEvents::FocusEvent::create(HTML::EventNames::focus);
auto focus_event = UIEvents::FocusEvent::create(verify_cast<DOM::Node>(*focus_event_target).document().preferred_window_object(), HTML::EventNames::focus);
focus_event->set_related_target(related_focus_target);
focus_event_target->dispatch_event(move(focus_event));
focus_event_target->dispatch_event(*focus_event);
}
}
}
@ -411,7 +411,7 @@ bool HTMLElement::fire_a_synthetic_pointer_event(FlyString const& type, DOM::Ele
// 1. Let event be the result of creating an event using PointerEvent.
// 2. Initialize event's type attribute to e.
// FIXME: Actually create a PointerEvent!
auto event = UIEvents::MouseEvent::create(type);
auto event = UIEvents::MouseEvent::create(document().preferred_window_object(), type);
// 3. Initialize event's bubbles and cancelable attributes to true.
event->set_bubbles(true);
@ -433,7 +433,7 @@ bool HTMLElement::fire_a_synthetic_pointer_event(FlyString const& type, DOM::Ele
// FIXME: 8. event's getModifierState() method is to return values appropriately describing the current state of the key input device.
// 9. Return the result of dispatching event at target.
return target.dispatch_event(move(event));
return target.dispatch_event(*event);
}
// https://html.spec.whatwg.org/multipage/interaction.html#dom-click

View file

@ -65,10 +65,10 @@ void HTMLFormElement::submit_form(RefPtr<HTMLElement> submitter, bool from_submi
SubmitEventInit event_init {};
event_init.submitter = submitter_button;
auto submit_event = SubmitEvent::create(EventNames::submit, event_init);
auto submit_event = SubmitEvent::create(document().preferred_window_object(), EventNames::submit, event_init);
submit_event->set_bubbles(true);
submit_event->set_cancelable(true);
bool continue_ = dispatch_event(submit_event);
bool continue_ = dispatch_event(*submit_event);
m_firing_submission_events = false;

View file

@ -92,7 +92,7 @@ void run_iframe_load_event_steps(HTML::HTMLIFrameElement& element)
// FIXME: 4. Set childDocument's iframe load in progress flag.
// 5. Fire an event named load at element.
element.dispatch_event(DOM::Event::create(HTML::EventNames::load));
element.dispatch_event(*DOM::Event::create(element.document().preferred_window_object(), HTML::EventNames::load));
// FIXME: 6. Unset childDocument's iframe load in progress flag.
}

View file

@ -26,7 +26,7 @@ HTMLImageElement::HTMLImageElement(DOM::Document& document, DOM::QualifiedName q
set_needs_style_update(true);
this->document().set_needs_layout();
queue_an_element_task(HTML::Task::Source::DOMManipulation, [this] {
dispatch_event(DOM::Event::create(EventNames::load));
dispatch_event(*DOM::Event::create(this->document().preferred_window_object(), EventNames::load));
});
};
@ -35,7 +35,7 @@ HTMLImageElement::HTMLImageElement(DOM::Document& document, DOM::QualifiedName q
set_needs_style_update(true);
this->document().set_needs_layout();
queue_an_element_task(HTML::Task::Source::DOMManipulation, [this] {
dispatch_event(DOM::Event::create(EventNames::error));
dispatch_event(*DOM::Event::create(this->document().preferred_window_object(), EventNames::error));
});
};

View file

@ -90,15 +90,15 @@ void HTMLInputElement::run_input_activation_behavior()
return;
// 2. Fire an event named input at the element with the bubbles and composed attributes initialized to true.
auto input_event = DOM::Event::create(HTML::EventNames::input);
auto input_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::input);
input_event->set_bubbles(true);
input_event->set_composed(true);
dispatch_event(move(input_event));
dispatch_event(*input_event);
// 3. Fire an event named change at the element with the bubbles attribute initialized to true.
auto change_event = DOM::Event::create(HTML::EventNames::change);
auto change_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::change);
change_event->set_bubbles(true);
dispatch_event(move(change_event));
dispatch_event(*change_event);
} else if (type_state() == TypeAttributeState::SubmitButton) {
RefPtr<HTMLFormElement> form;
// 1. If the element does not have a form owner, then return.
@ -112,7 +112,7 @@ void HTMLInputElement::run_input_activation_behavior()
// 3. Submit the form owner from the element.
form->submit_form(this);
} else {
dispatch_event(DOM::Event::create(EventNames::change));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), EventNames::change));
}
}
@ -125,15 +125,15 @@ void HTMLInputElement::did_edit_text_node(Badge<BrowsingContext>)
// NOTE: This is a bit ad-hoc, but basically implements part of "4.10.5.5 Common event behaviors"
// https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
auto input_event = DOM::Event::create(HTML::EventNames::input);
auto input_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::input);
input_event->set_bubbles(true);
input_event->set_composed(true);
dispatch_event(move(input_event));
dispatch_event(*input_event);
// FIXME: This should only fire when the input is "committed", whatever that means.
auto change_event = DOM::Event::create(HTML::EventNames::change);
auto change_event = DOM::Event::create(document().preferred_window_object(), HTML::EventNames::change);
change_event->set_bubbles(true);
dispatch_event(move(change_event));
dispatch_event(*change_event);
});
}

View file

@ -96,7 +96,7 @@ void HTMLObjectElement::queue_element_task_to_run_object_representation_steps()
// 3. If that failed, fire an event named error at the element, then jump to the step below labeled fallback.
if (!url.is_valid()) {
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error));
return run_object_representation_fallback_steps();
}
@ -123,7 +123,7 @@ void HTMLObjectElement::queue_element_task_to_run_object_representation_steps()
void HTMLObjectElement::resource_did_fail()
{
// 4.7. If the load failed (e.g. there was an HTTP 404 error, there was a DNS error), fire an event named error at the element, then jump to the step below labeled fallback.
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error));
run_object_representation_fallback_steps();
}
@ -261,7 +261,7 @@ void HTMLObjectElement::run_object_representation_completed_steps(Representation
// 4.11. If the object element does not represent its nested browsing context, then once the resource is completely loaded, queue an element task on the DOM manipulation task source given the object element to fire an event named load at the element.
if (representation != Representation::NestedBrowsingContext) {
queue_an_element_task(HTML::Task::Source::DOMManipulation, [&]() {
dispatch_event(DOM::Event::create(HTML::EventNames::load));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::load));
});
}

View file

@ -48,7 +48,7 @@ void HTMLScriptElement::execute_script()
// 3. If the script's script is null for scriptElement, then fire an event named error at scriptElement, and return.
if (!m_script) {
dbgln("HTMLScriptElement: Refusing to run script because the script's script is null.");
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error));
return;
}
@ -95,7 +95,7 @@ void HTMLScriptElement::execute_script()
// 7. If scriptElement is from an external file, then fire an event named load at scriptElement.
if (m_from_an_external_file)
dispatch_event(DOM::Event::create(HTML::EventNames::load));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::load));
}
// https://mimesniff.spec.whatwg.org/#javascript-mime-type-essence-match
@ -259,7 +259,7 @@ void HTMLScriptElement::prepare_script()
if (src.is_empty()) {
dbgln("HTMLScriptElement: Refusing to run script because the src attribute is empty.");
queue_an_element_task(HTML::Task::Source::Unspecified, [this] {
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error));
});
return;
}
@ -272,7 +272,7 @@ void HTMLScriptElement::prepare_script()
if (!url.is_valid()) {
dbgln("HTMLScriptElement: Refusing to run script because the src URL '{}' is invalid.", url);
queue_an_element_task(HTML::Task::Source::Unspecified, [this] {
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(document().preferred_window_object(), HTML::EventNames::error));
});
return;
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/MessageEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/MessageEvent.h>
namespace Web::HTML {
MessageEvent* MessageEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init)
{
return window_object.heap().allocate<MessageEvent>(window_object.realm(), window_object, event_name, event_init);
}
MessageEvent* MessageEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
MessageEvent::MessageEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init)
: DOM::Event(window_object, event_name, event_init)
, m_data(event_init.data)
, m_origin(event_init.origin)
, m_last_event_id(event_init.last_event_id)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::MessageEventPrototype>("MessageEvent"));
}
MessageEvent::~MessageEvent() = default;
void MessageEvent::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_data);
}
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Dex <dexes.ttp@gmail.com>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -17,36 +18,32 @@ struct MessageEventInit : public DOM::EventInit {
};
class MessageEvent : public DOM::Event {
JS_OBJECT(MessageEvent, DOM::Event);
public:
using WrapperType = Bindings::MessageEventWrapper;
static MessageEvent* create(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init = {});
static MessageEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init);
static NonnullRefPtr<MessageEvent> create(FlyString const& event_name, MessageEventInit const& event_init = {})
{
return adopt_ref(*new MessageEvent(event_name, event_init));
}
static NonnullRefPtr<MessageEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init)
{
return MessageEvent::create(event_name, event_init);
}
MessageEvent(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init);
virtual ~MessageEvent() override;
virtual ~MessageEvent() override = default;
MessageEvent& impl() { return *this; }
JS::Value data() const { return m_data.value(); }
JS::Value data() const { return m_data; }
String const& origin() const { return m_origin; }
String const& last_event_id() const { return m_last_event_id; }
protected:
MessageEvent(FlyString const& event_name, MessageEventInit const& event_init)
: DOM::Event(event_name, event_init)
, m_data(JS::make_handle(event_init.data))
, m_origin(event_init.origin)
, m_last_event_id(event_init.last_event_id)
{
}
private:
virtual void visit_edges(Cell::Visitor&) override;
JS::Handle<JS::Value> m_data;
JS::Value m_data;
String m_origin;
String m_last_event_id;
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::HTML::MessageEvent& object) { return &object; }
using MessageEventWrapper = Web::HTML::MessageEvent;
}

View file

@ -1,5 +1,6 @@
#import <DOM/Event.idl>
[NoInstanceWrapper]
interface MessageEvent : Event {
constructor(DOMString type, optional MessageEventInit eventInitDict = {});

View file

@ -80,7 +80,7 @@ void MessagePort::post_message(JS::Value message)
MessageEventInit event_init {};
event_init.data = message;
event_init.origin = "<origin>";
strong_port->dispatch_event(MessageEvent::create(HTML::EventNames::message, event_init));
strong_port->dispatch_event(*MessageEvent::create(verify_cast<Bindings::WindowObject>(strong_port->wrapper()->global_object()), HTML::EventNames::message, event_init));
}));
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/PageTransitionEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/PageTransitionEvent.h>
namespace Web::HTML {
PageTransitionEvent* PageTransitionEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init)
{
return window_object.heap().allocate<PageTransitionEvent>(window_object.realm(), window_object, event_name, event_init);
}
PageTransitionEvent* PageTransitionEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
PageTransitionEvent::PageTransitionEvent(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init)
: DOM::Event(window_object, event_name, event_init)
, m_persisted(event_init.persisted)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::PageTransitionEventPrototype>("PageTransitionEvent"));
}
PageTransitionEvent::~PageTransitionEvent() = default;
}

View file

@ -15,30 +15,27 @@ struct PageTransitionEventInit : public DOM::EventInit {
};
class PageTransitionEvent final : public DOM::Event {
JS_OBJECT(PageTransitionEvent, DOM::Event);
public:
using WrapperType = Bindings::PageTransitionEventWrapper;
static PageTransitionEvent* create(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init);
static PageTransitionEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init);
static NonnullRefPtr<PageTransitionEvent> create(FlyString const& event_name, PageTransitionEventInit const& event_init)
{
return adopt_ref(*new PageTransitionEvent(event_name, event_init));
}
static NonnullRefPtr<PageTransitionEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init)
{
return PageTransitionEvent::create(event_name, event_init);
}
PageTransitionEvent(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init);
virtual ~PageTransitionEvent() override = default;
virtual ~PageTransitionEvent() override;
PageTransitionEvent& impl() { return *this; }
bool persisted() const { return m_persisted; }
protected:
PageTransitionEvent(FlyString const& event_name, PageTransitionEventInit const& event_init)
: DOM::Event(event_name, event_init)
, m_persisted(event_init.persisted)
{
}
private:
bool m_persisted { false };
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::HTML::PageTransitionEvent& object) { return &object; }
using PageTransitionEventWrapper = Web::HTML::PageTransitionEvent;
}

View file

@ -236,9 +236,9 @@ void HTMLParser::the_end()
// FIXME: 1. Set the Document's load timing info's DOM content loaded event start time to the current high resolution time given the Document's relevant global object.
// 2. Fire an event named DOMContentLoaded at the Document object, with its bubbles attribute initialized to true.
auto content_loaded_event = DOM::Event::create(HTML::EventNames::DOMContentLoaded);
auto content_loaded_event = DOM::Event::create(document->preferred_window_object(), HTML::EventNames::DOMContentLoaded);
content_loaded_event->set_bubbles(true);
document->dispatch_event(content_loaded_event);
document->dispatch_event(*content_loaded_event);
// FIXME: 3. Set the Document's load timing info's DOM content loaded event end time to the current high resolution time given the Document's relevant global object.
@ -275,7 +275,7 @@ void HTMLParser::the_end()
// 5. Fire an event named load at window, with legacy target override flag set.
// FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event()
// We should reorganize this so that the flag appears explicitly here instead.
window->dispatch_event(DOM::Event::create(HTML::EventNames::load));
window->dispatch_event(*DOM::Event::create(document->preferred_window_object(), HTML::EventNames::load));
// FIXME: 6. Invoke WebDriver BiDi load complete with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "complete", and url is the Document object's URL.

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/PromiseRejectionEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/PromiseRejectionEvent.h>
namespace Web::HTML {
PromiseRejectionEvent* PromiseRejectionEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
{
return window_object.heap().allocate<PromiseRejectionEvent>(window_object.realm(), window_object, event_name, event_init);
}
PromiseRejectionEvent* PromiseRejectionEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
PromiseRejectionEvent::PromiseRejectionEvent(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
: DOM::Event(window_object, event_name, event_init)
, m_promise(const_cast<JS::Promise*>(event_init.promise.cell()))
, m_reason(event_init.reason)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::PromiseRejectionEventPrototype>("PromiseRejectionEvent"));
}
PromiseRejectionEvent::~PromiseRejectionEvent() = default;
void PromiseRejectionEvent::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_promise);
visitor.visit(m_reason);
}
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -17,35 +18,33 @@ struct PromiseRejectionEventInit : public DOM::EventInit {
JS::Value reason;
};
class PromiseRejectionEvent : public DOM::Event {
class PromiseRejectionEvent final : public DOM::Event {
JS_OBJECT(PromiseRejectionEvent, DOM::Event);
public:
using WrapperType = Bindings::PromiseRejectionEventWrapper;
static PromiseRejectionEvent* create(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init = {});
static PromiseRejectionEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init);
static NonnullRefPtr<PromiseRejectionEvent> create(FlyString const& event_name, PromiseRejectionEventInit const& event_init = {})
{
return adopt_ref(*new PromiseRejectionEvent(event_name, event_init));
}
static NonnullRefPtr<PromiseRejectionEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
{
return PromiseRejectionEvent::create(event_name, event_init);
}
PromiseRejectionEvent(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init);
virtual ~PromiseRejectionEvent() override = default;
virtual ~PromiseRejectionEvent() override;
PromiseRejectionEvent& impl() { return *this; }
// Needs to return a pointer for the generated JS bindings to work.
JS::Promise const* promise() const { return m_promise.cell(); }
JS::Value reason() const { return m_reason.value(); }
JS::Promise const* promise() const { return m_promise; }
JS::Value reason() const { return m_reason; }
protected:
PromiseRejectionEvent(FlyString const& event_name, PromiseRejectionEventInit const& event_init)
: DOM::Event(event_name, event_init)
, m_promise(event_init.promise)
, m_reason(JS::make_handle(event_init.reason))
{
}
private:
virtual void visit_edges(Cell::Visitor&) override;
JS::Handle<JS::Promise> m_promise;
JS::Handle<JS::Value> m_reason;
JS::Promise* m_promise { nullptr };
JS::Value m_reason;
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::HTML::PromiseRejectionEvent& object) { return &object; }
using PromiseRejectionEventWrapper = Web::HTML::PromiseRejectionEvent;
}

View file

@ -1,6 +1,6 @@
#import <DOM/Event.idl>
[Exposed=(Window,Worker)]
[Exposed=(Window,Worker), NoInstanceWrapper]
interface PromiseRejectionEvent : Event {
constructor(DOMString type, PromiseRejectionEventInit eventInitDict);

View file

@ -217,12 +217,12 @@ void EnvironmentSettingsObject::notify_about_rejected_promises(Badge<EventLoop>)
/* .promise = */ promise_handle,
/* .reason = */ promise.result(),
};
auto promise_rejection_event = PromiseRejectionEvent::create(HTML::EventNames::unhandledrejection, event_init);
// FIXME: This currently assumes that global is a WindowObject.
auto& window = verify_cast<Bindings::WindowObject>(*global.cell());
bool not_handled = window.impl().dispatch_event(move(promise_rejection_event));
auto promise_rejection_event = PromiseRejectionEvent::create(window, HTML::EventNames::unhandledrejection, event_init);
bool not_handled = window.impl().dispatch_event(*promise_rejection_event);
// 3. If notHandled is false, then the promise rejection is handled. Otherwise, the promise rejection is not handled.

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/SubmitEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/SubmitEvent.h>
namespace Web::HTML {
SubmitEvent* SubmitEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init)
{
return window_object.heap().allocate<SubmitEvent>(window_object.realm(), window_object, event_name, event_init);
}
SubmitEvent* SubmitEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
SubmitEvent::SubmitEvent(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init)
: DOM::Event(window_object, event_name, event_init)
, m_submitter(event_init.submitter)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::SubmitEventPrototype>("SubmitEvent"));
}
SubmitEvent::~SubmitEvent() = default;
}

View file

@ -17,29 +17,21 @@ struct SubmitEventInit : public DOM::EventInit {
};
class SubmitEvent final : public DOM::Event {
JS_OBJECT(SubmitEvent, DOM::Event);
public:
using WrapperType = Bindings::SubmitEventWrapper;
static SubmitEvent* create(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
static SubmitEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
static NonnullRefPtr<SubmitEvent> create(FlyString const& event_name, SubmitEventInit const& event_init)
{
return adopt_ref(*new SubmitEvent(event_name, event_init));
}
static NonnullRefPtr<SubmitEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init)
{
return SubmitEvent::create(event_name, event_init);
}
virtual ~SubmitEvent() override;
virtual ~SubmitEvent() override = default;
SubmitEvent(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
SubmitEvent& impl() { return *this; }
RefPtr<HTMLElement> submitter() const { return m_submitter; }
private:
SubmitEvent(FlyString const& event_name, SubmitEventInit const& event_init)
: DOM::Event(event_name, event_init)
, m_submitter(event_init.submitter)
{
}
RefPtr<HTMLElement> m_submitter;
};

View file

@ -1,6 +1,7 @@
#import <DOM/Event.idl>
#import <HTML/HTMLElement.idl>
[NoInstanceWrapper]
interface SubmitEvent : Event {
constructor(DOMString type, optional SubmitEventInit eventInitDict = {});

View file

@ -279,7 +279,7 @@ void Window::did_call_location_replace(Badge<Bindings::LocationObject>, String u
browsing_context->loader().load(move(new_url), FrameLoader::Type::Navigation);
}
bool Window::dispatch_event(NonnullRefPtr<DOM::Event> event)
bool Window::dispatch_event(DOM::Event& event)
{
return DOM::EventDispatcher::dispatch(*this, event, true);
}
@ -458,7 +458,7 @@ void Window::fire_a_page_transition_event(FlyString const& event_name, bool pers
// with the persisted attribute initialized to persisted,
HTML::PageTransitionEventInit event_init {};
event_init.persisted = persisted;
auto event = HTML::PageTransitionEvent::create(event_name, event_init);
auto event = HTML::PageTransitionEvent::create(associated_document().preferred_window_object(), event_name, event_init);
// ...the cancelable attribute initialized to true,
event->set_cancelable(true);
@ -467,7 +467,7 @@ void Window::fire_a_page_transition_event(FlyString const& event_name, bool pers
event->set_bubbles(true);
// and legacy target override flag set.
dispatch_event(move(event));
dispatch_event(*event);
}
// https://html.spec.whatwg.org/#dom-queuemicrotask
@ -567,7 +567,9 @@ DOM::ExceptionOr<void> Window::post_message(JS::Value message, String const&)
HTML::MessageEventInit event_init {};
event_init.data = message;
event_init.origin = "<origin>";
strong_this->dispatch_event(HTML::MessageEvent::create(HTML::EventNames::message, event_init));
auto* wrapper = static_cast<Bindings::WindowObject*>(strong_this->wrapper());
VERIFY(wrapper);
strong_this->dispatch_event(*HTML::MessageEvent::create(*wrapper, HTML::EventNames::message, event_init));
});
return {};
}
@ -688,4 +690,9 @@ void Window::set_associated_document(DOM::Document& document)
m_associated_document = document;
}
void Window::set_current_event(DOM::Event* event)
{
m_current_event = JS::make_handle(event);
}
}

View file

@ -43,7 +43,7 @@ public:
virtual void ref_event_target() override { RefCounted::ref(); }
virtual void unref_event_target() override { RefCounted::unref(); }
virtual bool dispatch_event(NonnullRefPtr<DOM::Event>) override;
virtual bool dispatch_event(DOM::Event&) override;
virtual JS::Object* create_wrapper(JS::Realm&) override;
Page* page();
@ -92,8 +92,9 @@ public:
CSS::Screen& screen() { return *m_screen; }
DOM::Event const* current_event() const { return m_current_event; }
void set_current_event(DOM::Event* event) { m_current_event = event; }
DOM::Event* current_event() { return m_current_event.cell(); }
DOM::Event const* current_event() const { return m_current_event.cell(); }
void set_current_event(DOM::Event* event);
CSS::CSSStyleDeclaration* get_computed_style(DOM::Element&) const;
NonnullRefPtr<CSS::MediaQueryList> match_media(String);
@ -157,7 +158,7 @@ private:
NonnullOwnPtr<HighResolutionTime::Performance> m_performance;
NonnullRefPtr<Crypto::Crypto> m_crypto;
NonnullOwnPtr<CSS::Screen> m_screen;
RefPtr<DOM::Event> m_current_event;
JS::Handle<DOM::Event> m_current_event;
AnimationFrameCallbackDriver m_animation_frame_callback_driver;

View file

@ -148,7 +148,8 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti
MessageEventInit event_init {};
event_init.data = message;
event_init.origin = "<origin>";
dispatch_event(MessageEvent::create(HTML::EventNames::message, event_init));
// FIXME: The cast here is totally bogus, since workers don't have a WindowObject..
dispatch_event(*MessageEvent::create(verify_cast<Bindings::WindowObject>(*m_worker_scope), HTML::EventNames::message, event_init));
}));
return JS::js_undefined();

View file

@ -205,12 +205,12 @@ bool EventHandler::handle_mouseup(Gfx::IntPoint const& position, unsigned button
}
auto offset = compute_mouse_event_offset(position, *layout_node);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(UIEvents::EventNames::mouseup, offset.x(), offset.y(), position.x(), position.y(), button));
node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::mouseup, offset.x(), offset.y(), position.x(), position.y(), button));
handled_event = true;
bool run_activation_behavior = true;
if (node.ptr() == m_mousedown_target && button == GUI::MouseButton::Primary) {
run_activation_behavior = node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(UIEvents::EventNames::click, offset.x(), offset.y(), position.x(), position.y(), button));
run_activation_behavior = node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::click, offset.x(), offset.y(), position.x(), position.y(), button));
}
if (run_activation_behavior) {
@ -334,7 +334,7 @@ bool EventHandler::handle_mousedown(Gfx::IntPoint const& position, unsigned butt
m_mousedown_target = node;
auto offset = compute_mouse_event_offset(position, *layout_node);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(UIEvents::EventNames::mousedown, offset.x(), offset.y(), position.x(), position.y(), button));
node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::mousedown, offset.x(), offset.y(), position.x(), position.y(), button));
}
// NOTE: Dispatching an event may have disturbed the world.
@ -455,7 +455,7 @@ bool EventHandler::handle_mousemove(Gfx::IntPoint const& position, unsigned butt
}
auto offset = compute_mouse_event_offset(position, *layout_node);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(UIEvents::EventNames::mousemove, offset.x(), offset.y(), position.x(), position.y()));
node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::mousemove, offset.x(), offset.y(), position.x(), position.y()));
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paint_box())
return true;
@ -543,7 +543,7 @@ bool EventHandler::handle_doubleclick(Gfx::IntPoint const& position, unsigned bu
return false;
auto offset = compute_mouse_event_offset(position, *layout_node);
node->dispatch_event(UIEvents::MouseEvent::create_from_platform_event(UIEvents::EventNames::dblclick, offset.x(), offset.y(), position.x(), position.y(), button));
node->dispatch_event(*UIEvents::MouseEvent::create_from_platform_event(node->document().preferred_window_object(), UIEvents::EventNames::dblclick, offset.x(), offset.y(), position.x(), position.y(), button));
// NOTE: Dispatching an event may have disturbed the world.
if (!paint_root() || paint_root() != node->document().paint_box())
@ -722,15 +722,15 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin
return true;
}
auto event = UIEvents::KeyboardEvent::create_from_platform_event(UIEvents::EventNames::keydown, key, modifiers, code_point);
auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->preferred_window_object(), UIEvents::EventNames::keydown, key, modifiers, code_point);
if (RefPtr<DOM::Element> focused_element = document->focused_element())
return focused_element->dispatch_event(move(event));
return focused_element->dispatch_event(*event);
if (RefPtr<HTML::HTMLElement> body = m_browsing_context.active_document()->body())
return body->dispatch_event(move(event));
return body->dispatch_event(*event);
return document->root().dispatch_event(move(event));
return document->root().dispatch_event(*event);
}
bool EventHandler::handle_keyup(KeyCode key, unsigned modifiers, u32 code_point)
@ -739,15 +739,15 @@ bool EventHandler::handle_keyup(KeyCode key, unsigned modifiers, u32 code_point)
if (!document)
return false;
auto event = UIEvents::KeyboardEvent::create_from_platform_event(UIEvents::EventNames::keyup, key, modifiers, code_point);
auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->preferred_window_object(), UIEvents::EventNames::keyup, key, modifiers, code_point);
if (RefPtr<DOM::Element> focused_element = document->focused_element())
return document->focused_element()->dispatch_event(move(event));
return document->focused_element()->dispatch_event(*event);
if (RefPtr<HTML::HTMLElement> body = document->body())
return body->dispatch_event(move(event));
return body->dispatch_event(*event);
return document->root().dispatch_event(move(event));
return document->root().dispatch_event(*event);
}
void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_node)

View file

@ -4,13 +4,21 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/FocusEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/UIEvents/FocusEvent.h>
namespace Web::UIEvents {
FocusEvent::FocusEvent(FlyString const& event_name, FocusEventInit const& event_init)
: UIEvent(event_name)
FocusEvent* FocusEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, FocusEventInit const& event_init)
{
return window_object.heap().allocate<FocusEvent>(window_object.realm(), window_object, event_name, event_init);
}
FocusEvent::FocusEvent(Bindings::WindowObject& window_object, FlyString const& event_name, FocusEventInit const& event_init)
: UIEvent(window_object, event_name)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::FocusEventPrototype>("FocusEvent"));
set_related_target(const_cast<DOM::EventTarget*>(event_init.related_target.ptr()));
}

View file

@ -15,18 +15,20 @@ struct FocusEventInit : public UIEventInit {
};
class FocusEvent final : public UIEvent {
public:
using WrapperType = Bindings::FocusEventWrapper;
JS_OBJECT(FocusEvent, UIEvent);
public:
static FocusEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const& event_init);
FocusEvent(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const&);
virtual ~FocusEvent() override;
static NonnullRefPtr<FocusEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const& event_init)
{
return adopt_ref(*new FocusEvent(event_name, event_init));
}
private:
FocusEvent(FlyString const& event_name, FocusEventInit const&);
FocusEvent& impl() { return *this; }
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::UIEvents::FocusEvent& object) { return &object; }
using FocusEventWrapper = Web::UIEvents::FocusEvent;
}

View file

@ -1,6 +1,6 @@
#import <UIEvents/UIEvent.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface FocusEvent : UIEvent {
constructor(DOMString type, optional FocusEventInit eventInitDict = {});

View file

@ -1,10 +1,12 @@
/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/CharacterTypes.h>
#include <LibWeb/Bindings/KeyboardEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/UIEvents/KeyboardEvent.h>
namespace Web::UIEvents {
@ -65,7 +67,7 @@ static unsigned long determine_key_code(KeyCode platform_key, u32 code_point)
return platform_key;
}
NonnullRefPtr<KeyboardEvent> KeyboardEvent::create_from_platform_event(FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point)
KeyboardEvent* KeyboardEvent::create_from_platform_event(Bindings::WindowObject& window_object, FlyString const& event_name, KeyCode platform_key, unsigned modifiers, u32 code_point)
{
// FIXME: Figure out what these should actually contain.
String event_key = key_code_to_string(platform_key);
@ -87,7 +89,7 @@ NonnullRefPtr<KeyboardEvent> KeyboardEvent::create_from_platform_event(FlyString
event_init.bubbles = true;
event_init.cancelable = true;
event_init.composed = true;
return KeyboardEvent::create(event_name, event_init);
return KeyboardEvent::create(window_object, event_name, event_init);
}
bool KeyboardEvent::get_modifier_state(String const& key_arg)
@ -102,4 +104,34 @@ bool KeyboardEvent::get_modifier_state(String const& key_arg)
return m_meta_key;
return false;
}
KeyboardEvent* KeyboardEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, KeyboardEventInit const& event_init)
{
return window_object.heap().allocate<KeyboardEvent>(window_object.realm(), window_object, event_name, event_init);
}
KeyboardEvent* KeyboardEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, KeyboardEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
KeyboardEvent::KeyboardEvent(Bindings::WindowObject& window_object, FlyString const& event_name, KeyboardEventInit const& event_init)
: UIEvent(window_object, event_name, event_init)
, m_key(event_init.key)
, m_code(event_init.code)
, m_location(event_init.location)
, m_ctrl_key(event_init.ctrl_key)
, m_shift_key(event_init.shift_key)
, m_alt_key(event_init.alt_key)
, m_meta_key(event_init.meta_key)
, m_repeat(event_init.repeat)
, m_is_composing(event_init.is_composing)
, m_key_code(event_init.key_code)
, m_char_code(event_init.char_code)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::KeyboardEventPrototype>("KeyboardEvent"));
}
KeyboardEvent::~KeyboardEvent() = default;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -25,21 +25,18 @@ struct KeyboardEventInit : public EventModifierInit {
// https://www.w3.org/TR/uievents/#interface-keyboardevent
class KeyboardEvent final : public UIEvent {
JS_OBJECT(KeyboardEvent, UIEvent);
public:
using WrapperType = Bindings::KeyboardEventWrapper;
static KeyboardEvent* create(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init = {});
static KeyboardEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init);
static KeyboardEvent* create_from_platform_event(Bindings::WindowObject&, FlyString const& event_name, KeyCode, unsigned modifiers, u32 code_point);
static NonnullRefPtr<KeyboardEvent> create(FlyString const& event_name, KeyboardEventInit const& event_init = {})
{
return adopt_ref(*new KeyboardEvent(event_name, event_init));
}
static NonnullRefPtr<KeyboardEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init)
{
return KeyboardEvent::create(event_name, event_init);
}
KeyboardEvent(Bindings::WindowObject&, FlyString const& event_name, KeyboardEventInit const& event_init);
static NonnullRefPtr<KeyboardEvent> create_from_platform_event(FlyString const& event_name, KeyCode, unsigned modifiers, u32 code_point);
virtual ~KeyboardEvent() override;
virtual ~KeyboardEvent() override = default;
KeyboardEvent& impl() { return *this; }
u32 key_code() const { return m_key_code; }
u32 char_code() const { return m_char_code; }
@ -61,20 +58,6 @@ public:
virtual u32 which() const override { return m_key_code; }
private:
KeyboardEvent(FlyString const& event_name, KeyboardEventInit const& event_init)
: UIEvent(event_name, event_init)
, m_key(event_init.key)
, m_code(event_init.code)
, m_location(event_init.location)
, m_ctrl_key(event_init.ctrl_key)
, m_shift_key(event_init.shift_key)
, m_alt_key(event_init.alt_key)
, m_meta_key(event_init.meta_key)
, m_repeat(event_init.repeat)
, m_is_composing(event_init.is_composing)
, m_key_code(event_init.key_code)
, m_char_code(event_init.char_code) {};
String m_key;
String m_code;
u32 m_location { 0 };
@ -89,3 +72,8 @@ private:
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::UIEvents::KeyboardEvent& object) { return &object; }
using KeyboardEventWrapper = Web::UIEvents::KeyboardEvent;
}

View file

@ -1,6 +1,6 @@
#import <UIEvents/EventModifier.idl>
[Exposed=Window]
[Exposed=Window, NoInstanceWrapper]
interface KeyboardEvent : UIEvent {
constructor(DOMString type, optional KeyboardEventInit eventInitDict = {});

View file

@ -1,27 +1,33 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGUI/Event.h>
#include <LibWeb/Bindings/MouseEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/UIEvents/EventNames.h>
#include <LibWeb/UIEvents/MouseEvent.h>
namespace Web::UIEvents {
MouseEvent::MouseEvent(FlyString const& event_name, MouseEventInit const& event_init)
: UIEvent(event_name, event_init)
MouseEvent::MouseEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MouseEventInit const& event_init)
: UIEvent(window_object, event_name, event_init)
, m_offset_x(event_init.offset_x)
, m_offset_y(event_init.offset_y)
, m_client_x(event_init.client_x)
, m_client_y(event_init.client_y)
, m_button(event_init.button)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::MouseEventPrototype>("MouseEvent"));
set_event_characteristics();
}
MouseEvent::~MouseEvent() = default;
// https://www.w3.org/TR/uievents/#dom-mouseevent-button
static i16 determine_button(unsigned mouse_button)
{
@ -41,7 +47,12 @@ static i16 determine_button(unsigned mouse_button)
}
}
NonnullRefPtr<MouseEvent> MouseEvent::create_from_platform_event(FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button)
MouseEvent* MouseEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MouseEventInit const& event_init)
{
return window_object.heap().allocate<MouseEvent>(window_object.realm(), window_object, event_name, event_init);
}
MouseEvent* MouseEvent::create_from_platform_event(Bindings::WindowObject& window_object, FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button)
{
MouseEventInit event_init {};
event_init.offset_x = offset_x;
@ -49,7 +60,7 @@ NonnullRefPtr<MouseEvent> MouseEvent::create_from_platform_event(FlyString const
event_init.client_x = client_x;
event_init.client_y = client_y;
event_init.button = determine_button(mouse_button);
return MouseEvent::create(event_name, event_init);
return MouseEvent::create(window_object, event_name, event_init);
}
void MouseEvent::set_event_characteristics()

View file

@ -22,17 +22,17 @@ struct MouseEventInit : public EventModifierInit {
};
class MouseEvent final : public UIEvent {
JS_OBJECT(MouseEvent, UIEvent);
public:
using WrapperType = Bindings::MouseEventWrapper;
static MouseEvent* create(Bindings::WindowObject&, FlyString const& event_name, MouseEventInit const& event_init = {});
static MouseEvent* create_from_platform_event(Bindings::WindowObject&, FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button = 1);
static NonnullRefPtr<MouseEvent> create(FlyString const& event_name, MouseEventInit const& event_init = {})
{
return adopt_ref(*new MouseEvent(event_name, event_init));
}
MouseEvent(Bindings::WindowObject&, FlyString const& event_name, MouseEventInit const& event_init);
static NonnullRefPtr<MouseEvent> create_from_platform_event(FlyString const& event_name, double offset_x, double offset_y, double client_x, double client_y, unsigned mouse_button = 1);
virtual ~MouseEvent() override;
virtual ~MouseEvent() override = default;
MouseEvent& impl() { return *this; }
double offset_x() const { return m_offset_x; }
double offset_y() const { return m_offset_y; }
@ -48,8 +48,6 @@ public:
virtual u32 which() const override { return m_button + 1; }
private:
MouseEvent(FlyString const& event_name, MouseEventInit const& event_init);
void set_event_characteristics();
double m_offset_x { 0 };
@ -60,3 +58,8 @@ private:
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::UIEvents::MouseEvent& object) { return &object; }
using MouseEventWrapper = Web::UIEvents::MouseEvent;
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/UIEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/UIEvents/UIEvent.h>
namespace Web::UIEvents {
UIEvent* UIEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name)
{
return window_object.heap().allocate<UIEvent>(window_object.realm(), window_object, event_name);
}
UIEvent* UIEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, UIEventInit const& event_init)
{
return window_object.heap().allocate<UIEvent>(window_object.realm(), window_object, event_name, event_init);
}
UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_name)
: Event(window_object, event_name)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::UIEventPrototype>("UIEvent"));
}
UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_name, UIEventInit const& event_init)
: Event(window_object, event_name, event_init)
, m_view(event_init.view)
, m_detail(event_init.detail)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::UIEventPrototype>("UIEvent"));
}
UIEvent::~UIEvent() = default;
}

View file

@ -18,20 +18,18 @@ struct UIEventInit : public DOM::EventInit {
};
class UIEvent : public DOM::Event {
JS_OBJECT(UIEvent, DOM::Event);
public:
using WrapperType = Bindings::UIEventWrapper;
static UIEvent* create(Bindings::WindowObject&, FlyString const& type);
static UIEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init);
static NonnullRefPtr<UIEvent> create(FlyString const& type)
{
return adopt_ref(*new UIEvent(type));
}
UIEvent(Bindings::WindowObject&, FlyString const& event_name);
UIEvent(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init);
static NonnullRefPtr<UIEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init)
{
return adopt_ref(*new UIEvent(event_name, event_init));
}
virtual ~UIEvent() override;
virtual ~UIEvent() override = default;
UIEvent& impl() { return *this; }
HTML::Window const* view() const { return m_view; }
int detail() const { return m_detail; }
@ -45,19 +43,13 @@ public:
}
protected:
explicit UIEvent(FlyString const& event_name)
: Event(event_name)
{
}
UIEvent(FlyString const& event_name, UIEventInit const& event_init)
: Event(event_name, event_init)
, m_view(event_init.view)
, m_detail(event_init.detail)
{
}
RefPtr<HTML::Window> m_view;
int m_detail { 0 };
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::UIEvents::UIEvent& object) { return &object; }
using UIEventWrapper = Web::UIEvents::UIEvent;
}

View file

@ -1,5 +1,6 @@
#import <DOM/Event.idl>
[NoInstanceWrapper]
interface UIEvent : Event {
constructor(DOMString type, optional UIEventInit eventInitDict = {});
readonly attribute Window? view;

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/WebGLContextEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/WebGL/WebGLContextEvent.h>
namespace Web::WebGL {
WebGLContextEvent* WebGLContextEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init)
{
return window_object.heap().allocate<WebGLContextEvent>(window_object.realm(), window_object, event_name, event_init);
}
WebGLContextEvent* WebGLContextEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
WebGLContextEvent::WebGLContextEvent(Bindings::WindowObject& window_object, FlyString const& type, WebGLContextEventInit const& event_init)
: DOM::Event(window_object, type, event_init)
, m_status_message(event_init.status_message)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::WebGLContextEventPrototype>("WebGLContextEvent"));
}
WebGLContextEvent::~WebGLContextEvent() = default;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -15,31 +16,27 @@ struct WebGLContextEventInit final : public DOM::EventInit {
};
class WebGLContextEvent final : public DOM::Event {
JS_OBJECT(WebGLContextEvent, DOM::Event);
public:
using WrapperType = Bindings::WebGLContextEventWrapper;
static WebGLContextEvent* create(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init);
static WebGLContextEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init);
static NonnullRefPtr<WebGLContextEvent> create(FlyString const& type, WebGLContextEventInit const& event_init)
{
return adopt_ref(*new WebGLContextEvent(type, event_init));
}
WebGLContextEvent(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init);
static NonnullRefPtr<WebGLContextEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init)
{
return adopt_ref(*new WebGLContextEvent(type, event_init));
}
virtual ~WebGLContextEvent() override;
virtual ~WebGLContextEvent() override = default;
WebGLContextEvent& impl() { return *this; }
String const& status_message() const { return m_status_message; }
private:
WebGLContextEvent(FlyString const& type, WebGLContextEventInit const& event_init)
: DOM::Event(type, event_init)
, m_status_message(event_init.status_message)
{
}
String m_status_message { String::empty() };
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::WebGL::WebGLContextEvent& object) { return &object; }
using WebGLContextEventWrapper = Web::WebGL::WebGLContextEvent;
}

View file

@ -5,6 +5,7 @@
*/
#include <LibWeb/Bindings/Wrapper.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/HTMLCanvasElement.h>
#include <LibWeb/WebGL/WebGLContextEvent.h>
#include <LibWeb/WebGL/WebGLRenderingContext.h>
@ -16,10 +17,10 @@ static void fire_webgl_context_event(HTML::HTMLCanvasElement& canvas_element, Fl
{
// To fire a WebGL context event named e means that an event using the WebGLContextEvent interface, with its type attribute [DOM4] initialized to e, its cancelable attribute initialized to true, and its isTrusted attribute [DOM4] initialized to true, is to be dispatched at the given object.
// FIXME: Consider setting a status message.
auto event = WebGLContextEvent::create(type, WebGLContextEventInit {});
auto event = WebGLContextEvent::create(canvas_element.document().preferred_window_object(), type, WebGLContextEventInit {});
event->set_is_trusted(true);
event->set_cancelable(true);
canvas_element.dispatch_event(move(event));
canvas_element.dispatch_event(*event);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-creation-error

View file

@ -8,7 +8,6 @@
#include <LibJS/Parser.h>
#include <LibJS/Runtime/ArrayBuffer.h>
#include <LibJS/Runtime/FunctionObject.h>
#include <LibWeb/Bindings/EventWrapper.h>
#include <LibWeb/Bindings/WebSocketWrapper.h>
#include <LibWeb/DOM/DOMException.h>
#include <LibWeb/DOM/Document.h>
@ -173,13 +172,13 @@ void WebSocket::on_open()
// 1. Change the readyState attribute's value to OPEN (1).
// 2. Change the extensions attribute's value to the extensions in use, if it is not the null value. [WSP]
// 3. Change the protocol attribute's value to the subprotocol in use, if it is not the null value. [WSP]
dispatch_event(DOM::Event::create(HTML::EventNames::open));
dispatch_event(*DOM::Event::create(*m_window->wrapper(), HTML::EventNames::open));
}
// https://websockets.spec.whatwg.org/#feedback-from-the-protocol
void WebSocket::on_error()
{
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(*m_window->wrapper(), HTML::EventNames::error));
}
// https://websockets.spec.whatwg.org/#feedback-from-the-protocol
@ -191,7 +190,7 @@ void WebSocket::on_close(u16 code, String reason, bool was_clean)
event_init.was_clean = was_clean;
event_init.code = code;
event_init.reason = move(reason);
dispatch_event(HTML::CloseEvent::create(HTML::EventNames::close, event_init));
dispatch_event(*HTML::CloseEvent::create(*m_window->wrapper(), HTML::EventNames::close, event_init));
}
// https://websockets.spec.whatwg.org/#feedback-from-the-protocol
@ -204,7 +203,7 @@ void WebSocket::on_message(ByteBuffer message, bool is_text)
HTML::MessageEventInit event_init;
event_init.data = JS::js_string(wrapper()->vm(), text_message);
event_init.origin = url();
dispatch_event(HTML::MessageEvent::create(HTML::EventNames::message, event_init));
dispatch_event(*HTML::MessageEvent::create(*m_window->wrapper(), HTML::EventNames::message, event_init));
return;
}
@ -218,7 +217,7 @@ void WebSocket::on_message(ByteBuffer message, bool is_text)
HTML::MessageEventInit event_init;
event_init.data = JS::ArrayBuffer::create(realm, message);
event_init.origin = url();
dispatch_event(HTML::MessageEvent::create(HTML::EventNames::message, event_init));
dispatch_event(*HTML::MessageEvent::create(*m_window->wrapper(), HTML::EventNames::message, event_init));
return;
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/ProgressEventPrototype.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/XHR/ProgressEvent.h>
namespace Web::XHR {
ProgressEvent* ProgressEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init)
{
return window_object.heap().allocate<ProgressEvent>(window_object.realm(), window_object, event_name, event_init);
}
ProgressEvent* ProgressEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init)
{
return create(window_object, event_name, event_init);
}
ProgressEvent::ProgressEvent(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init)
: Event(window_object, event_name, event_init)
, m_length_computable(event_init.length_computable)
, m_loaded(event_init.loaded)
, m_total(event_init.total)
{
set_prototype(&window_object.ensure_web_prototype<Bindings::ProgressEventPrototype>("ProgressEvent"));
}
ProgressEvent::~ProgressEvent() = default;
}

View file

@ -19,37 +19,32 @@ struct ProgressEventInit : public DOM::EventInit {
u32 total { 0 };
};
class ProgressEvent : public DOM::Event {
class ProgressEvent final : public DOM::Event {
JS_OBJECT(ProgressEvent, DOM::Event);
public:
using WrapperType = Bindings::ProgressEventWrapper;
static ProgressEvent* create(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
static ProgressEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
static NonnullRefPtr<ProgressEvent> create(FlyString const& event_name, ProgressEventInit const& event_init)
{
return adopt_ref(*new ProgressEvent(event_name, event_init));
}
static NonnullRefPtr<ProgressEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init)
{
return ProgressEvent::create(event_name, event_init);
}
ProgressEvent(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
virtual ~ProgressEvent() override = default;
virtual ~ProgressEvent() override;
ProgressEvent& impl() { return *this; }
bool length_computable() const { return m_length_computable; }
u64 loaded() const { return m_loaded; }
u64 total() const { return m_total; }
protected:
ProgressEvent(FlyString const& event_name, ProgressEventInit const& event_init)
: Event(event_name, event_init)
, m_length_computable(event_init.length_computable)
, m_loaded(event_init.loaded)
, m_total(event_init.total)
{
}
private:
bool m_length_computable { false };
u64 m_loaded { 0 };
u64 m_total { 0 };
};
}
namespace Web::Bindings {
inline JS::Object* wrap(JS::Realm&, Web::XHR::ProgressEvent& object) { return &object; }
using ProgressEventWrapper = Web::XHR::ProgressEvent;
}

View file

@ -1,5 +1,6 @@
#import <DOM/Event.idl>
[NoInstanceWrapper]
interface ProgressEvent : Event {
constructor(DOMString type, optional ProgressEventInit eventInitDict = {});

View file

@ -16,7 +16,6 @@
#include <LibJS/Runtime/FunctionObject.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibTextCodec/Decoder.h>
#include <LibWeb/Bindings/EventWrapper.h>
#include <LibWeb/Bindings/IDLAbstractOperations.h>
#include <LibWeb/Bindings/XMLHttpRequestWrapper.h>
#include <LibWeb/DOM/DOMException.h>
@ -53,7 +52,7 @@ XMLHttpRequest::~XMLHttpRequest() = default;
void XMLHttpRequest::set_ready_state(ReadyState ready_state)
{
m_ready_state = ready_state;
dispatch_event(DOM::Event::create(EventNames::readystatechange));
dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), EventNames::readystatechange));
}
void XMLHttpRequest::fire_progress_event(String const& event_name, u64 transmitted, u64 length)
@ -62,7 +61,7 @@ void XMLHttpRequest::fire_progress_event(String const& event_name, u64 transmitt
event_init.length_computable = true;
event_init.loaded = transmitted;
event_init.total = length;
dispatch_event(ProgressEvent::create(event_name, event_init));
dispatch_event(*ProgressEvent::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), event_name, event_init));
}
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsetext
@ -469,7 +468,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod
if (should_enforce_same_origin_policy && !m_window->associated_document().origin().is_same_origin(request_url_origin)) {
dbgln("XHR failed to load: Same-Origin Policy violation: {} may not load {}", m_window->associated_document().url(), request_url);
set_ready_state(ReadyState::Done);
dispatch_event(DOM::Event::create(HTML::EventNames::error));
dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), HTML::EventNames::error));
return {};
}
@ -539,7 +538,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod
xhr.m_status = status_code.value_or(0);
xhr.m_response_headers = move(response_headers);
xhr.m_send = false;
xhr.dispatch_event(DOM::Event::create(EventNames::readystatechange));
xhr.dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(xhr.wrapper()->global_object()), EventNames::readystatechange));
xhr.fire_progress_event(EventNames::load, transmitted, length);
xhr.fire_progress_event(EventNames::loadend, transmitted, length);
},
@ -551,7 +550,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod
auto& xhr = const_cast<XMLHttpRequest&>(*strong_this);
xhr.set_ready_state(ReadyState::Done);
xhr.set_status(status_code.value_or(0));
xhr.dispatch_event(DOM::Event::create(HTML::EventNames::error));
xhr.dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(xhr.wrapper()->global_object()), HTML::EventNames::error));
},
m_timeout,
[weak_this = make_weak_ptr()] {
@ -559,7 +558,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod
if (!strong_this)
return;
auto& xhr = const_cast<XMLHttpRequest&>(*strong_this);
xhr.dispatch_event(DOM::Event::create(EventNames::timeout));
xhr.dispatch_event(*DOM::Event::create(verify_cast<Bindings::WindowObject>(xhr.wrapper()->global_object()), EventNames::timeout));
});
} else {
TODO();

View file

@ -175,9 +175,9 @@ void XMLDocumentBuilder::document_end()
// FIXME: Set the Document's load timing info's DOM content loaded event start time to the current high resolution time given the Document's relevant global object.
// Fire an event named DOMContentLoaded at the Document object, with its bubbles attribute initialized to true.
auto content_loaded_event = DOM::Event::create(HTML::EventNames::DOMContentLoaded);
auto content_loaded_event = DOM::Event::create(document->preferred_window_object(), HTML::EventNames::DOMContentLoaded);
content_loaded_event->set_bubbles(true);
document->dispatch_event(content_loaded_event);
document->dispatch_event(*content_loaded_event);
// FIXME: Set the Document's load timing info's DOM content loaded event end time to the current high resolution time given the Document's relevant global object.
@ -213,7 +213,7 @@ void XMLDocumentBuilder::document_end()
// Fire an event named load at window, with legacy target override flag set.
// FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event()
// We should reorganize this so that the flag appears explicitly here instead.
window->dispatch_event(DOM::Event::create(HTML::EventNames::load));
window->dispatch_event(*DOM::Event::create(document->preferred_window_object(), HTML::EventNames::load));
// FIXME: Invoke WebDriver BiDi load complete with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "complete", and url is the Document object's URL.

View file

@ -16,7 +16,7 @@ libweb_js_wrapper(CSS/CSSStyleSheet NO_INSTANCE)
libweb_js_wrapper(CSS/CSSSupportsRule NO_INSTANCE)
libweb_js_wrapper(CSS/MediaList NO_INSTANCE)
libweb_js_wrapper(CSS/MediaQueryList)
libweb_js_wrapper(CSS/MediaQueryListEvent)
libweb_js_wrapper(CSS/MediaQueryListEvent NO_INSTANCE)
libweb_js_wrapper(CSS/Screen)
libweb_js_wrapper(CSS/StyleSheet NO_INSTANCE)
libweb_js_wrapper(CSS/StyleSheetList NO_INSTANCE)
@ -27,7 +27,7 @@ libweb_js_wrapper(DOM/AbortSignal)
libweb_js_wrapper(DOM/CDATASection)
libweb_js_wrapper(DOM/CharacterData)
libweb_js_wrapper(DOM/Comment)
libweb_js_wrapper(DOM/CustomEvent)
libweb_js_wrapper(DOM/CustomEvent NO_INSTANCE)
libweb_js_wrapper(DOM/Document)
libweb_js_wrapper(DOM/DocumentFragment)
libweb_js_wrapper(DOM/DocumentType)
@ -35,7 +35,7 @@ libweb_js_wrapper(DOM/DOMException)
libweb_js_wrapper(DOM/DOMImplementation NO_INSTANCE)
libweb_js_wrapper(DOM/DOMTokenList NO_INSTANCE)
libweb_js_wrapper(DOM/Element)
libweb_js_wrapper(DOM/Event)
libweb_js_wrapper(DOM/Event NO_INSTANCE)
libweb_js_wrapper(DOM/EventTarget)
libweb_js_wrapper(DOM/HTMLCollection)
libweb_js_wrapper(DOM/MutationRecord)
@ -63,10 +63,10 @@ libweb_js_wrapper(Geometry/DOMRectList)
libweb_js_wrapper(Geometry/DOMRectReadOnly)
libweb_js_wrapper(HTML/CanvasGradient)
libweb_js_wrapper(HTML/CanvasRenderingContext2D)
libweb_js_wrapper(HTML/CloseEvent)
libweb_js_wrapper(HTML/CloseEvent NO_INSTANCE)
libweb_js_wrapper(HTML/DOMParser)
libweb_js_wrapper(HTML/DOMStringMap NO_INSTANCE)
libweb_js_wrapper(HTML/ErrorEvent)
libweb_js_wrapper(HTML/ErrorEvent NO_INSTANCE)
libweb_js_wrapper(HTML/History)
libweb_js_wrapper(HTML/HTMLAnchorElement)
libweb_js_wrapper(HTML/HTMLAreaElement)
@ -142,13 +142,13 @@ libweb_js_wrapper(HTML/HTMLUnknownElement)
libweb_js_wrapper(HTML/HTMLVideoElement)
libweb_js_wrapper(HTML/ImageData)
libweb_js_wrapper(HTML/MessageChannel)
libweb_js_wrapper(HTML/MessageEvent)
libweb_js_wrapper(HTML/MessageEvent NO_INSTANCE)
libweb_js_wrapper(HTML/MessagePort)
libweb_js_wrapper(HTML/PageTransitionEvent)
libweb_js_wrapper(HTML/PageTransitionEvent NO_INSTANCE)
libweb_js_wrapper(HTML/Path2D)
libweb_js_wrapper(HTML/PromiseRejectionEvent)
libweb_js_wrapper(HTML/PromiseRejectionEvent NO_INSTANCE)
libweb_js_wrapper(HTML/Storage)
libweb_js_wrapper(HTML/SubmitEvent)
libweb_js_wrapper(HTML/SubmitEvent NO_INSTANCE)
libweb_js_wrapper(HTML/TextMetrics)
libweb_js_wrapper(HTML/Worker)
libweb_js_wrapper(HTML/WorkerGlobalScope)
@ -176,15 +176,15 @@ libweb_js_wrapper(SVG/SVGRectElement)
libweb_js_wrapper(SVG/SVGSVGElement)
libweb_js_wrapper(SVG/SVGTextContentElement)
libweb_js_wrapper(Selection/Selection)
libweb_js_wrapper(UIEvents/FocusEvent)
libweb_js_wrapper(UIEvents/KeyboardEvent)
libweb_js_wrapper(UIEvents/MouseEvent)
libweb_js_wrapper(UIEvents/UIEvent)
libweb_js_wrapper(UIEvents/FocusEvent NO_INSTANCE)
libweb_js_wrapper(UIEvents/KeyboardEvent NO_INSTANCE)
libweb_js_wrapper(UIEvents/MouseEvent NO_INSTANCE)
libweb_js_wrapper(UIEvents/UIEvent NO_INSTANCE)
libweb_js_wrapper(URL/URL)
libweb_js_wrapper(URL/URLSearchParams ITERABLE)
libweb_js_wrapper(WebGL/WebGLContextEvent)
libweb_js_wrapper(WebGL/WebGLContextEvent NO_INSTANCE)
libweb_js_wrapper(WebGL/WebGLRenderingContext)
libweb_js_wrapper(WebSockets/WebSocket)
libweb_js_wrapper(XHR/ProgressEvent)
libweb_js_wrapper(XHR/ProgressEvent NO_INSTANCE)
libweb_js_wrapper(XHR/XMLHttpRequest)
libweb_js_wrapper(XHR/XMLHttpRequestEventTarget)