浏览代码

LibIDL: Support dictionary types when distinguishing argument indices

Idan Horowitz 1 年之前
父节点
当前提交
f2410071cd

+ 7 - 7
Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp

@@ -2091,14 +2091,14 @@ static DeprecatedString generate_constructor_for_idl_type(Type const& type)
 }
 
 // https://webidl.spec.whatwg.org/#dfn-distinguishing-argument-index
-static size_t resolve_distinguishing_argument_index(Vector<EffectiveOverloadSet::Item> const& items, size_t argument_count)
+static size_t resolve_distinguishing_argument_index(Interface const& interface, Vector<EffectiveOverloadSet::Item> 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])) {
+                if (!items[first_item_index].types[argument_index]->is_distinguishable_from(interface, items[second_item_index].types[argument_index])) {
                     found_indistinguishable = true;
                     break;
                 }
@@ -2114,7 +2114,7 @@ static size_t resolve_distinguishing_argument_index(Vector<EffectiveOverloadSet:
     VERIFY_NOT_REACHED();
 }
 
-static void generate_overload_arbiter(SourceGenerator& generator, auto const& overload_set, DeprecatedString const& class_name)
+static void generate_overload_arbiter(SourceGenerator& generator, auto const& overload_set, IDL::Interface const& interface, DeprecatedString const& class_name)
 {
     auto function_generator = generator.fork();
     function_generator.set("class_name", class_name);
@@ -2149,7 +2149,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@)
 
         auto distinguishing_argument_index = 0u;
         if (effective_overload_set.size() > 1)
-            distinguishing_argument_index = resolve_distinguishing_argument_index(effective_overload_set, argument_count);
+            distinguishing_argument_index = resolve_distinguishing_argument_index(interface, effective_overload_set, argument_count);
 
         function_generator.set("current_argument_count", DeprecatedString::number(argument_count));
         function_generator.set("overload_count", DeprecatedString::number(effective_overload_set.size()));
@@ -3200,7 +3200,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@)
     for (auto const& overload_set : interface.overload_sets) {
         if (overload_set.value.size() == 1)
             continue;
-        generate_overload_arbiter(generator, overload_set, class_name);
+        generate_overload_arbiter(generator, overload_set, interface, class_name);
     }
 
     if (interface.has_stringifier) {
@@ -3442,7 +3442,7 @@ void @namespace_class@::visit_edges(JS::Cell::Visitor& visitor)
     for (auto const& overload_set : interface.overload_sets) {
         if (overload_set.value.size() == 1)
             continue;
-        generate_overload_arbiter(generator, overload_set, interface.namespace_class);
+        generate_overload_arbiter(generator, overload_set, interface, interface.namespace_class);
     }
 
     generator.append(R"~~~(
@@ -3846,7 +3846,7 @@ void @constructor_class@::initialize(JS::Realm& realm)
     for (auto const& overload_set : interface.static_overload_sets) {
         if (overload_set.value.size() == 1)
             continue;
-        generate_overload_arbiter(generator, overload_set, interface.constructor_class);
+        generate_overload_arbiter(generator, overload_set, interface, interface.constructor_class);
     }
 
     generator.append(R"~~~(

+ 11 - 7
Userland/Libraries/LibIDL/Types.cpp

@@ -71,13 +71,12 @@ bool Type::includes_undefined() const
 }
 
 // https://webidl.spec.whatwg.org/#dfn-distinguishable
-bool Type::is_distinguishable_from(IDL::Type const& other) const
+bool Type::is_distinguishable_from(IDL::Interface const& interface, IDL::Type const& other) const
 {
     // 1. If one type includes a nullable type and the other type either includes a nullable type,
     //    is a union type with flattened member types including a dictionary type, or is a dictionary type,
     //    return false.
-    // FIXME: "is a union type with flattened member types including a dictionary type, or is a dictionary type,"
-    if (includes_nullable_type() && other.includes_nullable_type())
+    if (includes_nullable_type() && (other.includes_nullable_type() || (other.is_union() && any_of(other.as_union().flattened_member_types(), [&interface](auto const& type) { return interface.dictionaries.contains(type->name()); })) || interface.dictionaries.contains(other.name())))
         return false;
 
     // 2. If both types are either a union type or nullable union type, return true if each member type
@@ -88,7 +87,7 @@ bool Type::is_distinguishable_from(IDL::Type const& other) const
 
         for (auto& this_member_type : this_union.member_types()) {
             for (auto& other_member_type : other_union.member_types()) {
-                if (!this_member_type->is_distinguishable_from(other_member_type))
+                if (!this_member_type->is_distinguishable_from(interface, other_member_type))
                     return false;
             }
         }
@@ -102,7 +101,7 @@ bool Type::is_distinguishable_from(IDL::Type const& other) const
         auto const& non_union = is_union() ? other : *this;
 
         for (auto& member_type : the_union.member_types()) {
-            if (!non_union.is_distinguishable_from(member_type))
+            if (!non_union.is_distinguishable_from(interface, member_type))
                 return false;
         }
         return true;
@@ -148,7 +147,7 @@ bool Type::is_distinguishable_from(IDL::Type const& other) const
     };
     // clang-format on
 
-    auto determine_category = [](Type const& type) -> DistinguishabilityCategory {
+    auto determine_category = [&interface](Type const& type) -> DistinguishabilityCategory {
         if (type.is_undefined())
             return DistinguishabilityCategory::Undefined;
         if (type.is_boolean())
@@ -165,7 +164,12 @@ bool Type::is_distinguishable_from(IDL::Type const& other) const
             return DistinguishabilityCategory::Symbol;
         // FIXME: InterfaceLike - see below
         // FIXME: CallbackFunction
-        // FIXME: DictionaryLike
+        // DictionaryLike
+        // * Dictionary Types
+        // * Record Types
+        // FIXME: * Callback Interface Types
+        if (interface.dictionaries.contains(type.name()) || (type.is_parameterized() && type.name() == "record"sv))
+            return DistinguishabilityCategory::DictionaryLike;
         // FIXME: Frozen array types are included in "sequence-like"
         if (type.is_sequence())
             return DistinguishabilityCategory::SequenceLike;

+ 1 - 1
Userland/Libraries/LibIDL/Types.h

@@ -134,7 +134,7 @@ public:
     bool is_sequence() const { return is_parameterized() && m_name == "sequence"; }
 
     // https://webidl.spec.whatwg.org/#dfn-distinguishable
-    bool is_distinguishable_from(Type const& other) const;
+    bool is_distinguishable_from(Interface const&, Type const& other) const;
 
     bool is_json(Interface const&) const;