LibWeb: Use CSO if running script is null in HostPromiseRejectionTracker

This commit is contained in:
Luke Wilde 2022-06-27 19:53:30 +01:00 committed by Linus Groh
parent 1d5b03ce17
commit 62491cda0b
Notes: sideshowbarker 2024-07-17 11:06:06 +09:00
2 changed files with 39 additions and 13 deletions

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Unhandled Promise rejection with no [[ScriptOrModule]] for the current execution context</title>
</head>
<body>
<button onclick="
Promise.reject(new Error('Success!'));
window.timer = setTimeout(() => {
const element = document.createElement('p');
element.innerText = 'Did not receieve unhandledrejection event in 100ms.';
element.style.color = 'red';
document.body.appendChild(element);
}, 100)
">
Click me to cause an unhandled promise rejection.
</button>
<script>
window.onunhandledrejection = (rejectionEvent) => {
clearTimeout(window.timer);
const element = document.createElement("p");
element.innerText = rejectionEvent.reason.message;
element.style.color = "green";
document.body.appendChild(element);
}
</script>
</body>
</html>

View file

@ -55,8 +55,7 @@ JS::VM& main_thread_vm()
vm->host_promise_rejection_tracker = [](JS::Promise& promise, JS::Promise::RejectionOperation operation) { vm->host_promise_rejection_tracker = [](JS::Promise& promise, JS::Promise::RejectionOperation operation) {
// 1. Let script be the running script. // 1. Let script be the running script.
// The running script is the script in the [[HostDefined]] field in the ScriptOrModule component of the running JavaScript execution context. // The running script is the script in the [[HostDefined]] field in the ScriptOrModule component of the running JavaScript execution context.
// FIXME: This currently assumes there's only a ClassicScript. HTML::Script* script { nullptr };
HTML::ClassicScript* script { nullptr };
vm->running_execution_context().script_or_module.visit( vm->running_execution_context().script_or_module.visit(
[&script](WeakPtr<JS::Script>& js_script) { [&script](WeakPtr<JS::Script>& js_script) {
script = verify_cast<HTML::ClassicScript>(js_script->host_defined()); script = verify_cast<HTML::ClassicScript>(js_script->host_defined());
@ -67,19 +66,17 @@ JS::VM& main_thread_vm()
[](Empty) { [](Empty) {
}); });
// If there's no script, we're out of luck. Return. // 2. If script is a classic script and script's muted errors is true, then return.
// FIXME: This can happen from JS::NativeFunction, which makes its callee contexts [[ScriptOrModule]] null. // NOTE: is<T>() returns false if nullptr is passed.
if (!script) { if (is<HTML::ClassicScript>(script)) {
dbgln("FIXME: Unable to process unhandled promise rejection in host_promise_rejection_tracker as the running script is null."); auto const& classic_script = static_cast<HTML::ClassicScript const&>(*script);
return; if (classic_script.muted_errors() == HTML::ClassicScript::MutedErrors::Yes)
return;
} }
// 2. If script's muted errors is true, terminate these steps. // 3. Let settings object be the current settings object.
if (script->muted_errors() == HTML::ClassicScript::MutedErrors::Yes) // 4. If script is not null, then set settings object to script's settings object.
return; auto& settings_object = script ? script->settings_object() : HTML::current_settings_object();
// 3. Let settings object be script's settings object.
auto& settings_object = script->settings_object();
switch (operation) { switch (operation) {
case JS::Promise::RejectionOperation::Reject: case JS::Promise::RejectionOperation::Reject: