diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 30e210e1836..218776f4e72 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -428,6 +428,12 @@ static ErrorOr parse_exposure_set(IDL::Interface& interface) return ExposedTo::Window; if (exposed == "Worker"sv) return ExposedTo::AllWorkers; + if (exposed == "DedicatedWorker"sv) + return ExposedTo::DedicatedWorker; + if (exposed == "SharedWorker"sv) + return ExposedTo::SharedWorker; + if (exposed == "ServiceWorker"sv) + return ExposedTo::ServiceWorker; if (exposed == "AudioWorklet"sv) return ExposedTo::AudioWorklet; diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 48e6d67e22e..4082513b62f 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -270,6 +270,7 @@ set(SOURCES HTML/DataTransfer.cpp HTML/Dates.cpp HTML/DecodedImageData.cpp + HTML/DedicatedWorkerGlobalScope.cpp HTML/DocumentState.cpp HTML/DOMParser.cpp HTML/DOMStringMap.cpp diff --git a/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.cpp new file mode 100644 index 00000000000..eca46407c5c --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Web::HTML { + +JS_DEFINE_ALLOCATOR(DedicatedWorkerGlobalScope); + +DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(JS::Realm& realm, JS::NonnullGCPtr page) + : WorkerGlobalScope(realm, page) +{ + m_legacy_platform_object_flags = LegacyPlatformObjectFlags { .has_global_interface_extended_attribute = true }; +} + +DedicatedWorkerGlobalScope::~DedicatedWorkerGlobalScope() = default; + +void DedicatedWorkerGlobalScope::initialize_web_interfaces_impl() +{ + auto& realm = this->realm(); + add_dedicated_worker_exposed_interfaces(*this); + + WEB_SET_PROTOTYPE_FOR_INTERFACE(DedicatedWorkerGlobalScope); + + DedicatedWorkerGlobalScopeGlobalMixin::initialize(realm, *this); + + Base::initialize_web_interfaces_impl(); +} + +// https://html.spec.whatwg.org/multipage/workers.html#dom-dedicatedworkerglobalscope-close +void DedicatedWorkerGlobalScope::close() +{ + // The close() method steps are to close a worker given this. + close_a_worker(); +} + +void DedicatedWorkerGlobalScope::finalize() +{ + Base::finalize(); + WindowOrWorkerGlobalScopeMixin::finalize(); +} + +WebIDL::ExceptionOr DedicatedWorkerGlobalScope::post_message(JS::Value message, StructuredSerializeOptions const& options) +{ + // The postMessage(message, transfer) and postMessage(message, options) methods on DedicatedWorkerGlobalScope objects act as if, + // when invoked, it immediately invoked the respective postMessage(message, transfer) and postMessage(message, options) + // on the port, with the same arguments, and returned the same return value. + return m_internal_port->post_message(message, options); +} + +#undef __ENUMERATE +#define __ENUMERATE(attribute_name, event_name) \ + void DedicatedWorkerGlobalScope::set_##attribute_name(WebIDL::CallbackType* value) \ + { \ + set_event_handler_attribute(event_name, move(value)); \ + } \ + WebIDL::CallbackType* DedicatedWorkerGlobalScope::attribute_name() \ + { \ + return event_handler_attribute(event_name); \ + } +ENUMERATE_DEDICATED_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE) +#undef __ENUMERATE + +} diff --git a/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.h new file mode 100644 index 00000000000..15f19116d0a --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +#define ENUMERATE_DEDICATED_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(E) \ + E(onmessage, HTML::EventNames::message) \ + E(onmessageerror, HTML::EventNames::messageerror) + +namespace Web::HTML { + +class DedicatedWorkerGlobalScope + : public WorkerGlobalScope + , public Bindings::DedicatedWorkerGlobalScopeGlobalMixin { + WEB_PLATFORM_OBJECT(DedicatedWorkerGlobalScope, WorkerGlobalScope); + JS_DECLARE_ALLOCATOR(DedicatedWorkerGlobalScope); + +public: + virtual ~DedicatedWorkerGlobalScope() override; + + WebIDL::ExceptionOr post_message(JS::Value message, StructuredSerializeOptions const&); + + void set_name(String name) { m_name = move(name); } + String name() const { return m_name; } + + void close(); + +#undef __ENUMERATE +#define __ENUMERATE(attribute_name, event_name) \ + void set_##attribute_name(WebIDL::CallbackType*); \ + WebIDL::CallbackType* attribute_name(); + ENUMERATE_DEDICATED_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE) +#undef __ENUMERATE + + virtual void finalize() override; + +private: + DedicatedWorkerGlobalScope(JS::Realm&, JS::NonnullGCPtr); + + virtual void initialize_web_interfaces_impl() override; + + String m_name; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.idl b/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.idl new file mode 100644 index 00000000000..d3084eb0728 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/DedicatedWorkerGlobalScope.idl @@ -0,0 +1,15 @@ +#import + +// https://html.spec.whatwg.org/multipage/workers.html#dedicatedworkerglobalscope +[Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker] +interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + [Replaceable] readonly attribute DOMString name; + + // FIXME: IDL overload issue here + // FIXME: undefined postMessage(any message, sequence transfer); + undefined postMessage(any message, optional StructuredSerializeOptions options = {}); + undefined close(); + + attribute EventHandler onmessage; + attribute EventHandler onmessageerror; +}; diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp index ec3ce8230fb..de2a8fbe1cd 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp @@ -5,7 +5,6 @@ */ #include -#include #include #include #include @@ -31,16 +30,11 @@ WorkerGlobalScope::WorkerGlobalScope(JS::Realm& realm, JS::NonnullGCPtr) +void WorkerGlobalScope::initialize_web_interfaces_impl() { auto& realm = this->realm(); Base::initialize(realm); - // FIXME: Handle shared worker - add_dedicated_worker_exposed_interfaces(*this); - - WEB_SET_PROTOTYPE_FOR_INTERFACE(WorkerGlobalScope); - WindowOrWorkerGlobalScopeMixin::initialize(realm); m_navigator = WorkerNavigator::create(*this); @@ -71,7 +65,7 @@ void WorkerGlobalScope::set_internal_port(JS::NonnullGCPtr port) } // https://html.spec.whatwg.org/multipage/workers.html#close-a-worker -void WorkerGlobalScope::close() +void WorkerGlobalScope::close_a_worker() { // 1. Discard any tasks that have been added to workerGlobal's relevant agent's event loop's task queues. relevant_settings_object(*this).responsible_event_loop().task_queue().remove_tasks_matching([](HTML::Task const&) { @@ -147,11 +141,6 @@ JS::NonnullGCPtr WorkerGlobalScope::navigator() const return *m_navigator; } -WebIDL::ExceptionOr WorkerGlobalScope::post_message(JS::Value message, StructuredSerializeOptions const& options) -{ - return m_internal_port->post_message(message, options); -} - #undef __ENUMERATE #define __ENUMERATE(attribute_name, event_name) \ void WorkerGlobalScope::set_##attribute_name(WebIDL::CallbackType* value) \ diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h index 93333b2212e..34cbad1356f 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h @@ -18,16 +18,13 @@ #include #include -// FIXME: message/messageerror belong on subclasses only -#define ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(E) \ - E(onerror, HTML::EventNames::error) \ - E(onlanguagechange, HTML::EventNames::languagechange) \ - E(ononline, HTML::EventNames::online) \ - E(onoffline, HTML::EventNames::offline) \ - E(onrejectionhandled, HTML::EventNames::rejectionhandled) \ - E(onunhandledrejection, HTML::EventNames::unhandledrejection) \ - E(onmessage, HTML::EventNames::message) \ - E(onmessageerror, HTML::EventNames::messageerror) +#define ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(E) \ + E(onerror, HTML::EventNames::error) \ + E(onlanguagechange, HTML::EventNames::languagechange) \ + E(ononline, HTML::EventNames::online) \ + E(onoffline, HTML::EventNames::offline) \ + E(onrejectionhandled, HTML::EventNames::rejectionhandled) \ + E(onunhandledrejection, HTML::EventNames::unhandledrejection) namespace Web::HTML { @@ -76,8 +73,6 @@ public: ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE) #undef __ENUMERATE - WebIDL::ExceptionOr post_message(JS::Value message, StructuredSerializeOptions const&); - JS::NonnullGCPtr fonts(); // Non-IDL public methods @@ -91,7 +86,7 @@ public: void set_internal_port(JS::NonnullGCPtr port); - void initialize_web_interfaces(Badge); + void initialize_web_interfaces(Badge) { initialize_web_interfaces_impl(); } Web::Page* page() { return m_page.ptr(); } @@ -99,20 +94,24 @@ public: bool is_closing() const { return m_closing; } - void close(); - protected: explicit WorkerGlobalScope(JS::Realm&, JS::NonnullGCPtr); + virtual void initialize_web_interfaces_impl(); + + void close_a_worker(); + + virtual void finalize() override; + + JS::GCPtr m_internal_port; + private: virtual void visit_edges(Cell::Visitor&) override; - virtual void finalize() override; JS::GCPtr m_location; JS::GCPtr m_navigator; JS::NonnullGCPtr m_page; - JS::GCPtr m_internal_port; // FIXME: Add all these internal slots diff --git a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl index b29e0e3e057..b652098e7b1 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl +++ b/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.idl @@ -20,12 +20,6 @@ interface WorkerGlobalScope : EventTarget { attribute EventHandler ononline; attribute EventHandler onrejectionhandled; attribute EventHandler onunhandledrejection; - - // FIXME: IDL overload issue here - // FIXME: undefined postMessage(any message, sequence transfer); - undefined postMessage(any message, optional StructuredSerializeOptions options = {}); - attribute EventHandler onmessage; - attribute EventHandler onmessageerror; }; WorkerGlobalScope includes WindowOrWorkerGlobalScope; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 58746b7c66a..1a0c12f9178 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -101,6 +101,7 @@ libweb_js_bindings(HTML/CloseEvent) libweb_js_bindings(HTML/CloseWatcher) libweb_js_bindings(HTML/CustomElements/CustomElementRegistry) libweb_js_bindings(HTML/DataTransfer) +libweb_js_bindings(HTML/DedicatedWorkerGlobalScope GLOBAL) libweb_js_bindings(HTML/DOMParser) libweb_js_bindings(HTML/DOMStringMap) libweb_js_bindings(HTML/DragEvent) diff --git a/Userland/Services/WebWorker/ConnectionFromClient.cpp b/Userland/Services/WebWorker/ConnectionFromClient.cpp index dae20477dfb..7cf23268651 100644 --- a/Userland/Services/WebWorker/ConnectionFromClient.cpp +++ b/Userland/Services/WebWorker/ConnectionFromClient.cpp @@ -63,9 +63,9 @@ Web::Page const& ConnectionFromClient::page() const return m_page_host->page(); } -void ConnectionFromClient::start_dedicated_worker(URL::URL const& url, String const& type, String const&, String const&, Web::HTML::TransferDataHolder const& implicit_port, Web::HTML::SerializedEnvironmentSettingsObject const& outside_settings) +void ConnectionFromClient::start_dedicated_worker(URL::URL const& url, String const& type, String const&, String const& name, Web::HTML::TransferDataHolder const& implicit_port, Web::HTML::SerializedEnvironmentSettingsObject const& outside_settings) { - m_worker_host = make_ref_counted(url, type); + m_worker_host = make_ref_counted(url, type, name); // FIXME: Yikes, const_cast to move? Feels like a LibIPC bug. // We should be able to move non-copyable types from a Message type. m_worker_host->run(page(), move(const_cast(implicit_port)), outside_settings); diff --git a/Userland/Services/WebWorker/ConnectionFromClient.h b/Userland/Services/WebWorker/ConnectionFromClient.h index b6b7722196a..b6d86c3edfe 100644 --- a/Userland/Services/WebWorker/ConnectionFromClient.h +++ b/Userland/Services/WebWorker/ConnectionFromClient.h @@ -41,7 +41,7 @@ private: Web::Page& page(); Web::Page const& page() const; - virtual void start_dedicated_worker(URL::URL const& url, String const&, String const&, String const&, Web::HTML::TransferDataHolder const&, Web::HTML::SerializedEnvironmentSettingsObject const&) override; + virtual void start_dedicated_worker(URL::URL const& url, String const& type, String const&, String const& name, Web::HTML::TransferDataHolder const&, Web::HTML::SerializedEnvironmentSettingsObject const&) override; virtual void handle_file_return(i32 error, Optional const& file, i32 request_id) override; JS::Handle m_page_host; diff --git a/Userland/Services/WebWorker/DedicatedWorkerHost.cpp b/Userland/Services/WebWorker/DedicatedWorkerHost.cpp index 3c150c62bc6..13fcaf22329 100644 --- a/Userland/Services/WebWorker/DedicatedWorkerHost.cpp +++ b/Userland/Services/WebWorker/DedicatedWorkerHost.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -20,9 +21,10 @@ namespace WebWorker { -DedicatedWorkerHost::DedicatedWorkerHost(URL::URL url, String type) +DedicatedWorkerHost::DedicatedWorkerHost(URL::URL url, String type, String name) : m_url(move(url)) , m_type(move(type)) + , m_name(move(name)) { } @@ -46,7 +48,7 @@ void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::Trans // FIXME: Proper support for both SharedWorkerGlobalScope and DedicatedWorkerGlobalScope if (is_shared) TODO(); - return Web::Bindings::main_thread_vm().heap().allocate_without_realm(realm, page); + return Web::Bindings::main_thread_vm().heap().allocate_without_realm(realm, page); }, nullptr); @@ -64,7 +66,10 @@ void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::Trans console_object.console().set_client(*m_console); // 10. Set worker global scope's name to the value of options's name member. - // FIXME: name property requires the SharedWorkerGlobalScope or DedicatedWorkerGlobalScope child class to be used + if (is_shared) + TODO(); + else + static_cast(*worker_global_scope).set_name(m_name); // 11. Append owner to worker global scope's owner set. // FIXME: support for 'owner' set on WorkerGlobalScope diff --git a/Userland/Services/WebWorker/DedicatedWorkerHost.h b/Userland/Services/WebWorker/DedicatedWorkerHost.h index 4bfeb95a916..9fe1f05ce93 100644 --- a/Userland/Services/WebWorker/DedicatedWorkerHost.h +++ b/Userland/Services/WebWorker/DedicatedWorkerHost.h @@ -17,7 +17,7 @@ namespace WebWorker { class DedicatedWorkerHost : public RefCounted { public: - explicit DedicatedWorkerHost(URL::URL url, String type); + explicit DedicatedWorkerHost(URL::URL url, String type, String name); ~DedicatedWorkerHost(); void run(JS::NonnullGCPtr, Web::HTML::TransferDataHolder message_port_data, Web::HTML::SerializedEnvironmentSettingsObject const&); @@ -27,6 +27,7 @@ private: URL::URL m_url; String m_type; + String m_name; }; }