mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 07:25:07 +00:00
LibWeb: Make more JS modules actually run
First, we had a logic typo where we were checking parse errors for non-empty instead of non-null. Fixing this caused more modules to actually start executing. As usual, this tripped on some "empty backup incumbent settings object stack" bugs, so this patch also pushes a module execution context in two places where it makes sense. Co-Authored-By: networkException <networkexception@serenityos.org>
This commit is contained in:
parent
a2c3db8367
commit
2d69a009fb
2 changed files with 29 additions and 6 deletions
|
@ -480,18 +480,22 @@ ErrorOr<void> initialize_main_thread_vm()
|
||||||
// 1. Let completion be null.
|
// 1. Let completion be null.
|
||||||
// NOTE: Our JS::Completion does not support non JS::Value types for its [[Value]], a such we
|
// NOTE: Our JS::Completion does not support non JS::Value types for its [[Value]], a such we
|
||||||
// use JS::ThrowCompletionOr here.
|
// use JS::ThrowCompletionOr here.
|
||||||
|
|
||||||
|
auto& vm = realm.vm();
|
||||||
|
JS::GCPtr<JS::Module> module = nullptr;
|
||||||
|
|
||||||
auto completion = [&]() -> JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Module>> {
|
auto completion = [&]() -> JS::ThrowCompletionOr<JS::NonnullGCPtr<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 Completion Record { [[Type]]: throw, [[Value]]: a new TypeError, [[Target]]: empty }.
|
||||||
if (!module_script) {
|
if (!module_script) {
|
||||||
return JS::throw_completion(JS::TypeError::create(realm, DeprecatedString::formatted("Loading imported module '{}' failed.", module_request.module_specifier)));
|
return JS::throw_completion(JS::TypeError::create(realm, DeprecatedString::formatted("Loading imported module '{}' failed.", module_request.module_specifier)));
|
||||||
}
|
}
|
||||||
// 3. Otherwise, if moduleScript's parse error is not null, then:
|
// 3. Otherwise, if moduleScript's parse error is not null, then:
|
||||||
else if (!module_script->parse_error().is_empty()) {
|
else if (!module_script->parse_error().is_null()) {
|
||||||
// 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 Completion Record { [[Type]]: throw, [[Value]]: parseError, [[Target]]: empty }.
|
||||||
return 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.
|
||||||
if (load_state) {
|
if (load_state) {
|
||||||
|
@ -500,18 +504,28 @@ ErrorOr<void> initialize_main_thread_vm()
|
||||||
load_state_as_fetch_context.parse_error = parse_error;
|
load_state_as_fetch_context.parse_error = parse_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return completion;
|
||||||
}
|
}
|
||||||
// 4. Otherwise, set completion to Completion Record { [[Type]]: normal, [[Value]]: result's record, [[Target]]: empty }.
|
// 4. Otherwise, set completion to Completion Record { [[Type]]: normal, [[Value]]: result's record, [[Target]]: empty }.
|
||||||
else {
|
else {
|
||||||
auto* record = static_cast<HTML::JavaScriptModuleScript&>(*module_script).record();
|
module = static_cast<HTML::JavaScriptModuleScript&>(*module_script).record();
|
||||||
|
return JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Module>>(*module);
|
||||||
return JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Module>>(*record);
|
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
// 5. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
// 5. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion).
|
||||||
HTML::TemporaryExecutionContext context { host_defined_environment_settings_object(realm) };
|
// NON-STANDARD: To ensure that LibJS can find the module on the stack, we push a new execution context.
|
||||||
|
|
||||||
|
auto module_execution_context = JS::ExecutionContext::create(realm.heap());
|
||||||
|
module_execution_context->realm = realm;
|
||||||
|
if (module)
|
||||||
|
module_execution_context->script_or_module = JS::NonnullGCPtr { *module };
|
||||||
|
vm.push_execution_context(*module_execution_context);
|
||||||
|
|
||||||
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
JS::finish_loading_imported_module(referrer, module_request, payload, completion);
|
||||||
|
|
||||||
|
vm.pop_execution_context();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 13. Fetch a single imported module script given url, fetchClient, destination, fetchOptions, settingsObject, fetchReferrer,
|
// 13. Fetch a single imported module script given url, fetchClient, destination, fetchOptions, settingsObject, fetchReferrer,
|
||||||
|
|
|
@ -147,6 +147,12 @@ JS::Promise* JavaScriptModuleScript::run(PreventErrorReporting)
|
||||||
auto record = m_record;
|
auto record = m_record;
|
||||||
VERIFY(record);
|
VERIFY(record);
|
||||||
|
|
||||||
|
// NON-STANDARD: To ensure that LibJS can find the module on the stack, we push a new execution context.
|
||||||
|
auto module_execution_context = JS::ExecutionContext::create(heap());
|
||||||
|
module_execution_context->realm = &settings.realm();
|
||||||
|
module_execution_context->script_or_module = JS::NonnullGCPtr<JS::Module> { *record };
|
||||||
|
vm().push_execution_context(*module_execution_context);
|
||||||
|
|
||||||
// 2. Set evaluationPromise to record.Evaluate().
|
// 2. Set evaluationPromise to record.Evaluate().
|
||||||
auto elevation_promise_or_error = record->evaluate(vm());
|
auto elevation_promise_or_error = record->evaluate(vm());
|
||||||
|
|
||||||
|
@ -161,6 +167,9 @@ JS::Promise* JavaScriptModuleScript::run(PreventErrorReporting)
|
||||||
} else {
|
} else {
|
||||||
evaluation_promise = elevation_promise_or_error.value();
|
evaluation_promise = elevation_promise_or_error.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NON-STANDARD: Pop the execution context mentioned above.
|
||||||
|
vm().pop_execution_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: 7. If preventErrorReporting is false, then upon rejection of evaluationPromise with reason, report the exception given by reason for script.
|
// FIXME: 7. If preventErrorReporting is false, then upon rejection of evaluationPromise with reason, report the exception given by reason for script.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue