mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:07:35 +00:00
LibWeb: Add dictionary types to idl_type_name_to_cpp_type
This allows dictionaries to appear in sequences, records and unions.
This commit is contained in:
parent
567abd52a3
commit
d0ebe80f69
2 changed files with 139 additions and 132 deletions
|
@ -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 (is_wrappable_type(type)) {
|
||||||
if (type.nullable)
|
if (type.nullable)
|
||||||
|
@ -93,7 +93,7 @@ CppType idl_type_name_to_cpp_type(Type const& type)
|
||||||
if (type.name == "sequence") {
|
if (type.name == "sequence") {
|
||||||
auto& parameterized_type = verify_cast<ParameterizedType>(type);
|
auto& parameterized_type = verify_cast<ParameterizedType>(type);
|
||||||
auto& sequence_type = parameterized_type.parameters.first();
|
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);
|
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)
|
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<ParameterizedType>(type);
|
auto& parameterized_type = verify_cast<ParameterizedType>(type);
|
||||||
auto& record_key_type = parameterized_type.parameters[0];
|
auto& record_key_type = parameterized_type.parameters[0];
|
||||||
auto& record_value_type = parameterized_type.parameters[1];
|
auto& record_value_type = parameterized_type.parameters[1];
|
||||||
auto record_key_cpp_type = idl_type_name_to_cpp_type(record_key_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);
|
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 };
|
return { .name = String::formatted("OrderedHashMap<{}, {}>", record_key_cpp_type.name, record_value_cpp_type.name), .sequence_storage_type = SequenceStorageType::Vector };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is<UnionType>(type)) {
|
if (is<UnionType>(type)) {
|
||||||
auto& union_type = verify_cast<UnionType>(type);
|
auto& union_type = verify_cast<UnionType>(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 ? "?" : "");
|
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.
|
// 4. Set result[typedKey] to typedValue.
|
||||||
// 5. Return result.
|
// 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);
|
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.
|
// 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_generator = scoped_generator.fork();
|
||||||
|
|
||||||
auto& union_type = verify_cast<IDL::UnionType>(*parameter.type);
|
auto& union_type = verify_cast<IDL::UnionType>(*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));
|
union_generator.set("recursion_depth", String::number(recursion_depth));
|
||||||
|
|
||||||
// A lambda is used because Variants without "Empty" can't easily be default initialized.
|
// 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.
|
// 4. Return the result of converting x to T.
|
||||||
|
|
||||||
auto union_numeric_type_generator = union_generator.fork();
|
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.set("numeric_type", cpp_type.name);
|
||||||
|
|
||||||
union_numeric_type_generator.append(R"~~~(
|
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("iterable_cpp_name", iterable_cpp_name);
|
||||||
sequence_generator.set("iterator_method_cpp_name", iterator_method_cpp_name);
|
sequence_generator.set("iterator_method_cpp_name", iterator_method_cpp_name);
|
||||||
sequence_generator.set("recursion_depth", String::number(recursion_depth));
|
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.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));
|
sequence_generator.set("sequence.storage_type", sequence_storage_type_to_cpp_storage_type_name(sequence_cpp_type.sequence_storage_type));
|
||||||
|
|
||||||
|
|
|
@ -64,129 +64,6 @@ struct Type : public RefCounted<Type> {
|
||||||
bool is_numeric() const { return is_integer() || name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); }
|
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<Type> member_types)
|
|
||||||
: Type(move(name), nullable)
|
|
||||||
, member_types(move(member_types))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~UnionType() override = default;
|
|
||||||
|
|
||||||
NonnullRefPtrVector<Type> member_types;
|
|
||||||
|
|
||||||
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
|
|
||||||
NonnullRefPtrVector<Type> flattened_member_types() const
|
|
||||||
{
|
|
||||||
// 1. Let T be the union type.
|
|
||||||
|
|
||||||
// 2. Initialize S to ∅.
|
|
||||||
NonnullRefPtrVector<Type> 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<UnionType>(type)) {
|
|
||||||
auto& union_member_type = verify_cast<UnionType>(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<UnionType>(type)) {
|
|
||||||
auto& union_member_type = verify_cast<UnionType>(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<UnionType>(type)) {
|
|
||||||
auto& union_type = verify_cast<UnionType>(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 {
|
struct Parameter {
|
||||||
NonnullRefPtr<Type> type;
|
NonnullRefPtr<Type> type;
|
||||||
String name;
|
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()); }
|
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<Type> member_types)
|
||||||
|
: Type(move(name), nullable)
|
||||||
|
, member_types(move(member_types))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~UnionType() override = default;
|
||||||
|
|
||||||
|
NonnullRefPtrVector<Type> member_types;
|
||||||
|
|
||||||
|
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
|
||||||
|
NonnullRefPtrVector<Type> flattened_member_types() const
|
||||||
|
{
|
||||||
|
// 1. Let T be the union type.
|
||||||
|
|
||||||
|
// 2. Initialize S to ∅.
|
||||||
|
NonnullRefPtrVector<Type> 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<UnionType>(type)) {
|
||||||
|
auto& union_member_type = verify_cast<UnionType>(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<UnionType>(type)) {
|
||||||
|
auto& union_member_type = verify_cast<UnionType>(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<UnionType>(type)) {
|
||||||
|
auto& union_type = verify_cast<UnionType>(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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue