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.
This commit is contained in:
Luke Wilde 2021-09-27 16:10:56 +01:00 committed by Andreas Kling
parent b04fafee74
commit f7ac3545cc
8 changed files with 99 additions and 1 deletions

View file

@ -1,10 +1,12 @@
/*
* Copyright (c) 2020, 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/MessageEventWrapper.h>
@ -17,6 +19,8 @@ namespace Web::Bindings {
EventWrapper* wrap(JS::GlobalObject& global_object, DOM::Event& event)
{
if (is<DOM::CustomEvent>(event))
return static_cast<CustomEventWrapper*>(wrap_impl(global_object, static_cast<DOM::CustomEvent&>(event)));
if (is<HTML::CloseEvent>(event))
return static_cast<CloseEventWrapper*>(wrap_impl(global_object, static_cast<HTML::CloseEvent&>(event)));
if (is<HTML::MessageEvent>(event))

View file

@ -22,6 +22,8 @@
#include <LibWeb/Bindings/CloseEventPrototype.h>
#include <LibWeb/Bindings/CommentConstructor.h>
#include <LibWeb/Bindings/CommentPrototype.h>
#include <LibWeb/Bindings/CustomEventConstructor.h>
#include <LibWeb/Bindings/CustomEventPrototype.h>
#include <LibWeb/Bindings/DOMExceptionConstructor.h>
#include <LibWeb/Bindings/DOMExceptionPrototype.h>
#include <LibWeb/Bindings/DOMImplementationConstructor.h>
@ -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) \

View file

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

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/DOM/CustomEvent.h>
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 thiss dispatch flag is set, then return.
if (dispatched())
return;
// 2. Initialize this with type, bubbles, and cancelable.
initialize(type, bubbles, cancelable);
// 3. Set thiss detail attribute to detail.
m_detail = detail;
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/DOM/Event.h>
namespace Web::DOM {
// https://dom.spec.whatwg.org/#customevent
class CustomEvent : public Event {
public:
using WrapperType = Bindings::CustomEventWrapper;
static NonnullRefPtr<CustomEvent> 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() };
};
}

View file

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

View file

@ -18,6 +18,7 @@
#include <LibWeb/CSS/StyleComputer.h>
#include <LibWeb/Cookie/ParsedCookie.h>
#include <LibWeb/DOM/Comment.h>
#include <LibWeb/DOM/CustomEvent.h>
#include <LibWeb/DOM/DOMException.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/DocumentFragment.h>
@ -739,7 +740,7 @@ NonnullRefPtr<Event> 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") {

View file

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