mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 13:36:13 +03:00
LibWeb: Make DOM::Event and all its subclasses GC-allocated
This commit is contained in:
parent
a4ddb0ef87
commit
7c3db526b0
Notes:
sideshowbarker
2024-07-17 07:28:23 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/7c3db526b0 Pull-request: https://github.com/SerenityOS/serenity/pull/14816 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/linusg ✅
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
@ -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&);
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
33
Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp
Normal file
33
Userland/Libraries/LibWeb/CSS/MediaQueryListEvent.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/MediaQueryListEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/CSS/MediaQueryListEvent.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
MediaQueryListEvent* MediaQueryListEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<MediaQueryListEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
MediaQueryListEvent* MediaQueryListEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
MediaQueryListEvent::MediaQueryListEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MediaQueryListEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name, event_init)
|
||||
, m_media(event_init.media)
|
||||
, m_matches(event_init.matches)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::MediaQueryListEventPrototype>("MediaQueryListEvent"));
|
||||
}
|
||||
|
||||
MediaQueryListEvent::~MediaQueryListEvent() = default;
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface MediaQueryListEvent : Event {
|
||||
constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {});
|
||||
|
||||
|
@ -60,7 +60,7 @@ void AbortSignal::signal_abort(JS::Value reason)
|
||||
m_abort_algorithms.clear();
|
||||
|
||||
// 5. Fire an event named abort at signal.
|
||||
dispatch_event(Event::create(HTML::EventNames::abort));
|
||||
dispatch_event(*Event::create(verify_cast<Bindings::WindowObject>(wrapper()->global_object()), HTML::EventNames::abort));
|
||||
}
|
||||
|
||||
void AbortSignal::set_onabort(Bindings::CallbackType* event_handler)
|
||||
|
@ -1,15 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/CustomEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/CustomEvent.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
CustomEvent* CustomEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<CustomEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
CustomEvent* CustomEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name)
|
||||
: Event(window_object, event_name)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::CustomEventPrototype>("CustomEvent"));
|
||||
}
|
||||
|
||||
CustomEvent::CustomEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
: Event(window_object, event_name, event_init)
|
||||
, m_detail(event_init.detail)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::CustomEventPrototype>("CustomEvent"));
|
||||
}
|
||||
|
||||
CustomEvent::~CustomEvent() = default;
|
||||
|
||||
void CustomEvent::visit_edges(JS::Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_detail);
|
||||
}
|
||||
|
||||
@ -21,7 +50,7 @@ void CustomEvent::init_custom_event(String const& type, bool bubbles, bool cance
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize(type, bubbles, cancelable);
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
|
||||
// 3. Set this’s detail attribute to detail.
|
||||
m_detail = detail;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@ -16,41 +17,34 @@ struct CustomEventInit : public EventInit {
|
||||
|
||||
// https://dom.spec.whatwg.org/#customevent
|
||||
class CustomEvent : public Event {
|
||||
JS_OBJECT(CustomEvent, Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::CustomEventWrapper;
|
||||
static CustomEvent* create(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init = {});
|
||||
static CustomEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<CustomEvent> create(FlyString const& event_name, CustomEventInit const& event_init = {})
|
||||
{
|
||||
return adopt_ref(*new CustomEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<CustomEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init)
|
||||
{
|
||||
return CustomEvent::create(event_name, event_init);
|
||||
}
|
||||
CustomEvent(Bindings::WindowObject&, FlyString const& event_name);
|
||||
CustomEvent(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init);
|
||||
|
||||
virtual ~CustomEvent() override = default;
|
||||
virtual ~CustomEvent() override;
|
||||
|
||||
CustomEvent& impl() { return *this; }
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-customevent-detail
|
||||
JS::Value detail() const { return m_detail; }
|
||||
|
||||
void visit_edges(JS::Cell::Visitor&);
|
||||
virtual void visit_edges(JS::Cell::Visitor&) override;
|
||||
|
||||
void init_custom_event(String const& type, bool bubbles, bool cancelable, JS::Value detail);
|
||||
|
||||
private:
|
||||
explicit CustomEvent(FlyString const& event_name)
|
||||
: Event(event_name)
|
||||
{
|
||||
}
|
||||
|
||||
CustomEvent(FlyString const& event_name, CustomEventInit const& event_init)
|
||||
: Event(event_name, event_init)
|
||||
, m_detail(event_init.detail)
|
||||
{
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent-type-bubbles-cancelable-detail-detail
|
||||
JS::Value m_detail { JS::js_null() };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::CustomEvent& object) { return &object; }
|
||||
using CustomEventWrapper = Web::DOM::CustomEvent;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[Exposed=(Window,Worker), CustomVisit]
|
||||
[Exposed=(Window,Worker), NoInstanceWrapper]
|
||||
interface CustomEvent : Event {
|
||||
constructor(DOMString type, optional CustomEventInit eventInitDict = {});
|
||||
|
||||
|
@ -1160,51 +1160,53 @@ NonnullRefPtr<Range> Document::create_range()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-document-createevent
|
||||
DOM::ExceptionOr<NonnullRefPtr<Event>> Document::create_event(String const& interface)
|
||||
DOM::ExceptionOr<JS::NonnullGCPtr<Event>> Document::create_event(String const& interface)
|
||||
{
|
||||
auto& window_object = preferred_window_object();
|
||||
|
||||
// NOTE: This is named event here, since we do step 5 and 6 as soon as possible for each case.
|
||||
// 1. Let constructor be null.
|
||||
RefPtr<Event> event;
|
||||
JS::GCPtr<Event> event;
|
||||
|
||||
// 2. If interface is an ASCII case-insensitive match for any of the strings in the first column in the following table,
|
||||
// then set constructor to the interface in the second column on the same row as the matching string:
|
||||
auto interface_lowercase = interface.to_lowercase();
|
||||
if (interface_lowercase == "beforeunloadevent") {
|
||||
event = Event::create(""); // FIXME: Create BeforeUnloadEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create BeforeUnloadEvent
|
||||
} else if (interface_lowercase == "compositionevent") {
|
||||
event = Event::create(""); // FIXME: Create CompositionEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
|
||||
} else if (interface_lowercase == "customevent") {
|
||||
event = CustomEvent::create("");
|
||||
event = CustomEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "devicemotionevent") {
|
||||
event = Event::create(""); // FIXME: Create DeviceMotionEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create DeviceMotionEvent
|
||||
} else if (interface_lowercase == "deviceorientationevent") {
|
||||
event = Event::create(""); // FIXME: Create DeviceOrientationEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create DeviceOrientationEvent
|
||||
} else if (interface_lowercase == "dragevent") {
|
||||
event = Event::create(""); // FIXME: Create DragEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create DragEvent
|
||||
} else if (interface_lowercase.is_one_of("event", "events")) {
|
||||
event = Event::create("");
|
||||
event = Event::create(window_object, "");
|
||||
} else if (interface_lowercase == "focusevent") {
|
||||
event = UIEvents::FocusEvent::create("");
|
||||
event = UIEvents::FocusEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "hashchangeevent") {
|
||||
event = Event::create(""); // FIXME: Create HashChangeEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create HashChangeEvent
|
||||
} else if (interface_lowercase == "htmlevents") {
|
||||
event = Event::create("");
|
||||
event = Event::create(window_object, "");
|
||||
} else if (interface_lowercase == "keyboardevent") {
|
||||
event = UIEvents::KeyboardEvent::create("");
|
||||
event = UIEvents::KeyboardEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "messageevent") {
|
||||
event = HTML::MessageEvent::create("");
|
||||
event = HTML::MessageEvent::create(window_object, "");
|
||||
} else if (interface_lowercase.is_one_of("mouseevent", "mouseevents")) {
|
||||
event = UIEvents::MouseEvent::create("");
|
||||
event = UIEvents::MouseEvent::create(window_object, "");
|
||||
} else if (interface_lowercase == "storageevent") {
|
||||
event = Event::create(""); // FIXME: Create StorageEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create StorageEvent
|
||||
} else if (interface_lowercase == "svgevents") {
|
||||
event = Event::create("");
|
||||
event = Event::create(window_object, "");
|
||||
} else if (interface_lowercase == "textevent") {
|
||||
event = Event::create(""); // FIXME: Create CompositionEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
|
||||
} else if (interface_lowercase == "touchevent") {
|
||||
event = Event::create(""); // FIXME: Create TouchEvent
|
||||
event = Event::create(window_object, ""); // FIXME: Create TouchEvent
|
||||
} else if (interface_lowercase.is_one_of("uievent", "uievents")) {
|
||||
event = UIEvents::UIEvent::create("");
|
||||
event = UIEvents::UIEvent::create(window_object, "");
|
||||
}
|
||||
|
||||
// 3. If constructor is null, then throw a "NotSupportedError" DOMException.
|
||||
@ -1228,7 +1230,7 @@ DOM::ExceptionOr<NonnullRefPtr<Event>> Document::create_event(String const& inte
|
||||
event->set_initialized(false);
|
||||
|
||||
// 10. Return event.
|
||||
return event.release_nonnull();
|
||||
return JS::NonnullGCPtr(*event);
|
||||
}
|
||||
|
||||
void Document::set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement* script)
|
||||
@ -1408,7 +1410,7 @@ void Document::update_readiness(HTML::DocumentReadyState readiness_value)
|
||||
// FIXME: 3. Otherwise, if readinessValue is "interactive", and document's load timing info's DOM interactive time is 0, then set document's load timing info's DOM interactive time to now.
|
||||
|
||||
// 3. Fire an event named readystatechange at document.
|
||||
dispatch_event(Event::create(HTML::EventNames::readystatechange));
|
||||
dispatch_event(*Event::create(preferred_window_object(), HTML::EventNames::readystatechange));
|
||||
}
|
||||
|
||||
Page* Document::page()
|
||||
@ -1448,8 +1450,8 @@ void Document::completely_finish_loading()
|
||||
}
|
||||
// Otherwise, if container is non-null, then queue an element task on the DOM manipulation task source given container to fire an event named load at container.
|
||||
else if (container) {
|
||||
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container]() mutable {
|
||||
container->dispatch_event(DOM::Event::create(HTML::EventNames::load));
|
||||
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container, this]() mutable {
|
||||
container->dispatch_event(*DOM::Event::create(preferred_window_object(), HTML::EventNames::load));
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1560,7 +1562,7 @@ void Document::run_the_resize_steps()
|
||||
return;
|
||||
m_last_viewport_size = viewport_size;
|
||||
|
||||
window().dispatch_event(DOM::Event::create(UIEvents::EventNames::resize));
|
||||
window().dispatch_event(*DOM::Event::create(preferred_window_object(), UIEvents::EventNames::resize));
|
||||
|
||||
update_layout();
|
||||
}
|
||||
@ -1596,9 +1598,9 @@ void Document::evaluate_media_queries_and_report_changes()
|
||||
CSS::MediaQueryListEventInit init;
|
||||
init.media = media_query_list->media();
|
||||
init.matches = now_matches;
|
||||
auto event = CSS::MediaQueryListEvent::create(HTML::EventNames::change, init);
|
||||
auto event = CSS::MediaQueryListEvent::create(preferred_window_object(), HTML::EventNames::change, init);
|
||||
event->set_is_trusted(true);
|
||||
media_query_list->dispatch_event(event);
|
||||
media_query_list->dispatch_event(*event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@ public:
|
||||
NonnullRefPtr<Text> create_text_node(String const& data);
|
||||
NonnullRefPtr<Comment> create_comment(String const& data);
|
||||
NonnullRefPtr<Range> create_range();
|
||||
ExceptionOr<NonnullRefPtr<Event>> create_event(String const& interface);
|
||||
ExceptionOr<JS::NonnullGCPtr<Event>> create_event(String const& interface);
|
||||
|
||||
void set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement*);
|
||||
HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; }
|
||||
|
@ -1,17 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2020, the SerenityOS developers.
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWeb/Bindings/EventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/Event.h>
|
||||
#include <LibWeb/DOM/Node.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
|
||||
JS::NonnullGCPtr<Event> Event::create(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init)
|
||||
{
|
||||
return *window_object.heap().allocate<Event>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
JS::NonnullGCPtr<Event> Event::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, EventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
Event::Event(Bindings::WindowObject& window_object, FlyString const& type)
|
||||
: PlatformObject(window_object.ensure_web_prototype<Bindings::EventPrototype>("Event"))
|
||||
, m_type(type)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
|
||||
Event::Event(Bindings::WindowObject& window_object, FlyString const& type, EventInit const& event_init)
|
||||
: PlatformObject(window_object.ensure_web_prototype<Bindings::EventPrototype>("Event"))
|
||||
, m_type(type)
|
||||
, m_bubbles(event_init.bubbles)
|
||||
, m_cancelable(event_init.cancelable)
|
||||
, m_composed(event_init.composed)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-path-append
|
||||
void Event::append_to_path(EventTarget& invocation_target, RefPtr<EventTarget> shadow_adjusted_target, RefPtr<EventTarget> related_target, TouchTargetList& touch_targets, bool slot_in_closed_tree)
|
||||
{
|
||||
@ -46,7 +76,7 @@ void Event::set_cancelled_flag()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-initialize
|
||||
void Event::initialize(String const& type, bool bubbles, bool cancelable)
|
||||
void Event::initialize_event(String const& type, bool bubbles, bool cancelable)
|
||||
{
|
||||
// 1. Set event’s initialized flag.
|
||||
m_initialized = true;
|
||||
@ -80,7 +110,7 @@ void Event::init_event(String const& type, bool bubbles, bool cancelable)
|
||||
return;
|
||||
|
||||
// 2. Initialize this with type, bubbles, and cancelable.
|
||||
initialize(type, bubbles, cancelable);
|
||||
initialize_event(type, bubbles, cancelable);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-timestamp
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@ -7,8 +7,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <LibWeb/Bindings/PlatformObject.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/Bindings/Wrappable.h>
|
||||
#include <LibWeb/DOM/EventTarget.h>
|
||||
|
||||
namespace Web::DOM {
|
||||
@ -19,12 +19,10 @@ struct EventInit {
|
||||
bool composed { false };
|
||||
};
|
||||
|
||||
class Event
|
||||
: public RefCounted<Event>
|
||||
, public Bindings::Wrappable {
|
||||
public:
|
||||
using WrapperType = Bindings::EventWrapper;
|
||||
class Event : public Bindings::PlatformObject {
|
||||
JS_OBJECT(Event, Bindings::PlatformObject);
|
||||
|
||||
public:
|
||||
enum Phase : u16 {
|
||||
None = 0,
|
||||
CapturingPhase = 1,
|
||||
@ -47,17 +45,16 @@ public:
|
||||
|
||||
using Path = Vector<PathEntry>;
|
||||
|
||||
static NonnullRefPtr<Event> create(FlyString const& event_name, EventInit const& event_init = {})
|
||||
{
|
||||
return adopt_ref(*new Event(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<Event> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init)
|
||||
{
|
||||
return Event::create(event_name, event_init);
|
||||
}
|
||||
static JS::NonnullGCPtr<Event> create(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init = {});
|
||||
static JS::NonnullGCPtr<Event> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init);
|
||||
|
||||
Event(Bindings::WindowObject&, FlyString const& type);
|
||||
Event(Bindings::WindowObject&, FlyString const& type, EventInit const& event_init);
|
||||
|
||||
virtual ~Event() = default;
|
||||
|
||||
Event& impl() { return *this; }
|
||||
|
||||
double time_stamp() const;
|
||||
|
||||
FlyString const& type() const { return m_type; }
|
||||
@ -149,21 +146,7 @@ public:
|
||||
NonnullRefPtrVector<EventTarget> composed_path() const;
|
||||
|
||||
protected:
|
||||
explicit Event(FlyString const& type)
|
||||
: m_type(type)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
Event(FlyString const& type, EventInit const& event_init)
|
||||
: m_type(type)
|
||||
, m_bubbles(event_init.bubbles)
|
||||
, m_cancelable(event_init.cancelable)
|
||||
, m_composed(event_init.composed)
|
||||
, m_initialized(true)
|
||||
{
|
||||
}
|
||||
|
||||
void initialize(String const&, bool, bool);
|
||||
void initialize_event(String const&, bool, bool);
|
||||
|
||||
private:
|
||||
FlyString m_type;
|
||||
@ -195,3 +178,8 @@ private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::DOM::Event& object) { return &object; }
|
||||
using EventWrapper = Web::DOM::Event;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <DOM/EventTarget.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface Event {
|
||||
|
||||
constructor(DOMString type, optional EventInit eventInitDict = {});
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibWeb/Bindings/EventTargetWrapper.h>
|
||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/EventWrapper.h>
|
||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/AbortSignal.h>
|
||||
@ -92,7 +90,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEvent
|
||||
auto& global = realm.global_object();
|
||||
|
||||
// 7. Let currentEvent be undefined.
|
||||
RefPtr<Event> current_event;
|
||||
Event* current_event = nullptr;
|
||||
|
||||
// 8. If global is a Window object, then:
|
||||
if (is<Bindings::WindowObject>(global)) {
|
||||
@ -207,10 +205,10 @@ void EventDispatcher::invoke(Event::PathEntry& struct_, Event& event, Event::Pha
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-event-dispatch
|
||||
bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<Event> event, bool legacy_target_override)
|
||||
bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, Event& event, bool legacy_target_override)
|
||||
{
|
||||
// 1. Set event’s dispatch flag.
|
||||
event->set_dispatched(true);
|
||||
event.set_dispatched(true);
|
||||
|
||||
// 2. Let targetOverride be target, if legacy target override flag is not given, and target’s associated Document otherwise. [HTML]
|
||||
// NOTE: legacy target override flag is only used by HTML and only when target is a Window object.
|
||||
@ -225,24 +223,24 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
RefPtr<EventTarget> activation_target;
|
||||
|
||||
// 4. Let relatedTarget be the result of retargeting event’s relatedTarget against target.
|
||||
RefPtr<EventTarget> related_target = retarget(event->related_target(), target);
|
||||
RefPtr<EventTarget> related_target = retarget(event.related_target(), target);
|
||||
|
||||
bool clear_targets = false;
|
||||
// 5. If target is not relatedTarget or target is event’s relatedTarget, then:
|
||||
if (related_target != target || event->related_target() == target) {
|
||||
if (related_target != target || event.related_target() == target) {
|
||||
// 1. Let touchTargets be a new list.
|
||||
Event::TouchTargetList touch_targets;
|
||||
|
||||
// 2. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against target to touchTargets.
|
||||
for (auto& touch_target : event->touch_target_list()) {
|
||||
for (auto& touch_target : event.touch_target_list()) {
|
||||
touch_targets.append(retarget(touch_target, target));
|
||||
}
|
||||
|
||||
// 3. Append to an event path with event, target, targetOverride, relatedTarget, touchTargets, and false.
|
||||
event->append_to_path(*target, target_override, related_target, touch_targets, false);
|
||||
event.append_to_path(*target, target_override, related_target, touch_targets, false);
|
||||
|
||||
// 4. Let isActivationEvent be true, if event is a MouseEvent object and event’s type attribute is "click"; otherwise false.
|
||||
bool is_activation_event = is<UIEvents::MouseEvent>(*event) && event->type() == HTML::EventNames::click;
|
||||
bool is_activation_event = is<UIEvents::MouseEvent>(event) && event.type() == HTML::EventNames::click;
|
||||
|
||||
// 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target.
|
||||
if (is_activation_event && target->activation_behavior)
|
||||
@ -265,13 +263,13 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
// FIXME: 2. If parent is a slottable and is assigned, then set slottable to parent.
|
||||
|
||||
// 3. Let relatedTarget be the result of retargeting event’s relatedTarget against parent.
|
||||
related_target = retarget(event->related_target(), parent);
|
||||
related_target = retarget(event.related_target(), parent);
|
||||
|
||||
// 4. Let touchTargets be a new list.
|
||||
touch_targets.clear();
|
||||
|
||||
// 5. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against parent to touchTargets.
|
||||
for (auto& touch_target : event->touch_target_list()) {
|
||||
for (auto& touch_target : event.touch_target_list()) {
|
||||
touch_targets.append(retarget(touch_target, parent));
|
||||
}
|
||||
|
||||
@ -279,11 +277,11 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
if (is<HTML::Window>(parent)
|
||||
|| (is<Node>(parent) && verify_cast<Node>(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*parent)))) {
|
||||
// 1. If isActivationEvent is true, event’s bubbles attribute is true, activationTarget is null, and parent has activation behavior, then set activationTarget to parent.
|
||||
if (is_activation_event && event->bubbles() && !activation_target && parent->activation_behavior)
|
||||
if (is_activation_event && event.bubbles() && !activation_target && parent->activation_behavior)
|
||||
activation_target = parent;
|
||||
|
||||
// 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree.
|
||||
event->append_to_path(*parent, nullptr, related_target, touch_targets, slot_in_closed_tree);
|
||||
event.append_to_path(*parent, nullptr, related_target, touch_targets, slot_in_closed_tree);
|
||||
|
||||
}
|
||||
// 7. Otherwise, if parent is relatedTarget, then set parent to null.
|
||||
@ -299,7 +297,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
activation_target = target;
|
||||
|
||||
// 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree.
|
||||
event->append_to_path(*parent, target, related_target, touch_targets, slot_in_closed_tree);
|
||||
event.append_to_path(*parent, target, related_target, touch_targets, slot_in_closed_tree);
|
||||
}
|
||||
|
||||
// 9. If parent is non-null, then set parent to the result of invoking parent’s get the parent with event.
|
||||
@ -312,7 +310,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
}
|
||||
|
||||
// 10. Let clearTargetsStruct be the last struct in event’s path whose shadow-adjusted target is non-null.
|
||||
auto clear_targets_struct = event->path().last_matching([](auto& entry) {
|
||||
auto clear_targets_struct = event.path().last_matching([](auto& entry) {
|
||||
return !entry.shadow_adjusted_target.is_null();
|
||||
});
|
||||
|
||||
@ -349,32 +347,32 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
activation_target->legacy_pre_activation_behavior();
|
||||
|
||||
// 13. For each struct in event’s path, in reverse order:
|
||||
for (auto& entry : event->path().in_reverse()) {
|
||||
for (auto& entry : event.path().in_reverse()) {
|
||||
// 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET.
|
||||
if (entry.shadow_adjusted_target)
|
||||
event->set_phase(Event::Phase::AtTarget);
|
||||
event.set_phase(Event::Phase::AtTarget);
|
||||
// 2. Otherwise, set event’s eventPhase attribute to CAPTURING_PHASE.
|
||||
else
|
||||
event->set_phase(Event::Phase::CapturingPhase);
|
||||
event.set_phase(Event::Phase::CapturingPhase);
|
||||
|
||||
// 3. Invoke with struct, event, "capturing", and legacyOutputDidListenersThrowFlag if given.
|
||||
invoke(entry, event, Event::Phase::CapturingPhase);
|
||||
}
|
||||
|
||||
// 14. For each struct in event’s path:
|
||||
for (auto& entry : event->path()) {
|
||||
for (auto& entry : event.path()) {
|
||||
// 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET.
|
||||
if (entry.shadow_adjusted_target) {
|
||||
event->set_phase(Event::Phase::AtTarget);
|
||||
event.set_phase(Event::Phase::AtTarget);
|
||||
}
|
||||
// 2. Otherwise:
|
||||
else {
|
||||
// 1. If event’s bubbles attribute is false, then continue.
|
||||
if (!event->bubbles())
|
||||
if (!event.bubbles())
|
||||
continue;
|
||||
|
||||
// 2. Set event’s eventPhase attribute to BUBBLING_PHASE.
|
||||
event->set_phase(Event::Phase::BubblingPhase);
|
||||
event.set_phase(Event::Phase::BubblingPhase);
|
||||
}
|
||||
|
||||
// 3. Invoke with struct, event, "bubbling", and legacyOutputDidListenersThrowFlag if given.
|
||||
@ -383,35 +381,35 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
}
|
||||
|
||||
// 6. Set event’s eventPhase attribute to NONE.
|
||||
event->set_phase(Event::Phase::None);
|
||||
event.set_phase(Event::Phase::None);
|
||||
|
||||
// 7. Set event’s currentTarget attribute to null.
|
||||
event->set_current_target(nullptr);
|
||||
event.set_current_target(nullptr);
|
||||
|
||||
// 8. Set event’s path to the empty list.
|
||||
event->clear_path();
|
||||
event.clear_path();
|
||||
|
||||
// 9. Unset event’s dispatch flag, stop propagation flag, and stop immediate propagation flag.
|
||||
event->set_dispatched(false);
|
||||
event->set_stop_propagation(false);
|
||||
event->set_stop_immediate_propagation(false);
|
||||
event.set_dispatched(false);
|
||||
event.set_stop_propagation(false);
|
||||
event.set_stop_immediate_propagation(false);
|
||||
|
||||
// 10. If clearTargets, then:
|
||||
if (clear_targets) {
|
||||
// 1. Set event’s target to null.
|
||||
event->set_target(nullptr);
|
||||
event.set_target(nullptr);
|
||||
|
||||
// 2. Set event’s relatedTarget to null.
|
||||
event->set_related_target(nullptr);
|
||||
event.set_related_target(nullptr);
|
||||
|
||||
// 3. Set event’s touch target list to the empty list.
|
||||
event->clear_touch_target_list();
|
||||
event.clear_touch_target_list();
|
||||
}
|
||||
|
||||
// 11. If activationTarget is non-null, then:
|
||||
if (activation_target) {
|
||||
// 1. If event’s canceled flag is unset, then run activationTarget’s activation behavior with event.
|
||||
if (!event->cancelled()) {
|
||||
if (!event.cancelled()) {
|
||||
activation_target->activation_behavior(event);
|
||||
activation_target->legacy_cancelled_activation_behavior_was_not_called();
|
||||
}
|
||||
@ -422,7 +420,7 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||
}
|
||||
|
||||
// 12. Return false if event’s canceled flag is set; otherwise true.
|
||||
return !event->cancelled();
|
||||
return !event.cancelled();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace Web::DOM {
|
||||
|
||||
class EventDispatcher {
|
||||
public:
|
||||
static bool dispatch(NonnullRefPtr<EventTarget>, NonnullRefPtr<Event>, bool legacy_target_override = false);
|
||||
static bool dispatch(NonnullRefPtr<EventTarget>, Event&, bool legacy_target_override = false);
|
||||
|
||||
private:
|
||||
static void invoke(Event::PathEntry&, Event&, Event::Phase);
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <LibJS/Runtime/VM.h>
|
||||
#include <LibWeb/Bindings/DocumentWrapper.h>
|
||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/EventWrapper.h>
|
||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/DOM/AbortSignal.h>
|
||||
@ -204,17 +202,17 @@ void EventTarget::remove_from_event_listener_list(DOMEventListener& listener)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent
|
||||
ExceptionOr<bool> EventTarget::dispatch_event_binding(NonnullRefPtr<Event> event)
|
||||
ExceptionOr<bool> EventTarget::dispatch_event_binding(Event& event)
|
||||
{
|
||||
// 1. If event’s dispatch flag is set, or if its initialized flag is not set, then throw an "InvalidStateError" DOMException.
|
||||
if (event->dispatched())
|
||||
if (event.dispatched())
|
||||
return DOM::InvalidStateError::create("The event is already being dispatched.");
|
||||
|
||||
if (!event->initialized())
|
||||
if (!event.initialized())
|
||||
return DOM::InvalidStateError::create("Cannot dispatch an uninitialized event.");
|
||||
|
||||
// 2. Initialize event’s isTrusted attribute to false.
|
||||
event->set_is_trusted(false);
|
||||
event.set_is_trusted(false);
|
||||
|
||||
// 3. Return the result of dispatching event to this.
|
||||
return dispatch_event(event);
|
||||
@ -736,9 +734,9 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local
|
||||
event_target->activate_event_handler(local_name, *event_handler);
|
||||
}
|
||||
|
||||
bool EventTarget::dispatch_event(NonnullRefPtr<Event> event)
|
||||
bool EventTarget::dispatch_event(Event& event)
|
||||
{
|
||||
return EventDispatcher::dispatch(*this, move(event));
|
||||
return EventDispatcher::dispatch(*this, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ public:
|
||||
void add_event_listener_without_options(FlyString const& type, IDLEventListener& callback);
|
||||
void remove_event_listener_without_options(FlyString const& type, IDLEventListener& callback);
|
||||
|
||||
virtual bool dispatch_event(NonnullRefPtr<Event>);
|
||||
ExceptionOr<bool> dispatch_event_binding(NonnullRefPtr<Event>);
|
||||
virtual bool dispatch_event(Event&);
|
||||
ExceptionOr<bool> dispatch_event_binding(Event&);
|
||||
|
||||
virtual JS::Object* create_wrapper(JS::Realm&) = 0;
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <LibJS/AST.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibWeb/Bindings/EventWrapper.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/Bindings/NodeWrapper.h>
|
||||
#include <LibWeb/Bindings/NodeWrapperFactory.h>
|
||||
|
@ -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;
|
||||
|
34
Userland/Libraries/LibWeb/HTML/CloseEvent.cpp
Normal file
34
Userland/Libraries/LibWeb/HTML/CloseEvent.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/CloseEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/HTML/CloseEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
CloseEvent* CloseEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<CloseEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
CloseEvent* CloseEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
CloseEvent::CloseEvent(Bindings::WindowObject& window_object, FlyString const& event_name, CloseEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name, event_init)
|
||||
, m_was_clean(event_init.was_clean)
|
||||
, m_code(event_init.code)
|
||||
, m_reason(event_init.reason)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::CloseEventPrototype>("CloseEvent"));
|
||||
}
|
||||
|
||||
CloseEvent::~CloseEvent() = default;
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@ -17,36 +18,31 @@ struct CloseEventInit : public DOM::EventInit {
|
||||
};
|
||||
|
||||
class CloseEvent : public DOM::Event {
|
||||
JS_OBJECT(CloseEvent, DOM::Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::CloseEventWrapper;
|
||||
static CloseEvent* create(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init = {});
|
||||
static CloseEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<CloseEvent> create(FlyString const& event_name, CloseEventInit const& event_init = {})
|
||||
{
|
||||
return adopt_ref(*new CloseEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<CloseEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init)
|
||||
{
|
||||
return CloseEvent::create(event_name, event_init);
|
||||
}
|
||||
CloseEvent(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init);
|
||||
|
||||
virtual ~CloseEvent() override = default;
|
||||
virtual ~CloseEvent() override;
|
||||
|
||||
CloseEvent& impl() { return *this; }
|
||||
|
||||
bool was_clean() const { return m_was_clean; }
|
||||
u16 code() const { return m_code; }
|
||||
String reason() const { return m_reason; }
|
||||
|
||||
protected:
|
||||
CloseEvent(FlyString const& event_name, CloseEventInit const& event_init)
|
||||
: DOM::Event(event_name, event_init)
|
||||
, m_was_clean(event_init.was_clean)
|
||||
, m_code(event_init.code)
|
||||
, m_reason(event_init.reason)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_was_clean { false };
|
||||
u16 m_code { 0 };
|
||||
String m_reason;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::HTML::CloseEvent& object) { return &object; }
|
||||
using CloseEventWrapper = Web::HTML::CloseEvent;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface CloseEvent : Event {
|
||||
constructor(DOMString type, optional CloseEventInit eventInitDict = {});
|
||||
|
||||
|
42
Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp
Normal file
42
Userland/Libraries/LibWeb/HTML/ErrorEvent.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/ErrorEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/HTML/ErrorEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
ErrorEvent* ErrorEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<ErrorEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
ErrorEvent* ErrorEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
ErrorEvent::ErrorEvent(Bindings::WindowObject& window_object, FlyString const& event_name, ErrorEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name)
|
||||
, m_message(event_init.message)
|
||||
, m_filename(event_init.filename)
|
||||
, m_lineno(event_init.lineno)
|
||||
, m_colno(event_init.colno)
|
||||
, m_error(event_init.error)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::ErrorEventPrototype>("ErrorEvent"));
|
||||
}
|
||||
|
||||
ErrorEvent::~ErrorEvent() = default;
|
||||
|
||||
void ErrorEvent::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_error);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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));
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
40
Userland/Libraries/LibWeb/HTML/MessageEvent.cpp
Normal file
40
Userland/Libraries/LibWeb/HTML/MessageEvent.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/MessageEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/HTML/MessageEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
MessageEvent* MessageEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<MessageEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
MessageEvent* MessageEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
MessageEvent::MessageEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MessageEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name, event_init)
|
||||
, m_data(event_init.data)
|
||||
, m_origin(event_init.origin)
|
||||
, m_last_event_id(event_init.last_event_id)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::MessageEventPrototype>("MessageEvent"));
|
||||
}
|
||||
|
||||
MessageEvent::~MessageEvent() = default;
|
||||
|
||||
void MessageEvent::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_data);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface MessageEvent : Event {
|
||||
constructor(DOMString type, optional MessageEventInit eventInitDict = {});
|
||||
|
||||
|
@ -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));
|
||||
}));
|
||||
}
|
||||
|
||||
|
32
Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp
Normal file
32
Userland/Libraries/LibWeb/HTML/PageTransitionEvent.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/PageTransitionEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/HTML/PageTransitionEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
PageTransitionEvent* PageTransitionEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<PageTransitionEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
PageTransitionEvent* PageTransitionEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
PageTransitionEvent::PageTransitionEvent(Bindings::WindowObject& window_object, FlyString const& event_name, PageTransitionEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name, event_init)
|
||||
, m_persisted(event_init.persisted)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::PageTransitionEventPrototype>("PageTransitionEvent"));
|
||||
}
|
||||
|
||||
PageTransitionEvent::~PageTransitionEvent() = default;
|
||||
|
||||
}
|
@ -15,30 +15,27 @@ struct PageTransitionEventInit : public DOM::EventInit {
|
||||
};
|
||||
|
||||
class PageTransitionEvent final : public DOM::Event {
|
||||
JS_OBJECT(PageTransitionEvent, DOM::Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::PageTransitionEventWrapper;
|
||||
static PageTransitionEvent* create(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init);
|
||||
static PageTransitionEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<PageTransitionEvent> create(FlyString const& event_name, PageTransitionEventInit const& event_init)
|
||||
{
|
||||
return adopt_ref(*new PageTransitionEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<PageTransitionEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init)
|
||||
{
|
||||
return PageTransitionEvent::create(event_name, event_init);
|
||||
}
|
||||
PageTransitionEvent(Bindings::WindowObject&, FlyString const& event_name, PageTransitionEventInit const& event_init);
|
||||
|
||||
virtual ~PageTransitionEvent() override = default;
|
||||
virtual ~PageTransitionEvent() override;
|
||||
|
||||
PageTransitionEvent& impl() { return *this; }
|
||||
|
||||
bool persisted() const { return m_persisted; }
|
||||
|
||||
protected:
|
||||
PageTransitionEvent(FlyString const& event_name, PageTransitionEventInit const& event_init)
|
||||
: DOM::Event(event_name, event_init)
|
||||
, m_persisted(event_init.persisted)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_persisted { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::HTML::PageTransitionEvent& object) { return &object; }
|
||||
using PageTransitionEventWrapper = Web::HTML::PageTransitionEvent;
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
40
Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp
Normal file
40
Userland/Libraries/LibWeb/HTML/PromiseRejectionEvent.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/PromiseRejectionEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/HTML/PromiseRejectionEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
PromiseRejectionEvent* PromiseRejectionEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<PromiseRejectionEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
PromiseRejectionEvent* PromiseRejectionEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
PromiseRejectionEvent::PromiseRejectionEvent(Bindings::WindowObject& window_object, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name, event_init)
|
||||
, m_promise(const_cast<JS::Promise*>(event_init.promise.cell()))
|
||||
, m_reason(event_init.reason)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::PromiseRejectionEventPrototype>("PromiseRejectionEvent"));
|
||||
}
|
||||
|
||||
PromiseRejectionEvent::~PromiseRejectionEvent() = default;
|
||||
|
||||
void PromiseRejectionEvent::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_promise);
|
||||
visitor.visit(m_reason);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@ -17,35 +18,33 @@ struct PromiseRejectionEventInit : public DOM::EventInit {
|
||||
JS::Value reason;
|
||||
};
|
||||
|
||||
class PromiseRejectionEvent : public DOM::Event {
|
||||
class PromiseRejectionEvent final : public DOM::Event {
|
||||
JS_OBJECT(PromiseRejectionEvent, DOM::Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::PromiseRejectionEventWrapper;
|
||||
static PromiseRejectionEvent* create(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init = {});
|
||||
static PromiseRejectionEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<PromiseRejectionEvent> create(FlyString const& event_name, PromiseRejectionEventInit const& event_init = {})
|
||||
{
|
||||
return adopt_ref(*new PromiseRejectionEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<PromiseRejectionEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
||||
{
|
||||
return PromiseRejectionEvent::create(event_name, event_init);
|
||||
}
|
||||
PromiseRejectionEvent(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init);
|
||||
|
||||
virtual ~PromiseRejectionEvent() override = default;
|
||||
virtual ~PromiseRejectionEvent() override;
|
||||
|
||||
PromiseRejectionEvent& impl() { return *this; }
|
||||
|
||||
// Needs to return a pointer for the generated JS bindings to work.
|
||||
JS::Promise const* promise() const { return m_promise.cell(); }
|
||||
JS::Value reason() const { return m_reason.value(); }
|
||||
JS::Promise const* promise() const { return m_promise; }
|
||||
JS::Value reason() const { return m_reason; }
|
||||
|
||||
protected:
|
||||
PromiseRejectionEvent(FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
||||
: DOM::Event(event_name, event_init)
|
||||
, m_promise(event_init.promise)
|
||||
, m_reason(JS::make_handle(event_init.reason))
|
||||
{
|
||||
}
|
||||
private:
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
JS::Handle<JS::Promise> m_promise;
|
||||
JS::Handle<JS::Value> m_reason;
|
||||
JS::Promise* m_promise { nullptr };
|
||||
JS::Value m_reason;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::HTML::PromiseRejectionEvent& object) { return &object; }
|
||||
using PromiseRejectionEventWrapper = Web::HTML::PromiseRejectionEvent;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[Exposed=(Window,Worker)]
|
||||
[Exposed=(Window,Worker), NoInstanceWrapper]
|
||||
interface PromiseRejectionEvent : Event {
|
||||
constructor(DOMString type, PromiseRejectionEventInit eventInitDict);
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
32
Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp
Normal file
32
Userland/Libraries/LibWeb/HTML/SubmitEvent.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/SubmitEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/HTML/SubmitEvent.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
SubmitEvent* SubmitEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<SubmitEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
SubmitEvent* SubmitEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
SubmitEvent::SubmitEvent(Bindings::WindowObject& window_object, FlyString const& event_name, SubmitEventInit const& event_init)
|
||||
: DOM::Event(window_object, event_name, event_init)
|
||||
, m_submitter(event_init.submitter)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::SubmitEventPrototype>("SubmitEvent"));
|
||||
}
|
||||
|
||||
SubmitEvent::~SubmitEvent() = default;
|
||||
|
||||
}
|
@ -17,29 +17,21 @@ struct SubmitEventInit : public DOM::EventInit {
|
||||
};
|
||||
|
||||
class SubmitEvent final : public DOM::Event {
|
||||
JS_OBJECT(SubmitEvent, DOM::Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::SubmitEventWrapper;
|
||||
static SubmitEvent* create(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
|
||||
static SubmitEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<SubmitEvent> create(FlyString const& event_name, SubmitEventInit const& event_init)
|
||||
{
|
||||
return adopt_ref(*new SubmitEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<SubmitEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init)
|
||||
{
|
||||
return SubmitEvent::create(event_name, event_init);
|
||||
}
|
||||
virtual ~SubmitEvent() override;
|
||||
|
||||
virtual ~SubmitEvent() override = default;
|
||||
SubmitEvent(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
|
||||
|
||||
SubmitEvent& impl() { return *this; }
|
||||
|
||||
RefPtr<HTMLElement> submitter() const { return m_submitter; }
|
||||
|
||||
private:
|
||||
SubmitEvent(FlyString const& event_name, SubmitEventInit const& event_init)
|
||||
: DOM::Event(event_name, event_init)
|
||||
, m_submitter(event_init.submitter)
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<HTMLElement> m_submitter;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#import <DOM/Event.idl>
|
||||
#import <HTML/HTMLElement.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface SubmitEvent : Event {
|
||||
constructor(DOMString type, optional SubmitEventInit eventInitDict = {});
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
|
@ -15,18 +15,20 @@ struct FocusEventInit : public UIEventInit {
|
||||
};
|
||||
|
||||
class FocusEvent final : public UIEvent {
|
||||
public:
|
||||
using WrapperType = Bindings::FocusEventWrapper;
|
||||
JS_OBJECT(FocusEvent, UIEvent);
|
||||
|
||||
public:
|
||||
static FocusEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const& event_init);
|
||||
|
||||
FocusEvent(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const&);
|
||||
virtual ~FocusEvent() override;
|
||||
|
||||
static NonnullRefPtr<FocusEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const& event_init)
|
||||
{
|
||||
return adopt_ref(*new FocusEvent(event_name, event_init));
|
||||
}
|
||||
|
||||
private:
|
||||
FocusEvent(FlyString const& event_name, FocusEventInit const&);
|
||||
FocusEvent& impl() { return *this; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::UIEvents::FocusEvent& object) { return &object; }
|
||||
using FocusEventWrapper = Web::UIEvents::FocusEvent;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#import <UIEvents/UIEvent.idl>
|
||||
|
||||
[Exposed=Window]
|
||||
[Exposed=Window, NoInstanceWrapper]
|
||||
interface FocusEvent : UIEvent {
|
||||
|
||||
constructor(DOMString type, optional FocusEventInit eventInitDict = {});
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#import <UIEvents/EventModifier.idl>
|
||||
|
||||
[Exposed=Window]
|
||||
[Exposed=Window, NoInstanceWrapper]
|
||||
interface KeyboardEvent : UIEvent {
|
||||
|
||||
constructor(DOMString type, optional KeyboardEventInit eventInitDict = {});
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
39
Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp
Normal file
39
Userland/Libraries/LibWeb/UIEvents/UIEvent.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/UIEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/UIEvents/UIEvent.h>
|
||||
|
||||
namespace Web::UIEvents {
|
||||
|
||||
UIEvent* UIEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name)
|
||||
{
|
||||
return window_object.heap().allocate<UIEvent>(window_object.realm(), window_object, event_name);
|
||||
}
|
||||
|
||||
UIEvent* UIEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, UIEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<UIEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_name)
|
||||
: Event(window_object, event_name)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::UIEventPrototype>("UIEvent"));
|
||||
}
|
||||
|
||||
UIEvent::UIEvent(Bindings::WindowObject& window_object, FlyString const& event_name, UIEventInit const& event_init)
|
||||
: Event(window_object, event_name, event_init)
|
||||
, m_view(event_init.view)
|
||||
, m_detail(event_init.detail)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::UIEventPrototype>("UIEvent"));
|
||||
}
|
||||
|
||||
UIEvent::~UIEvent() = default;
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface UIEvent : Event {
|
||||
constructor(DOMString type, optional UIEventInit eventInitDict = {});
|
||||
readonly attribute Window? view;
|
||||
|
32
Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp
Normal file
32
Userland/Libraries/LibWeb/WebGL/WebGLContextEvent.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/WebGLContextEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/WebGL/WebGLContextEvent.h>
|
||||
|
||||
namespace Web::WebGL {
|
||||
|
||||
WebGLContextEvent* WebGLContextEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<WebGLContextEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
WebGLContextEvent* WebGLContextEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, WebGLContextEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
WebGLContextEvent::WebGLContextEvent(Bindings::WindowObject& window_object, FlyString const& type, WebGLContextEventInit const& event_init)
|
||||
: DOM::Event(window_object, type, event_init)
|
||||
, m_status_message(event_init.status_message)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::WebGLContextEventPrototype>("WebGLContextEvent"));
|
||||
}
|
||||
|
||||
WebGLContextEvent::~WebGLContextEvent() = default;
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
34
Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp
Normal file
34
Userland/Libraries/LibWeb/XHR/ProgressEvent.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/ProgressEventPrototype.h>
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/XHR/ProgressEvent.h>
|
||||
|
||||
namespace Web::XHR {
|
||||
|
||||
ProgressEvent* ProgressEvent::create(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init)
|
||||
{
|
||||
return window_object.heap().allocate<ProgressEvent>(window_object.realm(), window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
ProgressEvent* ProgressEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init)
|
||||
{
|
||||
return create(window_object, event_name, event_init);
|
||||
}
|
||||
|
||||
ProgressEvent::ProgressEvent(Bindings::WindowObject& window_object, FlyString const& event_name, ProgressEventInit const& event_init)
|
||||
: Event(window_object, event_name, event_init)
|
||||
, m_length_computable(event_init.length_computable)
|
||||
, m_loaded(event_init.loaded)
|
||||
, m_total(event_init.total)
|
||||
{
|
||||
set_prototype(&window_object.ensure_web_prototype<Bindings::ProgressEventPrototype>("ProgressEvent"));
|
||||
}
|
||||
|
||||
ProgressEvent::~ProgressEvent() = default;
|
||||
|
||||
}
|
@ -19,37 +19,32 @@ struct ProgressEventInit : public DOM::EventInit {
|
||||
u32 total { 0 };
|
||||
};
|
||||
|
||||
class ProgressEvent : public DOM::Event {
|
||||
class ProgressEvent final : public DOM::Event {
|
||||
JS_OBJECT(ProgressEvent, DOM::Event);
|
||||
|
||||
public:
|
||||
using WrapperType = Bindings::ProgressEventWrapper;
|
||||
static ProgressEvent* create(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
|
||||
static ProgressEvent* create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
|
||||
|
||||
static NonnullRefPtr<ProgressEvent> create(FlyString const& event_name, ProgressEventInit const& event_init)
|
||||
{
|
||||
return adopt_ref(*new ProgressEvent(event_name, event_init));
|
||||
}
|
||||
static NonnullRefPtr<ProgressEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init)
|
||||
{
|
||||
return ProgressEvent::create(event_name, event_init);
|
||||
}
|
||||
ProgressEvent(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
|
||||
|
||||
virtual ~ProgressEvent() override = default;
|
||||
virtual ~ProgressEvent() override;
|
||||
|
||||
ProgressEvent& impl() { return *this; }
|
||||
|
||||
bool length_computable() const { return m_length_computable; }
|
||||
u64 loaded() const { return m_loaded; }
|
||||
u64 total() const { return m_total; }
|
||||
|
||||
protected:
|
||||
ProgressEvent(FlyString const& event_name, ProgressEventInit const& event_init)
|
||||
: Event(event_name, event_init)
|
||||
, m_length_computable(event_init.length_computable)
|
||||
, m_loaded(event_init.loaded)
|
||||
, m_total(event_init.total)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_length_computable { false };
|
||||
u64 m_loaded { 0 };
|
||||
u64 m_total { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Web::Bindings {
|
||||
inline JS::Object* wrap(JS::Realm&, Web::XHR::ProgressEvent& object) { return &object; }
|
||||
using ProgressEventWrapper = Web::XHR::ProgressEvent;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#import <DOM/Event.idl>
|
||||
|
||||
[NoInstanceWrapper]
|
||||
interface ProgressEvent : Event {
|
||||
constructor(DOMString type, optional ProgressEventInit eventInitDict = {});
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user