From 39f5e32ee95858c4841b876c5016c82d4152448a Mon Sep 17 00:00:00 2001 From: Matthew Olsson Date: Sun, 18 Feb 2024 09:19:13 -0700 Subject: [PATCH] IDLGenerators: Add support for custom attribute [ExplicitNull] This can apply to optional, nullable parameters of platform types. This will cause the generator to generate the type as Optional> rather than JS::GCPtr, allowing the implementation to differentiate between the case where the argument was not passed, and the case where null or undefined was passed. Needing to differentiate these two cases is quite niche, hence why it is an opt-in behavior. --- .../BindingsGenerator/IDLGenerators.cpp | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 36da590155..8901ff89a6 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -374,6 +374,7 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter { auto scoped_generator = generator.fork(); auto acceptable_cpp_name = make_input_acceptable_cpp(cpp_name); + auto explicit_null = parameter.extended_attributes.contains("ExplicitNull"); scoped_generator.set("cpp_name", acceptable_cpp_name); scoped_generator.set("js_name", js_name); scoped_generator.set("js_suffix", js_suffix); @@ -381,6 +382,18 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter scoped_generator.set("string_type", string_to_fly_string ? "FlyString" : "String"); scoped_generator.set("parameter.type.name", parameter.type->name()); + if (explicit_null) { + if (!IDL::is_platform_object(*parameter.type)) { + dbgln("Parameter marked [ExplicitNull] in interface {} must be a platform object", interface.name); + VERIFY_NOT_REACHED(); + } + + if (!optional || !parameter.type->is_nullable()) { + dbgln("Parameter marked [ExplicitNull] in interface {} must be an optional and nullable type", interface.name); + VERIFY_NOT_REACHED(); + } + } + if (optional_default_value.has_value()) scoped_generator.set("parameter.optional_default_value", *optional_default_value); @@ -436,8 +449,19 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter )~~~"); } } else { + if (explicit_null) { + scoped_generator.append(R"~~~( + Optional> @cpp_name@; + if (maybe_@js_name@@js_suffix@.has_value()) { + auto @js_name@@js_suffix@ = maybe_@js_name@@js_suffix@.release_value(); +)~~~"); + } else { + scoped_generator.append(R"~~~( + JS::GCPtr<@parameter.type.name@> @cpp_name@; +)~~~"); + } + scoped_generator.append(R"~~~( - @parameter.type.name@* @cpp_name@ = nullptr; if (!@js_name@@js_suffix@.is_nullish()) { if (!@js_name@@js_suffix@.is_object() || !is<@parameter.type.name@>(@js_name@@js_suffix@.as_object())) return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@"); @@ -445,6 +469,12 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter @cpp_name@ = &static_cast<@parameter.type.name@&>(@js_name@@js_suffix@.as_object()); } )~~~"); + + if (explicit_null) { + scoped_generator.append(R"~~~( + } +)~~~"); + } } } else if (parameter.type->name() == "double" || parameter.type->name() == "float") { if (!optional) { @@ -1576,9 +1606,17 @@ static void generate_arguments(SourceGenerator& generator, Vector= @argument.size@ ? Optional { vm.argument(@argument.index@) } : OptionalNone {}; +)~~~"); + } else { + arguments_generator.append(R"~~~( auto arg@argument.index@ = vm.argument(@argument.index@); )~~~"); + } } bool legacy_null_to_empty_string = parameter.extended_attributes.contains("LegacyNullToEmptyString");