SharedWorker : script unblock shared worker common plumbing for SharedWorker (#44440)

part of https://github.com/servo/servo/issues/7458

Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
This commit is contained in:
Taym Haddadi
2026-04-23 07:54:21 +02:00
committed by GitHub
parent d0b2337118
commit 353e5248f1
5 changed files with 67 additions and 22 deletions

View File

@@ -129,6 +129,7 @@ use crate::dom::promise::Promise;
use crate::dom::readablestream::{CrossRealmTransformReadable, ReadableStream};
use crate::dom::serviceworker::ServiceWorker;
use crate::dom::serviceworkerregistration::ServiceWorkerRegistration;
use crate::dom::sharedworkerglobalscope::SharedWorkerGlobalScope;
use crate::dom::stream::underlyingsourcecontainer::UnderlyingSourceType;
use crate::dom::stream::writablestream::CrossRealmTransformWritable;
use crate::dom::types::{AbortSignal, DebuggerGlobalScope, MessageEvent};
@@ -2860,6 +2861,8 @@ impl GlobalScope {
Some(window.event_loop_sender())
} else if let Some(dedicated) = self.downcast::<DedicatedWorkerGlobalScope>() {
dedicated.event_loop_sender()
} else if let Some(shared_worker) = self.downcast::<SharedWorkerGlobalScope>() {
Some(shared_worker.event_loop_sender())
} else if let Some(service_worker) = self.downcast::<ServiceWorkerGlobalScope>() {
Some(service_worker.event_loop_sender())
} else {

View File

@@ -11,7 +11,7 @@ use devtools_traits::DevtoolScriptControlMsg;
use dom_struct::dom_struct;
use fonts::FontContext;
use js::context::JSContext;
use js::jsapi::{Heap, JSContext as RawJSContext, JSObject};
use js::jsapi::{Heap, JSObject};
use js::jsval::UndefinedValue;
use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue};
use net_traits::blob_url_store::UrlWithBlobClaim;
@@ -56,10 +56,10 @@ use crate::dom::webgpu::identityhub::IdentityHub;
use crate::dom::worker::{TrustedWorkerAddress, Worker};
use crate::dom::workerglobalscope::{ScriptFetchContext, WorkerGlobalScope};
use crate::messaging::{CommonScriptMsg, ScriptEventLoopReceiver, ScriptEventLoopSender};
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
use crate::realms::enter_realm;
use crate::script_module::{ModuleFetchClient, fetch_a_module_worker_script_graph};
use crate::script_runtime::ScriptThreadEventCategory::WorkerEvent;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext, Runtime, ThreadSafeJSContext};
use crate::script_runtime::{CanGc, Runtime, ThreadSafeJSContext};
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
use crate::task_source::TaskSourceName;
@@ -790,22 +790,6 @@ impl DedicatedWorkerGlobalScope {
}
}
#[expect(unsafe_code)]
pub(crate) unsafe extern "C" fn interrupt_callback(cx: *mut RawJSContext) -> bool {
let in_realm_proof = AlreadyInRealm::assert_for_cx(unsafe { SafeJSContext::from_ptr(cx) });
let global = unsafe { GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)) };
// If we are running the debugger script, just exit immediately.
let Some(worker) = global.downcast::<WorkerGlobalScope>() else {
assert!(global.is::<DebuggerGlobalScope>());
return false;
};
// A false response causes the script to terminate
assert!(worker.is::<DedicatedWorkerGlobalScope>());
!worker.is_closing()
}
/// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-worker-script>
fn fetch_a_classic_worker_script(
workerscope: &WorkerGlobalScope,

View File

@@ -2,17 +2,40 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crossbeam_channel::{Sender, unbounded};
use dom_struct::dom_struct;
use crate::dom::abstractworker::WorkerScriptMsg;
use crate::dom::bindings::codegen::Bindings::SharedWorkerGlobalScopeBinding::SharedWorkerGlobalScopeMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::CustomTraceable;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::messaging::{ScriptEventLoopReceiver, ScriptEventLoopSender};
pub(crate) enum SharedWorkerScriptMsg {
CommonWorker(WorkerScriptMsg),
}
// https://html.spec.whatwg.org/multipage/#the-sharedworkerglobalscope-interface
#[dom_struct]
pub(crate) struct SharedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope,
own_sender: Sender<SharedWorkerScriptMsg>,
}
impl SharedWorkerGlobalScope {
pub(crate) fn event_loop_sender(&self) -> ScriptEventLoopSender {
ScriptEventLoopSender::SharedWorker(self.own_sender.clone())
}
pub(crate) fn new_script_pair(&self) -> (ScriptEventLoopSender, ScriptEventLoopReceiver) {
let (sender, receiver) = unbounded();
(
ScriptEventLoopSender::SharedWorker(sender),
ScriptEventLoopReceiver::SharedWorker(receiver),
)
}
}
impl SharedWorkerGlobalScopeMethods<crate::DomTypeHolder> for SharedWorkerGlobalScope {

View File

@@ -15,6 +15,7 @@ use dom_struct::dom_struct;
use encoding_rs::UTF_8;
use fonts::FontContext;
use headers::{HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader};
use js::jsapi::JSContext as RawJSContext;
use js::realm::CurrentRealm;
use js::rust::{HandleValue, MutableHandleValue, ParentRuntime};
use mime::Mime;
@@ -58,7 +59,7 @@ use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::bindings::utils::define_all_exposed_interfaces;
use crate::dom::crypto::Crypto;
use crate::dom::csp::{GlobalCspReporting, Violation, parse_csp_list_from_metadata};
use crate::dom::dedicatedworkerglobalscope::{DedicatedWorkerGlobalScope, interrupt_callback};
use crate::dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use crate::dom::global_scope_script_execution::{ErrorReporting, RethrowErrors};
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlscriptelement::{SCRIPT_JS_MIMES, Script};
@@ -68,6 +69,7 @@ use crate::dom::performance::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::reporting::reportingendpoint::{ReportingEndpoint, SendReportsToEndpoints};
use crate::dom::reporting::reportingobserver::ReportingObserver;
use crate::dom::sharedworkerglobalscope::SharedWorkerGlobalScope;
use crate::dom::trustedtypes::trustedscripturl::TrustedScriptURL;
use crate::dom::trustedtypes::trustedtypepolicyfactory::TrustedTypePolicyFactory;
use crate::dom::types::ImageBitmap;
@@ -80,7 +82,7 @@ use crate::fetch::{CspViolationsProcessor, Fetch, RequestWithGlobalScope, load_w
use crate::messaging::{CommonScriptMsg, ScriptEventLoopReceiver, ScriptEventLoopSender};
use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask};
use crate::network_listener::{FetchResponseListener, ResourceTimingListener, submit_timing};
use crate::realms::enter_auto_realm;
use crate::realms::{AlreadyInRealm, InRealm, enter_auto_realm};
use crate::script_module::ScriptFetchOptions;
use crate::script_runtime::{CanGc, IntroductionType, JSContext, JSContextHelper, Runtime};
use crate::task::TaskCanceller;
@@ -1008,8 +1010,10 @@ impl WorkerGlobalScope {
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
if let Some(dedicated) = dedicated {
dedicated.new_script_pair()
} else if let Some(shared) = self.downcast::<SharedWorkerGlobalScope>() {
shared.new_script_pair()
} else {
panic!("need to implement a sender for SharedWorker/ServiceWorker")
panic!("need to implement a sender for ServiceWorker")
}
}
@@ -1052,6 +1056,20 @@ impl WorkerGlobalScope {
}
}
#[expect(unsafe_code)]
unsafe extern "C" fn interrupt_callback(cx: *mut RawJSContext) -> bool {
let in_realm_proof = AlreadyInRealm::assert_for_cx(unsafe { JSContext::from_ptr(cx) });
let global = unsafe { GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof)) };
// If we are running the debugger script, just exit immediately.
let Some(worker) = global.downcast::<WorkerGlobalScope>() else {
return false;
};
// A false response causes the script to terminate.
!worker.is_closing()
}
struct WorkerCspProcessor {
global_scope: DomRoot<GlobalScope>,
}

