mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-31 05:09:12 +00:00
LibWeb: Use ThrowCompletion AO to create throw completions
Corresponds to 4989b3457f
This commit is contained in:
parent
b05fe0127b
commit
da8a29376f
Notes:
github-actions[bot]
2025-07-08 16:10:44 +00:00
Author: https://github.com/AtkinsSJ
Commit: da8a29376f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5353
Reviewed-by: https://github.com/tcl3 ✅
2 changed files with 41 additions and 36 deletions
|
@ -104,9 +104,9 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
// This avoids doing an exhaustive garbage collection on process exit.
|
// This avoids doing an exhaustive garbage collection on process exit.
|
||||||
s_main_thread_vm->ref();
|
s_main_thread_vm->ref();
|
||||||
|
|
||||||
// 8.1.5.1 HostEnsureCanAddPrivateElement(O), https://html.spec.whatwg.org/multipage/webappapis.html#the-hostensurecanaddprivateelement-implementation
|
// 8.1.6.1 HostEnsureCanAddPrivateElement(O), https://html.spec.whatwg.org/multipage/webappapis.html#the-hostensurecanaddprivateelement-implementation
|
||||||
s_main_thread_vm->host_ensure_can_add_private_element = [](JS::Object const& object) -> JS::ThrowCompletionOr<void> {
|
s_main_thread_vm->host_ensure_can_add_private_element = [](JS::Object const& object) -> JS::ThrowCompletionOr<void> {
|
||||||
// 1. If O is a WindowProxy object, or implements Location, then return Completion { [[Type]]: throw, [[Value]]: a new TypeError }.
|
// 1. If O is a WindowProxy object, or implements Location, then return ThrowCompletion(a new TypeError).
|
||||||
if (is<HTML::WindowProxy>(object) || is<HTML::Location>(object))
|
if (is<HTML::WindowProxy>(object) || is<HTML::Location>(object))
|
||||||
return s_main_thread_vm->throw_completion<JS::TypeError>("Cannot add private elements to window or location object"sv);
|
return s_main_thread_vm->throw_completion<JS::TypeError>("Cannot add private elements to window or location object"sv);
|
||||||
|
|
||||||
|
@ -418,13 +418,11 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
|
|
||||||
// 2. If moduleMapRealm's global object implements WorkletGlobalScope or ServiceWorkerGlobalScope and loadState is undefined, then:
|
// 2. If moduleMapRealm's global object implements WorkletGlobalScope or ServiceWorkerGlobalScope and loadState is undefined, then:
|
||||||
if ((is<HTML::WorkletGlobalScope>(module_map_realm->global_object()) || is<ServiceWorker::ServiceWorkerGlobalScope>(module_map_realm->global_object())) && !load_state) {
|
if ((is<HTML::WorkletGlobalScope>(module_map_realm->global_object()) || is<ServiceWorker::ServiceWorkerGlobalScope>(module_map_realm->global_object())) && !load_state) {
|
||||||
// 1. Let completion be Completion Record { [[Type]]: throw, [[Value]]: a new TypeError, [[Target]]: empty }.
|
// 1. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, ThrowCompletion(a new TypeError)).
|
||||||
auto completion = JS::throw_completion(JS::TypeError::create(*module_map_realm, "Dynamic Import not available for Worklets or ServiceWorkers"_string));
|
auto completion = JS::throw_completion(JS::TypeError::create(*module_map_realm, "Dynamic Import not available for Worklets or ServiceWorkers"_string));
|
||||||
|
|
||||||
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
|
||||||
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
||||||
|
|
||||||
// 3. Return.
|
// 2. Return.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,13 +460,15 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
if (attribute.key == "type"sv)
|
if (attribute.key == "type"sv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// 1. Let completion be Completion Record { [[Type]]: throw, [[Value]]: a new SyntaxError exception, [[Target]]: empty }.
|
// 1. Let error be a new SyntaxError exception.
|
||||||
auto completion = JS::throw_completion(JS::SyntaxError::create(*module_map_realm, "Module request attributes must only contain a type attribute"_string));
|
auto error = JS::SyntaxError::create(*module_map_realm, "Module request attributes must only contain a type attribute"_string);
|
||||||
|
|
||||||
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
// FIXME: 2. If loadState is not undefined and loadState.[[ErrorToRethrow]] is null, set loadState.[[ErrorToRethrow]] to error.
|
||||||
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
|
||||||
|
|
||||||
// 3. Return.
|
// 3. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, ThrowCompletion(error)).
|
||||||
|
JS::finish_loading_imported_module(referrer, module_request, payload, JS::throw_completion(error));
|
||||||
|
|
||||||
|
// 4. Return.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,10 +479,10 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
|
|
||||||
// 3. If the previous step threw an exception, then:
|
// 3. If the previous step threw an exception, then:
|
||||||
if (maybe_exception.is_exception()) {
|
if (maybe_exception.is_exception()) {
|
||||||
// 1. Let completion be Completion Record { [[Type]]: throw, [[Value]]: resolutionError, [[Target]]: empty }.
|
// FIXME: 1. If loadState is not undefined and loadState.[[ErrorToRethrow]] is null, set loadState.[[ErrorToRethrow]] to resolutionError.
|
||||||
auto completion = exception_to_throw_completion(main_thread_vm(), maybe_exception.exception());
|
|
||||||
|
|
||||||
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, ThrowCompletion(resolutionError)).
|
||||||
|
auto completion = exception_to_throw_completion(main_thread_vm(), maybe_exception.exception());
|
||||||
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
||||||
|
|
||||||
// 3. Return.
|
// 3. Return.
|
||||||
|
@ -494,13 +494,15 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
|
|
||||||
// 5. If the result of running the module type allowed steps given moduleType and moduleMapRealm is false, then:
|
// 5. If the result of running the module type allowed steps given moduleType and moduleMapRealm is false, then:
|
||||||
if (!HTML::module_type_allowed(*module_map_realm, module_type)) {
|
if (!HTML::module_type_allowed(*module_map_realm, module_type)) {
|
||||||
// 1. Let completion be Completion Record { [[Type]]: throw, [[Value]]: a new TypeError exception, [[Target]]: empty }.
|
// 1. Let error be a new TypeError exception.
|
||||||
auto completion = JS::throw_completion(JS::SyntaxError::create(*module_map_realm, MUST(String::formatted("Module type '{}' is not supported", module_type))));
|
auto error = JS::TypeError::create(*module_map_realm, MUST(String::formatted("Module type '{}' is not supported", module_type)));
|
||||||
|
|
||||||
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
// FIXME: 2. If loadState is not undefined and loadState.[[ErrorToRethrow]] is null, set loadState.[[ErrorToRethrow]] to error.
|
||||||
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
|
||||||
|
|
||||||
// 3. Return
|
// 3. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, ThrowCompletion(error)).
|
||||||
|
JS::finish_loading_imported_module(referrer, module_request, payload, JS::throw_completion(error));
|
||||||
|
|
||||||
|
// 4. Return
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,10 +521,10 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
|
|
||||||
// 9. If the previous step threw an exception, then:
|
// 9. If the previous step threw an exception, then:
|
||||||
if (url.is_exception()) {
|
if (url.is_exception()) {
|
||||||
// 1. Let completion be Completion Record { [[Type]]: throw, [[Value]]: resolutionError, [[Target]]: empty }.
|
// FIXME: 1. If loadState is not undefined and loadState.[[ErrorToRethrow]] is null, set loadState.[[ErrorToRethrow]] to resolutionError.
|
||||||
auto completion = exception_to_throw_completion(main_thread_vm(), url.exception());
|
|
||||||
|
|
||||||
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
// 2. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, ThrowCompletion(resolutionError)).
|
||||||
|
auto completion = exception_to_throw_completion(main_thread_vm(), url.exception());
|
||||||
HTML::TemporaryExecutionContext context { *module_map_realm };
|
HTML::TemporaryExecutionContext context { *module_map_realm };
|
||||||
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
||||||
|
|
||||||
|
@ -568,7 +570,7 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
GC::Ptr<JS::Module> module = nullptr;
|
GC::Ptr<JS::Module> module = nullptr;
|
||||||
|
|
||||||
auto completion = [&]() -> JS::ThrowCompletionOr<GC::Ref<JS::Module>> {
|
auto completion = [&]() -> JS::ThrowCompletionOr<GC::Ref<JS::Module>> {
|
||||||
// 2. If moduleScript is null, then set completion to Completion Record { [[Type]]: throw, [[Value]]: a new TypeError, [[Target]]: empty }.
|
// 2. If moduleScript is null, then set completion to ThrowCompletion(a new TypeError).
|
||||||
if (!module_script) {
|
if (!module_script) {
|
||||||
return JS::throw_completion(JS::TypeError::create(realm, ByteString::formatted("Loading imported module '{}' failed.", module_request.module_specifier)));
|
return JS::throw_completion(JS::TypeError::create(realm, ByteString::formatted("Loading imported module '{}' failed.", module_request.module_specifier)));
|
||||||
}
|
}
|
||||||
|
@ -577,7 +579,7 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
// 1. Let parseError be moduleScript's parse error.
|
// 1. Let parseError be moduleScript's parse error.
|
||||||
auto parse_error = module_script->parse_error();
|
auto parse_error = module_script->parse_error();
|
||||||
|
|
||||||
// 2. Set completion to Completion Record { [[Type]]: throw, [[Value]]: parseError, [[Target]]: empty }.
|
// 2. Set completion to ThrowCompletion(parseError).
|
||||||
auto completion = JS::throw_completion(parse_error);
|
auto completion = JS::throw_completion(parse_error);
|
||||||
|
|
||||||
// 3. If loadState is not undefined and loadState.[[ParseError]] is null, set loadState.[[ParseError]] to parseError.
|
// 3. If loadState is not undefined and loadState.[[ParseError]] is null, set loadState.[[ParseError]] to parseError.
|
||||||
|
@ -590,7 +592,7 @@ void initialize_main_thread_vm(AgentType type)
|
||||||
|
|
||||||
return completion;
|
return completion;
|
||||||
}
|
}
|
||||||
// 4. Otherwise, set completion to Completion Record { [[Type]]: normal, [[Value]]: moduleScript's record, [[Target]]: empty }.
|
// 4. Otherwise, set completion to NormalCompletion(moduleScript's record).
|
||||||
else {
|
else {
|
||||||
module = static_cast<HTML::JavaScriptModuleScript&>(*module_script).record();
|
module = static_cast<HTML::JavaScriptModuleScript&>(*module_script).record();
|
||||||
return JS::ThrowCompletionOr<GC::Ref<JS::Module>>(*module);
|
return JS::ThrowCompletionOr<GC::Ref<JS::Module>>(*module);
|
||||||
|
|
|
@ -84,19 +84,22 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, GC::Ptr<JS::Envi
|
||||||
if (can_run_script(realm) == RunScriptDecision::DoNotRun)
|
if (can_run_script(realm) == RunScriptDecision::DoNotRun)
|
||||||
return JS::normal_completion(JS::js_undefined());
|
return JS::normal_completion(JS::js_undefined());
|
||||||
|
|
||||||
// 3. Prepare to run script given realm.
|
// FIXME: 3. Record classic script execution start time given script.
|
||||||
|
|
||||||
|
// 4. Prepare to run script given realm.
|
||||||
prepare_to_run_script(realm);
|
prepare_to_run_script(realm);
|
||||||
|
|
||||||
// 4. Let evaluationStatus be null.
|
// 5. Let evaluationStatus be null.
|
||||||
JS::Completion evaluation_status;
|
JS::Completion evaluation_status;
|
||||||
|
|
||||||
// 5. If script's error to rethrow is not null, then set evaluationStatus to Completion { [[Type]]: throw, [[Value]]: script's error to rethrow, [[Target]]: empty }.
|
// 6. If script's error to rethrow is not null, then set evaluationStatus to ThrowCompletion(script's error to rethrow).
|
||||||
if (!error_to_rethrow().is_null()) {
|
if (!error_to_rethrow().is_null()) {
|
||||||
evaluation_status = JS::Completion { JS::Completion::Type::Throw, error_to_rethrow() };
|
evaluation_status = JS::throw_completion(error_to_rethrow());
|
||||||
} else {
|
}
|
||||||
|
// 7. Otherwise, set evaluationStatus to ScriptEvaluation(script's record).
|
||||||
|
else {
|
||||||
auto timer = Core::ElapsedTimer::start_new();
|
auto timer = Core::ElapsedTimer::start_new();
|
||||||
|
|
||||||
// 6. Otherwise, set evaluationStatus to ScriptEvaluation(script's record).
|
|
||||||
evaluation_status = vm().bytecode_interpreter().run(*m_script_record, lexical_environment_override);
|
evaluation_status = vm().bytecode_interpreter().run(*m_script_record, lexical_environment_override);
|
||||||
|
|
||||||
// FIXME: If ScriptEvaluation does not complete because the user agent has aborted the running script, leave evaluationStatus as null.
|
// FIXME: If ScriptEvaluation does not complete because the user agent has aborted the running script, leave evaluationStatus as null.
|
||||||
|
@ -104,7 +107,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, GC::Ptr<JS::Envi
|
||||||
dbgln_if(HTML_SCRIPT_DEBUG, "ClassicScript: Finished running script {}, Duration: {}ms", filename(), timer.elapsed_milliseconds());
|
dbgln_if(HTML_SCRIPT_DEBUG, "ClassicScript: Finished running script {}, Duration: {}ms", filename(), timer.elapsed_milliseconds());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. If evaluationStatus is an abrupt completion, then:
|
// 8. If evaluationStatus is an abrupt completion, then:
|
||||||
if (evaluation_status.is_abrupt()) {
|
if (evaluation_status.is_abrupt()) {
|
||||||
// 1. If rethrow errors is true and script's muted errors is false, then:
|
// 1. If rethrow errors is true and script's muted errors is false, then:
|
||||||
if (rethrow_errors == RethrowErrors::Yes && m_muted_errors == MutedErrors::No) {
|
if (rethrow_errors == RethrowErrors::Yes && m_muted_errors == MutedErrors::No) {
|
||||||
|
@ -138,15 +141,15 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, GC::Ptr<JS::Envi
|
||||||
return evaluation_status;
|
return evaluation_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Clean up after running script with realm.
|
// 9. Clean up after running script with realm.
|
||||||
clean_up_after_running_script(realm);
|
clean_up_after_running_script(realm);
|
||||||
|
|
||||||
// 9. If evaluationStatus is a normal completion, then return evaluationStatus.
|
// 10. If evaluationStatus is a normal completion, then return evaluationStatus.
|
||||||
VERIFY(!evaluation_status.is_abrupt());
|
VERIFY(!evaluation_status.is_abrupt());
|
||||||
return evaluation_status;
|
return evaluation_status;
|
||||||
|
|
||||||
// FIXME: 10. If we've reached this point, evaluationStatus was left as null because the script was aborted prematurely during evaluation.
|
// FIXME: 11. If we've reached this point, evaluationStatus was left as null because the script was aborted prematurely during evaluation.
|
||||||
// Return Completion { [[Type]]: throw, [[Value]]: a new "QuotaExceededError" DOMException, [[Target]]: empty }.
|
// Return ThrowCompletion(a new "QuotaExceededError" DOMException).
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassicScript::ClassicScript(URL::URL base_url, ByteString filename, JS::Realm& realm)
|
ClassicScript::ClassicScript(URL::URL base_url, ByteString filename, JS::Realm& realm)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue