ladybird/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp
Andrew Kaster 124c378472 LibWeb+WebWorker: Move worker execution into a new WebWorker process
We now create a WorkerAgent for the parent context, which is currently
only a Window. Note that Workers can have Workers per the spec.

The WorkerAgent spawns a WebWorker process to hold the actual
script execution of the Worker. This is modeled with the
DedicatedWorkerHost object in the WebWorker process.
A start_dedicated_worker IPC method in the WebWorker IPC creates the
WorkerHost object. Future different worker types may use different IPC
messages to create their WorkerHost instance.

This implementation cannot yet postMessage between the parent and the
child processes.

Co-Authored-By: Andreas Kling <kling@serenityos.org>
2023-11-15 12:56:33 +01:00

108 lines
4.5 KiB
C++

/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Vector.h>
#include <LibWeb/Bindings/DedicatedWorkerExposedInterfaces.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/WorkerGlobalScopePrototype.h>
#include <LibWeb/Forward.h>
#include <LibWeb/HTML/EventHandler.h>
#include <LibWeb/HTML/EventNames.h>
#include <LibWeb/HTML/WorkerGlobalScope.h>
#include <LibWeb/HTML/WorkerLocation.h>
#include <LibWeb/HTML/WorkerNavigator.h>
namespace Web::HTML {
WorkerGlobalScope::WorkerGlobalScope(JS::Realm& realm, Web::Page& page)
: DOM::EventTarget(realm)
, m_page(page)
{
}
WorkerGlobalScope::~WorkerGlobalScope() = default;
void WorkerGlobalScope::initialize_web_interfaces(Badge<WorkerEnvironmentSettingsObject>)
{
auto& realm = this->realm();
Base::initialize(realm);
// FIXME: Handle shared worker
add_dedicated_worker_exposed_interfaces(*this);
Object::set_prototype(&Bindings::ensure_web_prototype<Bindings::WorkerGlobalScopePrototype>(realm, "WorkerGlobalScope"));
WindowOrWorkerGlobalScopeMixin::initialize(realm);
m_navigator = WorkerNavigator::create(*this);
}
void WorkerGlobalScope::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
WindowOrWorkerGlobalScopeMixin::visit_edges(visitor);
visitor.visit(m_location.ptr());
visitor.visit(m_navigator.ptr());
}
// https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-libraries
WebIDL::ExceptionOr<void> WorkerGlobalScope::import_scripts(Vector<String> urls)
{
// The algorithm may optionally be customized by supplying custom perform the fetch hooks,
// which if provided will be used when invoking fetch a classic worker-imported script.
// NOTE: Service Workers is an example of a specification that runs this algorithm with its own options for the perform the fetch hook.
// FIXME: 1. If worker global scope's type is "module", throw a TypeError exception.
// FIXME: 2. Let settings object be the current settings object.
// 3. If urls is empty, return.
if (urls.is_empty())
return {};
// FIXME: 4. Parse each value in urls relative to settings object. If any fail, throw a "SyntaxError" DOMException.
// FIXME: 5. For each url in the resulting URL records, run these substeps:
// 1. Fetch a classic worker-imported script given url and settings object, passing along any custom perform the fetch steps provided.
// If this succeeds, let script be the result. Otherwise, rethrow the exception.
// 2. Run the classic script script, with the rethrow errors argument set to true.
// NOTE: script will run until it either returns, fails to parse, fails to catch an exception,
// or gets prematurely aborted by the terminate a worker algorithm defined above.
// If an exception was thrown or if the script was prematurely aborted, then abort all these steps,
// letting the exception or aborting continue to be processed by the calling script.
return {};
}
// https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-location
JS::NonnullGCPtr<WorkerLocation> WorkerGlobalScope::location() const
{
// The location attribute must return the WorkerLocation object whose associated WorkerGlobalScope object is the WorkerGlobalScope object.
return *m_location;
}
// https://html.spec.whatwg.org/multipage/workers.html#dom-worker-navigator
JS::NonnullGCPtr<WorkerNavigator> WorkerGlobalScope::navigator() const
{
// The navigator attribute of the WorkerGlobalScope interface must return an instance of the WorkerNavigator interface,
// which represents the identity and state of the user agent (the client).
return *m_navigator;
}
#undef __ENUMERATE
#define __ENUMERATE(attribute_name, event_name) \
void WorkerGlobalScope::set_##attribute_name(WebIDL::CallbackType* value) \
{ \
set_event_handler_attribute(event_name, move(value)); \
} \
WebIDL::CallbackType* WorkerGlobalScope::attribute_name() \
{ \
return event_handler_attribute(event_name); \
}
ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE)
#undef __ENUMERATE
}