diff options
Diffstat (limited to 'Userland')
56 files changed, 415 insertions, 333 deletions
diff --git a/Userland/Libraries/LibWeb/Bindings/CallbackType.cpp b/Userland/Libraries/LibWeb/Bindings/CallbackType.cpp new file mode 100644 index 0000000000..a575548be5 --- /dev/null +++ b/Userland/Libraries/LibWeb/Bindings/CallbackType.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibJS/Runtime/Object.h> +#include <LibWeb/Bindings/CallbackType.h> + +namespace Web::Bindings { + +CallbackType::CallbackType(JS::Object& callback, HTML::EnvironmentSettingsObject& callback_context) + : callback(callback) + , callback_context(callback_context) +{ +} + +StringView CallbackType::class_name() const { return "CallbackType"sv; } +void CallbackType::visit_edges(Cell::Visitor& visitor) +{ + Cell::visit_edges(visitor); + visitor.visit(&callback); +} + +} diff --git a/Userland/Libraries/LibWeb/Bindings/CallbackType.h b/Userland/Libraries/LibWeb/Bindings/CallbackType.h index 8b4d0cd538..b1f2cebbb3 100644 --- a/Userland/Libraries/LibWeb/Bindings/CallbackType.h +++ b/Userland/Libraries/LibWeb/Bindings/CallbackType.h @@ -1,28 +1,30 @@ /* * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org> + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include <LibJS/Heap/Handle.h> +#include <LibJS/Heap/Cell.h> #include <LibWeb/Forward.h> namespace Web::Bindings { // https://heycam.github.io/webidl/#idl-callback-interface -struct CallbackType { - CallbackType(JS::Handle<JS::Object> callback, HTML::EnvironmentSettingsObject& callback_context) - : callback(move(callback)) - , callback_context(callback_context) - { - } +class CallbackType final : public JS::Cell { +public: + CallbackType(JS::Object& callback, HTML::EnvironmentSettingsObject& callback_context); - JS::Handle<JS::Object> callback; + JS::Object& callback; // https://heycam.github.io/webidl/#dfn-callback-context HTML::EnvironmentSettingsObject& callback_context; + +private: + virtual StringView class_name() const override; + virtual void visit_edges(Cell::Visitor&) override; }; } diff --git a/Userland/Libraries/LibWeb/Bindings/EventListenerWrapper.cpp b/Userland/Libraries/LibWeb/Bindings/EventListenerWrapper.cpp deleted file mode 100644 index ebcc9a890f..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventListenerWrapper.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <LibJS/Runtime/FunctionObject.h> -#include <LibJS/Runtime/GlobalObject.h> -#include <LibWeb/Bindings/EventListenerWrapper.h> -#include <LibWeb/DOM/IDLEventListener.h> - -namespace Web { -namespace Bindings { - -EventListenerWrapper::EventListenerWrapper(JS::Realm& realm, DOM::IDLEventListener& impl) - : Wrapper(*realm.intrinsics().object_prototype()) - , m_impl(impl) -{ -} - -} -} diff --git a/Userland/Libraries/LibWeb/Bindings/EventListenerWrapper.h b/Userland/Libraries/LibWeb/Bindings/EventListenerWrapper.h deleted file mode 100644 index 8c1dbcd216..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/EventListenerWrapper.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <LibWeb/Bindings/Wrapper.h> - -namespace Web { -namespace Bindings { - -class EventListenerWrapper final : public Wrapper { - JS_OBJECT(EventListenerWrapper, Wrapper); - -public: - EventListenerWrapper(JS::Realm& realm, DOM::IDLEventListener&); - virtual ~EventListenerWrapper() override = default; - - DOM::IDLEventListener& impl() { return *m_impl; } - DOM::IDLEventListener const& impl() const { return *m_impl; } - -private: - NonnullRefPtr<DOM::IDLEventListener> m_impl; -}; - -} -} diff --git a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp index 74c7ece8ab..66ea40e872 100644 --- a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp +++ b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.cpp @@ -92,11 +92,10 @@ JS::Completion invoke_callback(Bindings::CallbackType& callback, Optional<JS::Va this_argument = JS::js_undefined(); // 3. Let F be the ECMAScript object corresponding to callable. - auto* function_object = callback.callback.cell(); - VERIFY(function_object); + auto& function_object = callback.callback; // 4. If ! IsCallable(F) is false: - if (!function_object->is_function()) { + if (!function_object.is_function()) { // 1. Note: This is only possible when the callback function came from an attribute marked with [LegacyTreatNonObjectAsNull]. // 2. Return the result of converting undefined to the callback functionâs return type. @@ -106,7 +105,7 @@ JS::Completion invoke_callback(Bindings::CallbackType& callback, Optional<JS::Va // 5. Let realm be Fâs associated Realm. // See the comment about associated realm on step 4 of call_user_object_operation. - auto& realm = function_object->shape().realm(); + auto& realm = function_object.shape().realm(); // 6. Let relevant settings be realmâs settings object. auto& relevant_settings = verify_cast<HTML::EnvironmentSettingsObject>(*realm.host_defined()); @@ -124,8 +123,8 @@ JS::Completion invoke_callback(Bindings::CallbackType& callback, Optional<JS::Va // For simplicity, we currently make the caller do this. However, this means we can't throw exceptions at this point like the spec wants us to. // 11. Let callResult be Call(F, thisArg, esArgs). - auto& vm = function_object->vm(); - auto call_result = JS::call(vm, verify_cast<JS::FunctionObject>(*function_object), this_argument.value(), move(args)); + auto& vm = function_object.vm(); + auto call_result = JS::call(vm, verify_cast<JS::FunctionObject>(function_object), this_argument.value(), move(args)); // 12. If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return. if (call_result.is_throw_completion()) { diff --git a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h index 0f7ea9226a..7ad5afadf1 100644 --- a/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h +++ b/Userland/Libraries/LibWeb/Bindings/IDLAbstractOperations.h @@ -54,7 +54,7 @@ JS::Completion call_user_object_operation(Bindings::CallbackType& callback, Stri this_argument = JS::js_undefined(); // 3. Let O be the ECMAScript object corresponding to value. - auto& object = *callback.callback.cell(); + auto& object = callback.callback; // 4. Let realm be Oâs associated Realm. auto& realm = object.shape().realm(); @@ -126,8 +126,7 @@ JS::Completion invoke_callback(Bindings::CallbackType& callback, Optional<JS::Va template<typename... Args> JS::Completion invoke_callback(Bindings::CallbackType& callback, Optional<JS::Value> this_argument, Args&&... args) { - auto* function_object = callback.callback.cell(); - VERIFY(function_object); + auto& function_object = callback.callback; JS::MarkedVector<JS::Value> arguments_list { function_object->vm().heap() }; (arguments_list.append(forward<Args>(args)), ...); diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp index 32624314d2..b331cef7ec 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.cpp @@ -229,7 +229,7 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::prompt) static JS::ThrowCompletionOr<TimerHandler> make_timer_handler(JS::VM& vm, JS::Value handler) { if (handler.is_function()) - return Bindings::CallbackType(JS::make_handle<JS::Object>(handler.as_function()), HTML::incumbent_settings_object()); + return JS::make_handle(vm.heap().allocate_without_realm<Bindings::CallbackType>(handler.as_function(), HTML::incumbent_settings_object())); return TRY(handler.to_string(vm)); } @@ -311,8 +311,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame) auto* callback_object = TRY(vm.argument(0).to_object(vm)); if (!callback_object->is_function()) return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); - NonnullOwnPtr<Bindings::CallbackType> callback = adopt_own(*new Bindings::CallbackType(JS::make_handle(callback_object), HTML::incumbent_settings_object())); - return JS::Value(impl->request_animation_frame(move(callback))); + auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_object, HTML::incumbent_settings_object()); + return JS::Value(impl->request_animation_frame(*callback)); } JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame) @@ -334,9 +334,9 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::queue_microtask) if (!callback_object->is_function()) return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); - auto callback = adopt_own(*new Bindings::CallbackType(JS::make_handle(callback_object), HTML::incumbent_settings_object())); + auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_object, HTML::incumbent_settings_object()); - impl->queue_microtask(move(callback)); + impl->queue_microtask(*callback); return JS::js_undefined(); } @@ -350,9 +350,9 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_idle_callback) return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAFunctionNoParam); // FIXME: accept options object - auto callback = adopt_own(*new Bindings::CallbackType(JS::make_handle(callback_object), HTML::incumbent_settings_object())); + auto* callback = vm.heap().allocate_without_realm<Bindings::CallbackType>(*callback_object, HTML::incumbent_settings_object()); - return JS::Value(impl->request_idle_callback(move(callback))); + return JS::Value(impl->request_idle_callback(*callback)); } JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_idle_callback) @@ -748,25 +748,26 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::name_setter) return JS::js_undefined(); } -#define __ENUMERATE(attribute, event_name) \ - JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter) \ - { \ - auto* impl = TRY(impl_from(vm)); \ - auto retval = impl->attribute(); \ - if (!retval) \ - return JS::js_null(); \ - return retval->callback.cell(); \ - } \ - JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_setter) \ - { \ - auto* impl = TRY(impl_from(vm)); \ - auto value = vm.argument(0); \ - Optional<Bindings::CallbackType> cpp_value; \ - if (value.is_object()) { \ - cpp_value = Bindings::CallbackType { JS::make_handle(&value.as_object()), HTML::incumbent_settings_object() }; \ - } \ - impl->set_##attribute(cpp_value); \ - return JS::js_undefined(); \ +#define __ENUMERATE(attribute, event_name) \ + JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_getter) \ + { \ + auto* impl = TRY(impl_from(vm)); \ + auto retval = impl->attribute(); \ + if (!retval) \ + return JS::js_null(); \ + return &retval->callback; \ + } \ + JS_DEFINE_NATIVE_FUNCTION(WindowObject::attribute##_setter) \ + { \ + auto* impl = TRY(impl_from(vm)); \ + auto value = vm.argument(0); \ + Bindings::CallbackType* cpp_value; \ + if (value.is_object()) { \ + cpp_value = vm.heap().allocate_without_realm<Bindings::CallbackType>( \ + value.as_object(), HTML::incumbent_settings_object()); \ + } \ + impl->set_##attribute(cpp_value); \ + return JS::js_undefined(); \ } ENUMERATE_GLOBAL_EVENT_HANDLERS(__ENUMERATE) ENUMERATE_WINDOW_EVENT_HANDLERS(__ENUMERATE) diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObject.h b/Userland/Libraries/LibWeb/Bindings/WindowObject.h index b3bd2e61f5..86cc00a6d4 100644 --- a/Userland/Libraries/LibWeb/Bindings/WindowObject.h +++ b/Userland/Libraries/LibWeb/Bindings/WindowObject.h @@ -24,7 +24,7 @@ namespace Web { namespace Bindings { // https://html.spec.whatwg.org/#timerhandler -using TimerHandler = Variant<CallbackType, String>; +using TimerHandler = Variant<JS::Handle<CallbackType>, String>; class WindowObject : public JS::GlobalObject diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index cb794c1f3d..da2e149af8 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -2,9 +2,9 @@ include(libweb_generators) set(SOURCES Bindings/AudioConstructor.cpp - Bindings/CrossOriginAbstractOperations.cpp Bindings/CSSNamespace.cpp - Bindings/EventListenerWrapper.cpp + Bindings/CallbackType.cpp + Bindings/CrossOriginAbstractOperations.cpp Bindings/EventTargetWrapperFactory.cpp Bindings/EventWrapperFactory.cpp Bindings/IDLAbstractOperations.cpp @@ -97,12 +97,14 @@ set(SOURCES DOM/EventDispatcher.cpp DOM/EventTarget.cpp DOM/HTMLCollection.cpp + DOM/IDLEventListener.cpp DOM/LiveNodeList.cpp DOM/MutationObserver.cpp DOM/MutationRecord.cpp DOM/MutationType.cpp DOM/NamedNodeMap.cpp DOM/Node.cpp + DOM/NodeFilter.cpp DOM/NodeIterator.cpp DOM/NodeOperations.cpp DOM/ParentNode.cpp @@ -146,6 +148,7 @@ set(SOURCES HTML/CrossOrigin/Reporting.cpp HTML/DOMParser.cpp HTML/DOMStringMap.cpp + HTML/EventHandler.cpp HTML/EventLoop/EventLoop.cpp HTML/EventLoop/Task.cpp HTML/EventLoop/TaskQueue.cpp diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp b/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp index 23bda33f00..74caf27013 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryList.cpp @@ -57,7 +57,7 @@ JS::Object* MediaQueryList::create_wrapper(JS::Realm& realm) } // https://www.w3.org/TR/cssom-view/#dom-mediaquerylist-addlistener -void MediaQueryList::add_listener(RefPtr<DOM::IDLEventListener> listener) +void MediaQueryList::add_listener(DOM::IDLEventListener* listener) { // 1. If listener is null, terminate these steps. if (!listener) @@ -67,19 +67,19 @@ void MediaQueryList::add_listener(RefPtr<DOM::IDLEventListener> listener) // callback set to listener, and capture set to false, unless there already is an event listener // in that list with the same type, callback, and capture. // (NOTE: capture is set to false by default) - add_event_listener_without_options(HTML::EventNames::change, listener); + add_event_listener_without_options(HTML::EventNames::change, *listener); } // https://www.w3.org/TR/cssom-view/#dom-mediaquerylist-removelistener -void MediaQueryList::remove_listener(RefPtr<DOM::IDLEventListener> listener) +void MediaQueryList::remove_listener(DOM::IDLEventListener* listener) { // 1. Remove an event listener from the associated list of event listeners, whose type is change, callback is listener, and capture is false. // NOTE: While the spec doesn't technically use remove_event_listener and instead manipulates the list directly, every major engine uses remove_event_listener. // This means if an event listener removes another event listener that comes after it, the removed event listener will not be invoked. - remove_event_listener_without_options(HTML::EventNames::change, listener); + remove_event_listener_without_options(HTML::EventNames::change, *listener); } -void MediaQueryList::set_onchange(Optional<Bindings::CallbackType> event_handler) +void MediaQueryList::set_onchange(Bindings::CallbackType* event_handler) { set_event_handler_attribute(HTML::EventNames::change, event_handler); } diff --git a/Userland/Libraries/LibWeb/CSS/MediaQueryList.h b/Userland/Libraries/LibWeb/CSS/MediaQueryList.h index 0c6c5df248..71f88439bb 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQueryList.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQueryList.h @@ -45,10 +45,10 @@ public: virtual void unref_event_target() override { unref(); } virtual JS::Object* create_wrapper(JS::Realm&) override; - void add_listener(RefPtr<DOM::IDLEventListener> listener); - void remove_listener(RefPtr<DOM::IDLEventListener> listener); + void add_listener(DOM::IDLEventListener*); + void remove_listener(DOM::IDLEventListener*); - void set_onchange(Optional<Bindings::CallbackType>); + void set_onchange(Bindings::CallbackType*); Bindings::CallbackType* onchange(); private: diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp index df48463fe3..86f1404a70 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.cpp @@ -63,9 +63,9 @@ void AbortSignal::signal_abort(JS::Value reason) dispatch_event(Event::create(HTML::EventNames::abort)); } -void AbortSignal::set_onabort(Optional<Bindings::CallbackType> event_handler) +void AbortSignal::set_onabort(Bindings::CallbackType* event_handler) { - set_event_handler_attribute(HTML::EventNames::abort, move(event_handler)); + set_event_handler_attribute(HTML::EventNames::abort, event_handler); } Bindings::CallbackType* AbortSignal::onabort() diff --git a/Userland/Libraries/LibWeb/DOM/AbortSignal.h b/Userland/Libraries/LibWeb/DOM/AbortSignal.h index b05e1e9d06..3166e87a67 100644 --- a/Userland/Libraries/LibWeb/DOM/AbortSignal.h +++ b/Userland/Libraries/LibWeb/DOM/AbortSignal.h @@ -47,7 +47,7 @@ public: void signal_abort(JS::Value reason); - void set_onabort(Optional<Bindings::CallbackType>); + void set_onabort(Bindings::CallbackType*); Bindings::CallbackType* onabort(); // https://dom.spec.whatwg.org/#dom-abortsignal-reason diff --git a/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp b/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp index 39ceba325e..29c53a1b59 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp +++ b/Userland/Libraries/LibWeb/DOM/DOMEventListener.cpp @@ -9,6 +9,14 @@ #include <LibWeb/DOM/IDLEventListener.h> namespace Web::DOM { + DOMEventListener::DOMEventListener() = default; DOMEventListener::~DOMEventListener() = default; + +void DOMEventListener::visit_edges(Cell::Visitor& visitor) +{ + Cell::visit_edges(visitor); + visitor.visit(callback.ptr()); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/DOMEventListener.h b/Userland/Libraries/LibWeb/DOM/DOMEventListener.h index 41de2ef1a1..a5a9b5d5d5 100644 --- a/Userland/Libraries/LibWeb/DOM/DOMEventListener.h +++ b/Userland/Libraries/LibWeb/DOM/DOMEventListener.h @@ -7,13 +7,15 @@ #pragma once #include <AK/FlyString.h> +#include <LibJS/Heap/GCPtr.h> +#include <LibJS/Runtime/Object.h> #include <LibWeb/Forward.h> namespace Web::DOM { // https://dom.spec.whatwg.org/#concept-event-listener // NOTE: The spec calls this "event listener", and it's *importantly* not the same as "EventListener" -class DOMEventListener : public RefCounted<DOMEventListener> { +class DOMEventListener : public JS::Cell { public: DOMEventListener(); ~DOMEventListener(); @@ -22,7 +24,7 @@ public: FlyString type; // callback (null or an EventListener object) - RefPtr<IDLEventListener> callback; + JS::GCPtr<IDLEventListener> callback; // signal (null or an AbortSignal object) RefPtr<DOM::AbortSignal> signal; @@ -38,6 +40,10 @@ public: // removed (a boolean for bookkeeping purposes, initially false) bool removed { false }; + +private: + virtual void visit_edges(Cell::Visitor&) override; + virtual StringView class_name() const override { return "DOMEventListener"sv; } }; } diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index b15b17d3b4..796ee21a18 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -1744,15 +1744,15 @@ ExceptionOr<Document::PrefixAndTagName> Document::validate_qualified_name(String } // https://dom.spec.whatwg.org/#dom-document-createnodeiterator -NonnullRefPtr<NodeIterator> Document::create_node_iterator(Node& root, unsigned what_to_show, RefPtr<NodeFilter> filter) +NonnullRefPtr<NodeIterator> Document::create_node_iterator(Node& root, unsigned what_to_show, NodeFilter* filter) { - return NodeIterator::create(root, what_to_show, move(filter)); + return NodeIterator::create(root, what_to_show, filter); } // https://dom.spec.whatwg.org/#dom-document-createtreewalker -NonnullRefPtr<TreeWalker> Document::create_tree_walker(Node& root, unsigned what_to_show, RefPtr<NodeFilter> filter) +NonnullRefPtr<TreeWalker> Document::create_tree_walker(Node& root, unsigned what_to_show, NodeFilter* filter) { - return TreeWalker::create(root, what_to_show, move(filter)); + return TreeWalker::create(root, what_to_show, filter); } void Document::register_node_iterator(Badge<NodeIterator>, NodeIterator& node_iterator) diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index ee8cd13dbc..8a54391068 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -350,8 +350,8 @@ public: }; static ExceptionOr<PrefixAndTagName> validate_qualified_name(String const& qualified_name); - NonnullRefPtr<NodeIterator> create_node_iterator(Node& root, unsigned what_to_show, RefPtr<NodeFilter>); - NonnullRefPtr<TreeWalker> create_tree_walker(Node& root, unsigned what_to_show, RefPtr<NodeFilter>); + NonnullRefPtr<NodeIterator> create_node_iterator(Node& root, unsigned what_to_show, NodeFilter*); + NonnullRefPtr<TreeWalker> create_tree_walker(Node& root, unsigned what_to_show, NodeFilter*); void register_node_iterator(Badge<NodeIterator>, NodeIterator&); void unregister_node_iterator(Badge<NodeIterator>, NodeIterator&); diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp index b37bc4fde8..6324301e7c 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp @@ -57,7 +57,7 @@ static EventTarget* retarget(EventTarget* left, EventTarget* right) } // https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke -bool EventDispatcher::inner_invoke(Event& event, Vector<NonnullRefPtr<DOM::DOMEventListener>>& listeners, Event::Phase phase, bool invocation_target_in_shadow_tree) +bool EventDispatcher::inner_invoke(Event& event, Vector<JS::Handle<DOM::DOMEventListener>>& listeners, Event::Phase phase, bool invocation_target_in_shadow_tree) { // 1. Let found be false. bool found = false; @@ -84,11 +84,11 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<NonnullRefPtr<DOM::DOMEv // 5. If listenerâs once is true, then remove listener from eventâs currentTarget attribute valueâs event listener list. if (listener->once) - event.current_target()->remove_from_event_listener_list(listener); + event.current_target()->remove_from_event_listener_list(*listener); // 6. Let global be listener callbackâs associated Realmâs global object. auto& callback = listener->callback->callback(); - auto& realm = callback.callback->shape().realm(); + auto& realm = callback.callback.shape().realm(); auto& global = realm.global_object(); // 7. Let currentEvent be undefined. diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.h b/Userland/Libraries/LibWeb/DOM/EventDispatcher.h index 045bbaeb46..13ac65efb4 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.h +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.h @@ -18,7 +18,7 @@ public: private: static void invoke(Event::PathEntry&, Event&, Event::Phase); - static bool inner_invoke(Event&, Vector<NonnullRefPtr<DOM::DOMEventListener>>&, Event::Phase, bool); + static bool inner_invoke(Event&, Vector<JS::Handle<DOM::DOMEventListener>>&, Event::Phase, bool); }; } diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp index 3c4851390c..3fa4f53160 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -20,6 +20,7 @@ #include <LibWeb/Bindings/IDLAbstractOperations.h> #include <LibWeb/Bindings/MainThreadVM.h> #include <LibWeb/DOM/AbortSignal.h> +#include <LibWeb/DOM/DOMEventListener.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/DOM/EventDispatcher.h> @@ -99,89 +100,91 @@ static FlattenedAddEventListenerOptions flatten_add_event_listener_options(Varia } // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener -void EventTarget::add_event_listener(FlyString const& type, RefPtr<IDLEventListener> callback, Variant<AddEventListenerOptions, bool> const& options) +void EventTarget::add_event_listener(FlyString const& type, IDLEventListener* callback, Variant<AddEventListenerOptions, bool> const& options) { // 1. Let capture, passive, once, and signal be the result of flattening more options. auto flattened_options = flatten_add_event_listener_options(options); // 2. Add an event listener with this and an event listener whose type is type, callback is callback, capture is capture, passive is passive, // once is once, and signal is signal. - auto event_listener = adopt_ref(*new DOMEventListener); + + // FIXME: Don't use main_thread_internal_window_object() when EventTarget can find its own heap. + auto* event_listener = Bindings::main_thread_internal_window_object().heap().allocate_without_realm<DOMEventListener>(); event_listener->type = type; - event_listener->callback = move(callback); + event_listener->callback = callback; event_listener->signal = move(flattened_options.signal); event_listener->capture = flattened_options.capture; event_listener->passive = flattened_options.passive; event_listener->once = flattened_options.once; - add_an_event_listener(move(event_listener)); + add_an_event_listener(*event_listener); } -void EventTarget::add_event_listener_without_options(FlyString const& type, RefPtr<IDLEventListener> callback) +void EventTarget::add_event_listener_without_options(FlyString const& type, IDLEventListener& callback) { - add_event_listener(type, move(callback), AddEventListenerOptions {}); + add_event_listener(type, &callback, AddEventListenerOptions {}); } // https://dom.spec.whatwg.org/#add-an-event-listener -void EventTarget::add_an_event_listener(NonnullRefPtr<DOMEventListener> listener) +void EventTarget::add_an_event_listener(DOMEventListener& listener) { // FIXME: 1. If eventTarget is a ServiceWorkerGlobalScope object, its service workerâs script resourceâs has ever been evaluated flag is set, // and listenerâs type matches the type attribute value of any of the service worker events, then report a warning to the console // that this might not give the expected results. [SERVICE-WORKERS] // 2. If listenerâs signal is not null and is aborted, then return. - if (listener->signal && listener->signal->aborted()) + if (listener.signal && listener.signal->aborted()) return; // 3. If listenerâs callback is null, then return. - if (listener->callback.is_null()) + if (!listener.callback) return; // 4. If eventTargetâs event listener list does not contain an event listener whose type is listenerâs type, callback is listenerâs callback, // and capture is listenerâs capture, then append listener to eventTargetâs event listener list. auto it = m_event_listener_list.find_if([&](auto& entry) { - return entry->type == listener->type - && entry->callback->callback().callback.cell() == listener->callback->callback().callback.cell() - && entry->capture == listener->capture; + return entry->type == listener.type + && &entry->callback->callback().callback == &listener.callback->callback().callback + && entry->capture == listener.capture; }); if (it == m_event_listener_list.end()) - m_event_listener_list.append(listener); + m_event_listener_list.append(JS::make_handle(listener)); // 5. If listenerâs signal is not null, then add the following abort steps to it: - if (listener->signal) { - listener->signal->add_abort_algorithm([strong_event_target = NonnullRefPtr(*this), listener]() mutable { + if (listener.signal) { + listener.signal->add_abort_algorithm([strong_event_target = NonnullRefPtr(*this), listener = JS::make_handle(&listener)]() mutable { // 1. Remove an event listener with eventTarget and listener. - strong_event_target->remove_an_event_listener(listener); + strong_event_target->remove_an_event_listener(*listener); }); } } // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener -void EventTarget::remove_event_listener(FlyString const& type, RefPtr<IDLEventListener> callback, Variant<EventListenerOptions, bool> const& options) +void EventTarget::remove_event_listener(FlyString const& type, IDLEventListener* callback, Variant<EventListenerOptions, bool> const& options) { // 1. Let capture be the result of flattening options. bool capture = flatten_event_listener_options(options); // 2. If thisâs event listener list contains an event listener whose type is type, callback is callback, and capture is capture, // then remove an event listener with this and that event listener. - auto callbacks_match = [&](NonnullRefPtr<DOMEventListener>& entry) { - if (entry->callback.is_null() && callback.is_null()) + auto callbacks_match = [&](DOMEventListener& entry) { + if (!entry.callback && !callback) return true; - if (entry->callback.is_null() || callback.is_null()) + if (!entry.callback || !callback) return false; - return entry->callback->callback().callback.cell() == callback->callback().callback.cell(); + return &entry.callback->callback().callback == &callback->callback().callback; }; auto it = m_event_listener_list.find_if([&](auto& entry) { return entry->type == type - && callbacks_match(entry) + && callbacks_match(*entry) && entry->capture == capture; }); if (it != m_event_listener_list.end()) - remove_an_event_listener(*it); + remove_an_event_listener(**it); } -void EventTarget::remove_event_listener_without_options(FlyString const& type, RefPtr<IDLEventListener> callback) +void EventTarget::remove_event_listener_without_options(FlyString const& type, IDLEventListener& callback) { - remove_event_listener(type, move(callback), EventListenerOptions {}); + remove_event_listener(type, &callback, EventListenerOptions {}); } // https://dom.spec.whatwg.org/#remove-an-event-listener @@ -192,12 +195,12 @@ void EventTarget::remove_an_event_listener(DOMEventListener& listener) // 2. Set listenerâs removed to true and remove listener from eventTargetâs event listener list. listener.removed = true; - m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.ptr() == &listener; }); + m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.cell() == &listener; }); } void EventTarget::remove_from_event_listener_list(DOMEventListener& listener) { - m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.ptr() == &listener; }); + m_event_listener_list.remove_first_matching([&](auto& entry) { return entry.cell() == &listener; }); } // https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent @@ -309,7 +312,7 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin auto& event_handler = event_handler_iterator->value; // 3. If eventHandler's value is an internal raw uncompiled handler, then: - if (event_handler.value.has<String>()) { + if (event_handler->value.has<String>()) { // 1. If eventTarget is an element, then let element be eventTarget, and document be element's node document. // Otherwise, eventTarget is a Window object, let element be null, and document be eventTarget's associated Document. RefPtr<Element> element; @@ -332,7 +335,7 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin return nullptr; // 3. Let body be the uncompiled script body in eventHandler's value. - auto& body = event_handler.value.get<String>(); + auto& body = event_handler->value.get<String>(); // FIXME: 4. Let location be the location where the script body originated, as given by eventHandler's value. @@ -448,16 +451,16 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin function->set_script_or_module({}); // 12. Set eventHandler's value to the result of creating a Web IDL EventHandler callback function object whose object reference is function and whose callback context is settings object. - event_handler.value = Bindings::CallbackType { JS::make_handle(static_cast<JS::Object*>(function)), settings_object }; + event_handler->value = realm.heap().allocate_without_realm<Bindings::CallbackType>(*function, settings_object); } // 4. Return eventHandler's value. - VERIFY(event_handler.value.has<Bindings::CallbackType>()); - return event_handler.value.get_pointer<Bindings::CallbackType>(); + VERIFY(event_handler->value.has<Bindings::CallbackType*>()); + return *event_handler->value.get_pointer<Bindings::CallbackType*>(); } // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-attributes:event-handler-idl-attributes-3 -void EventTarget::set_event_handler_attribute(FlyString const& name, Optional<Bindings::CallbackType> value) +void EventTarget::set_event_handler_attribute(FlyString const& name, Bindings::CallbackType* value) { // 1. Let eventTarget be the result of determining the target of an event handler given this object and name. auto event_target = determine_target_of_event_handler(*this, name); @@ -467,7 +470,7 @@ void EventTarget::set_event_handler_attribute(FlyString const& name, Optional<Bi return; // 3. If the given value is null, then deactivate an event handler given eventTarget and name. - if (!value.has_value()) { + if (!value) { event_target->deactivate_event_handler(name); return; } @@ -482,25 +485,25 @@ void EventTarget::set_event_handler_attribute(FlyString const& name, Optional<Bi // 3. Set eventHandler's value to the given value. if (event_handler_iterator == handler_map.end()) { // NOTE: See the optimization comment in get_current_value_of_event_handler about why this is done. - HTML::EventHandler new_event_handler { move(value.value()) }; + auto* new_event_handler = Bindings::main_thread_internal_window_object().heap().allocate_without_realm<HTML::EventHandler>(*value); // 4. Activate an event handler given eventTarget and name. // Optimization: We pass in the event handler here instead of having activate_event_handler do another hash map lookup just to get the same object. // This handles a new event handler while the other path handles an existing event handler. As such, both paths must have their own // unique call to activate_event_handler. - event_target->activate_event_handler(name, new_event_handler); + event_target->activate_event_handler(name, *new_event_handler); - handler_map.set(name, move(new_event_handler)); + handler_map.set(name, JS::make_handle(new_event_handler)); return; } auto& event_handler = event_handler_iterator->value; - event_handler.value = move(value.value()); + event_handler->value = value; // 4. Activate an event handler given eventTarget and name. // NOTE: See the optimization comment above. - event_target->activate_event_handler(name, event_handler); + event_target->activate_event_handler(name, *event_handler); } // https://html.spec.whatwg.org/multipage/webappapis.html#activate-an-event-handler @@ -516,8 +519,8 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl JS::Realm* realm = nullptr; // See step 3.1. in get_current_value_of_event_handler(), which explains these assumptions. - if (event_handler.value.has<Bindings::CallbackType>()) { - realm = &event_handler.value.get<Bindings::CallbackType>().callback_context.realm(); + if (event_handler.value.has<Bindings::CallbackType*>()) { + realm = &event_handler.value.get<Bindings::CallbackType*>()->callback_context.realm(); } else if (is<Element>(this)) { realm = &verify_cast<Element>(*this).document().realm(); } else { @@ -555,15 +558,15 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl 0, "", realm); // NOTE: As per the spec, the callback context is arbitrary. - Bindings::CallbackType callback { JS::make_handle(static_cast<JS::Object*>(callback_function)), verify_cast<HTML::EnvironmentSettingsObject>(*realm->host_defined()) }; + auto* callback = realm->heap().allocate_without_realm<Bindings::CallbackType>(*callback_function, verify_cast<HTML::EnvironmentSettingsObject>(*realm->host_defined())); // 5. Let listener be a new event listener whose type is the event handler event type corresponding to eventHandler and callback is callback. - auto listener = adopt_ref(*new DOMEventListener); + auto* listener = realm->heap().allocate_without_realm<DOMEventListener>(); listener->type = name; - listener->callback = adopt_ref(*new IDLEventListener(move(callback))); + listener->callback = IDLEventListener::create(*realm, *callback).ptr(); // 6. Add an event listener with eventTarget and listener. - add_an_event_listener(listener); + add_an_event_listener(*listener); // 7. Set eventHandler's listener to listener. event_handler.listener = listener; @@ -585,12 +588,12 @@ void EventTarget::deactivate_event_handler(FlyString const& name) // 4. Let listener be eventHandler's listener. (NOTE: Not necessary) // 5. If listener is not null, then remove an event listener with eventTarget and listener. - if (event_handler.listener) { - remove_an_event_listener(*event_handler.listener); + if (event_handler->listener) { + remove_an_event_listener(*event_handler->listener); } // 6. Set eventHandler's listener to null. - event_handler.listener = nullptr; + event_handler->listener = nullptr; // 3. Set eventHandler's value to null. // NOTE: This is done out of order since our equivalent of setting value to null is removing the event handler from the map. @@ -617,7 +620,7 @@ JS::ThrowCompletionOr<void> EventTarget::process_event_handler_for_event(FlyStri JS::Completion return_value_or_error; // Needed for wrapping. - auto* callback_object = callback->callback.cell(); + auto* callback_object = &callback->callback; auto& realm = callback_object->shape().realm(); if (special_error_event_handling) { @@ -717,20 +720,20 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local // NOTE: See the optimization comments in set_event_handler_attribute. if (event_handler_iterator == handler_map.end()) { - HTML::EventHandler new_event_handler { value }; + auto* new_event_handler = Bindings::main_thread_internal_window_object().heap().allocate_without_realm<HTML::EventHandler>(value); // 6. Activate an event handler given eventTarget and name. - event_target->activate_event_handler(local_name, new_event_handler); + event_target->activate_event_handler(local_name, *new_event_handler); - handler_map.set(local_name, move(new_event_handler)); + handler_map.set(local_name, JS::make_handle(new_event_handler)); return; } auto& event_handler = event_handler_iterator->value; // 6. Activate an event handler given eventTarget and name. - event_handler.value = value; - event_target->activate_event_handler(local_name, event_handler); + event_handler->value = value; + event_target->activate_event_handler(local_name, *event_handler); } bool EventTarget::dispatch_event(NonnullRefPtr<Event> event) diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index 854776eb0f..81fa073610 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -29,12 +29,12 @@ public: virtual bool is_focusable() const { return false; } - void add_event_listener(FlyString const& type, RefPtr<IDLEventListener> callback, Variant<AddEventListenerOptions, bool> const& options); - void remove_event_listener(FlyString const& type, RefPtr<IDLEventListener> callback, Variant<EventListenerOptions, bool> const& options); + void add_event_listener(FlyString const& type, IDLEventListener* callback, Variant<AddEventListenerOptions, bool> const& options); + void remove_event_listener(FlyString const& type, IDLEventListener* callback, Variant<EventListenerOptions, bool> const& options); // NOTE: These are for internal use only. They operate as though addEventListener(type, callback) was called instead of addEventListener(type, callback, options). - void add_event_listener_without_options(FlyString const& type, RefPtr<IDLEventListener> callback); - void remove_event_listener_without_options(FlyString const& type, RefPtr<IDLEventListener> callback); + void add_event_listener_without_options(FlyString const& type, IDLEventListener& callback); + void remove_event_listener_without_options(FlyString const& type, IDLEventListener& callback); virtual bool dispatch_event(NonnullRefPtr<Event>); ExceptionOr<bool> dispatch_event_binding(NonnullRefPtr<Event>); @@ -43,7 +43,7 @@ public: virtual EventTarget* get_parent(Event const&) { return nullptr; } - void add_an_event_listener(NonnullRefPtr<DOMEventListener>); + void add_an_event_listener(DOMEventListener&); void remove_an_event_listener(DOMEventListener&); void remove_from_event_listener_list(DOMEventListener&); @@ -58,7 +58,7 @@ public: virtual void legacy_cancelled_activation_behavior_was_not_called() { } Bindings::CallbackType* event_handler_attribute(FlyString const& name); - void set_event_handler_attribute(FlyString const& name, Optional<Bindings::CallbackType>); + void set_event_handler_attribute(FlyString const& name, Bindings::CallbackType*); protected: EventTarget(); @@ -69,11 +69,11 @@ protected: void element_event_handler_attribute_changed(FlyString const& local_name, String const& value); private: - Vector<NonnullRefPtr<DOMEventListener>> m_event_listener_list; + Vector<JS::Handle<DOMEventListener>> m_event_listener_list; // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-map // Spec Note: The order of the entries of event handler map could be arbitrary. It is not observable through any algorithms that operate on the map. - HashMap<FlyString, HTML::EventHandler> m_event_handler_map; + HashMap<FlyString, JS::Handle<HTML::EventHandler>> m_event_handler_map; Bindings::CallbackType* get_current_value_of_event_handler(FlyString const& name); void activate_event_handler(FlyString const& name, HTML::EventHandler& event_handler); diff --git a/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp b/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp new file mode 100644 index 0000000000..5c4c75f582 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/IDLEventListener.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/DOM/IDLEventListener.h> + +namespace Web::DOM { + +JS::NonnullGCPtr<IDLEventListener> IDLEventListener::create(JS::Realm& realm, JS::NonnullGCPtr<Bindings::CallbackType> callback) +{ + return *realm.heap().allocate<IDLEventListener>(realm, realm, move(callback)); +} + +IDLEventListener::IDLEventListener(JS::Realm& realm, JS::NonnullGCPtr<Bindings::CallbackType> callback) + : JS::Object(*realm.intrinsics().object_prototype()) + , m_callback(move(callback)) +{ +} + +void IDLEventListener::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_callback.ptr()); +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/IDLEventListener.h b/Userland/Libraries/LibWeb/DOM/IDLEventListener.h index 2ed2b6c78c..f372353462 100644 --- a/Userland/Libraries/LibWeb/DOM/IDLEventListener.h +++ b/Userland/Libraries/LibWeb/DOM/IDLEventListener.h @@ -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 */ @@ -25,23 +25,28 @@ struct AddEventListenerOptions : public EventListenerOptions { Optional<NonnullRefPtr<AbortSignal>> signal; }; -class IDLEventListener - : public RefCounted<IDLEventListener> - , public Bindings::Wrappable { +class IDLEventListener final : public JS::Object { + JS_OBJECT(IDLEventListener, JS::Object); + public: - using WrapperType = Bindings::EventListenerWrapper; + IDLEventListener& impl() { return *this; } - explicit IDLEventListener(Bindings::CallbackType callback) - : m_callback(move(callback)) - { - } + static JS::NonnullGCPtr<IDLEventListener> create(JS::Realm&, JS::NonnullGCPtr<Bindings::CallbackType>); + IDLEventListener(JS::Realm&, JS::NonnullGCPtr<Bindings::CallbackType>); virtual ~IDLEventListener() = default; - Bindings::CallbackType& callback() { return m_callback; } + Bindings::CallbackType& callback() { return *m_callback; } private: - Bindings::CallbackType m_callback; + virtual void visit_edges(Cell::Visitor&) override; + + JS::NonnullGCPtr<Bindings::CallbackType> m_callback; }; } + +namespace Web::Bindings { +inline JS::Object* wrap(JS::Realm&, Web::DOM::IDLEventListener& object) { return &object; } +using EventListenerWrapper = Web::DOM::IDLEventListener; +} diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp index f489a7d016..e600ac58d9 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.cpp @@ -12,7 +12,7 @@ namespace Web::DOM { // https://dom.spec.whatwg.org/#dom-mutationobserver-mutationobserver -MutationObserver::MutationObserver(Bindings::WindowObject& window_object, Bindings::CallbackType callback) +MutationObserver::MutationObserver(Bindings::WindowObject& window_object, JS::Handle<Bindings::CallbackType> callback) : m_callback(move(callback)) { // 1. Set thisâs callback to callback. diff --git a/Userland/Libraries/LibWeb/DOM/MutationObserver.h b/Userland/Libraries/LibWeb/DOM/MutationObserver.h index e7dcf942ee..961220fda6 100644 --- a/Userland/Libraries/LibWeb/DOM/MutationObserver.h +++ b/Userland/Libraries/LibWeb/DOM/MutationObserver.h @@ -34,9 +34,9 @@ class MutationObserver final public: using WrapperType = Bindings::MutationObserverWrapper; - static NonnullRefPtr<MutationObserver> create_with_global_object(Bindings::WindowObject& window_object, Bindings::CallbackType callback) + static NonnullRefPtr<MutationObserver> create_with_global_object(Bindings::WindowObject& window_object, Bindings::CallbackType* callback) { - return adopt_ref(*new MutationObserver(window_object, move(callback))); + return adopt_ref(*new MutationObserver(window_object, JS::make_handle(callback))); } virtual ~MutationObserver() override = default; @@ -48,7 +48,7 @@ public: Vector<WeakPtr<Node>>& node_list() { return m_node_list; } Vector<WeakPtr<Node>> const& node_list() const { return m_node_list; } - Bindings::CallbackType& callback() { return m_callback; } + Bindings::CallbackType& callback() { return *m_callback; } void enqueue_record(Badge<Node>, NonnullRefPtr<MutationRecord> mutation_record) { @@ -56,10 +56,10 @@ public: } private: - MutationObserver(Bindings::WindowObject& window_object, Bindings::CallbackType callback); + MutationObserver(Bindings::WindowObject& window_object, JS::Handle<Bindings::CallbackType> callback); // https://dom.spec.whatwg.org/#concept-mo-callback - Bindings::CallbackType m_callback; + JS::Handle<Bindings::CallbackType> m_callback; // https://dom.spec.whatwg.org/#mutationobserver-node-list Vector<WeakPtr<Node>> m_node_list; diff --git a/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp b/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp new file mode 100644 index 0000000000..d1dbec9136 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/NodeFilter.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/Bindings/WindowObject.h> +#include <LibWeb/DOM/NodeFilter.h> + +namespace Web::DOM { + +JS::NonnullGCPtr<NodeFilter> NodeFilter::create(JS::Realm& realm, Bindings::CallbackType& callback) +{ + return *realm.heap().allocate<NodeFilter>(realm, realm, callback); +} + +NodeFilter::NodeFilter(JS::Realm& realm, Bindings::CallbackType& callback) + : PlatformObject(*realm.intrinsics().object_prototype()) + , m_callback(callback) +{ +} + +void NodeFilter::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(&m_callback); +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/NodeFilter.h b/Userland/Libraries/LibWeb/DOM/NodeFilter.h index 189dd359ce..89b7aa1354 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeFilter.h +++ b/Userland/Libraries/LibWeb/DOM/NodeFilter.h @@ -6,26 +6,22 @@ #pragma once -#include <AK/RefCounted.h> -#include <LibJS/Heap/Handle.h> #include <LibWeb/Bindings/CallbackType.h> -#include <LibWeb/Bindings/Wrappable.h> +#include <LibWeb/Bindings/PlatformObject.h> namespace Web::DOM { -class NodeFilter - : public RefCounted<NodeFilter> - , public Bindings::Wrappable { -public: - using WrapperType = Bindings::NodeFilterWrapper; +class NodeFilter final : public Bindings::PlatformObject { + JS_OBJECT(NodeFilter, Bindings::PlatformObject); - explicit NodeFilter(Bindings::CallbackType callback) - : m_callback(move(callback)) - { - } +public: + static JS::NonnullGCPtr<NodeFilter> create(JS::Realm&, Bindings::CallbackType&); + NodeFilter(JS::Realm&, Bindings::CallbackType&); virtual ~NodeFilter() = default; + NodeFilter& impl() { return *this; } + Bindings::CallbackType& callback() { return m_callback; } enum Result { @@ -35,12 +31,14 @@ public: }; private: - Bindings::CallbackType m_callback; + virtual void visit_edges(Cell::Visitor&) override; + + Bindings::CallbackType& m_callback; }; inline JS::Object* wrap(JS::Realm&, Web::DOM::NodeFilter& filter) { - return filter.callback().callback.cell(); + return &filter.callback().callback; } } diff --git a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp index ebf01cf928..31611c9e1b 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp +++ b/Userland/Libraries/LibWeb/DOM/NodeIterator.cpp @@ -26,7 +26,7 @@ NodeIterator::~NodeIterator() } // https://dom.spec.whatwg.org/#dom-document-createnodeiterator -NonnullRefPtr<NodeIterator> NodeIterator::create(Node& root, unsigned what_to_show, RefPtr<NodeFilter> filter) +NonnullRefPtr<NodeIterator> NodeIterator::create(Node& root, unsigned what_to_show, NodeFilter* filter) { // 1. Let iterator be a new NodeIterator object. // 2. Set iteratorâs root and iteratorâs reference to root. @@ -37,7 +37,7 @@ NonnullRefPtr<NodeIterator> NodeIterator::create(Node& root, unsigned what_to_sh iterator->m_what_to_show = what_to_show; // 5. Set iteratorâs filter to filter. - iterator->m_filter = move(filter); + iterator->m_filter = JS::make_handle(filter); // 6. Return iterator. return iterator; @@ -133,7 +133,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> NodeIterator::filter(Node& node) return NodeFilter::FILTER_SKIP; // 4. If traverserâs filter is null, then return FILTER_ACCEPT. - if (!m_filter) + if (!m_filter.cell()) return NodeFilter::FILTER_ACCEPT; // 5. Set traverserâs active flag. diff --git a/Userland/Libraries/LibWeb/DOM/NodeIterator.h b/Userland/Libraries/LibWeb/DOM/NodeIterator.h index 0423eaa64d..1c0123b8d0 100644 --- a/Userland/Libraries/LibWeb/DOM/NodeIterator.h +++ b/Userland/Libraries/LibWeb/DOM/NodeIterator.h @@ -21,14 +21,14 @@ public: virtual ~NodeIterator() override; - static NonnullRefPtr<NodeIterator> create(Node& root, unsigned what_to_show, RefPtr<NodeFilter>); + static NonnullRefPtr<NodeIterator> create(Node& root, unsigned what_to_show, NodeFilter*); NonnullRefPtr<Node> root() { return m_root; } NonnullRefPtr<Node> reference_node() { return m_reference.node; } bool pointer_before_reference_node() const { return m_reference.is_before_node; } unsigned what_to_show() const { return m_what_to_show; } - NodeFilter* filter() { return m_filter; } + NodeFilter* filter() { return m_filter.cell(); } JS::ThrowCompletionOr<RefPtr<Node>> next_node(); JS::ThrowCompletionOr<RefPtr<Node>> previous_node(); @@ -72,7 +72,7 @@ private: unsigned m_what_to_show { 0 }; // https://dom.spec.whatwg.org/#concept-traversal-filter - RefPtr<DOM::NodeFilter> m_filter; + JS::Handle<DOM::NodeFilter> m_filter; // https://dom.spec.whatwg.org/#concept-traversal-active bool m_active { false }; diff --git a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp index cbcaadd8b0..e63c2e67a5 100644 --- a/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp +++ b/Userland/Libraries/LibWeb/DOM/TreeWalker.cpp @@ -23,7 +23,7 @@ TreeWalker::TreeWalker(Node& root) } // https://dom.spec.whatwg.org/#dom-document-createtreewalker -NonnullRefPtr<TreeWalker> TreeWalker::create(Node& root, unsigned what_to_show, RefPtr<NodeFilter> filter) +NonnullRefPtr<TreeWalker> TreeWalker::create(Node& root, unsigned what_to_show, NodeFilter* filter) { // 1. Let walker be a new TreeWalker object. // 2. Set walkerâs root and walkerâs current to root. @@ -33,7 +33,7 @@ NonnullRefPtr<TreeWalker> TreeWalker::create(Node& root, unsigned what_to_show, walker->m_what_to_show = what_to_show; // 4. Set walkerâs filter to filter. - walker->m_filter = move(filter); + walker->m_filter = JS::make_handle(filter); // 5. Return walker. return walker; @@ -236,7 +236,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> TreeWalker::filter(Node& node) return NodeFilter::FILTER_SKIP; // 4. If traverserâs filter is null, then return FILTER_ACCEPT. - if (!m_filter) + if (!m_filter.cell()) return NodeFilter::FILTER_ACCEPT; // 5. Set traverserâs active flag. diff --git a/Userland/Libraries/LibWeb/DOM/TreeWalker.h b/Userland/Libraries/LibWeb/DOM/TreeWalker.h index 2a132fbb8a..7c4c322dce 100644 --- a/Userland/Libraries/LibWeb/DOM/TreeWalker.h +++ b/Userland/Libraries/LibWeb/DOM/TreeWalker.h @@ -19,7 +19,7 @@ class TreeWalker public: using WrapperType = Bindings::TreeWalkerWrapper; - static NonnullRefPtr<TreeWalker> create(Node& root, unsigned what_to_show, RefPtr<NodeFilter>); + static NonnullRefPtr<TreeWalker> create(Node& root, unsigned what_to_show, NodeFilter*); virtual ~TreeWalker() override = default; NonnullRefPtr<Node> current_node() const; @@ -35,7 +35,7 @@ public: NonnullRefPtr<Node> root() { return m_root; } - NodeFilter* filter() { return m_filter; } + NodeFilter* filter() { return m_filter.cell(); } unsigned what_to_show() const { return m_what_to_show; } @@ -66,7 +66,7 @@ private: unsigned m_what_to_show { 0 }; // https://dom.spec.whatwg.org/#concept-traversal-filter - RefPtr<DOM::NodeFilter> m_filter; + JS::Handle<DOM::NodeFilter> m_filter; // https://dom.spec.whatwg.org/#concept-traversal-active bool m_active { false }; diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index ed97f604f2..4cfb1359e2 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -217,7 +217,7 @@ class DOMStringMap; struct Environment; struct EnvironmentSettingsObject; class ErrorEvent; -struct EventHandler; +class EventHandler; class EventLoop; class HTMLAnchorElement; class HTMLAreaElement; @@ -451,7 +451,6 @@ class AbortControllerWrapper; class AbortSignalWrapper; class AttributeWrapper; class BlobWrapper; -struct CallbackType; class CanvasGradientWrapper; class CanvasRenderingContext2DWrapper; class CDATASectionWrapper; @@ -472,7 +471,6 @@ class DOMRectReadOnlyWrapper; class DOMRectWrapper; class ElementWrapper; class ErrorEventWrapper; -class EventListenerWrapper; class EventTargetWrapper; class EventWrapper; class FileWrapper; diff --git a/Userland/Libraries/LibWeb/HTML/EventHandler.cpp b/Userland/Libraries/LibWeb/HTML/EventHandler.cpp new file mode 100644 index 0000000000..8e421c3e88 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/EventHandler.cpp @@ -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); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/EventHandler.h b/Userland/Libraries/LibWeb/HTML/EventHandler.h index 888c6b8bb8..a7be161c6e 100644 --- a/Userland/Libraries/LibWeb/HTML/EventHandler.h +++ b/Userland/Libraries/LibWeb/HTML/EventHandler.h @@ -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; }; } diff --git a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp index fb39485202..76eb8c2edb 100644 --- a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp +++ b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h index facdc97a23..11c99dddee 100644 --- a/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h +++ b/Userland/Libraries/LibWeb/HTML/GlobalEventHandlers.h @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp index cbbc0e230d..52e527ec0f 100644 --- a/Userland/Libraries/LibWeb/HTML/MessagePort.cpp +++ b/Userland/Libraries/LibWeb/HTML/MessagePort.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/MessagePort.h b/Userland/Libraries/LibWeb/HTML/MessagePort.h index d2b5a476fb..3cebac0aa2 100644 --- a/Userland/Libraries/LibWeb/HTML/MessagePort.h +++ b/Userland/Libraries/LibWeb/HTML/MessagePort.h @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 2916345848..0e2d5c5fc5 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -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)); }; diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index be5b9793ed..e3d8c467e7 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -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; } diff --git a/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.cpp b/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.cpp index bd99461a9d..b33318e45d 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.cpp +++ b/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.h b/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.h index 9c9291dc88..a6d0009b7a 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.h +++ b/Userland/Libraries/LibWeb/HTML/WindowEventHandlers.h @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/Worker.cpp b/Userland/Libraries/LibWeb/HTML/Worker.cpp index b84aba47cf..0dc8b821be 100644 --- a/Userland/Libraries/LibWeb/HTML/Worker.cpp +++ b/Userland/Libraries/LibWeb/HTML/Worker.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/Worker.h b/Userland/Libraries/LibWeb/HTML/Worker.h index 0b7be28446..eb7a56bf3f 100644 --- a/Userland/Libraries/LibWeb/HTML/Worker.h +++ b/Userland/Libraries/LibWeb/HTML/Worker.h @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp index 1515d32640..0da867be35 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp @@ -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 diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h index 29802976f1..d92358e0d1 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h @@ -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 diff --git a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp index bd21e60034..25e37455e0 100644 --- a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp +++ b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp @@ -10,7 +10,7 @@ namespace Web::IntersectionObserver { // https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-intersectionobserver -NonnullRefPtr<IntersectionObserver> IntersectionObserver::create_with_global_object(JS::GlobalObject& global_object, Bindings::CallbackType const& callback, IntersectionObserverInit const& options) +NonnullRefPtr<IntersectionObserver> IntersectionObserver::create_with_global_object(JS::GlobalObject& global_object, Bindings::CallbackType* callback, IntersectionObserverInit const& options) { // FIXME: Implement (void)global_object; diff --git a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h index 9039205418..d18594f1a4 100644 --- a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h +++ b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.h @@ -25,7 +25,7 @@ class IntersectionObserver public: using WrapperType = Bindings::IntersectionObserverWrapper; - static NonnullRefPtr<IntersectionObserver> create_with_global_object(JS::GlobalObject&, Bindings::CallbackType const& callback, IntersectionObserverInit const& options = {}); + static NonnullRefPtr<IntersectionObserver> create_with_global_object(JS::GlobalObject&, Bindings::CallbackType* callback, IntersectionObserverInit const& options = {}); void observe(DOM::Element& target); void unobserve(DOM::Element& target); diff --git a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp index ace98e0743..32e7cf5afd 100644 --- a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp +++ b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.cpp @@ -10,7 +10,7 @@ namespace Web::ResizeObserver { // https://drafts.csswg.org/resize-observer/#dom-resizeobserver-resizeobserver -NonnullRefPtr<ResizeObserver> ResizeObserver::create_with_global_object(JS::GlobalObject& global_object, Bindings::CallbackType const& callback) +NonnullRefPtr<ResizeObserver> ResizeObserver::create_with_global_object(JS::GlobalObject& global_object, Bindings::CallbackType* callback) { // FIXME: Implement (void)global_object; diff --git a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h index 409fe9be9d..d7675dc347 100644 --- a/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h +++ b/Userland/Libraries/LibWeb/ResizeObserver/ResizeObserver.h @@ -24,7 +24,7 @@ class ResizeObserver public: using WrapperType = Bindings::ResizeObserverWrapper; - static NonnullRefPtr<ResizeObserver> create_with_global_object(JS::GlobalObject&, Bindings::CallbackType const& callback); + static NonnullRefPtr<ResizeObserver> create_with_global_object(JS::GlobalObject&, Bindings::CallbackType* callback); void observe(DOM::Element& target, ResizeObserverOptions); void unobserve(DOM::Element& target); diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp index ca1197f25e..07be6b1499 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.cpp @@ -232,14 +232,14 @@ JS::Object* WebSocket::create_wrapper(JS::Realm& realm) } #undef __ENUMERATE -#define __ENUMERATE(attribute_name, event_name) \ - void WebSocket::set_##attribute_name(Optional<Bindings::CallbackType> value) \ - { \ - set_event_handler_attribute(event_name, move(value)); \ - } \ - Bindings::CallbackType* WebSocket::attribute_name() \ - { \ - return event_handler_attribute(event_name); \ +#define __ENUMERATE(attribute_name, event_name) \ + void WebSocket::set_##attribute_name(Bindings::CallbackType* value) \ + { \ + set_event_handler_attribute(event_name, value); \ + } \ + Bindings::CallbackType* WebSocket::attribute_name() \ + { \ + return event_handler_attribute(event_name); \ } ENUMERATE_WEBSOCKET_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE diff --git a/Userland/Libraries/LibWeb/WebSockets/WebSocket.h b/Userland/Libraries/LibWeb/WebSockets/WebSocket.h index c12662ca72..f082d28424 100644 --- a/Userland/Libraries/LibWeb/WebSockets/WebSocket.h +++ b/Userland/Libraries/LibWeb/WebSockets/WebSocket.h @@ -58,8 +58,8 @@ public: String url() const { return m_url.to_string(); } #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_WEBSOCKET_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index 260eab4e84..a1d1868a35 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -577,9 +577,9 @@ Bindings::CallbackType* XMLHttpRequest::onreadystatechange() return event_handler_attribute(Web::XHR::EventNames::readystatechange); } -void XMLHttpRequest::set_onreadystatechange(Optional<Bindings::CallbackType> value) +void XMLHttpRequest::set_onreadystatechange(Bindings::CallbackType* value) { - set_event_handler_attribute(Web::XHR::EventNames::readystatechange, move(value)); + set_event_handler_attribute(Web::XHR::EventNames::readystatechange, value); } // https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h index c2894d6743..bba94589bf 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h @@ -72,7 +72,7 @@ public: String get_all_response_headers() const; Bindings::CallbackType* onreadystatechange(); - void set_onreadystatechange(Optional<Bindings::CallbackType>); + void set_onreadystatechange(Bindings::CallbackType*); DOM::ExceptionOr<void> override_mime_type(String const& mime); diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.cpp index ee2114d7b9..afedb06cc5 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.cpp @@ -11,14 +11,14 @@ namespace Web::XHR { #undef __ENUMERATE -#define __ENUMERATE(attribute_name, event_name) \ - void XMLHttpRequestEventTarget::set_##attribute_name(Optional<Bindings::CallbackType> value) \ - { \ - set_event_handler_attribute(event_name, move(value)); \ - } \ - Bindings::CallbackType* XMLHttpRequestEventTarget::attribute_name() \ - { \ - return event_handler_attribute(event_name); \ +#define __ENUMERATE(attribute_name, event_name) \ + void XMLHttpRequestEventTarget::set_##attribute_name(Bindings::CallbackType* value) \ + { \ + set_event_handler_attribute(event_name, value); \ + } \ + Bindings::CallbackType* XMLHttpRequestEventTarget::attribute_name() \ + { \ + return event_handler_attribute(event_name); \ } ENUMERATE_XML_HTTP_REQUEST_EVENT_TARGET_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h index 5858299305..5307dd558d 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequestEventTarget.h @@ -30,8 +30,8 @@ public: virtual ~XMLHttpRequestEventTarget() override {}; #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_XML_HTTP_REQUEST_EVENT_TARGET_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE |