/* * Copyright (c) 2022, Ben Abraham * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #define ENUMERATE_WORKER_EVENT_HANDLERS(E) \ E(onmessage, HTML::EventNames::message) \ E(onmessageerror, HTML::EventNames::messageerror) namespace Web::HTML { struct WorkerOptions { String type { "classic" }; String credentials { "same-origin" }; String name { "" }; }; // https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface class Worker : public DOM::EventTarget { WEB_PLATFORM_OBJECT(Worker, DOM::EventTarget); public: static DOM::ExceptionOr> create(FlyString const& script_url, WorkerOptions const options, DOM::Document& document); static DOM::ExceptionOr> create_with_global_object(HTML::Window& window, FlyString const& script_url, WorkerOptions const options) { return Worker::create(script_url, options, window.impl().associated_document()); } DOM::ExceptionOr terminate(); void post_message(JS::Value message, JS::Value transfer); virtual ~Worker() = default; MessagePort* implicit_message_port() { return m_implicit_port.ptr(); } JS::GCPtr outside_message_port() { return m_outside_port; } #undef __ENUMERATE #define __ENUMERATE(attribute_name, event_name) \ void set_##attribute_name(Bindings::CallbackType*); \ Bindings::CallbackType* attribute_name(); ENUMERATE_WORKER_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE protected: Worker(FlyString const&, const WorkerOptions, DOM::Document&); private: static HTML::EventLoop& get_vm_event_loop(JS::VM& target_vm) { return static_cast(target_vm.custom_data())->event_loop; } virtual void visit_edges(Cell::Visitor&) override; FlyString m_script_url; WorkerOptions m_options; JS::GCPtr m_document; Bindings::WebEngineCustomData m_custom_data; NonnullRefPtr m_worker_vm; NonnullOwnPtr m_interpreter; WeakPtr m_inner_settings; JS::VM::InterpreterExecutionScope m_interpreter_scope; RefPtr m_console; JS::NonnullGCPtr m_implicit_port; JS::GCPtr m_outside_port; // NOTE: These are inside the worker VM. JS::GCPtr m_worker_realm; JS::GCPtr m_worker_scope; // FIXME: This is a mega-hack but necessary because HTML::Window holds all the prototypes and constructors. // There should be *no* Window object in a Worker context. JS::GCPtr m_worker_window; void run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_settings, MessagePort& outside_port, WorkerOptions const options); }; } WRAPPER_HACK(Worker, Web::HTML)