LibWeb: Implement prepare_to_run_script on a Realm&

Making further progress porting away from depending on the
EnvironmentSettingObject.
This commit is contained in:
Shannon Booth 2024-10-21 20:09:02 +13:00 committed by Andrew Kaster
commit 8dffd8e7d6
Notes: github-actions[bot] 2024-11-01 19:16:18 +00:00
10 changed files with 40 additions and 36 deletions

View file

@ -235,26 +235,25 @@ ErrorOr<void> initialize_main_thread_vm(HTML::EventLoop::Type type)
// 2. Queue a global task on the JavaScript engine task source given global to perform the following steps: // 2. Queue a global task on the JavaScript engine task source given global to perform the following steps:
HTML::queue_global_task(HTML::Task::Source::JavaScriptEngine, global, JS::create_heap_function(s_main_thread_vm->heap(), [&finalization_registry] { HTML::queue_global_task(HTML::Task::Source::JavaScriptEngine, global, JS::create_heap_function(s_main_thread_vm->heap(), [&finalization_registry] {
// FIXME: 1. Let entry be finalizationRegistry.[[CleanupCallback]].[[Callback]].[[Realm]]'s environment settings object. // 1. Let entry be finalizationRegistry.[[CleanupCallback]].[[Callback]].[[Realm]].
auto& realm = *finalization_registry.cleanup_callback().callback().realm(); auto& entry = *finalization_registry.cleanup_callback().callback().realm();
auto& entry = host_defined_environment_settings_object(realm);
// 2. Check if we can run script with entry. If this returns "do not run", then return. // 2. Check if we can run script with entry. If this returns "do not run", then return.
if (HTML::can_run_script(realm) == HTML::RunScriptDecision::DoNotRun) if (HTML::can_run_script(entry) == HTML::RunScriptDecision::DoNotRun)
return; return;
// 3. Prepare to run script with entry. // 3. Prepare to run script with entry.
entry.prepare_to_run_script(); HTML::prepare_to_run_script(entry);
// 4. Let result be the result of performing CleanupFinalizationRegistry(finalizationRegistry). // 4. Let result be the result of performing CleanupFinalizationRegistry(finalizationRegistry).
auto result = finalization_registry.cleanup(); auto result = finalization_registry.cleanup();
// 5. Clean up after running script with entry. // 5. Clean up after running script with entry.
HTML::clean_up_after_running_script(realm); HTML::clean_up_after_running_script(entry);
// 6. If result is an abrupt completion, then report the exception given by result.[[Value]]. // 6. If result is an abrupt completion, then report the exception given by result.[[Value]].
if (result.is_error()) if (result.is_error())
HTML::report_exception(result, finalization_registry.realm()); HTML::report_exception(result, entry);
})); }));
}; };
@ -286,8 +285,8 @@ ErrorOr<void> initialize_main_thread_vm(HTML::EventLoop::Type type)
if (HTML::can_run_script(*realm) == HTML::RunScriptDecision::DoNotRun) if (HTML::can_run_script(*realm) == HTML::RunScriptDecision::DoNotRun)
return; return;
// FIXME: 2. If realm is not null, then prepare to run script with realm. // 2. If realm is not null, then prepare to run script with realm.
job_settings->prepare_to_run_script(); HTML::prepare_to_run_script(*realm);
// IMPLEMENTATION DEFINED: Additionally to preparing to run a script, we also prepare to run a callback here. This matches WebIDL's // IMPLEMENTATION DEFINED: Additionally to preparing to run a script, we also prepare to run a callback here. This matches WebIDL's
// invoke_callback() / call_user_object_operation() functions, and prevents a crash in host_make_job_callback() // invoke_callback() / call_user_object_operation() functions, and prevents a crash in host_make_job_callback()

View file

