mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:47:37 +00:00
LibWeb: Move event listeners, handlers and callbacks to the GC heap
This patch moves the following things to being GC-allocated: - Bindings::CallbackType - HTML::EventHandler - DOM::IDLEventListener - DOM::DOMEventListener - DOM::NodeFilter Note that we only use PlatformObject for things that might be exposed to web content. Anything that is only used internally inherits directly from JS::Cell instead, making them a bit more lightweight.
This commit is contained in:
parent
967a3e5a45
commit
8cda70c892
57 changed files with 425 additions and 345 deletions
32
Userland/Libraries/LibWeb/HTML/EventHandler.cpp
Normal file
32
Userland/Libraries/LibWeb/HTML/EventHandler.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/WindowObject.h>
|
||||
#include <LibWeb/DOM/DOMEventListener.h>
|
||||
#include <LibWeb/HTML/EventHandler.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
EventHandler::EventHandler(String s)
|
||||
: value(move(s))
|
||||
{
|
||||
}
|
||||
|
||||
EventHandler::EventHandler(Bindings::CallbackType& c)
|
||||
: value(&c)
|
||||
{
|
||||
}
|
||||
|
||||
void EventHandler::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Cell::visit_edges(visitor);
|
||||
visitor.visit(listener);
|
||||
|
||||
if (auto* callback = value.get_pointer<Bindings::CallbackType*>())
|
||||
visitor.visit(*callback);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
@ -8,33 +8,29 @@
|
|||
|
||||
#include <AK/String.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <LibJS/Heap/Handle.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibJS/Heap/Cell.h>
|
||||
#include <LibWeb/Bindings/CallbackType.h>
|
||||
#include <LibWeb/DOM/DOMEventListener.h>
|
||||
|
||||
namespace Web::HTML {
|
||||
|
||||
struct EventHandler {
|
||||
EventHandler(String s)
|
||||
: value(move(s))
|
||||
{
|
||||
}
|
||||
|
||||
EventHandler(Bindings::CallbackType c)
|
||||
: value(move(c))
|
||||
{
|
||||
}
|
||||
class EventHandler final : public JS::Cell {
|
||||
public:
|
||||
explicit EventHandler(String);
|
||||
explicit EventHandler(Bindings::CallbackType&);
|
||||
|
||||
// Either uncompiled source code or a callback.
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-value
|
||||
// NOTE: This does not contain Empty as part of the optimization of not allocating all event handler attributes up front.
|
||||
// FIXME: The string should actually be an "internal raw uncompiled handler" struct. This struct is just the uncompiled source code plus a source location for reporting parse errors.
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#internal-raw-uncompiled-handler
|
||||
Variant<String, Bindings::CallbackType> value;
|
||||
Variant<String, Bindings::CallbackType*> value;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-listener
|
||||
RefPtr<DOM::DOMEventListener> listener;
|
||||
DOM::DOMEventListener* listener { nullptr };
|
||||
|
||||
private:
|
||||
virtual StringView class_name() const override { return "EventHandler"sv; }
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
namespace Web::HTML {
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void GlobalEventHandlers::set_##attribute_name(Optional<Bindings::CallbackType> value) \
|
||||
{ \
|
||||
global_event_handlers_to_event_target(event_name).set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* GlobalEventHandlers::attribute_name() \
|
||||
{ \
|
||||
return global_event_handlers_to_event_target(event_name).event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void GlobalEventHandlers::set_##attribute_name(Bindings::CallbackType* value) \
|
||||
{ \
|
||||
global_event_handlers_to_event_target(event_name).set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
Bindings::CallbackType* GlobalEventHandlers::attribute_name() \
|
||||
{ \
|
||||
return global_event_handlers_to_event_target(event_name).event_handler_attribute(event_name); \
|
||||
}
|
||||
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -84,8 +84,8 @@ public:
|
|||
virtual ~GlobalEventHandlers();
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Optional<Bindings::CallbackType>); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Bindings::CallbackType*); \
|
||||
Bindings::CallbackType* attribute_name();
|
||||
ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -106,14 +106,14 @@ void MessagePort::close()
|
|||
}
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void MessagePort::set_##attribute_name(Optional<Bindings::CallbackType> value) \
|
||||
{ \
|
||||
set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* MessagePort::attribute_name() \
|
||||
{ \
|
||||
return event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void MessagePort::set_##attribute_name(Bindings::CallbackType* value) \
|
||||
{ \
|
||||
set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
Bindings::CallbackType* MessagePort::attribute_name() \
|
||||
{ \
|
||||
return event_handler_attribute(event_name); \
|
||||
}
|
||||
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -53,8 +53,8 @@ public:
|
|||
void close();
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Optional<Bindings::CallbackType>); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Bindings::CallbackType*); \
|
||||
Bindings::CallbackType* attribute_name();
|
||||
ENUMERATE_MESSAGE_PORT_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -173,8 +173,8 @@ i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 t
|
|||
|
||||
handler.visit(
|
||||
// 2. If handler is a Function, then invoke handler given arguments with the callback this value set to thisArg. If this throws an exception, catch it, and report the exception.
|
||||
[&](Bindings::CallbackType& callback) {
|
||||
if (auto result = Bindings::IDL::invoke_callback(callback, window->wrapper(), arguments); result.is_error())
|
||||
[&](JS::Handle<Bindings::CallbackType> callback) {
|
||||
if (auto result = Bindings::IDL::invoke_callback(*callback, window->wrapper(), arguments); result.is_error())
|
||||
HTML::report_exception(result);
|
||||
},
|
||||
// 3. Otherwise:
|
||||
|
@ -237,9 +237,9 @@ i32 Window::run_timer_initialization_steps(Bindings::TimerHandler handler, i32 t
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#run-the-animation-frame-callbacks
|
||||
i32 Window::request_animation_frame(NonnullOwnPtr<Bindings::CallbackType> js_callback)
|
||||
i32 Window::request_animation_frame(Bindings::CallbackType& js_callback)
|
||||
{
|
||||
return m_animation_frame_callback_driver.add([this, js_callback = move(js_callback)](auto) mutable {
|
||||
return m_animation_frame_callback_driver.add([this, js_callback = JS::make_handle(js_callback)](auto) mutable {
|
||||
// 3. Invoke callback, passing now as the only argument,
|
||||
auto result = Bindings::IDL::invoke_callback(*js_callback, {}, JS::Value(performance().now()));
|
||||
|
||||
|
@ -471,10 +471,10 @@ void Window::fire_a_page_transition_event(FlyString const& event_name, bool pers
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-queuemicrotask
|
||||
void Window::queue_microtask(NonnullOwnPtr<Bindings::CallbackType> callback)
|
||||
void Window::queue_microtask(Bindings::CallbackType& callback)
|
||||
{
|
||||
// The queueMicrotask(callback) method must queue a microtask to invoke callback,
|
||||
HTML::queue_a_microtask(&associated_document(), [callback = move(callback)]() mutable {
|
||||
HTML::queue_a_microtask(&associated_document(), [callback = JS::make_handle(callback)]() mutable {
|
||||
auto result = Bindings::IDL::invoke_callback(*callback, {});
|
||||
// and if callback throws an exception, report the exception.
|
||||
if (result.is_error())
|
||||
|
@ -643,7 +643,7 @@ void Window::invoke_idle_callbacks()
|
|||
}
|
||||
|
||||
// https://w3c.github.io/requestidlecallback/#the-requestidlecallback-method
|
||||
u32 Window::request_idle_callback(NonnullOwnPtr<Bindings::CallbackType> callback)
|
||||
u32 Window::request_idle_callback(Bindings::CallbackType& callback)
|
||||
{
|
||||
// 1. Let window be this Window object.
|
||||
auto& window = *this;
|
||||
|
@ -652,8 +652,8 @@ u32 Window::request_idle_callback(NonnullOwnPtr<Bindings::CallbackType> callback
|
|||
// 3. Let handle be the current value of window's idle callback identifier.
|
||||
auto handle = window.m_idle_callback_identifier;
|
||||
// 4. Push callback to the end of window's list of idle request callbacks, associated with handle.
|
||||
auto handler = [callback = move(callback)](NonnullRefPtr<RequestIdleCallback::IdleDeadline> deadline) -> JS::Completion {
|
||||
auto& realm = callback->callback.cell()->shape().realm();
|
||||
auto handler = [callback = JS::make_handle(callback)](NonnullRefPtr<RequestIdleCallback::IdleDeadline> deadline) -> JS::Completion {
|
||||
auto& realm = callback->callback.shape().realm();
|
||||
auto* wrapped_deadline = Bindings::wrap(realm, *deadline);
|
||||
return Bindings::IDL::invoke_callback(const_cast<Bindings::CallbackType&>(*callback), {}, JS::Value(wrapped_deadline));
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
void alert(String const&);
|
||||
bool confirm(String const&);
|
||||
String prompt(String const&, String const&);
|
||||
i32 request_animation_frame(NonnullOwnPtr<Bindings::CallbackType> js_callback);
|
||||
i32 request_animation_frame(Bindings::CallbackType& js_callback);
|
||||
void cancel_animation_frame(i32);
|
||||
bool has_animation_frame_callbacks() const { return m_animation_frame_callback_driver.has_callbacks(); }
|
||||
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
void clear_timeout(i32);
|
||||
void clear_interval(i32);
|
||||
|
||||
void queue_microtask(NonnullOwnPtr<Bindings::CallbackType> callback);
|
||||
void queue_microtask(Bindings::CallbackType& callback);
|
||||
|
||||
int inner_width() const;
|
||||
int inner_height() const;
|
||||
|
@ -123,7 +123,7 @@ public:
|
|||
|
||||
void start_an_idle_period();
|
||||
|
||||
u32 request_idle_callback(NonnullOwnPtr<Bindings::CallbackType> callback);
|
||||
u32 request_idle_callback(Bindings::CallbackType& callback);
|
||||
void cancel_idle_callback(u32);
|
||||
|
||||
AnimationFrameCallbackDriver& animation_frame_callback_driver() { return m_animation_frame_callback_driver; }
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
namespace Web::HTML {
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void WindowEventHandlers::set_##attribute_name(Optional<Bindings::CallbackType> value) \
|
||||
{ \
|
||||
window_event_handlers_to_event_target().set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* WindowEventHandlers::attribute_name() \
|
||||
{ \
|
||||
return window_event_handlers_to_event_target().event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void WindowEventHandlers::set_##attribute_name(Bindings::CallbackType* value) \
|
||||
{ \
|
||||
window_event_handlers_to_event_target().set_event_handler_attribute(event_name, value); \
|
||||
} \
|
||||
Bindings::CallbackType* WindowEventHandlers::attribute_name() \
|
||||
{ \
|
||||
return window_event_handlers_to_event_target().event_handler_attribute(event_name); \
|
||||
}
|
||||
ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
virtual ~WindowEventHandlers();
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Optional<Bindings::CallbackType>); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Bindings::CallbackType*); \
|
||||
Bindings::CallbackType* attribute_name();
|
||||
ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -324,14 +324,14 @@ JS::Object* Worker::create_wrapper(JS::Realm& realm)
|
|||
}
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void Worker::set_##attribute_name(Optional<Bindings::CallbackType> value) \
|
||||
{ \
|
||||
set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* Worker::attribute_name() \
|
||||
{ \
|
||||
return event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void Worker::set_##attribute_name(Bindings::CallbackType* value) \
|
||||
{ \
|
||||
set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* Worker::attribute_name() \
|
||||
{ \
|
||||
return event_handler_attribute(event_name); \
|
||||
}
|
||||
ENUMERATE_WORKER_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -64,8 +64,8 @@ public:
|
|||
RefPtr<MessagePort> outside_message_port() { return m_outside_port; }
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Optional<Bindings::CallbackType>); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Bindings::CallbackType*); \
|
||||
Bindings::CallbackType* attribute_name();
|
||||
ENUMERATE_WORKER_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -75,14 +75,14 @@ NonnullRefPtr<WorkerNavigator const> WorkerGlobalScope::navigator() const
|
|||
}
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void WorkerGlobalScope::set_##attribute_name(Optional<Bindings::CallbackType> value) \
|
||||
{ \
|
||||
set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* WorkerGlobalScope::attribute_name() \
|
||||
{ \
|
||||
return event_handler_attribute(event_name); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void WorkerGlobalScope::set_##attribute_name(Bindings::CallbackType* value) \
|
||||
{ \
|
||||
set_event_handler_attribute(event_name, move(value)); \
|
||||
} \
|
||||
Bindings::CallbackType* WorkerGlobalScope::attribute_name() \
|
||||
{ \
|
||||
return event_handler_attribute(event_name); \
|
||||
}
|
||||
ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
DOM::ExceptionOr<void> import_scripts(Vector<String> urls);
|
||||
|
||||
#undef __ENUMERATE
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Optional<Bindings::CallbackType>); \
|
||||
#define __ENUMERATE(attribute_name, event_name) \
|
||||
void set_##attribute_name(Bindings::CallbackType*); \
|
||||
Bindings::CallbackType* attribute_name();
|
||||
ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue