From f7ac3545ccfae9e84b2ffb2b1b6f5cfd886a307e Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Mon, 27 Sep 2021 16:10:56 +0100 Subject: [PATCH] LibWeb: Add initial support for CustomEvent This is used surprisingly often. For example, it is used by a core YouTube library called Structured Page Fragments. It allows you to manually dispatch an event with arbitrary data attached to it. The only thing missing from this implementation is the constructor. This is because WrapperGenerator is currently missing dictionary capabilities. --- .../LibWeb/Bindings/EventWrapperFactory.cpp | 4 ++ .../LibWeb/Bindings/WindowObjectHelper.h | 3 ++ Userland/Libraries/LibWeb/CMakeLists.txt | 2 + Userland/Libraries/LibWeb/DOM/CustomEvent.cpp | 39 +++++++++++++++++++ Userland/Libraries/LibWeb/DOM/CustomEvent.h | 39 +++++++++++++++++++ Userland/Libraries/LibWeb/DOM/CustomEvent.idl | 8 ++++ Userland/Libraries/LibWeb/DOM/Document.cpp | 3 +- Userland/Libraries/LibWeb/Forward.h | 2 + 8 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 Userland/Libraries/LibWeb/DOM/CustomEvent.cpp create mode 100644 Userland/Libraries/LibWeb/DOM/CustomEvent.h create mode 100644 Userland/Libraries/LibWeb/DOM/CustomEvent.idl diff --git a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp b/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp index 71176cf4f6..ccdb1204f3 100644 --- a/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp +++ b/Userland/Libraries/LibWeb/Bindings/EventWrapperFactory.cpp @@ -1,10 +1,12 @@ /* * Copyright (c) 2020, Andreas Kling + * Copyright (c) 2021, Luke Wilde * * SPDX-License-Identifier: BSD-2-Clause */ #include +#include #include #include #include @@ -17,6 +19,8 @@ namespace Web::Bindings { EventWrapper* wrap(JS::GlobalObject& global_object, DOM::Event& event) { + if (is(event)) + return static_cast(wrap_impl(global_object, static_cast(event))); if (is(event)) return static_cast(wrap_impl(global_object, static_cast(event))); if (is(event)) diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h index 303ebb0f92..fd79b55a68 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -265,6 +267,7 @@ ADD_WINDOW_OBJECT_INTERFACE(CharacterData) \ ADD_WINDOW_OBJECT_INTERFACE(CloseEvent) \ ADD_WINDOW_OBJECT_INTERFACE(Comment) \ + ADD_WINDOW_OBJECT_INTERFACE(CustomEvent) \ ADD_WINDOW_OBJECT_INTERFACE(CSSStyleSheet) \ ADD_WINDOW_OBJECT_INTERFACE(DocumentFragment) \ ADD_WINDOW_OBJECT_INTERFACE(Document) \ diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 7df24978b9..e7c89a9f2e 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -45,6 +45,7 @@ set(SOURCES DOM/CharacterData.cpp DOM/CharacterData.idl DOM/Comment.cpp + DOM/CustomEvent.cpp DOM/DOMImplementation.cpp DOM/Document.cpp DOM/DocumentFragment.cpp @@ -328,6 +329,7 @@ libweb_js_wrapper(DOM/AbortController) libweb_js_wrapper(DOM/AbortSignal) libweb_js_wrapper(DOM/CharacterData) libweb_js_wrapper(DOM/Comment) +libweb_js_wrapper(DOM/CustomEvent) libweb_js_wrapper(DOM/Document) libweb_js_wrapper(DOM/DocumentFragment) libweb_js_wrapper(DOM/DocumentType) diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp new file mode 100644 index 0000000000..17c414f910 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Web::DOM { + +CustomEvent::CustomEvent(FlyString const& event_name) + : Event(event_name) +{ +} + +CustomEvent::~CustomEvent() +{ +} + +void CustomEvent::visit_edges(JS::Cell::Visitor& visitor) +{ + visitor.visit(m_detail); +} + +// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent +void CustomEvent::init_custom_event(String const& type, bool bubbles, bool cancelable, JS::Value detail) +{ + // 1. If this’s dispatch flag is set, then return. + if (dispatched()) + return; + + // 2. Initialize this with type, bubbles, and cancelable. + initialize(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 new file mode 100644 index 0000000000..ad4efe0499 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::DOM { + +// https://dom.spec.whatwg.org/#customevent +class CustomEvent : public Event { +public: + using WrapperType = Bindings::CustomEventWrapper; + + static NonnullRefPtr create(FlyString const& event_name) + { + return adopt_ref(*new CustomEvent(event_name)); + } + + virtual ~CustomEvent() override; + + // https://dom.spec.whatwg.org/#dom-customevent-detail + JS::Value detail() const { return m_detail; } + + void visit_edges(JS::Cell::Visitor&); + + void init_custom_event(String const& type, bool bubbles, bool cancelable, JS::Value detail); + +private: + CustomEvent(FlyString const&); + + // https://dom.spec.whatwg.org/#dom-customevent-initcustomevent-type-bubbles-cancelable-detail-detail + JS::Value m_detail { JS::js_null() }; +}; + +} diff --git a/Userland/Libraries/LibWeb/DOM/CustomEvent.idl b/Userland/Libraries/LibWeb/DOM/CustomEvent.idl new file mode 100644 index 0000000000..53abba31ac --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/CustomEvent.idl @@ -0,0 +1,8 @@ +[Exposed=(Window,Worker), CustomVisit] +interface CustomEvent : Event { + // FIXME: constructor(DOMString type, optional CustomEventInit eventInitDict = {}); + + readonly attribute any detail; + + undefined initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null); +}; diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 875a36e0a4..f16a5bd203 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -739,7 +740,7 @@ NonnullRefPtr Document::create_event(const String& interface) } else if (interface_lowercase == "compositionevent") { event = Event::create(""); // FIXME: Create CompositionEvent } else if (interface_lowercase == "customevent") { - event = Event::create(""); // FIXME: Create CustomEvent + event = CustomEvent::create(""); } else if (interface_lowercase == "devicemotionevent") { event = Event::create(""); // FIXME: Create DeviceMotionEvent } else if (interface_lowercase == "deviceorientationevent") { diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 241a09e83d..70d9eb29fc 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -62,6 +62,7 @@ class AbortController; class AbortSignal; class CharacterData; class Comment; +class CustomEvent; class Document; class DocumentFragment; class DocumentLoadEventDelayer; @@ -261,6 +262,7 @@ class CanvasRenderingContext2DWrapper; class CharacterDataWrapper; class CloseEventWrapper; class CommentWrapper; +class CustomEventWrapper; class DocumentFragmentWrapper; class DocumentTypeWrapper; class DocumentWrapper;