@ -1402,6 +1402,7 @@ void Navigation::initialize_the_navigation_api_entries_for_a_new_document(Vector
} }
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation // https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
// https://whatpr.org/html/9893/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
void Navigation::update_the_navigation_api_entries_for_a_same_document_navigation(JS::NonnullGCPtr<SessionHistoryEntry> destination_she, Bindings::NavigationType navigation_type) void Navigation::update_the_navigation_api_entries_for_a_same_document_navigation(JS::NonnullGCPtr<SessionHistoryEntry> destination_she, Bindings::NavigationType navigation_type)
{ {
auto& realm = relevant_realm(*this); auto& realm = relevant_realm(*this);
@ -1482,8 +1483,8 @@ void Navigation::update_the_navigation_api_entries_for_a_same_document_navigatio
if (m_ongoing_api_method_tracker != nullptr) if (m_ongoing_api_method_tracker != nullptr)
notify_about_the_committed_to_entry(*m_ongoing_api_method_tracker, *current_entry()); notify_about_the_committed_to_entry(*m_ongoing_api_method_tracker, *current_entry());
// 9. Prepare to run script given navigation's relevant settings object. // 9. Prepare to run script given navigation's relevant realm.
relevant_settings_object(*this).prepare_to_run_script(); prepare_to_run_script(realm);
// 10. Fire an event named currententrychange at navigation using NavigationCurrentEntryChangeEvent, // 10. Fire an event named currententrychange at navigation using NavigationCurrentEntryChangeEvent,
// with its navigationType attribute initialized to navigationType and its from initialized to oldCurrentNHE. // with its navigationType attribute initialized to navigationType and its from initialized to oldCurrentNHE.

View file

@ -88,8 +88,8 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors)
if (can_run_script(realm) == RunScriptDecision::DoNotRun) if (can_run_script(realm) == RunScriptDecision::DoNotRun)
return JS::normal_completion({}); return JS::normal_completion({});
// 3. Prepare to run script given settings. // 3. Prepare to run script given realm.
settings.prepare_to_run_script(); prepare_to_run_script(realm);
// 4. Let evaluationStatus be null. // 4. Let evaluationStatus be null.
JS::Completion evaluation_status; JS::Completion evaluation_status;

View file

@ -123,12 +123,15 @@ RunScriptDecision can_run_script(JS::Realm const& realm)
} }
// https://html.spec.whatwg.org/multipage/webappapis.html#prepare-to-run-script // https://html.spec.whatwg.org/multipage/webappapis.html#prepare-to-run-script
void EnvironmentSettingsObject::prepare_to_run_script() // https://whatpr.org/html/9893/b8ea975...df5706b/webappapis.html#prepare-to-run-script
void prepare_to_run_script(JS::Realm& realm)
{ {
// 1. Push settings's realm execution context onto the JavaScript execution context stack; it is now the running JavaScript execution context. // 1. Push realms's execution context onto the JavaScript execution context stack; it is now the running JavaScript execution context.
global_object().vm().push_execution_context(realm_execution_context()); realm.global_object().vm().push_execution_context(execution_context_of_realm(realm));
// FIXME: 2. Add settings to the currently running task's script evaluation environment settings object set. // FIXME: 2. If realm is a principal realm, then:
// FIXME: 2.1 Let settings be realm's settings object.
// FIXME: 2.2 Add settings to the currently running task's script evaluation environment settings object set.
} }
// https://whatpr.org/html/9893/b8ea975...df5706b/webappapis.html#concept-realm-execution-context // https://whatpr.org/html/9893/b8ea975...df5706b/webappapis.html#concept-realm-execution-context

View file

@ -96,8 +96,6 @@ public:
// https://fetch.spec.whatwg.org/#concept-fetch-group // https://fetch.spec.whatwg.org/#concept-fetch-group
Vector<JS::NonnullGCPtr<Fetch::Infrastructure::FetchRecord>>& fetch_group() { return m_fetch_group; } Vector<JS::NonnullGCPtr<Fetch::Infrastructure::FetchRecord>>& fetch_group() { return m_fetch_group; }
void prepare_to_run_script();
void prepare_to_run_callback(); void prepare_to_run_callback();
void clean_up_after_running_callback(); void clean_up_after_running_callback();
@ -137,10 +135,12 @@ private:
}; };
JS::ExecutionContext const& execution_context_of_realm(JS::Realm const&); JS::ExecutionContext const& execution_context_of_realm(JS::Realm const&);
inline JS::ExecutionContext& execution_context_of_realm(JS::Realm& realm) { return const_cast<JS::ExecutionContext&>(execution_context_of_realm(const_cast<JS::Realm const&>(realm))); }
RunScriptDecision can_run_script(JS::Realm const&); RunScriptDecision can_run_script(JS::Realm const&);
bool is_scripting_enabled(JS::Realm const&); bool is_scripting_enabled(JS::Realm const&);
bool is_scripting_disabled(JS::Realm const&); bool is_scripting_disabled(JS::Realm const&);
void prepare_to_run_script(JS::Realm&);
void clean_up_after_running_script(JS::Realm const&); void clean_up_after_running_script(JS::Realm const&);
EnvironmentSettingsObject& incumbent_settings_object(); EnvironmentSettingsObject& incumbent_settings_object();

