diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index c47c95b67c..dcf693a1fe 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -1925,7 +1925,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@@overload_suffi } // https://webidl.spec.whatwg.org/#compute-the-effective-overload-set -static EffectiveOverloadSet compute_the_effective_overload_set(auto const& overload_set) +static Vector compute_the_effective_overload_set(auto const& overload_set) { // 1. Let S be an ordered set. Vector overloads; @@ -2048,7 +2048,7 @@ static EffectiveOverloadSet compute_the_effective_overload_set(auto const& overl overload_id++; } - return EffectiveOverloadSet { move(overloads) }; + return overloads; } static DeprecatedString generate_constructor_for_idl_type(Type const& type) @@ -2090,6 +2090,30 @@ static DeprecatedString generate_constructor_for_idl_type(Type const& type) VERIFY_NOT_REACHED(); } +// https://webidl.spec.whatwg.org/#dfn-distinguishing-argument-index +static size_t resolve_distinguishing_argument_index(Vector const& items, size_t argument_count) +{ + for (auto argument_index = 0u; argument_index < argument_count; ++argument_index) { + bool found_indistinguishable = false; + + for (auto first_item_index = 0u; first_item_index < items.size(); ++first_item_index) { + for (auto second_item_index = first_item_index + 1; second_item_index < items.size(); ++second_item_index) { + if (!items[first_item_index].types[argument_index]->is_distinguishable_from(items[second_item_index].types[argument_index])) { + found_indistinguishable = true; + break; + } + } + if (found_indistinguishable) + break; + } + + if (!found_indistinguishable) + return argument_index; + } + + VERIFY_NOT_REACHED(); +} + static void generate_overload_arbiter(SourceGenerator& generator, auto const& overload_set, DeprecatedString const& class_name) { auto function_generator = generator.fork(); @@ -2102,8 +2126,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) Optional effective_overload_set; )~~~"); - auto all_possible_effective_overloads = compute_the_effective_overload_set(overload_set); - auto overloads_set = all_possible_effective_overloads.items(); + auto overloads_set = compute_the_effective_overload_set(overload_set); auto maximum_argument_count = 0u; for (auto const& overload : overloads_set) maximum_argument_count = max(maximum_argument_count, overload.types.size()); @@ -2115,29 +2138,28 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) // Namely, since that discards any overloads that don't have the exact number of arguments that were given, // we simply only provide the overloads that do have that number of arguments. for (auto argument_count = 0u; argument_count <= maximum_argument_count; ++argument_count) { - // FIXME: Calculate the distinguishing argument index now instead of at runtime. - - auto effective_overload_count = 0; + Vector effective_overload_set; for (auto const& overload : overloads_set) { if (overload.types.size() == argument_count) - effective_overload_count++; + effective_overload_set.append(overload); } - if (effective_overload_count == 0) + if (effective_overload_set.size() == 0) continue; + auto distinguishing_argument_index = 0u; + if (effective_overload_set.size() > 1) + distinguishing_argument_index = resolve_distinguishing_argument_index(effective_overload_set, argument_count); + function_generator.set("current_argument_count", DeprecatedString::number(argument_count)); - function_generator.set("overload_count", DeprecatedString::number(effective_overload_count)); + function_generator.set("overload_count", DeprecatedString::number(effective_overload_set.size())); function_generator.appendln(R"~~~( case @current_argument_count@: { Vector overloads; overloads.ensure_capacity(@overload_count@); )~~~"); - for (auto& overload : overloads_set) { - if (overload.types.size() != argument_count) - continue; - + for (auto& overload : effective_overload_set) { StringBuilder types_builder; types_builder.append("Vector> { "sv); StringBuilder optionality_builder; @@ -2175,8 +2197,9 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) function_generator.appendln(" overloads.empend(@overload.callable_id@, @overload.types@, @overload.optionality_values@);"); } + function_generator.set("overload_set.distinguishing_argument_index", DeprecatedString::number(distinguishing_argument_index)); function_generator.append(R"~~~( - effective_overload_set.emplace(move(overloads)); + effective_overload_set.emplace(move(overloads), @overload_set.distinguishing_argument_index@); break; } )~~~"); diff --git a/Userland/Libraries/LibIDL/Types.cpp b/Userland/Libraries/LibIDL/Types.cpp index 564f32c176..45dd7297d4 100644 --- a/Userland/Libraries/LibIDL/Types.cpp +++ b/Userland/Libraries/LibIDL/Types.cpp @@ -293,30 +293,6 @@ bool Type::is_json(Interface const& interface) const return false; } -// https://webidl.spec.whatwg.org/#dfn-distinguishing-argument-index -int EffectiveOverloadSet::distinguishing_argument_index() -{ - for (auto argument_index = 0u; argument_index < m_argument_count; ++argument_index) { - bool found_indistinguishable = false; - - for (auto first_item_index = 0u; first_item_index < m_items.size(); ++first_item_index) { - for (auto second_item_index = first_item_index + 1; second_item_index < m_items.size(); ++second_item_index) { - if (!m_items[first_item_index].types[argument_index]->is_distinguishable_from(m_items[second_item_index].types[argument_index])) { - found_indistinguishable = true; - break; - } - } - if (found_indistinguishable) - break; - } - - if (!found_indistinguishable) - return argument_index; - } - - VERIFY_NOT_REACHED(); -} - void EffectiveOverloadSet::remove_all_other_entries() { Vector new_items; diff --git a/Userland/Libraries/LibIDL/Types.h b/Userland/Libraries/LibIDL/Types.h index 1524d55d15..e6482b6885 100644 --- a/Userland/Libraries/LibIDL/Types.h +++ b/Userland/Libraries/LibIDL/Types.h @@ -415,9 +415,9 @@ public: Vector optionality_values; }; - EffectiveOverloadSet(Vector items) + EffectiveOverloadSet(Vector items, size_t distinguishing_argument_index) : m_items(move(items)) - , m_argument_count(m_items.is_empty() ? 0 : m_items.first().types.size()) + , m_distinguishing_argument_index(distinguishing_argument_index) { } @@ -433,7 +433,7 @@ public: bool is_empty() const { return m_items.is_empty(); } size_t size() const { return m_items.size(); } - int distinguishing_argument_index(); + size_t distinguishing_argument_index() const { return m_distinguishing_argument_index; } template bool has_overload_with_matching_argument_at_index(size_t index, Matches matches) @@ -454,7 +454,7 @@ public: private: // FIXME: This should be an "ordered set". Vector m_items; - size_t m_argument_count; + size_t m_distinguishing_argument_index { 0 }; Optional m_last_matching_item_index; }; diff --git a/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp b/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp index cef6292f4f..4298a8b527 100644 --- a/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp +++ b/Userland/Libraries/LibWeb/WebIDL/OverloadResolution.cpp @@ -56,6 +56,8 @@ 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) { + // 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. // 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).