LibWeb/Bindings: Implement LegacyLenientThis extended attribute

This commit is contained in:
Shannon Booth
2026-03-13 16:51:52 +01:00
committed by Shannon Booth
parent 604b79403c
commit 19af2bebc7
Notes: github-actions[bot] 2026-03-13 23:09:17 +00:00
2 changed files with 25 additions and 9 deletions

View File

@@ -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 realms 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 realms 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"~~~(

View File

@@ -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