LibWeb: Handle scenario when Window property setter is called on global

This commit fixes a regression introduced in
1528e9109c.

Turns out that the type of `this_value` in the property setter of the
Window object depends on how the variable is accessed. If the property
is accessed as a global variable, then this_value is of type `Window`.
For example:
```js
performance = null
```

However, when it is accessed as a property of the window object,
`this_value` is of type `WindowProxy`. For example:
```js
window.performance = null
```

This commit updates the window property setters generator to handle
both scenarios.

With this change https://discord.com/login works again.
This commit is contained in:
Aliaksandr Kalenik 2024-02-25 10:10:39 +01:00 committed by Andreas Kling
parent bc640b72b1
commit 8a829be25c
3 changed files with 27 additions and 6 deletions

View file

@ -3187,16 +3187,27 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@)
}
)~~~");
} else if (attribute.extended_attributes.contains("Replaceable"sv)) {
if (interface.name.is_one_of("Window")) {
if (interface.name == "Window"sv) {
attribute_generator.append(R"~~~(
JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@)
{
auto this_value = vm.this_value();
if (!this_value.is_object() || !is<WindowProxy>(this_value.as_object()))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "@namespaced_name@");
auto& window_proxy = static_cast<WindowProxy&>(this_value.as_object());
TRY(window_proxy.window()->internal_define_own_property("@attribute.name@", JS::PropertyDescriptor { .value = vm.argument(0), .writable = true }));
return JS::js_undefined();
JS::GCPtr<Window> window;
if (this_value.is_object()) {
if (is<WindowProxy>(this_value.as_object())) {
auto& window_proxy = static_cast<WindowProxy&>(this_value.as_object());
window = window_proxy.window();
} else if (is<Window>(this_value.as_object())) {
window = &static_cast<Window&>(this_value.as_object());
}
}
if (window) {
TRY(window->internal_define_own_property("@attribute.name@", JS::PropertyDescriptor { .value = vm.argument(0), .writable = true }));
return JS::js_undefined();
}
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "@namespaced_name@");
}
)~~~");
} else {

View file

@ -0,0 +1 @@
PASS

View file

@ -0,0 +1,9 @@
<script src="include.js"></script>
<script>
test(() => {
// Test passes if this script does not throw an exception.
performance;
performance = null;
println("PASS");
});
</script>