mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 04:57:44 +00:00
LibWeb: Make DOM::Event and all its subclasses GC-allocated
This commit is contained in:
parent
a4ddb0ef87
commit
7c3db526b0
76 changed files with 892 additions and 565 deletions
|
@ -39,7 +39,6 @@ interface CSSRule {
|
||||||
- It must have a public `using WrapperType = Bindings::HTMLDetailsElementWrapper;`
|
- 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:
|
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)
|
- 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.
|
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)
|
static bool should_emit_wrapper_factory(IDL::Interface const& interface)
|
||||||
{
|
{
|
||||||
// FIXME: This is very hackish.
|
// FIXME: This is very hackish.
|
||||||
if (interface.name == "Event")
|
|
||||||
return false;
|
|
||||||
if (interface.name == "EventTarget")
|
if (interface.name == "EventTarget")
|
||||||
return false;
|
return false;
|
||||||
if (interface.name == "Node")
|
if (interface.name == "Node")
|
||||||
|
@ -2042,6 +2040,7 @@ using namespace Web::IntersectionObserver;
|
||||||
using namespace Web::RequestIdleCallback;
|
using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
|
using namespace Web::UIEvents;
|
||||||
using namespace Web::WebGL;
|
using namespace Web::WebGL;
|
||||||
|
|
||||||
namespace Web::Bindings {
|
namespace Web::Bindings {
|
||||||
|
@ -2904,7 +2903,6 @@ void generate_constructor_implementation(IDL::Interface const& interface)
|
||||||
#include <LibWeb/Bindings/@wrapper_class@.h>
|
#include <LibWeb/Bindings/@wrapper_class@.h>
|
||||||
#endif
|
#endif
|
||||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
|
||||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/Bindings/NodeWrapper.h>
|
#include <LibWeb/Bindings/NodeWrapper.h>
|
||||||
#include <LibWeb/Bindings/NodeWrapperFactory.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>)
|
#if __has_include(<LibWeb/Bindings/@wrapper_class@.h>)
|
||||||
#include <LibWeb/Bindings/@wrapper_class@.h>
|
#include <LibWeb/Bindings/@wrapper_class@.h>
|
||||||
#endif
|
#endif
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
|
||||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/Bindings/LocationObject.h>
|
#include <LibWeb/Bindings/LocationObject.h>
|
||||||
#include <LibWeb/Bindings/WindowObject.h>
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
|
@ -3253,6 +3249,7 @@ using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
using namespace Web::SVG;
|
using namespace Web::SVG;
|
||||||
|
using namespace Web::UIEvents;
|
||||||
using namespace Web::URL;
|
using namespace Web::URL;
|
||||||
using namespace Web::WebSockets;
|
using namespace Web::WebSockets;
|
||||||
using namespace Web::XHR;
|
using namespace Web::XHR;
|
||||||
|
@ -3712,6 +3709,7 @@ using namespace Web::IntersectionObserver;
|
||||||
using namespace Web::RequestIdleCallback;
|
using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
|
using namespace Web::UIEvents;
|
||||||
using namespace Web::WebGL;
|
using namespace Web::WebGL;
|
||||||
|
|
||||||
namespace Web::Bindings {
|
namespace Web::Bindings {
|
||||||
|
@ -3830,6 +3828,7 @@ using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
using namespace Web::XHR;
|
using namespace Web::XHR;
|
||||||
|
using namespace Web::UIEvents;
|
||||||
using namespace Web::URL;
|
using namespace Web::URL;
|
||||||
using namespace Web::WebGL;
|
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,
|
/* .promise = */ promise,
|
||||||
/* .reason = */ promise.cell()->result(),
|
/* .reason = */ promise.cell()->result(),
|
||||||
};
|
};
|
||||||
auto promise_rejection_event = HTML::PromiseRejectionEvent::create(HTML::EventNames::rejectionhandled, event_init);
|
auto promise_rejection_event = HTML::PromiseRejectionEvent::create(window, HTML::EventNames::rejectionhandled, event_init);
|
||||||
window.impl().dispatch_event(move(promise_rejection_event));
|
window.impl().dispatch_event(*promise_rejection_event);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
#include <LibWeb/Bindings/ElementWrapper.h>
|
#include <LibWeb/Bindings/ElementWrapper.h>
|
||||||
#include <LibWeb/Bindings/EventTargetConstructor.h>
|
#include <LibWeb/Bindings/EventTargetConstructor.h>
|
||||||
#include <LibWeb/Bindings/EventTargetPrototype.h>
|
#include <LibWeb/Bindings/EventTargetPrototype.h>
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
|
||||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/Bindings/HistoryWrapper.h>
|
#include <LibWeb/Bindings/HistoryWrapper.h>
|
||||||
#include <LibWeb/Bindings/LocationObject.h>
|
#include <LibWeb/Bindings/LocationObject.h>
|
||||||
|
|
|
@ -6,7 +6,6 @@ set(SOURCES
|
||||||
Bindings/CallbackType.cpp
|
Bindings/CallbackType.cpp
|
||||||
Bindings/CrossOriginAbstractOperations.cpp
|
Bindings/CrossOriginAbstractOperations.cpp
|
||||||
Bindings/EventTargetWrapperFactory.cpp
|
Bindings/EventTargetWrapperFactory.cpp
|
||||||
Bindings/EventWrapperFactory.cpp
|
|
||||||
Bindings/IDLAbstractOperations.cpp
|
Bindings/IDLAbstractOperations.cpp
|
||||||
Bindings/ImageConstructor.cpp
|
Bindings/ImageConstructor.cpp
|
||||||
Bindings/LegacyPlatformObject.cpp
|
Bindings/LegacyPlatformObject.cpp
|
||||||
|
@ -47,6 +46,7 @@ set(SOURCES
|
||||||
CSS/MediaList.cpp
|
CSS/MediaList.cpp
|
||||||
CSS/MediaQuery.cpp
|
CSS/MediaQuery.cpp
|
||||||
CSS/MediaQueryList.cpp
|
CSS/MediaQueryList.cpp
|
||||||
|
CSS/MediaQueryListEvent.cpp
|
||||||
CSS/Parser/Block.cpp
|
CSS/Parser/Block.cpp
|
||||||
CSS/Parser/ComponentValue.cpp
|
CSS/Parser/ComponentValue.cpp
|
||||||
CSS/Parser/Declaration.cpp
|
CSS/Parser/Declaration.cpp
|
||||||
|
@ -145,9 +145,11 @@ set(SOURCES
|
||||||
HTML/Canvas/CanvasState.cpp
|
HTML/Canvas/CanvasState.cpp
|
||||||
HTML/CanvasGradient.cpp
|
HTML/CanvasGradient.cpp
|
||||||
HTML/CanvasRenderingContext2D.cpp
|
HTML/CanvasRenderingContext2D.cpp
|
||||||
|
HTML/CloseEvent.cpp
|
||||||
HTML/CrossOrigin/Reporting.cpp
|
HTML/CrossOrigin/Reporting.cpp
|
||||||
HTML/DOMParser.cpp
|
HTML/DOMParser.cpp
|
||||||
HTML/DOMStringMap.cpp
|
HTML/DOMStringMap.cpp
|
||||||
|
HTML/ErrorEvent.cpp
|
||||||
HTML/EventHandler.cpp
|
HTML/EventHandler.cpp
|
||||||
HTML/EventLoop/EventLoop.cpp
|
HTML/EventLoop/EventLoop.cpp
|
||||||
HTML/EventLoop/Task.cpp
|
HTML/EventLoop/Task.cpp
|
||||||
|
@ -232,7 +234,9 @@ set(SOURCES
|
||||||
HTML/HTMLVideoElement.cpp
|
HTML/HTMLVideoElement.cpp
|
||||||
HTML/ImageData.cpp
|
HTML/ImageData.cpp
|
||||||
HTML/MessageChannel.cpp
|
HTML/MessageChannel.cpp
|
||||||
|
HTML/MessageEvent.cpp
|
||||||
HTML/MessagePort.cpp
|
HTML/MessagePort.cpp
|
||||||
|
HTML/PageTransitionEvent.cpp
|
||||||
HTML/Parser/Entities.cpp
|
HTML/Parser/Entities.cpp
|
||||||
HTML/Parser/HTMLEncodingDetection.cpp
|
HTML/Parser/HTMLEncodingDetection.cpp
|
||||||
HTML/Parser/HTMLParser.cpp
|
HTML/Parser/HTMLParser.cpp
|
||||||
|
@ -241,12 +245,14 @@ set(SOURCES
|
||||||
HTML/Parser/ListOfActiveFormattingElements.cpp
|
HTML/Parser/ListOfActiveFormattingElements.cpp
|
||||||
HTML/Parser/StackOfOpenElements.cpp
|
HTML/Parser/StackOfOpenElements.cpp
|
||||||
HTML/Path2D.cpp
|
HTML/Path2D.cpp
|
||||||
|
HTML/PromiseRejectionEvent.cpp
|
||||||
HTML/Scripting/ClassicScript.cpp
|
HTML/Scripting/ClassicScript.cpp
|
||||||
HTML/Scripting/Environments.cpp
|
HTML/Scripting/Environments.cpp
|
||||||
HTML/Scripting/ExceptionReporter.cpp
|
HTML/Scripting/ExceptionReporter.cpp
|
||||||
HTML/Scripting/Script.cpp
|
HTML/Scripting/Script.cpp
|
||||||
HTML/Scripting/WindowEnvironmentSettingsObject.cpp
|
HTML/Scripting/WindowEnvironmentSettingsObject.cpp
|
||||||
HTML/Storage.cpp
|
HTML/Storage.cpp
|
||||||
|
HTML/SubmitEvent.cpp
|
||||||
HTML/SyntaxHighlighter/SyntaxHighlighter.cpp
|
HTML/SyntaxHighlighter/SyntaxHighlighter.cpp
|
||||||
HTML/TagNames.cpp
|
HTML/TagNames.cpp
|
||||||
HTML/TextMetrics.cpp
|
HTML/TextMetrics.cpp
|
||||||
|
@ -371,6 +377,7 @@ set(SOURCES
|
||||||
UIEvents/FocusEvent.cpp
|
UIEvents/FocusEvent.cpp
|
||||||
UIEvents/KeyboardEvent.cpp
|
UIEvents/KeyboardEvent.cpp
|
||||||
UIEvents/MouseEvent.cpp
|
UIEvents/MouseEvent.cpp
|
||||||
|
UIEvents/UIEvent.cpp
|
||||||
URL/URL.cpp
|
URL/URL.cpp
|
||||||
URL/URLSearchParams.cpp
|
URL/URLSearchParams.cpp
|
||||||
URL/URLSearchParamsIterator.cpp
|
URL/URLSearchParamsIterator.cpp
|
||||||
|
@ -386,10 +393,12 @@ set(SOURCES
|
||||||
WebAssembly/WebAssemblyTableObject.cpp
|
WebAssembly/WebAssemblyTableObject.cpp
|
||||||
WebAssembly/WebAssemblyTablePrototype.cpp
|
WebAssembly/WebAssemblyTablePrototype.cpp
|
||||||
WebGL/WebGLContextAttributes.cpp
|
WebGL/WebGLContextAttributes.cpp
|
||||||
|
WebGL/WebGLContextEvent.cpp
|
||||||
WebGL/WebGLRenderingContext.cpp
|
WebGL/WebGLRenderingContext.cpp
|
||||||
WebGL/WebGLRenderingContextBase.cpp
|
WebGL/WebGLRenderingContextBase.cpp
|
||||||
WebSockets/WebSocket.cpp
|
WebSockets/WebSocket.cpp
|
||||||
XHR/EventNames.cpp
|
XHR/EventNames.cpp
|
||||||
|
XHR/ProgressEvent.cpp
|
||||||
XHR/XMLHttpRequest.cpp
|
XHR/XMLHttpRequest.cpp
|
||||||
XHR/XMLHttpRequestEventTarget.cpp
|
XHR/XMLHttpRequestEventTarget.cpp
|
||||||
XML/XMLDocumentBuilder.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 };
|
bool matches { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
class MediaQueryListEvent : public DOM::Event {
|
class MediaQueryListEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(MediaQueryListEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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 = {})
|
MediaQueryListEvent(Bindings::WindowObject&, FlyString const& event_name, MediaQueryListEventInit const& event_init);
|
||||||
{
|
virtual ~MediaQueryListEvent() override;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~MediaQueryListEvent() override = default;
|
MediaQueryListEvent& impl() { return *this; }
|
||||||
|
|
||||||
String const& media() const { return m_media; }
|
String const& media() const { return m_media; }
|
||||||
bool matches() const { return m_matches; }
|
bool matches() const { return m_matches; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
String m_media;
|
String m_media;
|
||||||
bool m_matches;
|
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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface MediaQueryListEvent : Event {
|
interface MediaQueryListEvent : Event {
|
||||||
constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {});
|
constructor(CSSOMString type, optional MediaQueryListEventInit eventInitDict = {});
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ void AbortSignal::signal_abort(JS::Value reason)
|
||||||
m_abort_algorithms.clear();
|
m_abort_algorithms.clear();
|
||||||
|
|
||||||
// 5. Fire an event named abort at signal.
|
// 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)
|
void AbortSignal::set_onabort(Bindings::CallbackType* event_handler)
|
||||||
|
|
|
@ -1,15 +1,44 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/Bindings/CustomEventPrototype.h>
|
||||||
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/DOM/CustomEvent.h>
|
#include <LibWeb/DOM/CustomEvent.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
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)
|
void CustomEvent::visit_edges(JS::Cell::Visitor& visitor)
|
||||||
{
|
{
|
||||||
|
Base::visit_edges(visitor);
|
||||||
visitor.visit(m_detail);
|
visitor.visit(m_detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +50,7 @@ void CustomEvent::init_custom_event(String const& type, bool bubbles, bool cance
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 2. Initialize this with type, bubbles, and cancelable.
|
// 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.
|
// 3. Set this’s detail attribute to detail.
|
||||||
m_detail = detail;
|
m_detail = detail;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -16,41 +17,34 @@ struct CustomEventInit : public EventInit {
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#customevent
|
// https://dom.spec.whatwg.org/#customevent
|
||||||
class CustomEvent : public Event {
|
class CustomEvent : public Event {
|
||||||
|
JS_OBJECT(CustomEvent, Event);
|
||||||
|
|
||||||
public:
|
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 = {})
|
CustomEvent(Bindings::WindowObject&, FlyString const& event_name);
|
||||||
{
|
CustomEvent(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init);
|
||||||
return adopt_ref(*new CustomEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
static NonnullRefPtr<CustomEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CustomEventInit const& event_init)
|
|
||||||
{
|
|
||||||
return CustomEvent::create(event_name, event_init);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~CustomEvent() override = default;
|
virtual ~CustomEvent() override;
|
||||||
|
|
||||||
|
CustomEvent& impl() { return *this; }
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-customevent-detail
|
// https://dom.spec.whatwg.org/#dom-customevent-detail
|
||||||
JS::Value detail() const { return m_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);
|
void init_custom_event(String const& type, bool bubbles, bool cancelable, JS::Value detail);
|
||||||
|
|
||||||
private:
|
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
|
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent-type-bubbles-cancelable-detail-detail
|
||||||
JS::Value m_detail { JS::js_null() };
|
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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
[Exposed=(Window,Worker), CustomVisit]
|
[Exposed=(Window,Worker), NoInstanceWrapper]
|
||||||
interface CustomEvent : Event {
|
interface CustomEvent : Event {
|
||||||
constructor(DOMString type, optional CustomEventInit eventInitDict = {});
|
constructor(DOMString type, optional CustomEventInit eventInitDict = {});
|
||||||
|
|
||||||
|
|
|
@ -1160,51 +1160,53 @@ NonnullRefPtr<Range> Document::create_range()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-document-createevent
|
// 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.
|
// 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.
|
// 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,
|
// 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:
|
// then set constructor to the interface in the second column on the same row as the matching string:
|
||||||
auto interface_lowercase = interface.to_lowercase();
|
auto interface_lowercase = interface.to_lowercase();
|
||||||
if (interface_lowercase == "beforeunloadevent") {
|
if (interface_lowercase == "beforeunloadevent") {
|
||||||
event = Event::create(""); // FIXME: Create BeforeUnloadEvent
|
event = Event::create(window_object, ""); // FIXME: Create BeforeUnloadEvent
|
||||||
} else if (interface_lowercase == "compositionevent") {
|
} else if (interface_lowercase == "compositionevent") {
|
||||||
event = Event::create(""); // FIXME: Create CompositionEvent
|
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
|
||||||
} else if (interface_lowercase == "customevent") {
|
} else if (interface_lowercase == "customevent") {
|
||||||
event = CustomEvent::create("");
|
event = CustomEvent::create(window_object, "");
|
||||||
} else if (interface_lowercase == "devicemotionevent") {
|
} else if (interface_lowercase == "devicemotionevent") {
|
||||||
event = Event::create(""); // FIXME: Create DeviceMotionEvent
|
event = Event::create(window_object, ""); // FIXME: Create DeviceMotionEvent
|
||||||
} else if (interface_lowercase == "deviceorientationevent") {
|
} else if (interface_lowercase == "deviceorientationevent") {
|
||||||
event = Event::create(""); // FIXME: Create DeviceOrientationEvent
|
event = Event::create(window_object, ""); // FIXME: Create DeviceOrientationEvent
|
||||||
} else if (interface_lowercase == "dragevent") {
|
} 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")) {
|
} else if (interface_lowercase.is_one_of("event", "events")) {
|
||||||
event = Event::create("");
|
event = Event::create(window_object, "");
|
||||||
} else if (interface_lowercase == "focusevent") {
|
} else if (interface_lowercase == "focusevent") {
|
||||||
event = UIEvents::FocusEvent::create("");
|
event = UIEvents::FocusEvent::create(window_object, "");
|
||||||
} else if (interface_lowercase == "hashchangeevent") {
|
} else if (interface_lowercase == "hashchangeevent") {
|
||||||
event = Event::create(""); // FIXME: Create HashChangeEvent
|
event = Event::create(window_object, ""); // FIXME: Create HashChangeEvent
|
||||||
} else if (interface_lowercase == "htmlevents") {
|
} else if (interface_lowercase == "htmlevents") {
|
||||||
event = Event::create("");
|
event = Event::create(window_object, "");
|
||||||
} else if (interface_lowercase == "keyboardevent") {
|
} else if (interface_lowercase == "keyboardevent") {
|
||||||
event = UIEvents::KeyboardEvent::create("");
|
event = UIEvents::KeyboardEvent::create(window_object, "");
|
||||||
} else if (interface_lowercase == "messageevent") {
|
} else if (interface_lowercase == "messageevent") {
|
||||||
event = HTML::MessageEvent::create("");
|
event = HTML::MessageEvent::create(window_object, "");
|
||||||
} else if (interface_lowercase.is_one_of("mouseevent", "mouseevents")) {
|
} else if (interface_lowercase.is_one_of("mouseevent", "mouseevents")) {
|
||||||
event = UIEvents::MouseEvent::create("");
|
event = UIEvents::MouseEvent::create(window_object, "");
|
||||||
} else if (interface_lowercase == "storageevent") {
|
} else if (interface_lowercase == "storageevent") {
|
||||||
event = Event::create(""); // FIXME: Create StorageEvent
|
event = Event::create(window_object, ""); // FIXME: Create StorageEvent
|
||||||
} else if (interface_lowercase == "svgevents") {
|
} else if (interface_lowercase == "svgevents") {
|
||||||
event = Event::create("");
|
event = Event::create(window_object, "");
|
||||||
} else if (interface_lowercase == "textevent") {
|
} else if (interface_lowercase == "textevent") {
|
||||||
event = Event::create(""); // FIXME: Create CompositionEvent
|
event = Event::create(window_object, ""); // FIXME: Create CompositionEvent
|
||||||
} else if (interface_lowercase == "touchevent") {
|
} 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")) {
|
} 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.
|
// 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);
|
event->set_initialized(false);
|
||||||
|
|
||||||
// 10. Return event.
|
// 10. Return event.
|
||||||
return event.release_nonnull();
|
return JS::NonnullGCPtr(*event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement* script)
|
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.
|
// 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.
|
// 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()
|
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.
|
// 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) {
|
else if (container) {
|
||||||
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container]() mutable {
|
container->queue_an_element_task(HTML::Task::Source::DOMManipulation, [container, this]() mutable {
|
||||||
container->dispatch_event(DOM::Event::create(HTML::EventNames::load));
|
container->dispatch_event(*DOM::Event::create(preferred_window_object(), HTML::EventNames::load));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1560,7 +1562,7 @@ void Document::run_the_resize_steps()
|
||||||
return;
|
return;
|
||||||
m_last_viewport_size = viewport_size;
|
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();
|
update_layout();
|
||||||
}
|
}
|
||||||
|
@ -1596,9 +1598,9 @@ void Document::evaluate_media_queries_and_report_changes()
|
||||||
CSS::MediaQueryListEventInit init;
|
CSS::MediaQueryListEventInit init;
|
||||||
init.media = media_query_list->media();
|
init.media = media_query_list->media();
|
||||||
init.matches = now_matches;
|
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);
|
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<Text> create_text_node(String const& data);
|
||||||
NonnullRefPtr<Comment> create_comment(String const& data);
|
NonnullRefPtr<Comment> create_comment(String const& data);
|
||||||
NonnullRefPtr<Range> create_range();
|
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*);
|
void set_pending_parsing_blocking_script(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement*);
|
||||||
HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; }
|
HTML::HTMLScriptElement* pending_parsing_blocking_script() { return m_pending_parsing_blocking_script; }
|
||||||
|
|
|
@ -1,17 +1,47 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, the SerenityOS developers.
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/TypeCasts.h>
|
#include <AK/TypeCasts.h>
|
||||||
|
#include <LibWeb/Bindings/EventPrototype.h>
|
||||||
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
#include <LibWeb/DOM/Node.h>
|
#include <LibWeb/DOM/Node.h>
|
||||||
#include <LibWeb/DOM/ShadowRoot.h>
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
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
|
// 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)
|
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
|
// 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.
|
// 1. Set event’s initialized flag.
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
|
@ -80,7 +110,7 @@ void Event::init_event(String const& type, bool bubbles, bool cancelable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 2. Initialize this with type, bubbles, and cancelable.
|
// 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
|
// 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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -7,8 +7,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/FlyString.h>
|
#include <AK/FlyString.h>
|
||||||
|
#include <LibWeb/Bindings/PlatformObject.h>
|
||||||
#include <LibWeb/Bindings/WindowObject.h>
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/Bindings/Wrappable.h>
|
|
||||||
#include <LibWeb/DOM/EventTarget.h>
|
#include <LibWeb/DOM/EventTarget.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
@ -19,12 +19,10 @@ struct EventInit {
|
||||||
bool composed { false };
|
bool composed { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
class Event
|
class Event : public Bindings::PlatformObject {
|
||||||
: public RefCounted<Event>
|
JS_OBJECT(Event, Bindings::PlatformObject);
|
||||||
, public Bindings::Wrappable {
|
|
||||||
public:
|
|
||||||
using WrapperType = Bindings::EventWrapper;
|
|
||||||
|
|
||||||
|
public:
|
||||||
enum Phase : u16 {
|
enum Phase : u16 {
|
||||||
None = 0,
|
None = 0,
|
||||||
CapturingPhase = 1,
|
CapturingPhase = 1,
|
||||||
|
@ -47,17 +45,16 @@ public:
|
||||||
|
|
||||||
using Path = Vector<PathEntry>;
|
using Path = Vector<PathEntry>;
|
||||||
|
|
||||||
static NonnullRefPtr<Event> create(FlyString const& event_name, EventInit const& 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);
|
||||||
return adopt_ref(*new Event(event_name, event_init));
|
|
||||||
}
|
Event(Bindings::WindowObject&, FlyString const& type);
|
||||||
static NonnullRefPtr<Event> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, EventInit const& event_init)
|
Event(Bindings::WindowObject&, FlyString const& type, EventInit const& event_init);
|
||||||
{
|
|
||||||
return Event::create(event_name, event_init);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Event() = default;
|
virtual ~Event() = default;
|
||||||
|
|
||||||
|
Event& impl() { return *this; }
|
||||||
|
|
||||||
double time_stamp() const;
|
double time_stamp() const;
|
||||||
|
|
||||||
FlyString const& type() const { return m_type; }
|
FlyString const& type() const { return m_type; }
|
||||||
|
@ -149,21 +146,7 @@ public:
|
||||||
NonnullRefPtrVector<EventTarget> composed_path() const;
|
NonnullRefPtrVector<EventTarget> composed_path() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Event(FlyString const& type)
|
void initialize_event(String const&, bool, bool);
|
||||||
: 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);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FlyString m_type;
|
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>
|
#import <DOM/EventTarget.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface Event {
|
interface Event {
|
||||||
|
|
||||||
constructor(DOMString type, optional EventInit eventInitDict = {});
|
constructor(DOMString type, optional EventInit eventInitDict = {});
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
#include <LibJS/Runtime/FunctionObject.h>
|
#include <LibJS/Runtime/FunctionObject.h>
|
||||||
#include <LibWeb/Bindings/EventTargetWrapper.h>
|
#include <LibWeb/Bindings/EventTargetWrapper.h>
|
||||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
|
||||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||||
#include <LibWeb/Bindings/WindowObject.h>
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/DOM/AbortSignal.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();
|
auto& global = realm.global_object();
|
||||||
|
|
||||||
// 7. Let currentEvent be undefined.
|
// 7. Let currentEvent be undefined.
|
||||||
RefPtr<Event> current_event;
|
Event* current_event = nullptr;
|
||||||
|
|
||||||
// 8. If global is a Window object, then:
|
// 8. If global is a Window object, then:
|
||||||
if (is<Bindings::WindowObject>(global)) {
|
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
|
// 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.
|
// 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]
|
// 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.
|
// 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;
|
RefPtr<EventTarget> activation_target;
|
||||||
|
|
||||||
// 4. Let relatedTarget be the result of retargeting event’s relatedTarget against 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;
|
bool clear_targets = false;
|
||||||
// 5. If target is not relatedTarget or target is event’s relatedTarget, then:
|
// 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.
|
// 1. Let touchTargets be a new list.
|
||||||
Event::TouchTargetList touch_targets;
|
Event::TouchTargetList touch_targets;
|
||||||
|
|
||||||
// 2. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against target to touchTargets.
|
// 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));
|
touch_targets.append(retarget(touch_target, target));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Append to an event path with event, target, targetOverride, relatedTarget, touchTargets, and false.
|
// 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.
|
// 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.
|
// 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target.
|
||||||
if (is_activation_event && target->activation_behavior)
|
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.
|
// 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.
|
// 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.
|
// 4. Let touchTargets be a new list.
|
||||||
touch_targets.clear();
|
touch_targets.clear();
|
||||||
|
|
||||||
// 5. For each touchTarget of event’s touch target list, append the result of retargeting touchTarget against parent to touchTargets.
|
// 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));
|
touch_targets.append(retarget(touch_target, parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,11 +277,11 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||||
if (is<HTML::Window>(parent)
|
if (is<HTML::Window>(parent)
|
||||||
|| (is<Node>(parent) && verify_cast<Node>(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast<Node>(*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.
|
// 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;
|
activation_target = parent;
|
||||||
|
|
||||||
// 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree.
|
// 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.
|
// 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;
|
activation_target = target;
|
||||||
|
|
||||||
// 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree.
|
// 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.
|
// 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.
|
// 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();
|
return !entry.shadow_adjusted_target.is_null();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -349,32 +347,32 @@ bool EventDispatcher::dispatch(NonnullRefPtr<EventTarget> target, NonnullRefPtr<
|
||||||
activation_target->legacy_pre_activation_behavior();
|
activation_target->legacy_pre_activation_behavior();
|
||||||
|
|
||||||
// 13. For each struct in event’s path, in reverse order:
|
// 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.
|
// 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET.
|
||||||
if (entry.shadow_adjusted_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.
|
// 2. Otherwise, set event’s eventPhase attribute to CAPTURING_PHASE.
|
||||||
else
|
else
|
||||||
event->set_phase(Event::Phase::CapturingPhase);
|
event.set_phase(Event::Phase::CapturingPhase);
|
||||||
|
|
||||||
// 3. Invoke with struct, event, "capturing", and legacyOutputDidListenersThrowFlag if given.
|
// 3. Invoke with struct, event, "capturing", and legacyOutputDidListenersThrowFlag if given.
|
||||||
invoke(entry, event, Event::Phase::CapturingPhase);
|
invoke(entry, event, Event::Phase::CapturingPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 14. For each struct in event’s path:
|
// 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.
|
// 1. If struct’s shadow-adjusted target is non-null, then set event’s eventPhase attribute to AT_TARGET.
|
||||||
if (entry.shadow_adjusted_target) {
|
if (entry.shadow_adjusted_target) {
|
||||||
event->set_phase(Event::Phase::AtTarget);
|
event.set_phase(Event::Phase::AtTarget);
|
||||||
}
|
}
|
||||||
// 2. Otherwise:
|
// 2. Otherwise:
|
||||||
else {
|
else {
|
||||||
// 1. If event’s bubbles attribute is false, then continue.
|
// 1. If event’s bubbles attribute is false, then continue.
|
||||||
if (!event->bubbles())
|
if (!event.bubbles())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 2. Set event’s eventPhase attribute to BUBBLING_PHASE.
|
// 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.
|
// 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.
|
// 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.
|
// 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.
|
// 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.
|
// 9. Unset event’s dispatch flag, stop propagation flag, and stop immediate propagation flag.
|
||||||
event->set_dispatched(false);
|
event.set_dispatched(false);
|
||||||
event->set_stop_propagation(false);
|
event.set_stop_propagation(false);
|
||||||
event->set_stop_immediate_propagation(false);
|
event.set_stop_immediate_propagation(false);
|
||||||
|
|
||||||
// 10. If clearTargets, then:
|
// 10. If clearTargets, then:
|
||||||
if (clear_targets) {
|
if (clear_targets) {
|
||||||
// 1. Set event’s target to null.
|
// 1. Set event’s target to null.
|
||||||
event->set_target(nullptr);
|
event.set_target(nullptr);
|
||||||
|
|
||||||
// 2. Set event’s relatedTarget to null.
|
// 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.
|
// 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:
|
// 11. If activationTarget is non-null, then:
|
||||||
if (activation_target) {
|
if (activation_target) {
|
||||||
// 1. If event’s canceled flag is unset, then run activationTarget’s activation behavior with event.
|
// 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->activation_behavior(event);
|
||||||
activation_target->legacy_cancelled_activation_behavior_was_not_called();
|
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.
|
// 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 {
|
class EventDispatcher {
|
||||||
public:
|
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:
|
private:
|
||||||
static void invoke(Event::PathEntry&, Event&, Event::Phase);
|
static void invoke(Event::PathEntry&, Event&, Event::Phase);
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include <LibJS/Runtime/VM.h>
|
#include <LibJS/Runtime/VM.h>
|
||||||
#include <LibWeb/Bindings/DocumentWrapper.h>
|
#include <LibWeb/Bindings/DocumentWrapper.h>
|
||||||
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
#include <LibWeb/Bindings/EventTargetWrapperFactory.h>
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/EventWrapperFactory.h>
|
|
||||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||||
#include <LibWeb/DOM/AbortSignal.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
|
// 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.
|
// 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.");
|
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.");
|
return DOM::InvalidStateError::create("Cannot dispatch an uninitialized event.");
|
||||||
|
|
||||||
// 2. Initialize event’s isTrusted attribute to false.
|
// 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.
|
// 3. Return the result of dispatching event to this.
|
||||||
return dispatch_event(event);
|
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);
|
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 add_event_listener_without_options(FlyString const& type, IDLEventListener& callback);
|
||||||
void remove_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>);
|
virtual bool dispatch_event(Event&);
|
||||||
ExceptionOr<bool> dispatch_event_binding(NonnullRefPtr<Event>);
|
ExceptionOr<bool> dispatch_event_binding(Event&);
|
||||||
|
|
||||||
virtual JS::Object* create_wrapper(JS::Realm&) = 0;
|
virtual JS::Object* create_wrapper(JS::Realm&) = 0;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibJS/AST.h>
|
#include <LibJS/AST.h>
|
||||||
#include <LibJS/Runtime/FunctionObject.h>
|
#include <LibJS/Runtime/FunctionObject.h>
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||||
#include <LibWeb/Bindings/NodeWrapper.h>
|
#include <LibWeb/Bindings/NodeWrapper.h>
|
||||||
#include <LibWeb/Bindings/NodeWrapperFactory.h>
|
#include <LibWeb/Bindings/NodeWrapperFactory.h>
|
||||||
|
|
|
@ -455,10 +455,8 @@ class CanvasGradientWrapper;
|
||||||
class CanvasRenderingContext2DWrapper;
|
class CanvasRenderingContext2DWrapper;
|
||||||
class CDATASectionWrapper;
|
class CDATASectionWrapper;
|
||||||
class CharacterDataWrapper;
|
class CharacterDataWrapper;
|
||||||
class CloseEventWrapper;
|
|
||||||
class CommentWrapper;
|
class CommentWrapper;
|
||||||
class CryptoWrapper;
|
class CryptoWrapper;
|
||||||
class CustomEventWrapper;
|
|
||||||
class DocumentFragmentWrapper;
|
class DocumentFragmentWrapper;
|
||||||
class DocumentTypeWrapper;
|
class DocumentTypeWrapper;
|
||||||
class DocumentWrapper;
|
class DocumentWrapper;
|
||||||
|
@ -470,11 +468,8 @@ class DOMRectListWrapper;
|
||||||
class DOMRectReadOnlyWrapper;
|
class DOMRectReadOnlyWrapper;
|
||||||
class DOMRectWrapper;
|
class DOMRectWrapper;
|
||||||
class ElementWrapper;
|
class ElementWrapper;
|
||||||
class ErrorEventWrapper;
|
|
||||||
class EventTargetWrapper;
|
class EventTargetWrapper;
|
||||||
class EventWrapper;
|
|
||||||
class FileWrapper;
|
class FileWrapper;
|
||||||
class FocusEventWrapper;
|
|
||||||
class HeadersWrapper;
|
class HeadersWrapper;
|
||||||
class HeadersIteratorWrapper;
|
class HeadersIteratorWrapper;
|
||||||
class HistoryWrapper;
|
class HistoryWrapper;
|
||||||
|
@ -554,26 +549,19 @@ class HTMLVideoElementWrapper;
|
||||||
class IdleDeadlineWrapper;
|
class IdleDeadlineWrapper;
|
||||||
class ImageDataWrapper;
|
class ImageDataWrapper;
|
||||||
class IntersectionObserverWrapper;
|
class IntersectionObserverWrapper;
|
||||||
class KeyboardEventWrapper;
|
|
||||||
class LocationObject;
|
class LocationObject;
|
||||||
class MediaQueryListEventWrapper;
|
|
||||||
class MediaQueryListWrapper;
|
class MediaQueryListWrapper;
|
||||||
class MessageChannelWrapper;
|
class MessageChannelWrapper;
|
||||||
class MessageEventWrapper;
|
|
||||||
class MessagePortWrapper;
|
class MessagePortWrapper;
|
||||||
class MouseEventWrapper;
|
|
||||||
class MutationObserverWrapper;
|
class MutationObserverWrapper;
|
||||||
class MutationRecordWrapper;
|
class MutationRecordWrapper;
|
||||||
class NodeListWrapper;
|
class NodeListWrapper;
|
||||||
class NodeWrapper;
|
class NodeWrapper;
|
||||||
class OptionConstructor;
|
class OptionConstructor;
|
||||||
class PageTransitionEventWrapper;
|
|
||||||
class Path2DWrapper;
|
class Path2DWrapper;
|
||||||
class PerformanceTimingWrapper;
|
class PerformanceTimingWrapper;
|
||||||
class PerformanceWrapper;
|
class PerformanceWrapper;
|
||||||
class ProcessingInstructionWrapper;
|
class ProcessingInstructionWrapper;
|
||||||
class ProgressEventWrapper;
|
|
||||||
class PromiseRejectionEventWrapper;
|
|
||||||
class RangeConstructor;
|
class RangeConstructor;
|
||||||
class RangePrototype;
|
class RangePrototype;
|
||||||
class RangeWrapper;
|
class RangeWrapper;
|
||||||
|
@ -582,7 +570,6 @@ class ScreenWrapper;
|
||||||
class SelectionWrapper;
|
class SelectionWrapper;
|
||||||
class StaticRangeWrapper;
|
class StaticRangeWrapper;
|
||||||
class StorageWrapper;
|
class StorageWrapper;
|
||||||
class SubmitEventWrapper;
|
|
||||||
class SubtleCryptoWrapper;
|
class SubtleCryptoWrapper;
|
||||||
class SVGAnimatedLengthWrapper;
|
class SVGAnimatedLengthWrapper;
|
||||||
class SVGCircleElementWrapper;
|
class SVGCircleElementWrapper;
|
||||||
|
@ -604,7 +591,6 @@ class TextDecoderWrapper;
|
||||||
class TextEncoderWrapper;
|
class TextEncoderWrapper;
|
||||||
class TextMetricsWrapper;
|
class TextMetricsWrapper;
|
||||||
class TextWrapper;
|
class TextWrapper;
|
||||||
class UIEventWrapper;
|
|
||||||
class URLConstructor;
|
class URLConstructor;
|
||||||
class URLPrototype;
|
class URLPrototype;
|
||||||
class URLSearchParamsConstructor;
|
class URLSearchParamsConstructor;
|
||||||
|
@ -613,7 +599,6 @@ class URLSearchParamsIteratorWrapper;
|
||||||
class URLSearchParamsPrototype;
|
class URLSearchParamsPrototype;
|
||||||
class URLSearchParamsWrapper;
|
class URLSearchParamsWrapper;
|
||||||
class URLWrapper;
|
class URLWrapper;
|
||||||
class WebGLContextEventWrapper;
|
|
||||||
class WebGLRenderingContextWrapper;
|
class WebGLRenderingContextWrapper;
|
||||||
class WebSocketWrapper;
|
class WebSocketWrapper;
|
||||||
class WindowObject;
|
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) 2021, Dex♪ <dexes.ttp@gmail.com>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -17,36 +18,31 @@ struct CloseEventInit : public DOM::EventInit {
|
||||||
};
|
};
|
||||||
|
|
||||||
class CloseEvent : public DOM::Event {
|
class CloseEvent : public DOM::Event {
|
||||||
|
JS_OBJECT(CloseEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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 = {})
|
CloseEvent(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init);
|
||||||
{
|
|
||||||
return adopt_ref(*new CloseEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
static NonnullRefPtr<CloseEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, CloseEventInit const& event_init)
|
|
||||||
{
|
|
||||||
return CloseEvent::create(event_name, event_init);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~CloseEvent() override = default;
|
virtual ~CloseEvent() override;
|
||||||
|
|
||||||
|
CloseEvent& impl() { return *this; }
|
||||||
|
|
||||||
bool was_clean() const { return m_was_clean; }
|
bool was_clean() const { return m_was_clean; }
|
||||||
u16 code() const { return m_code; }
|
u16 code() const { return m_code; }
|
||||||
String reason() const { return m_reason; }
|
String reason() const { return m_reason; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool m_was_clean { false };
|
bool m_was_clean { false };
|
||||||
u16 m_code { 0 };
|
u16 m_code { 0 };
|
||||||
String m_reason;
|
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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface CloseEvent : Event {
|
interface CloseEvent : Event {
|
||||||
constructor(DOMString type, optional CloseEventInit eventInitDict = {});
|
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
|
// https://html.spec.whatwg.org/multipage/webappapis.html#errorevent
|
||||||
class ErrorEvent final : public DOM::Event {
|
class ErrorEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(ErrorEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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 = {})
|
ErrorEvent(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init);
|
||||||
{
|
|
||||||
return adopt_ref(*new ErrorEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
|
|
||||||
static NonnullRefPtr<ErrorEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ErrorEventInit const& event_init)
|
virtual ~ErrorEvent() override;
|
||||||
{
|
|
||||||
return ErrorEvent::create(event_name, event_init);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~ErrorEvent() override = default;
|
ErrorEvent& impl() { return *this; }
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/webappapis.html#dom-errorevent-message
|
// https://html.spec.whatwg.org/multipage/webappapis.html#dom-errorevent-message
|
||||||
String const& message() const { return m_message; }
|
String const& message() const { return m_message; }
|
||||||
|
@ -49,24 +46,21 @@ public:
|
||||||
u32 colno() const { return m_colno; }
|
u32 colno() const { return m_colno; }
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/webappapis.html#dom-errorevent-error
|
// 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:
|
private:
|
||||||
ErrorEvent(FlyString const& event_name, ErrorEventInit const& event_init)
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
: 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))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
String m_message { "" };
|
String m_message { "" };
|
||||||
String m_filename { "" }; // FIXME: This should be a USVString.
|
String m_filename { "" }; // FIXME: This should be a USVString.
|
||||||
u32 m_lineno { 0 };
|
u32 m_lineno { 0 };
|
||||||
u32 m_colno { 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.
|
// with related blur target as the related target.
|
||||||
if (blur_event_target) {
|
if (blur_event_target) {
|
||||||
// FIXME: Implement the "fire a focus event" spec operation.
|
// 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->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.
|
// with related focus target as the related target.
|
||||||
if (focus_event_target) {
|
if (focus_event_target) {
|
||||||
// FIXME: Implement the "fire a focus event" spec operation.
|
// 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->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.
|
// 1. Let event be the result of creating an event using PointerEvent.
|
||||||
// 2. Initialize event's type attribute to e.
|
// 2. Initialize event's type attribute to e.
|
||||||
// FIXME: Actually create a PointerEvent!
|
// 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.
|
// 3. Initialize event's bubbles and cancelable attributes to true.
|
||||||
event->set_bubbles(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.
|
// 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.
|
// 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
|
// 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 {};
|
SubmitEventInit event_init {};
|
||||||
event_init.submitter = submitter_button;
|
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_bubbles(true);
|
||||||
submit_event->set_cancelable(true);
|
submit_event->set_cancelable(true);
|
||||||
bool continue_ = dispatch_event(submit_event);
|
bool continue_ = dispatch_event(*submit_event);
|
||||||
|
|
||||||
m_firing_submission_events = false;
|
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.
|
// FIXME: 4. Set childDocument's iframe load in progress flag.
|
||||||
|
|
||||||
// 5. Fire an event named load at element.
|
// 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.
|
// 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);
|
set_needs_style_update(true);
|
||||||
this->document().set_needs_layout();
|
this->document().set_needs_layout();
|
||||||
queue_an_element_task(HTML::Task::Source::DOMManipulation, [this] {
|
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);
|
set_needs_style_update(true);
|
||||||
this->document().set_needs_layout();
|
this->document().set_needs_layout();
|
||||||
queue_an_element_task(HTML::Task::Source::DOMManipulation, [this] {
|
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;
|
return;
|
||||||
|
|
||||||
// 2. Fire an event named input at the element with the bubbles and composed attributes initialized to true.
|
// 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_bubbles(true);
|
||||||
input_event->set_composed(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.
|
// 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);
|
change_event->set_bubbles(true);
|
||||||
dispatch_event(move(change_event));
|
dispatch_event(*change_event);
|
||||||
} else if (type_state() == TypeAttributeState::SubmitButton) {
|
} else if (type_state() == TypeAttributeState::SubmitButton) {
|
||||||
RefPtr<HTMLFormElement> form;
|
RefPtr<HTMLFormElement> form;
|
||||||
// 1. If the element does not have a form owner, then return.
|
// 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.
|
// 3. Submit the form owner from the element.
|
||||||
form->submit_form(this);
|
form->submit_form(this);
|
||||||
} else {
|
} 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"
|
// 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
|
// https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
|
||||||
queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
|
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_bubbles(true);
|
||||||
input_event->set_composed(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.
|
// 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);
|
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.
|
// 3. If that failed, fire an event named error at the element, then jump to the step below labeled fallback.
|
||||||
if (!url.is_valid()) {
|
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();
|
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()
|
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.
|
// 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();
|
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.
|
// 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) {
|
if (representation != Representation::NestedBrowsingContext) {
|
||||||
queue_an_element_task(HTML::Task::Source::DOMManipulation, [&]() {
|
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.
|
// 3. If the script's script is null for scriptElement, then fire an event named error at scriptElement, and return.
|
||||||
if (!m_script) {
|
if (!m_script) {
|
||||||
dbgln("HTMLScriptElement: Refusing to run script because the script's script is null.");
|
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;
|
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.
|
// 7. If scriptElement is from an external file, then fire an event named load at scriptElement.
|
||||||
if (m_from_an_external_file)
|
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
|
// https://mimesniff.spec.whatwg.org/#javascript-mime-type-essence-match
|
||||||
|
@ -259,7 +259,7 @@ void HTMLScriptElement::prepare_script()
|
||||||
if (src.is_empty()) {
|
if (src.is_empty()) {
|
||||||
dbgln("HTMLScriptElement: Refusing to run script because the src attribute is empty.");
|
dbgln("HTMLScriptElement: Refusing to run script because the src attribute is empty.");
|
||||||
queue_an_element_task(HTML::Task::Source::Unspecified, [this] {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ void HTMLScriptElement::prepare_script()
|
||||||
if (!url.is_valid()) {
|
if (!url.is_valid()) {
|
||||||
dbgln("HTMLScriptElement: Refusing to run script because the src URL '{}' is invalid.", url);
|
dbgln("HTMLScriptElement: Refusing to run script because the src URL '{}' is invalid.", url);
|
||||||
queue_an_element_task(HTML::Task::Source::Unspecified, [this] {
|
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;
|
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) 2021, Dex♪ <dexes.ttp@gmail.com>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -17,36 +18,32 @@ struct MessageEventInit : public DOM::EventInit {
|
||||||
};
|
};
|
||||||
|
|
||||||
class MessageEvent : public DOM::Event {
|
class MessageEvent : public DOM::Event {
|
||||||
|
JS_OBJECT(MessageEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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 = {})
|
MessageEvent(Bindings::WindowObject&, FlyString const& event_name, MessageEventInit const& event_init);
|
||||||
{
|
virtual ~MessageEvent() override;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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& origin() const { return m_origin; }
|
||||||
String const& last_event_id() const { return m_last_event_id; }
|
String const& last_event_id() const { return m_last_event_id; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
MessageEvent(FlyString const& event_name, MessageEventInit const& event_init)
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
: 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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Handle<JS::Value> m_data;
|
JS::Value m_data;
|
||||||
String m_origin;
|
String m_origin;
|
||||||
String m_last_event_id;
|
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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface MessageEvent : Event {
|
interface MessageEvent : Event {
|
||||||
constructor(DOMString type, optional MessageEventInit eventInitDict = {});
|
constructor(DOMString type, optional MessageEventInit eventInitDict = {});
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ void MessagePort::post_message(JS::Value message)
|
||||||
MessageEventInit event_init {};
|
MessageEventInit event_init {};
|
||||||
event_init.data = message;
|
event_init.data = message;
|
||||||
event_init.origin = "<origin>";
|
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 {
|
class PageTransitionEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(PageTransitionEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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)
|
PageTransitionEvent(Bindings::WindowObject&, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~PageTransitionEvent() override = default;
|
virtual ~PageTransitionEvent() override;
|
||||||
|
|
||||||
|
PageTransitionEvent& impl() { return *this; }
|
||||||
|
|
||||||
bool persisted() const { return m_persisted; }
|
bool persisted() const { return m_persisted; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
PageTransitionEvent(FlyString const& event_name, PageTransitionEventInit const& event_init)
|
|
||||||
: DOM::Event(event_name, event_init)
|
|
||||||
, m_persisted(event_init.persisted)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool m_persisted { false };
|
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.
|
// 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.
|
// 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);
|
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.
|
// 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.
|
// 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()
|
// 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.
|
// 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.
|
// 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) 2021, Linus Groh <linusg@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -17,35 +18,33 @@ struct PromiseRejectionEventInit : public DOM::EventInit {
|
||||||
JS::Value reason;
|
JS::Value reason;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PromiseRejectionEvent : public DOM::Event {
|
class PromiseRejectionEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(PromiseRejectionEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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 = {})
|
PromiseRejectionEvent(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init);
|
||||||
{
|
|
||||||
return adopt_ref(*new PromiseRejectionEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
static NonnullRefPtr<PromiseRejectionEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
|
||||||
{
|
|
||||||
return PromiseRejectionEvent::create(event_name, event_init);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~PromiseRejectionEvent() override = default;
|
virtual ~PromiseRejectionEvent() override;
|
||||||
|
|
||||||
|
PromiseRejectionEvent& impl() { return *this; }
|
||||||
|
|
||||||
// Needs to return a pointer for the generated JS bindings to work.
|
// Needs to return a pointer for the generated JS bindings to work.
|
||||||
JS::Promise const* promise() const { return m_promise.cell(); }
|
JS::Promise const* promise() const { return m_promise; }
|
||||||
JS::Value reason() const { return m_reason.value(); }
|
JS::Value reason() const { return m_reason; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
PromiseRejectionEvent(FlyString const& event_name, PromiseRejectionEventInit const& event_init)
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
: DOM::Event(event_name, event_init)
|
|
||||||
, m_promise(event_init.promise)
|
|
||||||
, m_reason(JS::make_handle(event_init.reason))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Handle<JS::Promise> m_promise;
|
JS::Promise* m_promise { nullptr };
|
||||||
JS::Handle<JS::Value> m_reason;
|
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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
[Exposed=(Window,Worker)]
|
[Exposed=(Window,Worker), NoInstanceWrapper]
|
||||||
interface PromiseRejectionEvent : Event {
|
interface PromiseRejectionEvent : Event {
|
||||||
constructor(DOMString type, PromiseRejectionEventInit eventInitDict);
|
constructor(DOMString type, PromiseRejectionEventInit eventInitDict);
|
||||||
|
|
||||||
|
|
|
@ -217,12 +217,12 @@ void EnvironmentSettingsObject::notify_about_rejected_promises(Badge<EventLoop>)
|
||||||
/* .promise = */ promise_handle,
|
/* .promise = */ promise_handle,
|
||||||
/* .reason = */ promise.result(),
|
/* .reason = */ promise.result(),
|
||||||
};
|
};
|
||||||
auto promise_rejection_event = PromiseRejectionEvent::create(HTML::EventNames::unhandledrejection, event_init);
|
|
||||||
|
|
||||||
// FIXME: This currently assumes that global is a WindowObject.
|
// FIXME: This currently assumes that global is a WindowObject.
|
||||||
auto& window = verify_cast<Bindings::WindowObject>(*global.cell());
|
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.
|
// 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 {
|
class SubmitEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(SubmitEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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)
|
virtual ~SubmitEvent() override;
|
||||||
{
|
|
||||||
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 = default;
|
SubmitEvent(Bindings::WindowObject&, FlyString const& event_name, SubmitEventInit const& event_init);
|
||||||
|
|
||||||
|
SubmitEvent& impl() { return *this; }
|
||||||
|
|
||||||
RefPtr<HTMLElement> submitter() const { return m_submitter; }
|
RefPtr<HTMLElement> submitter() const { return m_submitter; }
|
||||||
|
|
||||||
private:
|
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;
|
RefPtr<HTMLElement> m_submitter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#import <DOM/Event.idl>
|
#import <DOM/Event.idl>
|
||||||
#import <HTML/HTMLElement.idl>
|
#import <HTML/HTMLElement.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface SubmitEvent : Event {
|
interface SubmitEvent : Event {
|
||||||
constructor(DOMString type, optional SubmitEventInit eventInitDict = {});
|
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);
|
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);
|
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,
|
// with the persisted attribute initialized to persisted,
|
||||||
HTML::PageTransitionEventInit event_init {};
|
HTML::PageTransitionEventInit event_init {};
|
||||||
event_init.persisted = persisted;
|
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,
|
// ...the cancelable attribute initialized to true,
|
||||||
event->set_cancelable(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);
|
event->set_bubbles(true);
|
||||||
|
|
||||||
// and legacy target override flag set.
|
// and legacy target override flag set.
|
||||||
dispatch_event(move(event));
|
dispatch_event(*event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/#dom-queuemicrotask
|
// 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 {};
|
HTML::MessageEventInit event_init {};
|
||||||
event_init.data = message;
|
event_init.data = message;
|
||||||
event_init.origin = "<origin>";
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -688,4 +690,9 @@ void Window::set_associated_document(DOM::Document& document)
|
||||||
m_associated_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 ref_event_target() override { RefCounted::ref(); }
|
||||||
virtual void unref_event_target() override { RefCounted::unref(); }
|
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;
|
virtual JS::Object* create_wrapper(JS::Realm&) override;
|
||||||
|
|
||||||
Page* page();
|
Page* page();
|
||||||
|
@ -92,8 +92,9 @@ public:
|
||||||
|
|
||||||
CSS::Screen& screen() { return *m_screen; }
|
CSS::Screen& screen() { return *m_screen; }
|
||||||
|
|
||||||
DOM::Event const* current_event() const { return m_current_event; }
|
DOM::Event* current_event() { return m_current_event.cell(); }
|
||||||
void set_current_event(DOM::Event* event) { m_current_event = event; }
|
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;
|
CSS::CSSStyleDeclaration* get_computed_style(DOM::Element&) const;
|
||||||
NonnullRefPtr<CSS::MediaQueryList> match_media(String);
|
NonnullRefPtr<CSS::MediaQueryList> match_media(String);
|
||||||
|
@ -157,7 +158,7 @@ private:
|
||||||
NonnullOwnPtr<HighResolutionTime::Performance> m_performance;
|
NonnullOwnPtr<HighResolutionTime::Performance> m_performance;
|
||||||
NonnullRefPtr<Crypto::Crypto> m_crypto;
|
NonnullRefPtr<Crypto::Crypto> m_crypto;
|
||||||
NonnullOwnPtr<CSS::Screen> m_screen;
|
NonnullOwnPtr<CSS::Screen> m_screen;
|
||||||
RefPtr<DOM::Event> m_current_event;
|
JS::Handle<DOM::Event> m_current_event;
|
||||||
|
|
||||||
AnimationFrameCallbackDriver m_animation_frame_callback_driver;
|
AnimationFrameCallbackDriver m_animation_frame_callback_driver;
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,8 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti
|
||||||
MessageEventInit event_init {};
|
MessageEventInit event_init {};
|
||||||
event_init.data = message;
|
event_init.data = message;
|
||||||
event_init.origin = "<origin>";
|
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();
|
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);
|
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;
|
handled_event = true;
|
||||||
|
|
||||||
bool run_activation_behavior = true;
|
bool run_activation_behavior = true;
|
||||||
if (node.ptr() == m_mousedown_target && button == GUI::MouseButton::Primary) {
|
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) {
|
if (run_activation_behavior) {
|
||||||
|
@ -334,7 +334,7 @@ bool EventHandler::handle_mousedown(Gfx::IntPoint const& position, unsigned butt
|
||||||
|
|
||||||
m_mousedown_target = node;
|
m_mousedown_target = node;
|
||||||
auto offset = compute_mouse_event_offset(position, *layout_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.
|
// 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);
|
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.
|
// NOTE: Dispatching an event may have disturbed the world.
|
||||||
if (!paint_root() || paint_root() != node->document().paint_box())
|
if (!paint_root() || paint_root() != node->document().paint_box())
|
||||||
return true;
|
return true;
|
||||||
|
@ -543,7 +543,7 @@ bool EventHandler::handle_doubleclick(Gfx::IntPoint const& position, unsigned bu
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto offset = compute_mouse_event_offset(position, *layout_node);
|
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.
|
// NOTE: Dispatching an event may have disturbed the world.
|
||||||
if (!paint_root() || paint_root() != node->document().paint_box())
|
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;
|
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())
|
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())
|
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)
|
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)
|
if (!document)
|
||||||
return false;
|
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())
|
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())
|
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)
|
void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_node)
|
||||||
|
|
|
@ -4,13 +4,21 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/Bindings/FocusEventPrototype.h>
|
||||||
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/UIEvents/FocusEvent.h>
|
#include <LibWeb/UIEvents/FocusEvent.h>
|
||||||
|
|
||||||
namespace Web::UIEvents {
|
namespace Web::UIEvents {
|
||||||
|
|
||||||
FocusEvent::FocusEvent(FlyString const& event_name, FocusEventInit const& event_init)
|
FocusEvent* FocusEvent::create_with_global_object(Bindings::WindowObject& window_object, FlyString const& event_name, FocusEventInit const& event_init)
|
||||||
: UIEvent(event_name)
|
|
||||||
{
|
{
|
||||||
|
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()));
|
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 {
|
class FocusEvent final : public UIEvent {
|
||||||
public:
|
JS_OBJECT(FocusEvent, UIEvent);
|
||||||
using WrapperType = Bindings::FocusEventWrapper;
|
|
||||||
|
|
||||||
|
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;
|
virtual ~FocusEvent() override;
|
||||||
|
|
||||||
static NonnullRefPtr<FocusEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, FocusEventInit const& event_init)
|
FocusEvent& impl() { return *this; }
|
||||||
{
|
|
||||||
return adopt_ref(*new FocusEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
FocusEvent(FlyString const& event_name, FocusEventInit const&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>
|
#import <UIEvents/UIEvent.idl>
|
||||||
|
|
||||||
[Exposed=Window]
|
[Exposed=Window, NoInstanceWrapper]
|
||||||
interface FocusEvent : UIEvent {
|
interface FocusEvent : UIEvent {
|
||||||
|
|
||||||
constructor(DOMString type, optional FocusEventInit eventInitDict = {});
|
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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/CharacterTypes.h>
|
#include <AK/CharacterTypes.h>
|
||||||
|
#include <LibWeb/Bindings/KeyboardEventPrototype.h>
|
||||||
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/UIEvents/KeyboardEvent.h>
|
#include <LibWeb/UIEvents/KeyboardEvent.h>
|
||||||
|
|
||||||
namespace Web::UIEvents {
|
namespace Web::UIEvents {
|
||||||
|
@ -65,7 +67,7 @@ static unsigned long determine_key_code(KeyCode platform_key, u32 code_point)
|
||||||
return platform_key;
|
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.
|
// FIXME: Figure out what these should actually contain.
|
||||||
String event_key = key_code_to_string(platform_key);
|
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.bubbles = true;
|
||||||
event_init.cancelable = true;
|
event_init.cancelable = true;
|
||||||
event_init.composed = 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)
|
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 m_meta_key;
|
||||||
return false;
|
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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -25,21 +25,18 @@ struct KeyboardEventInit : public EventModifierInit {
|
||||||
|
|
||||||
// https://www.w3.org/TR/uievents/#interface-keyboardevent
|
// https://www.w3.org/TR/uievents/#interface-keyboardevent
|
||||||
class KeyboardEvent final : public UIEvent {
|
class KeyboardEvent final : public UIEvent {
|
||||||
|
JS_OBJECT(KeyboardEvent, UIEvent);
|
||||||
|
|
||||||
public:
|
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 = {})
|
KeyboardEvent(Bindings::WindowObject&, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 key_code() const { return m_key_code; }
|
||||||
u32 char_code() const { return m_char_code; }
|
u32 char_code() const { return m_char_code; }
|
||||||
|
@ -61,20 +58,6 @@ public:
|
||||||
virtual u32 which() const override { return m_key_code; }
|
virtual u32 which() const override { return m_key_code; }
|
||||||
|
|
||||||
private:
|
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_key;
|
||||||
String m_code;
|
String m_code;
|
||||||
u32 m_location { 0 };
|
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>
|
#import <UIEvents/EventModifier.idl>
|
||||||
|
|
||||||
[Exposed=Window]
|
[Exposed=Window, NoInstanceWrapper]
|
||||||
interface KeyboardEvent : UIEvent {
|
interface KeyboardEvent : UIEvent {
|
||||||
|
|
||||||
constructor(DOMString type, optional KeyboardEventInit eventInitDict = {});
|
constructor(DOMString type, optional KeyboardEventInit eventInitDict = {});
|
||||||
|
|
|
@ -1,27 +1,33 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, the SerenityOS developers.
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibGUI/Event.h>
|
#include <LibGUI/Event.h>
|
||||||
|
#include <LibWeb/Bindings/MouseEventPrototype.h>
|
||||||
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
#include <LibWeb/HTML/EventNames.h>
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
#include <LibWeb/UIEvents/EventNames.h>
|
#include <LibWeb/UIEvents/EventNames.h>
|
||||||
#include <LibWeb/UIEvents/MouseEvent.h>
|
#include <LibWeb/UIEvents/MouseEvent.h>
|
||||||
|
|
||||||
namespace Web::UIEvents {
|
namespace Web::UIEvents {
|
||||||
|
|
||||||
MouseEvent::MouseEvent(FlyString const& event_name, MouseEventInit const& event_init)
|
MouseEvent::MouseEvent(Bindings::WindowObject& window_object, FlyString const& event_name, MouseEventInit const& event_init)
|
||||||
: UIEvent(event_name, event_init)
|
: UIEvent(window_object, event_name, event_init)
|
||||||
, m_offset_x(event_init.offset_x)
|
, m_offset_x(event_init.offset_x)
|
||||||
, m_offset_y(event_init.offset_y)
|
, m_offset_y(event_init.offset_y)
|
||||||
, m_client_x(event_init.client_x)
|
, m_client_x(event_init.client_x)
|
||||||
, m_client_y(event_init.client_y)
|
, m_client_y(event_init.client_y)
|
||||||
, m_button(event_init.button)
|
, m_button(event_init.button)
|
||||||
{
|
{
|
||||||
|
set_prototype(&window_object.ensure_web_prototype<Bindings::MouseEventPrototype>("MouseEvent"));
|
||||||
set_event_characteristics();
|
set_event_characteristics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MouseEvent::~MouseEvent() = default;
|
||||||
|
|
||||||
// https://www.w3.org/TR/uievents/#dom-mouseevent-button
|
// https://www.w3.org/TR/uievents/#dom-mouseevent-button
|
||||||
static i16 determine_button(unsigned mouse_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 {};
|
MouseEventInit event_init {};
|
||||||
event_init.offset_x = offset_x;
|
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_x = client_x;
|
||||||
event_init.client_y = client_y;
|
event_init.client_y = client_y;
|
||||||
event_init.button = determine_button(mouse_button);
|
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()
|
void MouseEvent::set_event_characteristics()
|
||||||
|
|
|
@ -22,17 +22,17 @@ struct MouseEventInit : public EventModifierInit {
|
||||||
};
|
};
|
||||||
|
|
||||||
class MouseEvent final : public UIEvent {
|
class MouseEvent final : public UIEvent {
|
||||||
|
JS_OBJECT(MouseEvent, UIEvent);
|
||||||
|
|
||||||
public:
|
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 = {})
|
MouseEvent(Bindings::WindowObject&, FlyString const& event_name, MouseEventInit const& event_init);
|
||||||
{
|
|
||||||
return adopt_ref(*new MouseEvent(event_name, 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_x() const { return m_offset_x; }
|
||||||
double offset_y() const { return m_offset_y; }
|
double offset_y() const { return m_offset_y; }
|
||||||
|
@ -48,8 +48,6 @@ public:
|
||||||
virtual u32 which() const override { return m_button + 1; }
|
virtual u32 which() const override { return m_button + 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MouseEvent(FlyString const& event_name, MouseEventInit const& event_init);
|
|
||||||
|
|
||||||
void set_event_characteristics();
|
void set_event_characteristics();
|
||||||
|
|
||||||
double m_offset_x { 0 };
|
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 {
|
class UIEvent : public DOM::Event {
|
||||||
|
JS_OBJECT(UIEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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)
|
UIEvent(Bindings::WindowObject&, FlyString const& event_name);
|
||||||
{
|
UIEvent(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init);
|
||||||
return adopt_ref(*new UIEvent(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
static NonnullRefPtr<UIEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, UIEventInit const& event_init)
|
virtual ~UIEvent() override;
|
||||||
{
|
|
||||||
return adopt_ref(*new UIEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~UIEvent() override = default;
|
UIEvent& impl() { return *this; }
|
||||||
|
|
||||||
HTML::Window const* view() const { return m_view; }
|
HTML::Window const* view() const { return m_view; }
|
||||||
int detail() const { return m_detail; }
|
int detail() const { return m_detail; }
|
||||||
|
@ -45,19 +43,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
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;
|
RefPtr<HTML::Window> m_view;
|
||||||
int m_detail { 0 };
|
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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface UIEvent : Event {
|
interface UIEvent : Event {
|
||||||
constructor(DOMString type, optional UIEventInit eventInitDict = {});
|
constructor(DOMString type, optional UIEventInit eventInitDict = {});
|
||||||
readonly attribute Window? view;
|
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, Luke Wilde <lukew@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -15,31 +16,27 @@ struct WebGLContextEventInit final : public DOM::EventInit {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebGLContextEvent final : public DOM::Event {
|
class WebGLContextEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(WebGLContextEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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)
|
WebGLContextEvent(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init);
|
||||||
{
|
|
||||||
return adopt_ref(*new WebGLContextEvent(type, event_init));
|
|
||||||
}
|
|
||||||
|
|
||||||
static NonnullRefPtr<WebGLContextEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& type, WebGLContextEventInit const& event_init)
|
virtual ~WebGLContextEvent() override;
|
||||||
{
|
|
||||||
return adopt_ref(*new WebGLContextEvent(type, event_init));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~WebGLContextEvent() override = default;
|
WebGLContextEvent& impl() { return *this; }
|
||||||
|
|
||||||
String const& status_message() const { return m_status_message; }
|
String const& status_message() const { return m_status_message; }
|
||||||
|
|
||||||
private:
|
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() };
|
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/Bindings/Wrapper.h>
|
||||||
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/HTML/HTMLCanvasElement.h>
|
#include <LibWeb/HTML/HTMLCanvasElement.h>
|
||||||
#include <LibWeb/WebGL/WebGLContextEvent.h>
|
#include <LibWeb/WebGL/WebGLContextEvent.h>
|
||||||
#include <LibWeb/WebGL/WebGLRenderingContext.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.
|
// 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.
|
// 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_is_trusted(true);
|
||||||
event->set_cancelable(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
|
// 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/Parser.h>
|
||||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||||
#include <LibJS/Runtime/FunctionObject.h>
|
#include <LibJS/Runtime/FunctionObject.h>
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/WebSocketWrapper.h>
|
#include <LibWeb/Bindings/WebSocketWrapper.h>
|
||||||
#include <LibWeb/DOM/DOMException.h>
|
#include <LibWeb/DOM/DOMException.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
@ -173,13 +172,13 @@ void WebSocket::on_open()
|
||||||
// 1. Change the readyState attribute's value to OPEN (1).
|
// 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]
|
// 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]
|
// 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
|
// https://websockets.spec.whatwg.org/#feedback-from-the-protocol
|
||||||
void WebSocket::on_error()
|
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
|
// 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.was_clean = was_clean;
|
||||||
event_init.code = code;
|
event_init.code = code;
|
||||||
event_init.reason = move(reason);
|
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
|
// 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;
|
HTML::MessageEventInit event_init;
|
||||||
event_init.data = JS::js_string(wrapper()->vm(), text_message);
|
event_init.data = JS::js_string(wrapper()->vm(), text_message);
|
||||||
event_init.origin = url();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +217,7 @@ void WebSocket::on_message(ByteBuffer message, bool is_text)
|
||||||
HTML::MessageEventInit event_init;
|
HTML::MessageEventInit event_init;
|
||||||
event_init.data = JS::ArrayBuffer::create(realm, message);
|
event_init.data = JS::ArrayBuffer::create(realm, message);
|
||||||
event_init.origin = url();
|
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;
|
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 };
|
u32 total { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProgressEvent : public DOM::Event {
|
class ProgressEvent final : public DOM::Event {
|
||||||
|
JS_OBJECT(ProgressEvent, DOM::Event);
|
||||||
|
|
||||||
public:
|
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)
|
ProgressEvent(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init);
|
||||||
{
|
|
||||||
return adopt_ref(*new ProgressEvent(event_name, event_init));
|
|
||||||
}
|
|
||||||
static NonnullRefPtr<ProgressEvent> create_with_global_object(Bindings::WindowObject&, FlyString const& event_name, ProgressEventInit const& event_init)
|
|
||||||
{
|
|
||||||
return ProgressEvent::create(event_name, event_init);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~ProgressEvent() override = default;
|
virtual ~ProgressEvent() override;
|
||||||
|
|
||||||
|
ProgressEvent& impl() { return *this; }
|
||||||
|
|
||||||
bool length_computable() const { return m_length_computable; }
|
bool length_computable() const { return m_length_computable; }
|
||||||
u64 loaded() const { return m_loaded; }
|
u64 loaded() const { return m_loaded; }
|
||||||
u64 total() const { return m_total; }
|
u64 total() const { return m_total; }
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool m_length_computable { false };
|
bool m_length_computable { false };
|
||||||
u64 m_loaded { 0 };
|
u64 m_loaded { 0 };
|
||||||
u64 m_total { 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>
|
#import <DOM/Event.idl>
|
||||||
|
|
||||||
|
[NoInstanceWrapper]
|
||||||
interface ProgressEvent : Event {
|
interface ProgressEvent : Event {
|
||||||
constructor(DOMString type, optional ProgressEventInit eventInitDict = {});
|
constructor(DOMString type, optional ProgressEventInit eventInitDict = {});
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include <LibJS/Runtime/FunctionObject.h>
|
#include <LibJS/Runtime/FunctionObject.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibTextCodec/Decoder.h>
|
#include <LibTextCodec/Decoder.h>
|
||||||
#include <LibWeb/Bindings/EventWrapper.h>
|
|
||||||
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
#include <LibWeb/Bindings/IDLAbstractOperations.h>
|
||||||
#include <LibWeb/Bindings/XMLHttpRequestWrapper.h>
|
#include <LibWeb/Bindings/XMLHttpRequestWrapper.h>
|
||||||
#include <LibWeb/DOM/DOMException.h>
|
#include <LibWeb/DOM/DOMException.h>
|
||||||
|
@ -53,7 +52,7 @@ XMLHttpRequest::~XMLHttpRequest() = default;
|
||||||
void XMLHttpRequest::set_ready_state(ReadyState ready_state)
|
void XMLHttpRequest::set_ready_state(ReadyState ready_state)
|
||||||
{
|
{
|
||||||
m_ready_state = 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)
|
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.length_computable = true;
|
||||||
event_init.loaded = transmitted;
|
event_init.loaded = transmitted;
|
||||||
event_init.total = length;
|
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
|
// 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)) {
|
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);
|
dbgln("XHR failed to load: Same-Origin Policy violation: {} may not load {}", m_window->associated_document().url(), request_url);
|
||||||
set_ready_state(ReadyState::Done);
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +538,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod
|
||||||
xhr.m_status = status_code.value_or(0);
|
xhr.m_status = status_code.value_or(0);
|
||||||
xhr.m_response_headers = move(response_headers);
|
xhr.m_response_headers = move(response_headers);
|
||||||
xhr.m_send = false;
|
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::load, transmitted, length);
|
||||||
xhr.fire_progress_event(EventNames::loadend, 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);
|
auto& xhr = const_cast<XMLHttpRequest&>(*strong_this);
|
||||||
xhr.set_ready_state(ReadyState::Done);
|
xhr.set_ready_state(ReadyState::Done);
|
||||||
xhr.set_status(status_code.value_or(0));
|
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,
|
m_timeout,
|
||||||
[weak_this = make_weak_ptr()] {
|
[weak_this = make_weak_ptr()] {
|
||||||
|
@ -559,7 +558,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> bod
|
||||||
if (!strong_this)
|
if (!strong_this)
|
||||||
return;
|
return;
|
||||||
auto& xhr = const_cast<XMLHttpRequest&>(*strong_this);
|
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 {
|
} else {
|
||||||
TODO();
|
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.
|
// 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.
|
// 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);
|
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.
|
// 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.
|
// 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()
|
// 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.
|
// 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.
|
// 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/CSSSupportsRule NO_INSTANCE)
|
||||||
libweb_js_wrapper(CSS/MediaList NO_INSTANCE)
|
libweb_js_wrapper(CSS/MediaList NO_INSTANCE)
|
||||||
libweb_js_wrapper(CSS/MediaQueryList)
|
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/Screen)
|
||||||
libweb_js_wrapper(CSS/StyleSheet NO_INSTANCE)
|
libweb_js_wrapper(CSS/StyleSheet NO_INSTANCE)
|
||||||
libweb_js_wrapper(CSS/StyleSheetList 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/CDATASection)
|
||||||
libweb_js_wrapper(DOM/CharacterData)
|
libweb_js_wrapper(DOM/CharacterData)
|
||||||
libweb_js_wrapper(DOM/Comment)
|
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/Document)
|
||||||
libweb_js_wrapper(DOM/DocumentFragment)
|
libweb_js_wrapper(DOM/DocumentFragment)
|
||||||
libweb_js_wrapper(DOM/DocumentType)
|
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/DOMImplementation NO_INSTANCE)
|
||||||
libweb_js_wrapper(DOM/DOMTokenList NO_INSTANCE)
|
libweb_js_wrapper(DOM/DOMTokenList NO_INSTANCE)
|
||||||
libweb_js_wrapper(DOM/Element)
|
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/EventTarget)
|
||||||
libweb_js_wrapper(DOM/HTMLCollection)
|
libweb_js_wrapper(DOM/HTMLCollection)
|
||||||
libweb_js_wrapper(DOM/MutationRecord)
|
libweb_js_wrapper(DOM/MutationRecord)
|
||||||
|
@ -63,10 +63,10 @@ libweb_js_wrapper(Geometry/DOMRectList)
|
||||||
libweb_js_wrapper(Geometry/DOMRectReadOnly)
|
libweb_js_wrapper(Geometry/DOMRectReadOnly)
|
||||||
libweb_js_wrapper(HTML/CanvasGradient)
|
libweb_js_wrapper(HTML/CanvasGradient)
|
||||||
libweb_js_wrapper(HTML/CanvasRenderingContext2D)
|
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/DOMParser)
|
||||||
libweb_js_wrapper(HTML/DOMStringMap NO_INSTANCE)
|
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/History)
|
||||||
libweb_js_wrapper(HTML/HTMLAnchorElement)
|
libweb_js_wrapper(HTML/HTMLAnchorElement)
|
||||||
libweb_js_wrapper(HTML/HTMLAreaElement)
|
libweb_js_wrapper(HTML/HTMLAreaElement)
|
||||||
|
@ -142,13 +142,13 @@ libweb_js_wrapper(HTML/HTMLUnknownElement)
|
||||||
libweb_js_wrapper(HTML/HTMLVideoElement)
|
libweb_js_wrapper(HTML/HTMLVideoElement)
|
||||||
libweb_js_wrapper(HTML/ImageData)
|
libweb_js_wrapper(HTML/ImageData)
|
||||||
libweb_js_wrapper(HTML/MessageChannel)
|
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/MessagePort)
|
||||||
libweb_js_wrapper(HTML/PageTransitionEvent)
|
libweb_js_wrapper(HTML/PageTransitionEvent NO_INSTANCE)
|
||||||
libweb_js_wrapper(HTML/Path2D)
|
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/Storage)
|
||||||
libweb_js_wrapper(HTML/SubmitEvent)
|
libweb_js_wrapper(HTML/SubmitEvent NO_INSTANCE)
|
||||||
libweb_js_wrapper(HTML/TextMetrics)
|
libweb_js_wrapper(HTML/TextMetrics)
|
||||||
libweb_js_wrapper(HTML/Worker)
|
libweb_js_wrapper(HTML/Worker)
|
||||||
libweb_js_wrapper(HTML/WorkerGlobalScope)
|
libweb_js_wrapper(HTML/WorkerGlobalScope)
|
||||||
|
@ -176,15 +176,15 @@ libweb_js_wrapper(SVG/SVGRectElement)
|
||||||
libweb_js_wrapper(SVG/SVGSVGElement)
|
libweb_js_wrapper(SVG/SVGSVGElement)
|
||||||
libweb_js_wrapper(SVG/SVGTextContentElement)
|
libweb_js_wrapper(SVG/SVGTextContentElement)
|
||||||
libweb_js_wrapper(Selection/Selection)
|
libweb_js_wrapper(Selection/Selection)
|
||||||
libweb_js_wrapper(UIEvents/FocusEvent)
|
libweb_js_wrapper(UIEvents/FocusEvent NO_INSTANCE)
|
||||||
libweb_js_wrapper(UIEvents/KeyboardEvent)
|
libweb_js_wrapper(UIEvents/KeyboardEvent NO_INSTANCE)
|
||||||
libweb_js_wrapper(UIEvents/MouseEvent)
|
libweb_js_wrapper(UIEvents/MouseEvent NO_INSTANCE)
|
||||||
libweb_js_wrapper(UIEvents/UIEvent)
|
libweb_js_wrapper(UIEvents/UIEvent NO_INSTANCE)
|
||||||
libweb_js_wrapper(URL/URL)
|
libweb_js_wrapper(URL/URL)
|
||||||
libweb_js_wrapper(URL/URLSearchParams ITERABLE)
|
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(WebGL/WebGLRenderingContext)
|
||||||
libweb_js_wrapper(WebSockets/WebSocket)
|
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/XMLHttpRequest)
|
||||||
libweb_js_wrapper(XHR/XMLHttpRequestEventTarget)
|
libweb_js_wrapper(XHR/XMLHttpRequestEventTarget)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue