From 19af2bebc78cf093aa2de6a35bd167296490b0a0 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Fri, 13 Mar 2026 16:51:52 +0100 Subject: [PATCH] LibWeb/Bindings: Implement LegacyLenientThis extended attribute --- .../BindingsGenerator/IDLGenerators.cpp | 29 +++++++++++++++---- .../ecmascript-binding/setter-argument.txt | 5 ++-- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index aaab2ac3713..395e83e4963 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -4130,13 +4130,20 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@) // 4. Let idlObject be null. // 5. If attribute is a regular attribute: - // FIXME: 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.) - auto* impl = TRY(impl_from(vm)); - + // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. + // (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.) // FIXME: 2. If jsValue is a platform object, then perform a security check, passing jsValue, id, and "setter". - // FIXME: 3. Let validThis be true if jsValue implements target, or false otherwise. - // FIXME: 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError. + // 3. Let validThis be true if jsValue implements target, or false otherwise. + auto maybe_impl = impl_from(vm); + + // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError. )~~~"); + if (!attribute.extended_attributes.contains("LegacyLenientThis")) { + attribute_generator.append(R"~~~( + auto impl = TRY(maybe_impl); +)~~~"); + } + // For [CEReactions]: https://html.spec.whatwg.org/multipage/custom-elements.html#cereactions if (attribute.extended_attributes.contains("CEReactions")) { @@ -4160,7 +4167,17 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@) return; } - // FIXME: 6. If validThis is false, then return undefined. + // 6. If validThis is false, then return undefined. + // NB: This is only possible if LegacyLenientThis is defined. + if (attribute.extended_attributes.contains("LegacyLenientThis")) { + attribute_generator.append(R"~~~( + if (maybe_impl.is_error()) + return JS::js_undefined(); + + auto impl = maybe_impl.release_value(); +)~~~"); + } + // 7. If attribute is declared with a [LegacyLenientSetter] extended attribute, then return undefined. if (auto legacy_lenient_setter_identifier = attribute.extended_attributes.get("LegacyLenientSetter"sv); legacy_lenient_setter_identifier.has_value()) { attribute_generator.append(R"~~~( diff --git a/Tests/LibWeb/Text/expected/wpt-import/webidl/ecmascript-binding/setter-argument.txt b/Tests/LibWeb/Text/expected/wpt-import/webidl/ecmascript-binding/setter-argument.txt index bfe3747a9de..c07e7c649f1 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/webidl/ecmascript-binding/setter-argument.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/webidl/ecmascript-binding/setter-argument.txt @@ -2,8 +2,7 @@ Harness status: OK Found 17 tests -16 Pass -1 Fail +17 Pass Pass String attribute setter should throw if this value is invalid Pass String attribute setter should treat no arguments as undefined Pass String attribute setter called with undefined should behave in the same way as no arguments @@ -14,7 +13,7 @@ Pass Object attribute setter called with undefined should behave in the same way Pass [Replaceable] setter should treat no arguments as undefined Pass [Replaceable] setter called with undefined should behave in the same way as no arguments Pass [Replaceable] setter called with other value should just work -Fail [LegacyLenientThis] setter should not throw even if this value is invalid, regardless of the arguments count +Pass [LegacyLenientThis] setter should not throw even if this value is invalid, regardless of the arguments count Pass [LegacyLenientThis] setter should treat no arguments as undefined Pass [LegacyLenientThis] setter called with undefined should behave in the same way as no arguments Pass [LegacyLenientSetter] setter should treat no arguments as undefined