From 70599d3f8d015ca0e5c704e8b0afad85a0f2fa1a Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Tue, 29 Oct 2024 00:57:16 +1300 Subject: [PATCH] LibWeb: Add support for dictionaries in overload resolution By making use of the known set of supported dictionary names in that overload set. Note that this list is typically very small (the max that we have currently is 1). --- .../BindingsGenerator/IDLGenerators.cpp | 28 ++++++++++++++++++- .../LibWeb/WebIDL/OverloadResolution.cpp | 26 ++++++++++------- .../LibWeb/WebIDL/OverloadResolution.h | 3 +- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 5ff07358c08..ce8a0064462 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -2250,6 +2250,21 @@ static size_t resolve_distinguishing_argument_index(Interface const& interface, VERIFY_NOT_REACHED(); } +static void generate_dictionary_types(SourceGenerator& generator, Vector const& dictionary_types) +{ + generator.append(R"~~~( + Vector dictionary_types { +)~~~"); + + for (auto const& dictionary : dictionary_types) { + generator.append(" \""); + generator.append(dictionary); + generator.appendln("\"sv,"); + } + + generator.append("};\n"); +} + static void generate_overload_arbiter(SourceGenerator& generator, auto const& overload_set, IDL::Interface const& interface, ByteString const& class_name, IsConstructor is_constructor) { auto function_generator = generator.fork(); @@ -2260,6 +2275,8 @@ static void generate_overload_arbiter(SourceGenerator& generator, auto const& ov function_generator.set("function.name:snakecase", make_input_acceptable_cpp(overload_set.key.to_snakecase())); + HashTable dictionary_types; + if (is_constructor == IsConstructor::Yes) { function_generator.append(R"~~~( JS::ThrowCompletionOr> @constructor_class@::construct(JS::FunctionObject& new_target) @@ -2324,6 +2341,10 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) optionality_builder.append(", "sv); } + auto const& type = overload.types[i]; + if (interface.dictionaries.contains(type->name())) + dictionary_types.set(type->name()); + types_builder.append(generate_constructor_for_idl_type(overload.types[i])); optionality_builder.append("IDL::Optionality::"sv); @@ -2360,11 +2381,16 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) function_generator.append(R"~~~( } +)~~~"); + + generate_dictionary_types(function_generator, dictionary_types.values()); + + function_generator.append(R"~~~( if (!effective_overload_set.has_value()) return vm.throw_completion(JS::ErrorType::OverloadResolutionFailed); - auto chosen_overload = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value())); + auto chosen_overload = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)); switch (chosen_overload.callable_id) { )~~~"); diff --git a/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp b/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp index 2f93afd73ef..a4d762bdcc1 100644 --- a/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp +++ b/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp @@ -54,10 +54,12 @@ static bool has_overload_with_argument_type_or_subtype_matching(IDL::EffectiveOv } // https://webidl.spec.whatwg.org/#es-overloads -JS::ThrowCompletionOr resolve_overload(JS::VM& vm, IDL::EffectiveOverloadSet& overloads) +JS::ThrowCompletionOr resolve_overload(JS::VM& vm, IDL::EffectiveOverloadSet& overloads, ReadonlySpan dictionary_types) { - // FIXME: The vast majority of this algorithm can be (and must be, in order to resolve the dictionary - // related FIXMEs below) evaluated at code-generation time. + auto is_dictionary = [&dictionary_types](IDL::Type const& type) { + return dictionary_types.contains_slow(type.name()); + }; + // 1. Let maxarg be the length of the longest type list of the entries in S. // 2. Let n be the size of args. // 3. Initialize argcount to be min(maxarg, n). @@ -135,17 +137,20 @@ JS::ThrowCompletionOr resolve_overload(JS::VM& vm, IDL::Effect // NOTE: This is the one case we can't use `has_overload_with_argument_type_or_subtype_matching()` because we also need to look // for dictionary types in the flattened members. else if ((value.is_undefined() || value.is_null()) - && overloads.has_overload_with_matching_argument_at_index(i, [](IDL::Type const& type, auto) { + && overloads.has_overload_with_matching_argument_at_index(i, [&is_dictionary](IDL::Type const& type, auto) { if (type.is_nullable()) return true; - // FIXME: - a dictionary type + if (is_dictionary(type)) + return true; + // FIXME: - an annotated type whose inner type is one of the above types if (type.is_union()) { auto flattened_members = type.as_union().flattened_member_types(); for (auto const& member : flattened_members) { if (member->is_nullable()) return true; - // FIXME: - a dictionary type + if (is_dictionary(type)) + return true; // FIXME: - an annotated type whose inner type is one of the above types } return false; @@ -270,10 +275,11 @@ JS::ThrowCompletionOr resolve_overload(JS::VM& vm, IDL::Effect // - a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types // then remove from S all other entries. else if (value.is_object() - && has_overload_with_argument_type_or_subtype_matching(overloads, i, [](IDL::Type const& type) { - dbgln("FIXME: a callback interface type"); - dbgln("FIXME: a dictionary type"); - dbgln("FIXME: a record type"); + && has_overload_with_argument_type_or_subtype_matching(overloads, i, [&is_dictionary](IDL::Type const& type) { + if (is_dictionary(type)) + return true; + // FIXME: a callback interface type + // FIXME: a record type return type.is_object(); })) { overloads.remove_all_other_entries(); diff --git a/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.h b/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.h index dbed20a9ab5..14cf87383de 100644 --- a/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.h +++ b/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -23,6 +24,6 @@ struct ResolvedOverload { }; // https://webidl.spec.whatwg.org/#es-overloads -JS::ThrowCompletionOr resolve_overload(JS::VM&, IDL::EffectiveOverloadSet&); +JS::ThrowCompletionOr resolve_overload(JS::VM&, IDL::EffectiveOverloadSet&, ReadonlySpan interface_dictionaries); }