View file

@ -133,8 +133,8 @@ JS::Promise* JavaScriptModuleScript::run(PreventErrorReporting)
return promise; return promise;
} }
// 3. Prepare to run script given settings. // 3. Prepare to run script given realm.
settings.prepare_to_run_script(); prepare_to_run_script(realm);
// 4. Let evaluationPromise be null. // 4. Let evaluationPromise be null.
JS::Promise* evaluation_promise = nullptr; JS::Promise* evaluation_promise = nullptr;

View file

@ -13,7 +13,7 @@ TemporaryExecutionContext::TemporaryExecutionContext(EnvironmentSettingsObject&
: m_environment_settings(environment_settings) : m_environment_settings(environment_settings)
, m_callbacks_enabled(callbacks_enabled) , m_callbacks_enabled(callbacks_enabled)
{ {
m_environment_settings->prepare_to_run_script(); prepare_to_run_script(m_environment_settings->realm());
if (m_callbacks_enabled == CallbacksEnabled::Yes) if (m_callbacks_enabled == CallbacksEnabled::Yes)
m_environment_settings->prepare_to_run_callback(); m_environment_settings->prepare_to_run_callback();
} }

View file

@ -1305,8 +1305,7 @@ WebIDL::ExceptionOr<JS::Value> structured_deserialize(JS::VM& vm, SerializationR
memory = DeserializationMemory { vm.heap() }; memory = DeserializationMemory { vm.heap() };
// IMPLEMENTATION DEFINED: We need to make sure there's an execution context for target_realm on the stack before constructing these JS objects // IMPLEMENTATION DEFINED: We need to make sure there's an execution context for target_realm on the stack before constructing these JS objects
auto& target_settings = Bindings::host_defined_environment_settings_object(target_realm); prepare_to_run_script(target_realm);
target_settings.prepare_to_run_script();
auto result = TRY(structured_deserialize_internal(vm, serialized.span(), target_realm, *memory)); auto result = TRY(structured_deserialize_internal(vm, serialized.span(), target_realm, *memory));

View file

@ -279,8 +279,8 @@ JS::ThrowCompletionOr<JS::Value> execute_a_function_body(HTML::Window const& win
// 5. If body begins with a directive prologue that contains a use strict directive then let strict be true, otherwise let strict be false. // 5. If body begins with a directive prologue that contains a use strict directive then let strict be true, otherwise let strict be false.
// NOTE: Handled in step 8 below. // NOTE: Handled in step 8 below.
// 6. Prepare to run a script with environment settings. // 6. Prepare to run a script with realm.
environment_settings.prepare_to_run_script(); HTML::prepare_to_run_script(realm);
// 7. Prepare to run a callback with environment settings. // 7. Prepare to run a callback with environment settings.
environment_settings.prepare_to_run_callback(); environment_settings.prepare_to_run_callback();

View file

@ -131,6 +131,8 @@ inline JS::Completion clean_up_on_return(HTML::EnvironmentSettingsObject& stored
return JS::Value { rejected_promise->promise() }; return JS::Value { rejected_promise->promise() };
} }
// https://webidl.spec.whatwg.org/#call-a-user-objects-operation
// https://whatpr.org/webidl/1437.html#call-a-user-objects-operation
JS::Completion call_user_object_operation(WebIDL::CallbackType& callback, String const& operation_name, Optional<JS::Value> this_argument, JS::MarkedVector<JS::Value> args) JS::Completion call_user_object_operation(WebIDL::CallbackType& callback, String const& operation_name, Optional<JS::Value> this_argument, JS::MarkedVector<JS::Value> args)
{ {
// 1. Let completion be an uninitialized variable. // 1. Let completion be an uninitialized variable.
@ -143,17 +145,17 @@ JS::Completion call_user_object_operation(WebIDL::CallbackType& callback, String
// 3. Let O be the ECMAScript object corresponding to value. // 3. Let O be the ECMAScript object corresponding to value.
auto& object = callback.callback; auto& object = callback.callback;
// 4. Let realm be Os associated Realm. // 4. Let relevant realm be Os associated Realm.
auto& realm = object->shape().realm(); auto& relevant_realm = object->shape().realm();
// 5. Let relevant settings be realms settings object. // 5. Let relevant settings be relvant realms settings object.
auto& relevant_settings = Bindings::host_defined_environment_settings_object(realm); auto& relevant_settings = Bindings::host_defined_environment_settings_object(relevant_realm);
// 6. Let stored settings be values callback context. // 6. Let stored settings be values callback context.
auto& stored_settings = callback.callback_context; auto& stored_settings = callback.callback_context;
// 7. Prepare to run script with relevant settings. // 7. Prepare to run script with relevant realm.
relevant_settings.prepare_to_run_script(); HTML::prepare_to_run_script(relevant_realm);
// 8. Prepare to run a callback with stored settings. // 8. Prepare to run a callback with stored settings.
stored_settings->prepare_to_run_callback(); stored_settings->prepare_to_run_callback();
@ -174,7 +176,7 @@ JS::Completion call_user_object_operation(WebIDL::CallbackType& callback, String
// 4. If ! IsCallable(X) is false, then set completion to a new Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}, and jump to the step labeled return. // 4. If ! IsCallable(X) is false, then set completion to a new Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}, and jump to the step labeled return.
if (!get_result.value().is_function()) { if (!get_result.value().is_function()) {
completion = realm.vm().template throw_completion<JS::TypeError>(JS::ErrorType::NotAFunction, get_result.value().to_string_without_side_effects()); completion = relevant_realm.vm().template throw_completion<JS::TypeError>(JS::ErrorType::NotAFunction, get_result.value().to_string_without_side_effects());
return clean_up_on_return(stored_settings, relevant_settings, completion, callback.operation_returns_promise); return clean_up_on_return(stored_settings, relevant_settings, completion, callback.operation_returns_promise);
} }
@ -240,7 +242,7 @@ JS::Completion invoke_callback(WebIDL::CallbackType& callback, Optional<JS::Valu
auto& stored_settings = callback.callback_context; auto& stored_settings = callback.callback_context;
// 8. Prepare to run script with relevant settings. // 8. Prepare to run script with relevant settings.
relevant_settings.prepare_to_run_script(); HTML::prepare_to_run_script(realm);
// 9. Prepare to run a callback with stored settings. // 9. Prepare to run a callback with stored settings.
stored_settings->prepare_to_run_callback(); stored_settings->prepare_to_run_callback();
@ -281,13 +283,13 @@ JS::Completion construct(WebIDL::CallbackType& callback, JS::MarkedVector<JS::Va
return realm.vm().template throw_completion<JS::TypeError>(JS::ErrorType::NotAConstructor, JS::Value(function_object).to_string_without_side_effects()); return realm.vm().template throw_completion<JS::TypeError>(JS::ErrorType::NotAConstructor, JS::Value(function_object).to_string_without_side_effects());
// 5. Let relevant settings be realms settings object. // 5. Let relevant settings be realms settings object.
auto& relevant_settings = Bindings::host_defined_environment_settings_object(realm); // NOTE: Not needed after ShadowRealm implementation.
// 6. Let stored settings be callables callback context. // 6. Let stored settings be callables callback context.
auto& stored_settings = callback.callback_context; auto& stored_settings = callback.callback_context;
// 7. Prepare to run script with relevant settings. // 7. Prepare to run script with relevant settings.
relevant_settings.prepare_to_run_script(); HTML::prepare_to_run_script(realm);
// 8. Prepare to run a callback with stored settings. // 8. Prepare to run a callback with stored settings.
stored_settings->prepare_to_run_callback(); stored_settings->prepare_to_run_callback();