mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 10:57:35 +00:00
LibWeb: Add support for dictionary types to union types
This also fixes some indentation issues in the generated code.
This commit is contained in:
parent
d0ebe80f69
commit
ced7e8ab28
1 changed files with 80 additions and 41 deletions
|
@ -671,6 +671,41 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
union_generator.set("union_type", union_type.to_variant(interface));
|
||||
union_generator.set("recursion_depth", String::number(recursion_depth));
|
||||
|
||||
// NOTE: This is handled out here as we need the dictionary conversion code for the {} optional default value.
|
||||
// 3. Let types be the flattened member types of the union type.
|
||||
auto types = union_type.flattened_member_types();
|
||||
|
||||
RefPtr<Type> dictionary_type;
|
||||
for (auto& dictionary : interface.dictionaries) {
|
||||
for (auto& type : types) {
|
||||
if (type.name == dictionary.key) {
|
||||
dictionary_type = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionary_type)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dictionary_type) {
|
||||
auto dictionary_generator = union_generator.fork();
|
||||
dictionary_generator.set("dictionary.type", dictionary_type->name);
|
||||
|
||||
// The lambda must take the JS::Value to convert as a parameter instead of capturing it in order to support union types being variadic.
|
||||
dictionary_generator.append(R"~~~(
|
||||
auto @js_name@@js_suffix@_to_dictionary = [&global_object, &vm](JS::Value @js_name@@js_suffix@) -> JS::ThrowCompletionOr<@dictionary.type@> {
|
||||
)~~~");
|
||||
|
||||
IDL::Parameter dictionary_parameter { .type = *dictionary_type, .name = acceptable_cpp_name, .optional_default_value = {}, .extended_attributes = {} };
|
||||
generate_to_cpp(dictionary_generator, dictionary_parameter, js_name, js_suffix, "dictionary_union_type"sv, interface, false, false, {}, false, recursion_depth + 1);
|
||||
|
||||
dictionary_generator.append(R"~~~(
|
||||
return dictionary_union_type;
|
||||
};
|
||||
)~~~");
|
||||
}
|
||||
|
||||
// A lambda is used because Variants without "Empty" can't easily be default initialized.
|
||||
// Plus, this would require the user of union types to always accept a Variant with an Empty type.
|
||||
|
||||
|
@ -679,8 +714,17 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// Note that all the other types only throw on a condition.
|
||||
|
||||
// The lambda must take the JS::Value to convert as a parameter instead of capturing it in order to support union types being variadic.
|
||||
|
||||
StringBuilder to_variant_captures;
|
||||
to_variant_captures.append("&global_object, &vm"sv);
|
||||
|
||||
if (dictionary_type)
|
||||
to_variant_captures.append(String::formatted(", &{}{}_to_dictionary", js_name, js_suffix));
|
||||
|
||||
union_generator.set("to_variant_captures", to_variant_captures.to_string());
|
||||
|
||||
union_generator.append(R"~~~(
|
||||
auto @js_name@@js_suffix@_to_variant = [&global_object, &vm](JS::Value @js_name@@js_suffix@) -> JS::ThrowCompletionOr<@union_type@> {
|
||||
auto @js_name@@js_suffix@_to_variant = [@to_variant_captures@](JS::Value @js_name@@js_suffix@) -> JS::ThrowCompletionOr<@union_type@> {
|
||||
// These might be unused.
|
||||
(void)global_object;
|
||||
(void)vm;
|
||||
|
@ -694,29 +738,16 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
)~~~");
|
||||
}
|
||||
|
||||
// 3. Let types be the flattened member types of the union type.
|
||||
auto types = union_type.flattened_member_types();
|
||||
|
||||
bool contains_dictionary_type = false;
|
||||
for (auto& dictionary : interface.dictionaries) {
|
||||
for (auto& type : types) {
|
||||
if (type.name == dictionary.key) {
|
||||
contains_dictionary_type = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (contains_dictionary_type)
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: 2. If the union type includes a nullable type and V is null or undefined, then return the IDL value null.
|
||||
if (union_type.includes_nullable_type()) {
|
||||
TODO();
|
||||
} else if (contains_dictionary_type) {
|
||||
// FIXME: 4. If V is null or undefined, then
|
||||
// 4.1 If types includes a dictionary type, then return the result of converting V to that dictionary type.
|
||||
TODO();
|
||||
} else if (dictionary_type) {
|
||||
// 4. If V is null or undefined, then
|
||||
// 4.1 If types includes a dictionary type, then return the result of converting V to that dictionary type.
|
||||
union_generator.append(R"~~~(
|
||||
if (@js_name@@js_suffix@.is_nullish())
|
||||
return @union_type@ { TRY(@js_name@@js_suffix@_to_dictionary(@js_name@@js_suffix@)) };
|
||||
)~~~");
|
||||
}
|
||||
|
||||
bool includes_object = false;
|
||||
|
@ -754,7 +785,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
|
||||
auto union_platform_object_type_generator = union_generator.fork();
|
||||
union_platform_object_type_generator.set("platform_object_type", String::formatted("{}Wrapper", type.name));
|
||||
auto cpp_type = IDL::idl_type_name_to_cpp_type(type);
|
||||
auto cpp_type = IDL::idl_type_name_to_cpp_type(type, interface);
|
||||
union_platform_object_type_generator.set("refptr_type", cpp_type.name);
|
||||
|
||||
union_platform_object_type_generator.append(R"~~~(
|
||||
|
@ -825,9 +856,12 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
// 1. Let method be ? GetMethod(V, @@iterator).
|
||||
// 2. If method is not undefined, return the result of creating a frozen array of that type from V and method.
|
||||
|
||||
// FIXME: 3. If types includes a dictionary type, then return the result of converting V to that dictionary type.
|
||||
if (contains_dictionary_type)
|
||||
TODO();
|
||||
// 3. If types includes a dictionary type, then return the result of converting V to that dictionary type.
|
||||
if (dictionary_type) {
|
||||
union_generator.append(R"~~~(
|
||||
return @union_type@ { TRY(@js_name@@js_suffix@_to_dictionary(@js_name@@js_suffix@)) };
|
||||
)~~~");
|
||||
}
|
||||
|
||||
// 4. If types includes a record type, then return the result of converting V to that record type.
|
||||
RefPtr<IDL::ParameterizedType> record_type;
|
||||
|
@ -874,7 +908,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
if (includes_boolean) {
|
||||
union_generator.append(R"~~~(
|
||||
if (@js_name@@js_suffix@.is_boolean())
|
||||
return @js_name@@js_suffix@.as_boolean();
|
||||
return @union_type@ { @js_name@@js_suffix@.as_bool() };
|
||||
)~~~");
|
||||
}
|
||||
|
||||
|
@ -979,7 +1013,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
} else if (includes_boolean) {
|
||||
// 17. If types includes boolean, then return the result of converting V to boolean.
|
||||
union_generator.append(R"~~~(
|
||||
return @js_name@@js_suffix@.to_boolean();
|
||||
return @union_type@ { @js_name@@js_suffix@.to_boolean() };
|
||||
)~~~");
|
||||
} else if (includes_bigint) {
|
||||
// 18. If types includes bigint, then return the result of converting V to bigint.
|
||||
|
@ -996,29 +1030,34 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
|
|||
|
||||
// Close the lambda and then perform the conversion.
|
||||
union_generator.append(R"~~~(
|
||||
};
|
||||
|
||||
)~~~");
|
||||
};
|
||||
)~~~");
|
||||
|
||||
if (!variadic) {
|
||||
if (!optional) {
|
||||
union_generator.append(R"~~~(
|
||||
@union_type@ @cpp_name@ = TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
@union_type@ @cpp_name@ = TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
} else {
|
||||
if (!optional_default_value.has_value()) {
|
||||
union_generator.append(R"~~~(
|
||||
Optional<@union_type@> @cpp_name@;
|
||||
if (!@js_name@@js_suffix@.is_undefined())
|
||||
@cpp_name@ = TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
Optional<@union_type@> @cpp_name@;
|
||||
if (!@js_name@@js_suffix@.is_undefined())
|
||||
@cpp_name@ = TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
} else {
|
||||
if (optional_default_value != "\"\"")
|
||||
if (optional_default_value == "\"\"") {
|
||||
union_generator.append(R"~~~(
|
||||
@union_type@ @cpp_name@ = @js_name@@js_suffix@.is_undefined() ? String::empty() : TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
} else if (optional_default_value == "{}") {
|
||||
VERIFY(dictionary_type);
|
||||
union_generator.append(R"~~~(
|
||||
@union_type@ @cpp_name@ = @js_name@@js_suffix@.is_undefined() ? TRY(@js_name@@js_suffix@_to_dictionary(@js_name@@js_suffix@)) : TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
} else {
|
||||
TODO();
|
||||
|
||||
union_generator.append(R"~~~(
|
||||
@union_type@ @cpp_name@ = @js_name@@js_suffix@.is_undefined() ? String::empty() : TRY(@js_name@@js_suffix@_to_variant(@js_name@@js_suffix@));
|
||||
)~~~");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue