From d0ebe80f69423ef31f89898fae1a55ccf771172f Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Sat, 19 Feb 2022 21:57:34 +0000 Subject: [PATCH] LibWeb: Add dictionary types to idl_type_name_to_cpp_type This allows dictionaries to appear in sequences, records and unions. --- .../LibWeb/WrapperGenerator/IDLGenerators.cpp | 25 +- .../LibWeb/WrapperGenerator/IDLTypes.h | 246 +++++++++--------- 2 files changed, 139 insertions(+), 132 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp index 5a99a08c16..6fbd35ee89 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp @@ -60,7 +60,7 @@ static StringView sequence_storage_type_to_cpp_storage_type_name(SequenceStorage } } -CppType idl_type_name_to_cpp_type(Type const& type) +CppType idl_type_name_to_cpp_type(Type const& type, Interface const& interface) { if (is_wrappable_type(type)) { if (type.nullable) @@ -93,7 +93,7 @@ CppType idl_type_name_to_cpp_type(Type const& type) if (type.name == "sequence") { auto& parameterized_type = verify_cast(type); auto& sequence_type = parameterized_type.parameters.first(); - auto sequence_cpp_type = idl_type_name_to_cpp_type(sequence_type); + auto sequence_cpp_type = idl_type_name_to_cpp_type(sequence_type, interface); auto storage_type_name = sequence_storage_type_to_cpp_storage_type_name(sequence_cpp_type.sequence_storage_type); if (sequence_cpp_type.sequence_storage_type == SequenceStorageType::MarkedVector) @@ -106,15 +106,22 @@ CppType idl_type_name_to_cpp_type(Type const& type) auto& parameterized_type = verify_cast(type); auto& record_key_type = parameterized_type.parameters[0]; auto& record_value_type = parameterized_type.parameters[1]; - auto record_key_cpp_type = idl_type_name_to_cpp_type(record_key_type); - auto record_value_cpp_type = idl_type_name_to_cpp_type(record_value_type); + auto record_key_cpp_type = idl_type_name_to_cpp_type(record_key_type, interface); + auto record_value_cpp_type = idl_type_name_to_cpp_type(record_value_type, interface); return { .name = String::formatted("OrderedHashMap<{}, {}>", record_key_cpp_type.name, record_value_cpp_type.name), .sequence_storage_type = SequenceStorageType::Vector }; } if (is(type)) { auto& union_type = verify_cast(type); - return { .name = union_type.to_variant(), .sequence_storage_type = SequenceStorageType::Vector }; + return { .name = union_type.to_variant(interface), .sequence_storage_type = SequenceStorageType::Vector }; + } + + if (!type.nullable) { + for (auto& dictionary : interface.dictionaries) { + if (type.name == dictionary.key) + return { .name = type.name, .sequence_storage_type = SequenceStorageType::Vector }; + } } dbgln("Unimplemented type for idl_type_name_to_cpp_type: {}{}", type.name, type.nullable ? "?" : ""); @@ -612,7 +619,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter // 4. Set result[typedKey] to typedValue. // 5. Return result. - auto record_cpp_type = IDL::idl_type_name_to_cpp_type(parameterized_type); + auto record_cpp_type = IDL::idl_type_name_to_cpp_type(parameterized_type, interface); record_generator.set("record.type", record_cpp_type.name); // If this is a recursive call to generate_to_cpp, assume that the caller has already handled converting the JS value to an object for us. @@ -661,7 +668,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter auto union_generator = scoped_generator.fork(); auto& union_type = verify_cast(*parameter.type); - union_generator.set("union_type", union_type.to_variant()); + union_generator.set("union_type", union_type.to_variant(interface)); union_generator.set("recursion_depth", String::number(recursion_depth)); // A lambda is used because Variants without "Empty" can't easily be default initialized. @@ -940,7 +947,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter // 4. Return the result of converting x to T. auto union_numeric_type_generator = union_generator.fork(); - auto cpp_type = IDL::idl_type_name_to_cpp_type(*numeric_type); + auto cpp_type = IDL::idl_type_name_to_cpp_type(*numeric_type, interface); union_numeric_type_generator.set("numeric_type", cpp_type.name); union_numeric_type_generator.append(R"~~~( @@ -1086,7 +1093,7 @@ void IDL::ParameterizedType::generate_sequence_from_iterable(SourceGenerator& ge sequence_generator.set("iterable_cpp_name", iterable_cpp_name); sequence_generator.set("iterator_method_cpp_name", iterator_method_cpp_name); sequence_generator.set("recursion_depth", String::number(recursion_depth)); - auto sequence_cpp_type = idl_type_name_to_cpp_type(parameters.first()); + auto sequence_cpp_type = idl_type_name_to_cpp_type(parameters.first(), interface); sequence_generator.set("sequence.type", sequence_cpp_type.name); sequence_generator.set("sequence.storage_type", sequence_storage_type_to_cpp_storage_type_name(sequence_cpp_type.sequence_storage_type)); diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLTypes.h b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLTypes.h index ce90bf927c..dcc1312b6c 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLTypes.h +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLTypes.h @@ -64,129 +64,6 @@ struct Type : public RefCounted { bool is_numeric() const { return is_integer() || name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); } }; -CppType idl_type_name_to_cpp_type(Type const& type); - -struct UnionType : public Type { - UnionType() = default; - - UnionType(String name, bool nullable, NonnullRefPtrVector member_types) - : Type(move(name), nullable) - , member_types(move(member_types)) - { - } - - virtual ~UnionType() override = default; - - NonnullRefPtrVector member_types; - - // https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types - NonnullRefPtrVector flattened_member_types() const - { - // 1. Let T be the union type. - - // 2. Initialize S to ∅. - NonnullRefPtrVector types; - - // 3. For each member type U of T: - for (auto& type : member_types) { - // FIXME: 1. If U is an annotated type, then set U to be the inner type of U. - - // 2. If U is a nullable type, then set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct) - - // 3. If U is a union type, then add to S the flattened member types of U. - if (is(type)) { - auto& union_member_type = verify_cast(type); - types.extend(union_member_type.flattened_member_types()); - } else { - // 4. Otherwise, U is not a union type. Add U to S. - types.append(type); - } - } - - // 4. Return S. - return types; - } - - // https://webidl.spec.whatwg.org/#dfn-number-of-nullable-member-types - size_t number_of_nullable_member_types() const - { - // 1. Let T be the union type. - - // 2. Initialize n to 0. - size_t num_nullable_member_types = 0; - - // 3. For each member type U of T: - for (auto& type : member_types) { - // 1. If U is a nullable type, then: - if (type.nullable) { - // 1. Set n to n + 1. - ++num_nullable_member_types; - - // 2. Set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct) - } - - // 2. If U is a union type, then: - if (is(type)) { - auto& union_member_type = verify_cast(type); - - // 1. Let m be the number of nullable member types of U. - // 2. Set n to n + m. - num_nullable_member_types += union_member_type.number_of_nullable_member_types(); - } - } - - // 4. Return n. - return num_nullable_member_types; - } - - // https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type - bool includes_nullable_type() const - { - // -> the type is a union type and its number of nullable member types is 1. - return number_of_nullable_member_types() == 1; - } - - // -> https://webidl.spec.whatwg.org/#dfn-includes-undefined - bool includes_undefined() const - { - // -> the type is a union type and one of its member types includes undefined. - for (auto& type : member_types) { - if (is(type)) { - auto& union_type = verify_cast(type); - if (union_type.includes_undefined()) - return true; - } - - if (type.name == "undefined"sv) - return true; - } - return false; - } - - String to_variant() const - { - StringBuilder builder; - builder.append("Variant<"); - - auto flattened_types = flattened_member_types(); - for (size_t type_index = 0; type_index < flattened_types.size(); ++type_index) { - auto& type = flattened_types.at(type_index); - - if (type_index > 0) - builder.append(", "); - - auto cpp_type = idl_type_name_to_cpp_type(type); - builder.append(cpp_type.name); - } - - if (includes_undefined()) - builder.append(", Empty"); - - builder.append('>'); - return builder.to_string(); - } -}; - struct Parameter { NonnullRefPtr type; String name; @@ -322,4 +199,127 @@ struct Interface { bool is_legacy_platform_object() const { return !extended_attributes.contains("Global") && (supports_indexed_properties() || supports_named_properties()); } }; +CppType idl_type_name_to_cpp_type(Type const& type, IDL::Interface const& interface); + +struct UnionType : public Type { + UnionType() = default; + + UnionType(String name, bool nullable, NonnullRefPtrVector member_types) + : Type(move(name), nullable) + , member_types(move(member_types)) + { + } + + virtual ~UnionType() override = default; + + NonnullRefPtrVector member_types; + + // https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types + NonnullRefPtrVector flattened_member_types() const + { + // 1. Let T be the union type. + + // 2. Initialize S to ∅. + NonnullRefPtrVector types; + + // 3. For each member type U of T: + for (auto& type : member_types) { + // FIXME: 1. If U is an annotated type, then set U to be the inner type of U. + + // 2. If U is a nullable type, then set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct) + + // 3. If U is a union type, then add to S the flattened member types of U. + if (is(type)) { + auto& union_member_type = verify_cast(type); + types.extend(union_member_type.flattened_member_types()); + } else { + // 4. Otherwise, U is not a union type. Add U to S. + types.append(type); + } + } + + // 4. Return S. + return types; + } + + // https://webidl.spec.whatwg.org/#dfn-number-of-nullable-member-types + size_t number_of_nullable_member_types() const + { + // 1. Let T be the union type. + + // 2. Initialize n to 0. + size_t num_nullable_member_types = 0; + + // 3. For each member type U of T: + for (auto& type : member_types) { + // 1. If U is a nullable type, then: + if (type.nullable) { + // 1. Set n to n + 1. + ++num_nullable_member_types; + + // 2. Set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct) + } + + // 2. If U is a union type, then: + if (is(type)) { + auto& union_member_type = verify_cast(type); + + // 1. Let m be the number of nullable member types of U. + // 2. Set n to n + m. + num_nullable_member_types += union_member_type.number_of_nullable_member_types(); + } + } + + // 4. Return n. + return num_nullable_member_types; + } + + // https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type + bool includes_nullable_type() const + { + // -> the type is a union type and its number of nullable member types is 1. + return number_of_nullable_member_types() == 1; + } + + // -> https://webidl.spec.whatwg.org/#dfn-includes-undefined + bool includes_undefined() const + { + // -> the type is a union type and one of its member types includes undefined. + for (auto& type : member_types) { + if (is(type)) { + auto& union_type = verify_cast(type); + if (union_type.includes_undefined()) + return true; + } + + if (type.name == "undefined"sv) + return true; + } + return false; + } + + String to_variant(IDL::Interface const& interface) const + { + StringBuilder builder; + builder.append("Variant<"); + + auto flattened_types = flattened_member_types(); + for (size_t type_index = 0; type_index < flattened_types.size(); ++type_index) { + auto& type = flattened_types.at(type_index); + + if (type_index > 0) + builder.append(", "); + + auto cpp_type = idl_type_name_to_cpp_type(type, interface); + builder.append(cpp_type.name); + } + + if (includes_undefined()) + builder.append(", Empty"); + + builder.append('>'); + return builder.to_string(); + } +}; + }