2023-11-08 15:47:41 -03:00
/*
* Copyright ( c ) 2023 , Andrew Kaster < akaster @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2026-05-21 10:33:23 -03:00
# include <AK/RefPtr.h>
2023-12-20 17:47:01 -03:00
# include <LibIPC/File.h>
2023-11-08 15:47:41 -03:00
# include <LibJS/Runtime/ConsoleObject.h>
2026-05-20 15:58:46 -03:00
# include <LibWeb/Bindings/MessageEvent.h>
2025-05-18 17:10:01 -03:00
# include <LibWeb/Fetch/Enums.h>
2023-11-08 15:47:41 -03:00
# include <LibWeb/Fetch/Fetching/Fetching.h>
# include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
2024-07-09 18:54:22 -03:00
# include <LibWeb/HTML/DedicatedWorkerGlobalScope.h>
2025-05-18 17:10:01 -03:00
# include <LibWeb/HTML/MessageEvent.h>
2024-10-17 09:46:48 -03:00
# include <LibWeb/HTML/MessagePort.h>
2023-11-08 15:47:41 -03:00
# include <LibWeb/HTML/Scripting/ClassicScript.h>
2024-03-05 13:42:10 -03:00
# include <LibWeb/HTML/Scripting/EnvironmentSettingsSnapshot.h>
2026-05-21 10:33:23 -03:00
# include <LibWeb/HTML/Scripting/Environments.h>
2023-11-08 15:47:41 -03:00
# include <LibWeb/HTML/Scripting/Fetching.h>
2025-05-18 17:10:01 -03:00
# include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
2023-11-08 15:47:41 -03:00
# include <LibWeb/HTML/Scripting/WorkerEnvironmentSettingsObject.h>
2025-05-18 17:10:01 -03:00
# include <LibWeb/HTML/SharedWorkerGlobalScope.h>
2023-11-08 15:47:41 -03:00
# include <LibWeb/HTML/WorkerDebugConsoleClient.h>
# include <LibWeb/HTML/WorkerGlobalScope.h>
2024-07-04 12:06:54 -03:00
# include <LibWeb/HighResolutionTime/TimeOrigin.h>
2023-11-08 15:47:41 -03:00
# include <LibWeb/Loader/ResourceLoader.h>
2026-03-07 17:08:19 -03:00
# include <WebWorker/PageHost.h>
2025-05-18 17:10:01 -03:00
# include <WebWorker/WorkerHost.h>
2023-11-08 15:47:41 -03:00
namespace WebWorker {
2025-05-18 17:10:01 -03:00
WorkerHost : : WorkerHost ( URL : : URL url , Web : : Bindings : : WorkerType type , String name )
2023-12-20 17:47:01 -03:00
: m_url ( move ( url ) )
2024-09-10 23:57:48 -03:00
, m_type ( type )
2024-07-09 18:54:22 -03:00
, m_name ( move ( name ) )
2023-11-08 15:47:41 -03:00
{
}
2025-05-18 17:10:01 -03:00
WorkerHost : : ~ WorkerHost ( ) = default ;
2023-11-08 15:47:41 -03:00
2026-02-24 17:49:50 -03:00
// https://html.spec.whatwg.org/multipage/workers.html#relevant-owner-to-add
static Web : : HTML : : WorkerGlobalScope : : Owner relevant_owner_to_add ( Web : : HTML : : SerializedEnvironmentSettingsObject const & outside_settings )
{
// Given an environment settings object o when creating or obtaining a worker, the relevant owner to add depends on the type of global object specified by o.
return outside_settings . global . visit (
// If o's global object is a WorkerGlobalScope object (i.e., if we are creating a nested dedicated worker), then the relevant owner is that global object.
[ ] ( Web : : HTML : : SerializedWorkerGlobalScope const & worker ) - > Web : : HTML : : WorkerGlobalScope : : Owner { return worker ; } ,
// Otherwise, o's global object is a Window object, and the relevant owner is that Window's associated Document.
[ ] ( Web : : HTML : : SerializedWindow const & window ) - > Web : : HTML : : WorkerGlobalScope : : Owner { return window . associated_document ; } ) ;
}
2023-11-08 15:47:41 -03:00
// https://html.spec.whatwg.org/multipage/workers.html#run-a-worker
2026-02-21 15:11:48 -03:00
void WorkerHost : : run ( GC : : Ref < Web : : Page > page , Web : : HTML : : TransferDataEncoder message_port_data , Web : : HTML : : SerializedEnvironmentSettingsObject const & outside_settings_snapshot , Web : : Bindings : : RequestCredentials credentials , bool is_shared )
2023-11-08 15:47:41 -03:00
{
2026-05-21 10:33:23 -03:00
m_is_shared = is_shared ;
2026-02-24 17:49:50 -03:00
// 1. Let is shared be true if worker is a SharedWorker object, and false otherwise.
// 2. Let owner be the relevant owner to add given outside settings.
auto owner = relevant_owner_to_add ( outside_settings_snapshot ) ;
2024-07-04 12:06:54 -03:00
// 3. Let unsafeWorkerCreationTime be the unsafe shared current time.
auto unsafe_worker_creation_time = Web : : HighResolutionTime : : unsafe_shared_current_time ( ) ;
2025-11-27 08:37:53 -03:00
// 5. Let realm execution context be the result of creating a new realm given agent and the following customizations:
2023-11-08 15:47:41 -03:00
auto realm_execution_context = Web : : Bindings : : create_a_new_javascript_realm (
2023-11-22 13:53:14 -03:00
Web : : Bindings : : main_thread_vm ( ) ,
2025-05-18 17:10:01 -03:00
[ page , is_shared ] ( JS : : Realm & realm ) - > JS : : Object * {
2025-11-27 08:37:53 -03:00
// For the global object, if is shared is true, create a new SharedWorkerGlobalScope object.
2023-11-08 15:47:41 -03:00
if ( is_shared )
2026-02-24 17:49:50 -03:00
return realm . heap ( ) . allocate < Web : : HTML : : SharedWorkerGlobalScope > ( realm , page ) ;
2025-11-27 08:37:53 -03:00
// Otherwise, create a new DedicatedWorkerGlobalScope object.
2026-02-24 17:49:50 -03:00
return realm . heap ( ) . allocate < Web : : HTML : : DedicatedWorkerGlobalScope > ( realm , page ) ;
2023-11-08 15:47:41 -03:00
} ,
nullptr ) ;
2025-11-27 08:37:53 -03:00
// 6. Let worker global scope be the global object of realm execution context's Realm component.
2023-11-08 15:47:41 -03:00
// NOTE: This is the DedicatedWorkerGlobalScope or SharedWorkerGlobalScope object created in the previous step.
2025-01-21 11:12:05 -03:00
GC : : Ref < Web : : HTML : : WorkerGlobalScope > worker_global_scope = as < Web : : HTML : : WorkerGlobalScope > ( realm_execution_context - > realm - > global_object ( ) ) ;
2026-05-21 10:33:23 -03:00
m_worker_global_scope = worker_global_scope ;
2023-11-08 15:47:41 -03:00
2026-01-08 18:31:15 -03:00
// AD-HOC: The spec assumes when setting up the worker environment settings object that the URL is already set on
// the worker global scope. This is not the case. This URL is only known after performing the fetch, and in
// particular after redirects. See spec issue: https://github.com/whatwg/html/issues/11340. The main part
// which will need some rework to fix in a nice way is setting up a temporary environment for use in
// performing the initial fetch.
//
// As a workaround for now, set the URL here before setting up the environment settings object.
worker_global_scope - > set_url ( m_url ) ;
2026-02-24 17:49:50 -03:00
// 9. Append owner to worker global scope's owner set.
// AD-HOC: We need to do this slightly out of order compared to the spec. We initialize
// web interfaces as part of step 7, which checks SecureContext for interface
// exposure which itself requires owner set to be populated.
worker_global_scope - > owner_set ( ) . append ( owner ) ;
2025-11-27 08:37:53 -03:00
// 7. Set up a worker environment settings object with realm execution context, outside settings, and
// unsafeWorkerCreationTime, and let inside settings be the result.
2025-03-12 09:16:18 -03:00
auto inside_settings = Web : : HTML : : WorkerEnvironmentSettingsObject : : setup ( page , move ( realm_execution_context ) , outside_settings_snapshot , unsafe_worker_creation_time ) ;
2026-05-21 10:33:23 -03:00
m_inside_settings = inside_settings ;
2023-11-08 15:47:41 -03:00
2025-11-27 08:37:53 -03:00
// AD-HOC: Create a console object for the worker.
2025-03-12 09:16:18 -03:00
auto & console_object = * inside_settings - > realm ( ) . intrinsics ( ) . console_object ( ) ;
2024-11-13 14:13:46 -03:00
m_console = console_object . heap ( ) . allocate < Web : : HTML : : WorkerDebugConsoleClient > ( console_object . console ( ) ) ;
2023-11-08 15:47:41 -03:00
VERIFY ( m_console ) ;
console_object . console ( ) . set_client ( * m_console ) ;
2025-11-27 08:37:53 -03:00
// 8. Set worker global scope's name to options["name"].
2025-05-18 17:10:01 -03:00
worker_global_scope - > set_name ( m_name ) ;
2023-11-08 15:47:41 -03:00
2024-03-05 13:42:10 -03:00
// IMPLEMENTATION DEFINED: We need an object to represent the fetch response's client
2025-03-12 09:16:18 -03:00
auto outside_settings = inside_settings - > realm ( ) . create < Web : : HTML : : EnvironmentSettingsSnapshot > ( inside_settings - > realm ( ) , inside_settings - > realm_execution_context ( ) . copy ( ) , outside_settings_snapshot ) ;
2024-03-05 13:42:10 -03:00
2026-01-05 03:20:18 -03:00
// HACK: The environment settings object used for the worker script fetch should have a Window as its global scope,
// but the EnvironmentSettingsSnapshot used here has a WorkerGlobalScope (we don't have access to a Window).
// This causes the Referrer-Policy spec's "determine request's referrer" algorithm to read the ESO's creation
// URL, whereas it would normally read the document's URL. To hack around this, we overwrite the creation URL
// (which is only used in the initial worker script fetch).
2026-02-21 15:11:48 -03:00
if ( auto const * window = outside_settings_snapshot . global . get_pointer < Web : : HTML : : SerializedWindow > ( ) )
outside_settings - > creation_url = window - > associated_document . url ;
2026-01-05 03:20:18 -03:00
2025-11-27 08:37:53 -03:00
// 10. If is shared is true, then:
2023-11-08 15:47:41 -03:00
if ( is_shared ) {
2025-05-18 17:10:01 -03:00
auto & shared_global_scope = static_cast < Web : : HTML : : SharedWorkerGlobalScope & > ( * worker_global_scope ) ;
2023-11-08 15:47:41 -03:00
// 1. Set worker global scope's constructor origin to outside settings's origin.
2025-05-18 17:10:01 -03:00
shared_global_scope . set_constructor_origin ( outside_settings - > origin ( ) ) ;
2025-11-27 08:37:53 -03:00
// 2. Set worker global scope's constructor URL to url.
2025-05-18 17:10:01 -03:00
shared_global_scope . set_constructor_url ( m_url ) ;
2025-11-27 08:37:53 -03:00
// 3. Set worker global scope's type to options["type"].
2025-05-18 17:10:01 -03:00
shared_global_scope . set_type ( m_type ) ;
2025-11-27 08:37:53 -03:00
// 4. Set worker global scope's credentials to options["credentials"].
2025-05-18 17:10:01 -03:00
shared_global_scope . set_credentials ( Web : : Fetch : : from_bindings_enum ( credentials ) ) ;
2023-11-08 15:47:41 -03:00
}
2025-11-27 08:37:53 -03:00
// 11. Let destination be "sharedworker" if is shared is true, and "worker" otherwise.
2023-11-08 15:47:41 -03:00
auto destination = is_shared ? Web : : Fetch : : Infrastructure : : Request : : Destination : : SharedWorker
: Web : : Fetch : : Infrastructure : : Request : : Destination : : Worker ;
2025-06-24 07:18:14 -03:00
// In both cases, let performFetch be the following perform the fetch hook given request, isTopLevel, and processCustomFetchResponse:
2025-05-18 17:10:01 -03:00
auto perform_fetch_function = [ inside_settings , worker_global_scope , is_shared ] ( GC : : Ref < Web : : Fetch : : Infrastructure : : Request > request , Web : : HTML : : TopLevelModule is_top_level , Web : : Fetch : : Infrastructure : : FetchAlgorithms : : ProcessResponseConsumeBodyFunction process_custom_fetch_response ) - > Web : : WebIDL : : ExceptionOr < void > {
2025-03-12 09:16:18 -03:00
auto & realm = inside_settings - > realm ( ) ;
2023-11-08 15:47:41 -03:00
auto & vm = realm . vm ( ) ;
Web : : Fetch : : Infrastructure : : FetchAlgorithms : : Input fetch_algorithms_input { } ;
2025-11-27 08:37:53 -03:00
// 1. If isTopLevel is false, fetch request with processResponseConsumeBody set to processCustomFetchResponse,
// and abort these steps.
2024-03-05 13:48:10 -03:00
if ( is_top_level = = Web : : HTML : : TopLevelModule : : No ) {
2023-11-08 15:47:41 -03:00
fetch_algorithms_input . process_response_consume_body = move ( process_custom_fetch_response ) ;
2025-09-30 13:15:55 -03:00
Web : : Fetch : : Fetching : : fetch ( realm , request , Web : : Fetch : : Infrastructure : : FetchAlgorithms : : create ( vm , move ( fetch_algorithms_input ) ) ) ;
2023-11-08 15:47:41 -03:00
return { } ;
}
// 2. Set request's reserved client to inside settings.
2025-03-12 09:16:18 -03:00
request - > set_reserved_client ( GC : : Ptr < Web : : HTML : : EnvironmentSettingsObject > ( inside_settings ) ) ;
2023-11-08 15:47:41 -03:00
2025-11-27 08:37:53 -03:00
// NB: We need to store the process custom fetch response function on the heap here, because we're storing it
// in another heap function
2024-11-14 12:01:23 -03:00
auto process_custom_fetch_response_function = GC : : create_function ( vm . heap ( ) , move ( process_custom_fetch_response ) ) ;
2023-11-08 15:47:41 -03:00
2025-11-27 08:37:53 -03:00
// 3. Fetch request with processResponseConsumeBody set to the following steps given response response and
// null, failure, or a byte sequence bodyBytes:
2025-05-18 17:10:01 -03:00
fetch_algorithms_input . process_response_consume_body = [ worker_global_scope , process_custom_fetch_response_function , inside_settings , is_shared ] ( auto response , auto body_bytes ) {
2025-03-12 09:16:18 -03:00
auto & vm = inside_settings - > vm ( ) ;
2024-11-25 14:01:26 -03:00
2023-11-08 15:47:41 -03:00
// 1. Set worker global scope's url to response's url.
worker_global_scope - > set_url ( response - > url ( ) . value_or ( { } ) ) ;
2026-01-06 12:41:29 -03:00
// 2. Set inside settings's creation URL to response's url.
inside_settings - > creation_url = worker_global_scope - > url ( ) ;
// 3. Initialize worker global scope's policy container given worker global scope, response, and inside
2025-11-27 08:37:53 -03:00
// settings.
2025-03-12 09:16:18 -03:00
worker_global_scope - > initialize_policy_container ( response , inside_settings ) ;
2024-11-25 14:01:26 -03:00
2026-01-06 12:41:29 -03:00
// 4. If the Run CSP initialization for a global object algorithm returns "Blocked" when executed upon
2025-11-27 08:37:53 -03:00
// worker global scope, set response to a network error. [CSP]
2024-11-25 14:01:26 -03:00
if ( worker_global_scope - > run_csp_initialization ( ) = = Web : : ContentSecurityPolicy : : Directives : : Directive : : Result : : Blocked ) {
2025-04-02 04:51:45 -03:00
response = Web : : Fetch : : Infrastructure : : Response : : network_error ( vm , " Blocked by Content Security Policy " _string ) ;
2024-11-25 14:01:26 -03:00
}
2025-05-18 17:10:01 -03:00
// FIXME: Use worker global scope's policy container's embedder policy
2026-01-06 12:41:29 -03:00
// FIXME: 5. If worker global scope's embedder policy's value is compatible with cross-origin isolation and is shared is true,
2023-11-08 15:47:41 -03:00
// then set agent's agent cluster's cross-origin isolation mode to "logical" or "concrete".
// The one chosen is implementation-defined.
2026-01-06 12:41:29 -03:00
// FIXME: 6. If the result of checking a global object's embedder policy with worker global scope, outside settings,
2023-11-08 15:47:41 -03:00
// and response is false, then set response to a network error.
2026-01-06 12:41:29 -03:00
// FIXME: 7. Set worker global scope's cross-origin isolated capability to true if agent's agent cluster's cross-origin
2023-11-08 15:47:41 -03:00
// isolation mode is "concrete".
if ( ! is_shared ) {
2026-01-06 12:41:29 -03:00
// FIXME: 8. If is shared is false and owner's cross-origin isolated capability is false, then set worker
2023-11-08 15:47:41 -03:00
// global scope's cross-origin isolated capability to false.
2026-01-06 12:41:29 -03:00
// FIXME: 9. If is shared is false and response's url's scheme is "data", then set worker global scope's
2023-11-08 15:47:41 -03:00
// cross-origin isolated capability to false.
}
2026-01-06 12:41:29 -03:00
// 10. Run processCustomFetchResponse with response and bodyBytes.
2023-11-08 15:47:41 -03:00
process_custom_fetch_response_function - > function ( ) ( response , body_bytes ) ;
} ;
2025-09-30 13:15:55 -03:00
Web : : Fetch : : Fetching : : fetch ( realm , request , Web : : Fetch : : Infrastructure : : FetchAlgorithms : : create ( vm , move ( fetch_algorithms_input ) ) ) ;
2023-11-08 15:47:41 -03:00
return { } ;
} ;
2025-03-12 09:16:18 -03:00
auto perform_fetch = Web : : HTML : : create_perform_the_fetch_hook ( inside_settings - > heap ( ) , move ( perform_fetch_function ) ) ;
2023-11-08 15:47:41 -03:00
2025-11-27 08:37:53 -03:00
// In both cases, let onComplete given script be the following steps:
2026-05-21 10:33:23 -03:00
RefPtr < WorkerHost > protected_this { * this } ;
auto on_complete_function = [ protected_this , page , inside_settings , worker_global_scope , message_port_data = move ( message_port_data ) , outside_settings_snapshot , url = m_url , is_shared ] ( GC : : Ptr < Web : : HTML : : Script > script ) mutable {
2025-03-12 09:16:18 -03:00
auto & realm = inside_settings - > realm ( ) ;
2025-07-17 10:51:04 -03:00
2023-11-08 15:47:41 -03:00
// 1. If script is null or if script's error to rethrow is non-null, then:
if ( ! script | | ! script - > error_to_rethrow ( ) . is_null ( ) ) {
2026-03-07 17:08:19 -03:00
// 1. Queue a global task on the DOM manipulation task source given worker's relevant global object to fire an event named error at worker.
as < WebWorker : : PageHost > ( page - > client ( ) ) . did_fail_loading_worker_script ( ) ;
2025-03-12 09:07:25 -03:00
// 2. Run the environment discarding steps for inside settings.
inside_settings - > discard_environment ( ) ;
2023-11-08 15:47:41 -03:00
// 3. Abort these steps.
2026-06-21 14:03:06 -03:00
auto reason = script ? script - > error_to_rethrow ( ) . to_utf16_string_without_side_effects ( ) . to_utf8 ( ) : " script was null " _string ;
dbgln ( " DedicatedWorkerHost: Unable to fetch script {} because {} " , url , reason ) ;
2023-11-08 15:47:41 -03:00
return ;
}
// FIXME: 2. Associate worker with worker global scope.
// What does this even mean?
2026-05-21 10:33:23 -03:00
GC : : Ptr < Web : : HTML : : MessagePort > inside_port ;
2023-12-20 17:47:01 -03:00
2026-05-21 10:33:23 -03:00
// 3. Let inside port be a new MessagePort object in inside settings's realm.
2025-11-27 08:37:53 -03:00
// 4. If is shared is false, then:
2026-05-21 10:33:23 -03:00
// 5. Entangle outside port and inside port.
// AD-HOC: For shared workers we defer the inside port creation (step 3) and entanglement
// (step 5) to connect_shared_worker_impl. Each connecting page gets its own pair
// since the connect event fires once per owner, not once at worker startup.
2025-11-27 08:37:53 -03:00
if ( ! is_shared ) {
2026-05-21 10:33:23 -03:00
inside_port = Web : : HTML : : MessagePort : : create ( realm ) ;
2025-11-27 08:37:53 -03:00
// FIXME: 1. Set inside port's message event target to worker global scope.
// 2. Set worker global scope's inside port to inside port.
2026-05-21 10:33:23 -03:00
worker_global_scope - > set_internal_port ( * inside_port ) ;
2023-12-20 17:47:01 -03:00
2026-05-21 10:33:23 -03:00
Web : : HTML : : TransferDataDecoder decoder { move ( message_port_data ) } ;
MUST ( inside_port - > transfer_receiving_steps ( decoder ) ) ;
}
2023-11-08 15:47:41 -03:00
// 6. Create a new WorkerLocation object and associate it with worker global scope.
2024-11-13 13:50:17 -03:00
worker_global_scope - > set_location ( realm . create < Web : : HTML : : WorkerLocation > ( * worker_global_scope ) ) ;
2023-11-08 15:47:41 -03:00
// FIXME: 7. Closing orphan workers: Start monitoring the worker such that no sooner than it
// stops being a protected worker, and no later than it stops being a permissible worker,
// worker global scope's closing flag is set to true.
// FIXME: 8. Suspending workers: Start monitoring the worker, such that whenever worker global scope's
// closing flag is false and the worker is a suspendable worker, the user agent suspends
// execution of script in that worker until such time as either the closing flag switches to
// true or the worker stops being a suspendable worker
// 9. Set inside settings's execution ready flag.
2025-03-12 09:16:18 -03:00
inside_settings - > execution_ready = true ;
2023-11-08 15:47:41 -03:00
// 10. If script is a classic script, then run the classic script script.
// Otherwise, it is a module script; run the module script script.
2025-11-27 08:37:53 -03:00
if ( auto * classic_script = as_if < Web : : HTML : : ClassicScript > ( * script ) )
( void ) classic_script - > run ( ) ;
2023-11-08 15:47:41 -03:00
else
2025-10-26 14:06:19 -03:00
( void ) as < Web : : HTML : : ModuleScript > ( * script ) . run ( ) ;
2023-11-08 15:47:41 -03:00
2026-05-21 10:33:23 -03:00
as < WebWorker : : PageHost > ( page - > client ( ) ) . did_finish_loading_worker_script ( Web : : HTML : : is_secure_context ( * inside_settings ) ) ;
2026-04-26 20:52:23 -03:00
2023-11-08 15:47:41 -03:00
// FIXME: 11. Enable outside port's port message queue.
2023-12-20 17:47:01 -03:00
// 12. If is shared is false, enable the port message queue of the worker's implicit port.
if ( ! is_shared ) {
2025-06-07 18:57:17 -03:00
inside_port - > enable ( ) ;
2023-12-20 17:47:01 -03:00
}
2023-11-08 15:47:41 -03:00
2025-06-24 07:18:14 -03:00
// 13. If is shared is true, then queue a global task on the DOM manipulation task source given worker
2023-11-08 15:47:41 -03:00
// global scope to fire an event named connect at worker global scope, using MessageEvent,
// with the data attribute initialized to the empty string, the ports attribute initialized
// to a new frozen array containing inside port, and the source attribute initialized to inside port.
2025-05-18 17:10:01 -03:00
if ( is_shared ) {
2026-05-21 10:33:23 -03:00
protected_this - > m_accepting_shared_worker_connections = true ;
protected_this - > connect_shared_worker_impl ( move ( message_port_data ) , outside_settings_snapshot , ShouldAppendOwner : : No ) ;
protected_this - > flush_pending_shared_worker_connections ( ) ;
2025-05-18 17:10:01 -03:00
}
2023-11-08 15:47:41 -03:00
// FIXME: 14. Enable the client message queue of the ServiceWorkerContainer object whose associated service
// worker client is worker global scope's relevant settings object.
// 15. Event loop: Run the responsible event loop specified by inside settings until it is destroyed.
2025-03-12 09:16:18 -03:00
inside_settings - > responsible_event_loop ( ) . schedule ( ) ;
2023-11-08 15:47:41 -03:00
// FIXME: We need to react to the closing flag being set on the responsible event loop
// And use that to shutdown the WorkerHost
// FIXME: 16. Clear the worker global scope's map of active timers.
// FIXME: 17. Disentangle all the ports in the list of the worker's ports.
// FIXME: 18. Empty worker global scope's owner set.
} ;
2025-03-12 09:16:18 -03:00
auto on_complete = Web : : HTML : : create_on_fetch_script_complete ( inside_settings - > vm ( ) . heap ( ) , move ( on_complete_function ) ) ;
2023-11-08 15:47:41 -03:00
2025-11-27 08:37:53 -03:00
// 12. Obtain script by switching on the value of options's type member:
2024-09-10 23:57:48 -03:00
if ( m_type = = Web : : Bindings : : WorkerType : : Classic ) {
2025-11-27 08:37:53 -03:00
// -> "classic":
// Fetch a classic worker script given url, outside settings, destination, inside settings, and with
// onComplete and performFetch as defined below.
2025-03-12 09:16:18 -03:00
if ( auto err = Web : : HTML : : fetch_classic_worker_script ( m_url , outside_settings , destination , inside_settings , perform_fetch , on_complete ) ; err . is_error ( ) ) {
2024-03-05 13:48:10 -03:00
dbgln ( " Failed to run worker script " ) ;
// FIXME: Abort the worker properly
TODO ( ) ;
}
} else {
2025-11-27 08:37:53 -03:00
// -> "module":
// Fetch a module worker script graph given url, outside settings, destination, the value of the credentials
// member of options, inside settings, and with onComplete and performFetch as defined below.
2024-09-10 23:57:48 -03:00
VERIFY ( m_type = = Web : : Bindings : : WorkerType : : Module ) ;
2024-03-05 13:48:10 -03:00
// FIXME: Pass credentials
2025-03-12 09:16:18 -03:00
if ( auto err = Web : : HTML : : fetch_module_worker_script_graph ( m_url , outside_settings , destination , inside_settings , perform_fetch , on_complete ) ; err . is_error ( ) ) {
2024-03-05 13:48:10 -03:00
dbgln ( " Failed to run worker script " ) ;
// FIXME: Abort the worker properly
TODO ( ) ;
}
2023-11-08 15:47:41 -03:00
}
}
2026-05-21 10:33:23 -03:00
void WorkerHost : : connect_shared_worker ( Web : : HTML : : TransferDataEncoder message_port_data , Web : : HTML : : SerializedEnvironmentSettingsObject outside_settings )
{
if ( ! m_is_shared | | ! m_accepting_shared_worker_connections ) {
m_pending_shared_worker_connections . append ( PendingSharedWorkerConnection {
. message_port_data = move ( message_port_data ) ,
. outside_settings = move ( outside_settings ) ,
} ) ;
return ;
}
connect_shared_worker_impl ( move ( message_port_data ) , outside_settings , ShouldAppendOwner : : Yes ) ;
}
// https://html.spec.whatwg.org/multipage/workers.html#dom-sharedworker
void WorkerHost : : connect_shared_worker_impl ( Web : : HTML : : TransferDataEncoder message_port_data , Web : : HTML : : SerializedEnvironmentSettingsObject const & outside_settings , ShouldAppendOwner should_append_owner )
{
VERIFY ( m_worker_global_scope ) ;
VERIFY ( m_inside_settings ) ;
auto & realm = m_inside_settings - > realm ( ) ;
// 11.5.5. Let insidePort be a new MessagePort in insideSettings's realm.
auto inside_port = Web : : HTML : : MessagePort : : create ( realm ) ;
// 11.5.6. Entangle outsidePort and insidePort.
Web : : HTML : : TransferDataDecoder decoder { move ( message_port_data ) } ;
MUST ( inside_port - > transfer_receiving_steps ( decoder ) ) ;
// 11.5.7. Queue a global task on the DOM manipulation task source given workerGlobalScope to
// fire an event named connect at workerGlobalScope, using MessageEvent, with the data
// attribute initialized to the empty string, the ports attribute initialized to a new
// frozen array containing only insidePort, and the source attribute initialized to
// insidePort.
Web : : HTML : : queue_global_task ( Web : : HTML : : Task : : Source : : DOMManipulation , * m_worker_global_scope , GC : : create_function ( realm . heap ( ) , [ worker_global_scope = GC : : Root { * m_worker_global_scope } , inside_port ] {
auto & realm = worker_global_scope - > realm ( ) ;
auto & vm = realm . vm ( ) ;
Web : : HTML : : TemporaryExecutionContext const context ( realm ) ;
Web : : Bindings : : MessageEventInit event_init { } ;
event_init . data = GC : : Ref { vm . empty_string ( ) } ;
event_init . ports . append ( inside_port ) ;
event_init . source = Web : : HTML : : NullableMessageEventSource { inside_port } ;
auto message_event = Web : : HTML : : MessageEvent : : create ( realm , Web : : HTML : : EventNames : : connect , event_init ) ;
worker_global_scope - > dispatch_event ( message_event ) ;
} ) ) ;
// 11.5.8. Append the relevant owner to add given outsideSettings to workerGlobalScope's owner set.
if ( should_append_owner = = ShouldAppendOwner : : Yes ) {
auto owner = relevant_owner_to_add ( outside_settings ) ;
m_worker_global_scope - > owner_set ( ) . append ( owner ) ;
}
}
void WorkerHost : : flush_pending_shared_worker_connections ( )
{
auto pending_connections = move ( m_pending_shared_worker_connections ) ;
for ( auto & connection : pending_connections )
connect_shared_worker_impl ( move ( connection . message_port_data ) , connection . outside_settings , ShouldAppendOwner : : Yes ) ;
}
2023-11-08 15:47:41 -03:00
}