From 9d2635d94bbb8ef6233c3d7292d107df72d17bec Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 10 Apr 2021 18:51:29 +0200 Subject: LibWeb: Support nullable EventListener parameters in WrapperGenerator The internal C++ function will now receive a RefPtr for 'EventListener?' and a NonnullRefPtr for 'EventListener'. Examples of this are addEventListener() and removeEventListener(), which both have nullable callback parameters. --- .../LibWeb/CodeGenerators/WrapperGenerator.cpp | 20 ++++++++++++++++++-- Userland/Libraries/LibWeb/DOM/EventTarget.cpp | 12 +++++++++--- Userland/Libraries/LibWeb/DOM/EventTarget.h | 4 ++-- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index 291b5ebc64..5f13b97ed8 100644 --- a/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -522,7 +522,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter else scoped_generator.set("return_statement", "return {};"); - // FIXME: Add support for optional to all types + // FIXME: Add support for optional and nullable to all types if (parameter.type.is_string()) { if (!optional) { scoped_generator.append(R"~~~( @@ -541,13 +541,26 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter )~~~"); } } else if (parameter.type.name == "EventListener") { - scoped_generator.append(R"~~~( + if (parameter.type.nullable) { + scoped_generator.append(R"~~~( + RefPtr @cpp_name@; + if (!@js_name@@js_suffix@.is_null()) { + if (!@js_name@@js_suffix@.is_function()) { + vm.throw_exception(global_object, JS::ErrorType::NotA, "Function"); + @return_statement@ + } + @cpp_name@ = adopt(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function()))); + } +)~~~"); + } else { + scoped_generator.append(R"~~~( if (!@js_name@@js_suffix@.is_function()) { vm.throw_exception(global_object, JS::ErrorType::NotA, "Function"); @return_statement@ } auto @cpp_name@ = adopt(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function()))); )~~~"); + } } else if (is_wrappable_type(parameter.type)) { scoped_generator.append(R"~~~( auto @cpp_name@_object = @js_name@@js_suffix@.to_object(global_object); @@ -774,6 +787,7 @@ void generate_implementation(const IDL::Interface& interface) #include #include #include +#include #include #include #include @@ -1111,6 +1125,8 @@ void generate_prototype_implementation(const IDL::Interface& interface) #include #include #include +#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp index 5f8ca71c8a..a42a2cd02d 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -39,19 +39,25 @@ EventTarget::~EventTarget() { } -void EventTarget::add_event_listener(const FlyString& event_name, NonnullRefPtr listener) +// https://dom.spec.whatwg.org/#add-an-event-listener +void EventTarget::add_event_listener(const FlyString& event_name, RefPtr listener) { + if (listener.is_null()) + return; auto existing_listener = m_listeners.first_matching([&](auto& entry) { return entry.listener->type() == event_name && &entry.listener->function() == &listener->function() && entry.listener->capture() == listener->capture(); }); if (existing_listener.has_value()) return; listener->set_type(event_name); - m_listeners.append({ event_name, move(listener) }); + m_listeners.append({ event_name, listener.release_nonnull() }); } -void EventTarget::remove_event_listener(const FlyString& event_name, NonnullRefPtr listener) +// https://dom.spec.whatwg.org/#remove-an-event-listener +void EventTarget::remove_event_listener(const FlyString& event_name, RefPtr listener) { + if (listener.is_null()) + return; m_listeners.remove_first_matching([&](auto& entry) { auto matches = entry.event_name == event_name && &entry.listener->function() == &listener->function() && entry.listener->capture() == listener->capture(); if (matches) diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index af1a1d7b0c..d74d633fec 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -45,8 +45,8 @@ public: void ref() { ref_event_target(); } void unref() { unref_event_target(); } - void add_event_listener(const FlyString& event_name, NonnullRefPtr); - void remove_event_listener(const FlyString& event_name, NonnullRefPtr); + void add_event_listener(const FlyString& event_name, RefPtr); + void remove_event_listener(const FlyString& event_name, RefPtr); void remove_from_event_listener_list(NonnullRefPtr); -- cgit v1.2.3