View File

@@ -32,6 +32,7 @@ use crate::dom::bindings::trace::CustomTraceable;
use crate::dom::csp::Violation;
use crate::dom::dedicatedworkerglobalscope::DedicatedWorkerScriptMsg;
use crate::dom::serviceworkerglobalscope::ServiceWorkerScriptMsg;
use crate::dom::sharedworkerglobalscope::SharedWorkerScriptMsg;
use crate::dom::worker::TrustedWorkerAddress;
use crate::script_runtime::ScriptThreadEventCategory;
use crate::task::TaskBox;
@@ -207,6 +208,8 @@ impl fmt::Debug for CommonScriptMsg {
pub(crate) enum ScriptEventLoopSender {
/// A sender that sends to the main `ScriptThread` event loop.
MainThread(Sender<MainThreadScriptMsg>),
/// A sender that sends to a `SharedWorker` event loop.
SharedWorker(Sender<SharedWorkerScriptMsg>),
/// A sender that sends to a `ServiceWorker` event loop.
ServiceWorker(Sender<ServiceWorkerScriptMsg>),
/// A sender that sends to a dedicated worker (such as a generic Web Worker) event loop.
@@ -225,6 +228,11 @@ impl ScriptEventLoopSender {
Self::MainThread(sender) => sender
.send(MainThreadScriptMsg::Common(message))
.map_err(|_| SendError(())),
Self::SharedWorker(sender) => sender
.send(SharedWorkerScriptMsg::CommonWorker(
WorkerScriptMsg::Common(message),
))
.map_err(|_| SendError(())),
Self::ServiceWorker(sender) => sender
.send(ServiceWorkerScriptMsg::CommonWorker(
WorkerScriptMsg::Common(message),
@@ -252,6 +260,8 @@ impl ScriptEventLoopSender {
pub(crate) enum ScriptEventLoopReceiver {
/// A receiver that receives messages to the main `ScriptThread` event loop.
MainThread(Receiver<MainThreadScriptMsg>),
/// A receiver that receives messages to shared worker event loops.
SharedWorker(Receiver<SharedWorkerScriptMsg>),
/// A receiver that receives messages to dedicated workers (such as a generic Web Worker) event loop.
DedicatedWorker(Receiver<DedicatedWorkerScriptMsg>),
}
@@ -264,6 +274,13 @@ impl ScriptEventLoopReceiver {
Ok(_) => panic!("unexpected main thread event message!"),
Err(_) => Err(()),
},
Self::SharedWorker(receiver) => match receiver.recv() {
Ok(SharedWorkerScriptMsg::CommonWorker(WorkerScriptMsg::Common(message))) => {
Ok(message)
},
Ok(_) => panic!("unexpected shared worker event message!"),
Err(_) => Err(()),
},
Self::DedicatedWorker(receiver) => match receiver.recv() {
Ok(DedicatedWorkerScriptMsg::CommonWorker(_, WorkerScriptMsg::Common(message))) => {
Ok(message)