diff options
author | Andreas Kling <kling@serenityos.org> | 2022-08-08 22:29:40 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-09-06 00:27:09 +0200 |
commit | 7c3db526b0b7a9f516499b00e901ec55c695c02e (patch) | |
tree | ce8243216d2b0446c35447db92d7991a1439e626 | |
parent | a4ddb0ef8746be22b07fce3cc67b9664a4bd01ef (diff) | |
download | serenity-7c3db526b0b7a9f516499b00e901ec55c695c02e.zip |
LibWeb: Make DOM::Event and all its subclasses GC-allocated
76 files changed, 893 insertions, 566 deletions
diff --git a/Documentation/Browser/AddNewIDLFile.md b/Documentation/Browser/AddNewIDLFile.md index 54f6e455bd..3147d361da 100644 --- a/Documentation/Browser/AddNewIDLFile.md +++ b/Documentation/Browser/AddNewIDLFile.md @@ -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. diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp index 96debf8136..3cb9904719 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp @@ -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; diff --git a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp deleted file mode 100644 index 6a3e33d0a1..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp +++ /dev/null @@ -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)); -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.h b/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.h deleted file mode 100644 index c57c13cdb5..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.h +++ /dev/null @@ -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&); - -} diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp index 69658f7312..03c8954b8a 100644 --- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp +++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp @@ -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; } diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp index b331cef7ec..c9b530b425 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -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> diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index da2e149af8..5c92b018a8 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -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 diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp new file mode 100644 index 0000000000..ed16e9d712 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h index b15089497b..e934b9fd50 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl index 7ea6ae1963..f1a2ed8319 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.idl @@ -1,5 +1,6 @@ #import <DOM/Event.idl> +[NoInstanceWrapper] interface MediaQueryListEvent : Event { constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp index 86f1404a70..dc28fb3d11 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp @@ -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) diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp index d2546166f5..1d5aefb56e 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp @@ -1,15 +1,44 @@ /* * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org> + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/Bindings/CustomEventPrototype.h> +#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/CustomEvent.h> namespace Web::DOM { +CustomEvent* CustomEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init) +{ + return window_object.heap().allocate<CustomEvent>(window_object.realm(), window_object, event_name, event_init); +} + +CustomEvent* CustomEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init) +{ + return create(window_object, event_name, event_init); +} + +CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name) + : Event(window_object, event_name) +{ + set_prototype(&window_object.ensure_web_prototype<Bindings::CustomEventPrototype>("CustomEvent")); +} + +CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init) + : Event(window_object, event_name, event_init) + , m_detail(event_init.detail) +{ + set_prototype(&window_object.ensure_web_prototype<Bindings::CustomEventPrototype>("CustomEvent")); +} + +CustomEvent::~CustomEvent() = default; + void CustomEvent::visit_edges(JS::Cell::Visitor& visitor) { + Base::visit_edges(visitor); visitor.visit(m_detail); } @@ -21,7 +50,7 @@ void CustomEvent::init_custom_event(String const& type, bool bubbles, bool cance return; // 2. Initialize this with type, bubbles, and cancelable. - initialize(type, bubbles, cancelable); + initialize_event(type, bubbles, cancelable); // 3. Set this’s detail attribute to detail. m_detail = detail; diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.h b/Userland/Libraries/LibWeb/DOM/CustomEvent.h index 6ecbd83950..5111b346be 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.h +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.h @@ -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); + + CustomEvent(Bindings::WindowObject&, FlyString const& event_name); + CustomEvent(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); - } + virtual ~CustomEvent() override; - virtual ~CustomEvent() override = default; + 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; +} diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.idl b/Userland/Libraries/LibWeb/DOM/CustomEvent.idl index 65bfc43ca7..1798e5088e 100644 --- a/Userland/Libraries/LibWeb/DOM/CustomEvent.idl +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.idl @@ -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 = {}); diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 95d189f44b..6f71447706 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -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); } } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 6222698bf3..f0b579ae66 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -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; } diff --git a/Userland/Libraries/LibWeb/DOM/Event.cpp b/Userland/Libraries/LibWeb/DOM/Event.cpp index 84203ad0c9..5ccba65e31 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.cpp +++ b/Userland/Libraries/LibWeb/DOM/Event.cpp @@ -1,17 +1,47 @@ /* * Copyright (c) 2020, the SerenityOS developers. * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org> + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ #include <AK/TypeCasts.h> +#include <LibWeb/Bindings/EventPrototype.h> +#include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/ShadowRoot.h> namespace Web::DOM { +JS::NonnullGCPtr<Event> Event::create(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init) +{ + return *window_object.heap().allocate<Event>(window_object.realm(), window_object, event_name, event_init); +} + +JS::NonnullGCPtr<Event> Event::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init) +{ + return create(window_object, event_name, event_init); +} + +Event::Event(Bindings::WindowObject& window_object, FlyString const& type) + : PlatformObject(window_object.ensure_web_prototype<Bindings::EventPrototype>("Event")) + , m_type(type) + , m_initialized(true) +{ +} + +Event::Event(Bindings::WindowObject& window_object, FlyString const& type, EventInit const& event_init) + : PlatformObject(window_object.ensure_web_prototype<Bindings::EventPrototype>("Event")) + , m_type(type) + , m_bubbles(event_init.bubbles) + , m_cancelable(event_init.cancelable) + , m_composed(event_init.composed) + , m_initialized(true) +{ +} + // https://dom.spec.whatwg.org/#concept-event-path-append void Event::append_to_path(EventTarget& invocation_target, RefPtr<EventTarget> shadow_adjusted_target, RefPtr<EventTarget> related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree) { @@ -46,7 +76,7 @@ void Event::set_cancelled_flag() } // https://dom.spec.whatwg.org/#concept-event-initialize -void Event::initialize(String const& type, bool bubbles, bool cancelable) +void Event::initialize_event(String const& type, bool bubbles, bool cancelable) { // 1. Set event’s initialized flag. m_initialized = true; @@ -80,7 +110,7 @@ void Event::init_event(String const& type, bool bubbles, bool cancelable) return; // 2. Initialize this with type, bubbles, and cancelable. - initialize(type, bubbles, cancelable); + initialize_event(type, bubbles, cancelable); } // https://dom.spec.whatwg.org/#dom-event-timestamp diff --git a/Userland/Libraries/LibWeb/DOM/Event.h b/Userland/Libraries/LibWeb/DOM/Event.h index 76d426c7c0..51e8533025 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.h +++ b/Userland/Libraries/LibWeb/DOM/Event.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/DOM/Event.idl b/Userland/Libraries/LibWeb/DOM/Event.idl index 7f34e239bd..1d60b287a5 100644 --- a/Userland/Libraries/LibWeb/DOM/Event.idl +++ b/Userland/Libraries/LibWeb/DOM/Event.idl @@ -1,5 +1,6 @@ #import <DOM/EventTarget.idl> +[NoInstanceWrapper] interface Event { constructor(DOMString type, optional EventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp index 6324301e7c..5112681d92 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp @@ -10,8 +10,6 @@ #include <LibJS/Runtime/FunctionObject.h> #include <LibWeb/Bindings/EventTargetWrapper.h> #include <LibWeb/Bindings/EventTargetWrapperFactory.h> -#include <LibWeb/Bindings/EventWrapper.h> -#include <LibWeb/Bindings/EventWrapperFactory.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> #include <LibWeb/Bindings/WindowObject.h> #include <LibWeb/DOM/AbortSignal.h> @@ -92,7 +90,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent auto& global = realm.global_object(); // 7. Let currentEvent be undefined. - RefPtr<Event> current_event; + Event* current_event = nullptr; // 8. If global is a Window object, then: if (is<Bindings::WindowObject>(global)) { @@ -207,10 +205,10 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha } // https://dom.spec.whatwg.org/#concept-event-dispatch -bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<Event> event, bool legacy_target_override) +bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event, bool legacy_target_override) { // 1. Set event’s dispatch flag. - event->set_dispatched(true); + event.set_dispatched(true); // 2. Let targetOverride be target, if legacy target override flag is not given, and target’s associated Document otherwise. [HTML] // NOTE: legacy target override flag is only used by HTML and only when target is a Window object. @@ -225,24 +223,24 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< RefPtr<EventTarget> activation_target; // 4. Let relatedTarget be the result of retargeting event’s relatedTarget against target. - RefPtr<EventTarget> related_target = retarget(event->related_target(), target); + RefPtr<EventTarget> related_target = retarget(event.related_target(), target); bool clear_targets = false; // 5. If target is not relatedTarget or target is event’s relatedTarget, then: - if (related_target != target || event->related_target() == target) { + if (related_target != target || event.related_target() == target) { // 1. Let touchTargets be a new list. Event::TouchTargetList touch_targets; // 2. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against target to touchTargets. - for (auto& touch_target : event->touch_target_list()) { + for (auto& touch_target : event.touch_target_list()) { touch_targets.append(retarget(touch_target, target)); } // 3. Append to an event path with event, target, targetOverride, relatedTarget, touchTargets, and false. - event->append_to_path(*target, target_override, related_target, touch_targets, false); + event.append_to_path(*target, target_override, related_target, touch_targets, false); // 4. Let isActivationEvent be true, if event is a MouseEvent object and event’s type attribute is "click"; otherwise false. - bool is_activation_event = is<UIEvents::MouseEvent>(*event) && event->type() == HTML::EventNames::click; + bool is_activation_event = is<UIEvents::MouseEvent>(event) && event.type() == HTML::EventNames::click; // 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target. if (is_activation_event && target->activation_behavior) @@ -265,13 +263,13 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< // FIXME: 2. If parent is a slottable and is assigned, then set slottable to parent. // 3. Let relatedTarget be the result of retargeting event’s relatedTarget against parent. - related_target = retarget(event->related_target(), parent); + related_target = retarget(event.related_target(), parent); // 4. Let touchTargets be a new list. touch_targets.clear(); // 5. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against parent to touchTargets. - for (auto& touch_target : event->touch_target_list()) { + for (auto& touch_target : event.touch_target_list()) { touch_targets.append(retarget(touch_target, parent)); } @@ -279,11 +277,11 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< if (is<HTML::Window>(parent) || (is<Node>(parent) && verify_cast<Node>(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*parent)))) { // 1. If isActivationEvent is true, event’s bubbles attribute is true, activationTarget is null, and parent has activation behavior, then set activationTarget to parent. - if (is_activation_event && event->bubbles() && !activation_target && parent->activation_behavior) + if (is_activation_event && event.bubbles() && !activation_target && parent->activation_behavior) activation_target = parent; // 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree. - event->append_to_path(*parent, nullptr, related_target, touch_targets, slot_in_closed_tree); + event.append_to_path(*parent, nullptr, related_target, touch_targets, slot_in_closed_tree); } // 7. Otherwise, if parent is relatedTarget, then set parent to null. @@ -299,7 +297,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< activation_target = target; // 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree. - event->append_to_path(*parent, target, related_target, touch_targets, slot_in_closed_tree); + event.append_to_path(*parent, target, related_target, touch_targets, slot_in_closed_tree); } // 9. If parent is non-null, then set parent to the result of invoking parent’s get the parent with event. @@ -312,7 +310,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< } // 10. Let clearTargetsStruct be the last struct in event’s path whose shadow-adjusted target is non-null. - auto clear_targets_struct = event->path().last_matching([](auto& entry) { + auto clear_targets_struct = event.path().last_matching([](auto& entry) { return !entry.shadow_adjusted_target.is_null(); }); @@ -349,32 +347,32 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< activation_target->legacy_pre_activation_behavior(); // 13. For each struct in event’s path, in reverse order: - for (auto& entry : event->path().in_reverse()) { + for (auto& entry : event.path().in_reverse()) { // 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET. if (entry.shadow_adjusted_target) - event->set_phase(Event::Phase::AtTarget); + event.set_phase(Event::Phase::AtTarget); // 2. Otherwise, set event’s eventPhase attribute to CAPTURING_PHASE. else - event->set_phase(Event::Phase::CapturingPhase); + event.set_phase(Event::Phase::CapturingPhase); // 3. Invoke with struct, event, "capturing", and legacyOutputDidListenersThrowFlag if given. invoke(entry, event, Event::Phase::CapturingPhase); } // 14. For each struct in event’s path: - for (auto& entry : event->path()) { + for (auto& entry : event.path()) { // 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET. if (entry.shadow_adjusted_target) { - event->set_phase(Event::Phase::AtTarget); + event.set_phase(Event::Phase::AtTarget); } // 2. Otherwise: else { // 1. If event’s bubbles attribute is false, then continue. - if (!event->bubbles()) + if (!event.bubbles()) continue; // 2. Set event’s eventPhase attribute to BUBBLING_PHASE. - event->set_phase(Event::Phase::BubblingPhase); + event.set_phase(Event::Phase::BubblingPhase); } // 3. Invoke with struct, event, "bubbling", and legacyOutputDidListenersThrowFlag if given. @@ -383,35 +381,35 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< } // 6. Set event’s eventPhase attribute to NONE. - event->set_phase(Event::Phase::None); + event.set_phase(Event::Phase::None); // 7. Set event’s currentTarget attribute to null. - event->set_current_target(nullptr); + event.set_current_target(nullptr); // 8. Set event’s path to the empty list. - event->clear_path(); + event.clear_path(); // 9. Unset event’s dispatch flag, stop propagation flag, and stop immediate propagation flag. - event->set_dispatched(false); - event->set_stop_propagation(false); - event->set_stop_immediate_propagation(false); + event.set_dispatched(false); + event.set_stop_propagation(false); + event.set_stop_immediate_propagation(false); // 10. If clearTargets, then: if (clear_targets) { // 1. Set event’s target to null. - event->set_target(nullptr); + event.set_target(nullptr); // 2. Set event’s relatedTarget to null. - event->set_related_target(nullptr); + event.set_related_target(nullptr); // 3. Set event’s touch target list to the empty list. - event->clear_touch_target_list(); + event.clear_touch_target_list(); } // 11. If activationTarget is non-null, then: if (activation_target) { // 1. If event’s canceled flag is unset, then run activationTarget’s activation behavior with event. - if (!event->cancelled()) { + if (!event.cancelled()) { activation_target->activation_behavior(event); activation_target->legacy_cancelled_activation_behavior_was_not_called(); } @@ -422,7 +420,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr< } // 12. Return false if event’s canceled flag is set; otherwise true. - return !event->cancelled(); + return !event.cancelled(); } } diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.h b/Userland/Libraries/LibWeb/DOM/EventDispatcher.h index 13ac65efb4..0943192787 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.h +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.h @@ -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); diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp index 3fa4f53160..c20e87f79f 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -15,8 +15,6 @@ #include <LibJS/Runtime/VM.h> #include <LibWeb/Bindings/DocumentWrapper.h> #include <LibWeb/Bindings/EventTargetWrapperFactory.h> -#include <LibWeb/Bindings/EventWrapper.h> -#include <LibWeb/Bindings/EventWrapperFactory.h> #include <LibWeb/Bindings/IDLAbstractOperations.h> #include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/DOM/AbortSignal.h> @@ -204,17 +202,17 @@ void EventTarget::remove_from_event_listener_list(DOMEventListener& listener) } // https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent -ExceptionOr<bool> EventTarget::dispatch_event_binding(NonnullRefPtr<Event> event) +ExceptionOr<bool> EventTarget::dispatch_event_binding(Event& event) { // 1. If event’s dispatch flag is set, or if its initialized flag is not set, then throw an "InvalidStateError" DOMException. - if (event->dispatched()) + if (event.dispatched()) return DOM::InvalidStateError::create("The event is already being dispatched."); - if (!event->initialized()) + if (!event.initialized()) return DOM::InvalidStateError::create("Cannot dispatch an uninitialized event."); // 2. Initialize event’s isTrusted attribute to false. - event->set_is_trusted(false); + event.set_is_trusted(false); // 3. Return the result of dispatching event to this. return dispatch_event(event); @@ -736,9 +734,9 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local event_target->activate_event_handler(local_name, *event_handler); } -bool EventTarget::dispatch_event(NonnullRefPtr<Event> event) +bool EventTarget::dispatch_event(Event& event) { - return EventDispatcher::dispatch(*this, move(event)); + return EventDispatcher::dispatch(*this, event); } } diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index 81fa073610..9d94fb9129 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -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; diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index a4b3235325..b3825ccee8 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -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> diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index b9d6356790..60f6d5002e 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -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; diff --git a/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp b/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp new file mode 100644 index 0000000000..6a1a0f9c6e --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/CloseEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/HTML/CloseEvent.h b/Userland/Libraries/LibWeb/HTML/CloseEvent.h index cff27b926c..db3f1ba2b1 100644 --- a/Userland/Libraries/LibWeb/HTML/CloseEvent.h +++ b/Userland/Libraries/LibWeb/HTML/CloseEvent.h @@ -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); + + CloseEvent(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); - } + virtual ~CloseEvent() override; - virtual ~CloseEvent() override = default; + 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; +} diff --git a/Userland/Libraries/LibWeb/HTML/CloseEvent.idl b/Userland/Libraries/LibWeb/HTML/CloseEvent.idl index 7abf0cb6a4..32b05d7598 100644 --- a/Userland/Libraries/LibWeb/HTML/CloseEvent.idl +++ b/Userland/Libraries/LibWeb/HTML/CloseEvent.idl @@ -1,5 +1,6 @@ #import <DOM/Event.idl> +[NoInstanceWrapper] interface CloseEvent : Event { constructor(DOMString type, optional CloseEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp b/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp new file mode 100644 index 0000000000..111f96a13d --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp @@ -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); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/ErrorEvent.h b/Userland/Libraries/LibWeb/HTML/ErrorEvent.h index 3dd9eae119..83b137f497 100644 --- a/Userland/Libraries/LibWeb/HTML/ErrorEvent.h +++ b/Userland/Libraries/LibWeb/HTML/ErrorEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index 36fd97e8c6..592f354d46 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp index b678522bd2..6f1b96b9ea 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -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; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp index dd4cfa9b21..83b6fb3c45 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLIFrameElement.cpp @@ -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. } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 35a83b0c87..6a2ecb60f4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -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)); }); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 766f45d40c..66557d5cae 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -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); }); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index 14f5fcdb46..baea923426 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -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)); }); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp index 79018bbd64..fee2ba9df5 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp @@ -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; } diff --git a/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp b/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp new file mode 100644 index 0000000000..8fa050904d --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/MessageEvent.cpp @@ -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); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/MessageEvent.h b/Userland/Libraries/LibWeb/HTML/MessageEvent.h index 334bfb41aa..5671f8bd01 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageEvent.h +++ b/Userland/Libraries/LibWeb/HTML/MessageEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/HTML/MessageEvent.idl b/Userland/Libraries/LibWeb/HTML/MessageEvent.idl index 7f5970ddf3..09da043a0d 100644 --- a/Userland/Libraries/LibWeb/HTML/MessageEvent.idl +++ b/Userland/Libraries/LibWeb/HTML/MessageEvent.idl @@ -1,5 +1,6 @@ #import <DOM/Event.idl> +[NoInstanceWrapper] interface MessageEvent : Event { constructor(DOMString type, optional MessageEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp index 52e527ec0f..b6938d6909 100644 --- a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp @@ -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)); })); } diff --git a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp new file mode 100644 index 0000000000..95d1e6a922 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h index a2477524f0..febd7ccb2b 100644 --- a/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h +++ b/Userland/Libraries/LibWeb/HTML/PageTransitionEvent.h @@ -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; - bool persisted() const { return m_persisted; } + PageTransitionEvent& impl() { return *this; } -protected: - PageTransitionEvent(FlyString const& event_name, PageTransitionEventInit const& event_init) - : DOM::Event(event_name, event_init) - , m_persisted(event_init.persisted) - { - } + bool persisted() const { return m_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; +} diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index 0a131cc9f7..ee78f35d5d 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -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. diff --git a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp new file mode 100644 index 0000000000..13b6099763 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp @@ -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); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h index ecf676f2de..1571127881 100644 --- a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h +++ b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.h @@ -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); + + PromiseRejectionEvent(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); - } + virtual ~PromiseRejectionEvent() override; - virtual ~PromiseRejectionEvent() override = default; + 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(); } - -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)) - { - } - - JS::Handle<JS::Promise> m_promise; - JS::Handle<JS::Value> m_reason; + JS::Promise const* promise() const { return m_promise; } + JS::Value reason() const { return m_reason; } + +private: + virtual void visit_edges(Cell::Visitor&) override; + + 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; +} diff --git a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.idl b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.idl index 44438306a4..d6e8570064 100644 --- a/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.idl +++ b/Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.idl @@ -1,6 +1,6 @@ #import <DOM/Event.idl> -[Exposed=(Window,Worker)] +[Exposed=(Window,Worker), NoInstanceWrapper] interface PromiseRejectionEvent : Event { constructor(DOMString type, PromiseRejectionEventInit eventInitDict); diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp index c407c3d8d2..150746aff1 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp @@ -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. diff --git a/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp b/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp new file mode 100644 index 0000000000..c7dce0f599 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/HTML/SubmitEvent.h b/Userland/Libraries/LibWeb/HTML/SubmitEvent.h index 54922b9a65..e3fdd37662 100644 --- a/Userland/Libraries/LibWeb/HTML/SubmitEvent.h +++ b/Userland/Libraries/LibWeb/HTML/SubmitEvent.h @@ -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); + + virtual ~SubmitEvent() override; - 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); - } + SubmitEvent(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init); - virtual ~SubmitEvent() override = default; + 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; }; diff --git a/Userland/Libraries/LibWeb/HTML/SubmitEvent.idl b/Userland/Libraries/LibWeb/HTML/SubmitEvent.idl index cf04698fc4..5e88dfcdbf 100644 --- a/Userland/Libraries/LibWeb/HTML/SubmitEvent.idl +++ b/Userland/Libraries/LibWeb/HTML/SubmitEvent.idl @@ -1,6 +1,7 @@ #import <DOM/Event.idl> #import <HTML/HTMLElement.idl> +[NoInstanceWrapper] interface SubmitEvent : Event { constructor(DOMString type, optional SubmitEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 0e2d5c5fc5..7c8227bf71 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -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); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index e3d8c467e7..a939846156 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -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; diff --git a/Userland/Libraries/LibWeb/HTML/Worker.cpp b/Userland/Libraries/LibWeb/HTML/Worker.cpp index 0dc8b821be..438ec11308 100644 --- a/Userland/Libraries/LibWeb/HTML/Worker.cpp +++ b/Userland/Libraries/LibWeb/HTML/Worker.cpp @@ -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(); diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 83854a6550..7e0864b451 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -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) diff --git a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp index 4a25d9f79b..f052059b8a 100644 --- a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.cpp @@ -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())); } diff --git a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h index 4a244dbede..544748dea6 100644 --- a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.h @@ -15,18 +15,20 @@ struct FocusEventInit : public UIEventInit { }; class FocusEvent final : public UIEvent { + JS_OBJECT(FocusEvent, UIEvent); + public: - using WrapperType = Bindings::FocusEventWrapper; + 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; +} diff --git a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.idl b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.idl index 1cba0af8fd..c46c9dd480 100644 --- a/Userland/Libraries/LibWeb/UIEvents/FocusEvent.idl +++ b/Userland/Libraries/LibWeb/UIEvents/FocusEvent.idl @@ -1,6 +1,6 @@ #import <UIEvents/UIEvent.idl> -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface FocusEvent : UIEvent { constructor(DOMString type, optional FocusEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp index ab5d29d35f..6f41ef8207 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.cpp @@ -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; + } diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h index 0901fb44b9..c5e618585e 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.idl b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.idl index e6685ca795..d7958f0019 100644 --- a/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.idl +++ b/Userland/Libraries/LibWeb/UIEvents/KeyboardEvent.idl @@ -1,6 +1,6 @@ #import <UIEvents/EventModifier.idl> -[Exposed=Window] +[Exposed=Window, NoInstanceWrapper] interface KeyboardEvent : UIEvent { constructor(DOMString type, optional KeyboardEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp index 89c4c5225f..4528497823 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.cpp @@ -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() diff --git a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h index bfacfcd106..01b6778be5 100644 --- a/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/MouseEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp b/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp new file mode 100644 index 0000000000..d7762b25bc --- /dev/null +++ b/Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/UIEvents/UIEvent.h b/Userland/Libraries/LibWeb/UIEvents/UIEvent.h index 9be4446a61..dd044d233a 100644 --- a/Userland/Libraries/LibWeb/UIEvents/UIEvent.h +++ b/Userland/Libraries/LibWeb/UIEvents/UIEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/UIEvents/UIEvent.idl b/Userland/Libraries/LibWeb/UIEvents/UIEvent.idl index 36e4a8885a..f22203d038 100644 --- a/Userland/Libraries/LibWeb/UIEvents/UIEvent.idl +++ b/Userland/Libraries/LibWeb/UIEvents/UIEvent.idl @@ -1,5 +1,6 @@ #import <DOM/Event.idl> +[NoInstanceWrapper] interface UIEvent : Event { constructor(DOMString type, optional UIEventInit eventInitDict = {}); readonly attribute Window? view; diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp new file mode 100644 index 0000000000..f90a738d52 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h index a574da2b90..9404cc93f8 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h +++ b/Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.h @@ -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; +} diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp index e20aafb18b..85fb40bfd4 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp +++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp index 07be6b1499..211d82aae2 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp @@ -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; } diff --git a/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp b/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp new file mode 100644 index 0000000000..975c69aff7 --- /dev/null +++ b/Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp @@ -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; + +} diff --git a/Userland/Libraries/LibWeb/XHR/ProgressEvent.h b/Userland/Libraries/LibWeb/XHR/ProgressEvent.h index e7ed17eb69..1c284f01c0 100644 --- a/Userland/Libraries/LibWeb/XHR/ProgressEvent.h +++ b/Userland/Libraries/LibWeb/XHR/ProgressEvent.h @@ -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); + + ProgressEvent(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); - } + virtual ~ProgressEvent() override; - virtual ~ProgressEvent() override = default; + 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; +} diff --git a/Userland/Libraries/LibWeb/XHR/ProgressEvent.idl b/Userland/Libraries/LibWeb/XHR/ProgressEvent.idl index b8d8515be9..8acde91623 100644 --- a/Userland/Libraries/LibWeb/XHR/ProgressEvent.idl +++ b/Userland/Libraries/LibWeb/XHR/ProgressEvent.idl @@ -1,5 +1,6 @@ #import <DOM/Event.idl> +[NoInstanceWrapper] interface ProgressEvent : Event { constructor(DOMString type, optional ProgressEventInit eventInitDict = {}); diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index a1d1868a35..d17665b99a 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -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(); diff --git a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp index 7f594c2719..6f92886970 100644 --- a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp +++ b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp @@ -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. diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 42bc5a9ca9..6e4691c772 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -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) |