From 1a7932601a29b8a8cca4e8b01e4ff52a02f749e4 Mon Sep 17 00:00:00 2001 From: Bastiaan van der Plaat Date: Mon, 5 May 2025 20:24:15 +0200 Subject: [PATCH] IDLGenerators: Fix Exposed extended attribute codegen --- .../BindingsGenerator/IDLGenerators.cpp | 45 +++++++++++++---- .../geometry/dommatrix-worker-exposed.txt | 6 +++ .../geometry/dommatrix-worker-exposed.html | 48 +++++++++++++++++++ 3 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/geometry/dommatrix-worker-exposed.txt create mode 100644 Tests/LibWeb/Text/input/geometry/dommatrix-worker-exposed.html diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 004dd7597db..743bd7d43a4 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace IDL { @@ -3500,22 +3501,34 @@ void @class_name@::initialize(JS::Realm& realm) )~~~"); } + // NOTE: Add more specified exposed global interface groups when needed. + StringBuilder window_exposed_only_members_builder; + SourceGenerator window_exposed_only_members_generator { window_exposed_only_members_builder, generator.clone_mapping() }; + auto generator_for_member = [&](auto const& name, auto& extended_attributes) -> SourceGenerator { + if (auto maybe_exposed = extended_attributes.get("Exposed"); maybe_exposed.has_value()) { + auto exposed_to = MUST(IDL::parse_exposure_set(name, *maybe_exposed)); + if (exposed_to == IDL::ExposedTo::Window) { + return window_exposed_only_members_generator.fork(); + } + } + return generator.fork(); + }; + // https://webidl.spec.whatwg.org/#es-attributes for (auto& attribute : interface.attributes) { bool has_unforgeable_attribute = attribute.extended_attributes.contains("LegacyUnforgeable"sv); if ((generate_unforgeables == GenerateUnforgeables::Yes && !has_unforgeable_attribute) || (generate_unforgeables == GenerateUnforgeables::No && has_unforgeable_attribute)) continue; + auto attribute_generator = generator_for_member(attribute.name, attribute.extended_attributes); if (attribute.extended_attributes.contains("FIXME")) { - auto fixme_attribute_generator = generator.fork(); - fixme_attribute_generator.set("attribute.name", attribute.name); - fixme_attribute_generator.append(R"~~~( + attribute_generator.set("attribute.name", attribute.name); + attribute_generator.append(R"~~~( @define_direct_property@("@attribute.name@"_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented); )~~~"); continue; } - auto attribute_generator = generator.fork(); attribute_generator.set("attribute.name", attribute.name); attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name); @@ -3541,9 +3554,9 @@ void @class_name@::initialize(JS::Realm& realm) continue; if (function.extended_attributes.contains("FIXME")) { - auto fixme_function_generator = generator.fork(); - fixme_function_generator.set("function.name", function.name); - fixme_function_generator.append(R"~~~( + auto function_generator = generator_for_member(function.name, function.extended_attributes); + function_generator.set("function.name", function.name); + function_generator.append(R"~~~( @define_direct_property@("@function.name@"_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented); )~~~"); } @@ -3572,7 +3585,8 @@ void @class_name@::initialize(JS::Realm& realm) if ((generate_unforgeables == GenerateUnforgeables::Yes && !has_unforgeable_attribute) || (generate_unforgeables == GenerateUnforgeables::No && has_unforgeable_attribute)) continue; - auto function_generator = generator.fork(); + auto const& function = overload_set.value.first(); + auto function_generator = generator_for_member(function.name, function.extended_attributes); function_generator.set("function.name", overload_set.key); function_generator.set("function.name:snakecase", make_input_acceptable_cpp(overload_set.key.to_snakecase())); function_generator.set("function.length", ByteString::number(get_shortest_function_length(overload_set.value))); @@ -3595,10 +3609,11 @@ void @class_name@::initialize(JS::Realm& realm) if ((generate_unforgeables == GenerateUnforgeables::Yes && !has_unforgeable_attribute) || (generate_unforgeables == GenerateUnforgeables::No && has_unforgeable_attribute)) should_generate_stringifier = false; } - if (interface.has_stringifier && should_generate_stringifier) { // FIXME: Do stringifiers need to be added to the unscopable list? - auto stringifier_generator = generator.fork(); + auto stringifier_generator = interface.stringifier_extended_attributes.has_value() + ? generator_for_member("stringifier"sv, *interface.stringifier_extended_attributes) + : generator.fork(); stringifier_generator.append(R"~~~( @define_native_function@(realm, "toString"_fly_string, to_string, 0, default_attributes); )~~~"); @@ -3691,6 +3706,16 @@ void @class_name@::initialize(JS::Realm& realm) )~~~"); } + if (!window_exposed_only_members_generator.as_string_view().is_empty()) { + auto window_only_property_declarations = generator.fork(); + window_only_property_declarations.set("defines", window_exposed_only_members_generator.as_string_view()); + window_only_property_declarations.append(R"~~~( + if (is(realm.global_object())) { +@defines@ + } +)~~~"); + } + if (!define_on_existing_object) { generator.append(R"~~~( Base::initialize(realm); diff --git a/Tests/LibWeb/Text/expected/geometry/dommatrix-worker-exposed.txt b/Tests/LibWeb/Text/expected/geometry/dommatrix-worker-exposed.txt new file mode 100644 index 00000000000..a8972ce6745 --- /dev/null +++ b/Tests/LibWeb/Text/expected/geometry/dommatrix-worker-exposed.txt @@ -0,0 +1,6 @@ +1. {"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"m11":1,"m12":2,"m13":0,"m14":0,"m21":3,"m22":4,"m23":0,"m24":0,"m31":0,"m32":0,"m33":1,"m34":0,"m41":5,"m42":6,"m43":0,"m44":1,"is2D":true,"isIdentity":false} +2. "matrix(1, 0, 0, 1, 0, 0)" +3. "Google Inc." +4. TypeError: undefined is not a function (evaluated from '.setMatrixValue') +5. [object DOMMatrix] +6. undefined diff --git a/Tests/LibWeb/Text/input/geometry/dommatrix-worker-exposed.html b/Tests/LibWeb/Text/input/geometry/dommatrix-worker-exposed.html new file mode 100644 index 00000000000..87a1c769721 --- /dev/null +++ b/Tests/LibWeb/Text/input/geometry/dommatrix-worker-exposed.html @@ -0,0 +1,48 @@ + + +