mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
serviceworker: turn-off event-loop, don't assume current scope, clear runtime on shutdown
This commit is contained in:
parent
89eb7c2aa2
commit
bd31860c5d
3 changed files with 49 additions and 46 deletions
|
@ -268,15 +268,12 @@ impl ServiceWorkerGlobalScope {
|
||||||
} = scope_things;
|
} = scope_things;
|
||||||
|
|
||||||
let serialized_worker_url = script_url.to_string();
|
let serialized_worker_url = script_url.to_string();
|
||||||
let origin = GlobalScope::current()
|
let origin = scope_url.origin();
|
||||||
.expect("No current global object")
|
|
||||||
.origin()
|
|
||||||
.immutable()
|
|
||||||
.clone();
|
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name(format!("ServiceWorker for {}", serialized_worker_url))
|
.name(format!("ServiceWorker for {}", serialized_worker_url))
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
thread_state::initialize(ThreadState::SCRIPT | ThreadState::IN_WORKER);
|
thread_state::initialize(ThreadState::SCRIPT | ThreadState::IN_WORKER);
|
||||||
|
let runtime = new_rt_and_cx(None);
|
||||||
let roots = RootCollection::new();
|
let roots = RootCollection::new();
|
||||||
let _stack_roots = ThreadLocalStackRoots::new(&roots);
|
let _stack_roots = ThreadLocalStackRoots::new(&roots);
|
||||||
|
|
||||||
|
@ -298,34 +295,19 @@ impl ServiceWorkerGlobalScope {
|
||||||
.referrer_policy(referrer_policy)
|
.referrer_policy(referrer_policy)
|
||||||
.origin(origin);
|
.origin(origin);
|
||||||
|
|
||||||
let (url, source) = match load_whole_resource(
|
|
||||||
request,
|
|
||||||
&init.resource_threads.sender(),
|
|
||||||
&GlobalScope::current().expect("No current global object"),
|
|
||||||
) {
|
|
||||||
Err(_) => {
|
|
||||||
println!("error loading script {}", serialized_worker_url);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
Ok((metadata, bytes)) => {
|
|
||||||
(metadata.final_url, String::from_utf8(bytes).unwrap())
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let runtime = new_rt_and_cx(None);
|
|
||||||
|
|
||||||
let (devtools_mpsc_chan, devtools_mpsc_port) = unbounded();
|
|
||||||
ROUTER
|
|
||||||
.route_ipc_receiver_to_crossbeam_sender(devtools_receiver, devtools_mpsc_chan);
|
|
||||||
|
|
||||||
// Service workers are time limited
|
// Service workers are time limited
|
||||||
// https://w3c.github.io/ServiceWorker/#service-worker-lifetime
|
// https://w3c.github.io/ServiceWorker/#service-worker-lifetime
|
||||||
let sw_lifetime_timeout = pref!(dom.serviceworker.timeout_seconds) as u64;
|
let sw_lifetime_timeout = pref!(dom.serviceworker.timeout_seconds) as u64;
|
||||||
let time_out_port = after(Duration::new(sw_lifetime_timeout, 0));
|
let time_out_port = after(Duration::new(sw_lifetime_timeout, 0));
|
||||||
|
|
||||||
|
let (devtools_mpsc_chan, devtools_mpsc_port) = unbounded();
|
||||||
|
ROUTER
|
||||||
|
.route_ipc_receiver_to_crossbeam_sender(devtools_receiver, devtools_mpsc_chan);
|
||||||
|
|
||||||
|
let resource_threads_sender = init.resource_threads.sender();
|
||||||
let global = ServiceWorkerGlobalScope::new(
|
let global = ServiceWorkerGlobalScope::new(
|
||||||
init,
|
init,
|
||||||
url,
|
script_url,
|
||||||
devtools_mpsc_port,
|
devtools_mpsc_port,
|
||||||
runtime,
|
runtime,
|
||||||
own_sender,
|
own_sender,
|
||||||
|
@ -334,6 +316,19 @@ impl ServiceWorkerGlobalScope {
|
||||||
swmanager_sender,
|
swmanager_sender,
|
||||||
scope_url,
|
scope_url,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let (_url, source) =
|
||||||
|
match load_whole_resource(request, &resource_threads_sender, &*global.upcast())
|
||||||
|
{
|
||||||
|
Err(_) => {
|
||||||
|
println!("error loading script {}", serialized_worker_url);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
Ok((metadata, bytes)) => {
|
||||||
|
(metadata.final_url, String::from_utf8(bytes).unwrap())
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let scope = global.upcast::<WorkerGlobalScope>();
|
let scope = global.upcast::<WorkerGlobalScope>();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -356,7 +351,7 @@ impl ServiceWorkerGlobalScope {
|
||||||
// until the event loop is destroyed,
|
// until the event loop is destroyed,
|
||||||
// which happens after the closing flag is set to true,
|
// which happens after the closing flag is set to true,
|
||||||
// or until the worker has run beyond its allocated time.
|
// or until the worker has run beyond its allocated time.
|
||||||
while !scope.is_closing() || !global.has_timed_out() {
|
while !scope.is_closing() && !global.has_timed_out() {
|
||||||
run_worker_event_loop(&*global, None);
|
run_worker_event_loop(&*global, None);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -364,6 +359,7 @@ impl ServiceWorkerGlobalScope {
|
||||||
scope.script_chan(),
|
scope.script_chan(),
|
||||||
CommonScriptMsg::CollectReports,
|
CommonScriptMsg::CollectReports,
|
||||||
);
|
);
|
||||||
|
scope.clear_js_runtime();
|
||||||
})
|
})
|
||||||
.expect("Thread spawning failed");
|
.expect("Thread spawning failed");
|
||||||
}
|
}
|
||||||
|
@ -390,15 +386,10 @@ impl ServiceWorkerGlobalScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_timed_out(&self) -> bool {
|
fn has_timed_out(&self) -> bool {
|
||||||
// Note: this should be included in the `select` inside `run_worker_event_loop`,
|
// TODO: https://w3c.github.io/ServiceWorker/#service-worker-lifetime
|
||||||
// otherwise a block on the select can prevent the timeout.
|
// Since we don't have a shutdown mechanism yet, see #26548
|
||||||
if self.time_out_port.try_recv().is_ok() {
|
// immediately stop the event-loop after executing the initial script.
|
||||||
let _ = self
|
true
|
||||||
.swmanager_sender
|
|
||||||
.send(ServiceWorkerMsg::Timeout(self.scope_url.clone()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_script_event(&self, msg: ServiceWorkerScriptMsg) {
|
fn handle_script_event(&self, msg: ServiceWorkerScriptMsg) {
|
||||||
|
|
|
@ -100,7 +100,7 @@ pub struct WorkerGlobalScope {
|
||||||
#[ignore_malloc_size_of = "Arc"]
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
closing: Option<Arc<AtomicBool>>,
|
closing: Option<Arc<AtomicBool>>,
|
||||||
#[ignore_malloc_size_of = "Defined in js"]
|
#[ignore_malloc_size_of = "Defined in js"]
|
||||||
runtime: Runtime,
|
runtime: DomRefCell<Option<Runtime>>,
|
||||||
location: MutNullableDom<WorkerLocation>,
|
location: MutNullableDom<WorkerLocation>,
|
||||||
navigator: MutNullableDom<WorkerNavigator>,
|
navigator: MutNullableDom<WorkerNavigator>,
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ impl WorkerGlobalScope {
|
||||||
worker_type,
|
worker_type,
|
||||||
worker_url: DomRefCell::new(worker_url),
|
worker_url: DomRefCell::new(worker_url),
|
||||||
closing,
|
closing,
|
||||||
runtime,
|
runtime: DomRefCell::new(Some(runtime)),
|
||||||
location: Default::default(),
|
location: Default::default(),
|
||||||
navigator: Default::default(),
|
navigator: Default::default(),
|
||||||
from_devtools_sender: init.from_devtools_sender,
|
from_devtools_sender: init.from_devtools_sender,
|
||||||
|
@ -161,8 +161,17 @@ impl WorkerGlobalScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear_js_runtime(&self) {
|
||||||
|
let runtime = self.runtime.borrow_mut().take();
|
||||||
|
drop(runtime);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn runtime_handle(&self) -> ParentRuntime {
|
pub fn runtime_handle(&self) -> ParentRuntime {
|
||||||
self.runtime.prepare_for_new_child()
|
self.runtime
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.prepare_for_new_child()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_devtools_sender(&self) -> Option<IpcSender<DevtoolScriptControlMsg>> {
|
pub fn from_devtools_sender(&self) -> Option<IpcSender<DevtoolScriptControlMsg>> {
|
||||||
|
@ -175,7 +184,7 @@ impl WorkerGlobalScope {
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn get_cx(&self) -> JSContext {
|
pub fn get_cx(&self) -> JSContext {
|
||||||
unsafe { JSContext::from_ptr(self.runtime.cx()) }
|
unsafe { JSContext::from_ptr(self.runtime.borrow().as_ref().unwrap().cx()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_closing(&self) -> bool {
|
pub fn is_closing(&self) -> bool {
|
||||||
|
@ -235,7 +244,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
rooted!(in(self.runtime.cx()) let mut rval = UndefinedValue());
|
rooted!(in(self.runtime.borrow().as_ref().unwrap().cx()) let mut rval = UndefinedValue());
|
||||||
for url in urls {
|
for url in urls {
|
||||||
let global_scope = self.upcast::<GlobalScope>();
|
let global_scope = self.upcast::<GlobalScope>();
|
||||||
let request = NetRequestInit::new(url.clone())
|
let request = NetRequestInit::new(url.clone())
|
||||||
|
@ -256,7 +265,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
||||||
Ok((metadata, bytes)) => (metadata.final_url, String::from_utf8(bytes).unwrap()),
|
Ok((metadata, bytes)) => (metadata.final_url, String::from_utf8(bytes).unwrap()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = self.runtime.evaluate_script(
|
let result = self.runtime.borrow().as_ref().unwrap().evaluate_script(
|
||||||
self.reflector().get_jsobject(),
|
self.reflector().get_jsobject(),
|
||||||
&source,
|
&source,
|
||||||
url.as_str(),
|
url.as_str(),
|
||||||
|
@ -401,8 +410,9 @@ impl WorkerGlobalScope {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn execute_script(&self, source: DOMString) {
|
pub fn execute_script(&self, source: DOMString) {
|
||||||
let _aes = AutoEntryScript::new(self.upcast());
|
let _aes = AutoEntryScript::new(self.upcast());
|
||||||
rooted!(in(self.runtime.cx()) let mut rval = UndefinedValue());
|
let cx = self.runtime.borrow().as_ref().unwrap().cx();
|
||||||
match self.runtime.evaluate_script(
|
rooted!(in(cx) let mut rval = UndefinedValue());
|
||||||
|
match self.runtime.borrow().as_ref().unwrap().evaluate_script(
|
||||||
self.reflector().get_jsobject(),
|
self.reflector().get_jsobject(),
|
||||||
&source,
|
&source,
|
||||||
self.worker_url.borrow().as_str(),
|
self.worker_url.borrow().as_str(),
|
||||||
|
@ -419,7 +429,7 @@ impl WorkerGlobalScope {
|
||||||
println!("evaluate_script failed");
|
println!("evaluate_script failed");
|
||||||
unsafe {
|
unsafe {
|
||||||
let ar = enter_realm(&*self);
|
let ar = enter_realm(&*self);
|
||||||
report_pending_exception(self.runtime.cx(), true, InRealm::Entered(&ar));
|
report_pending_exception(cx, true, InRealm::Entered(&ar));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -212,7 +212,9 @@ impl ServiceWorkerManager {
|
||||||
|
|
||||||
fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg) -> bool {
|
fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg) -> bool {
|
||||||
match msg {
|
match msg {
|
||||||
ServiceWorkerMsg::Timeout(scope) => {},
|
ServiceWorkerMsg::Timeout(_scope) => {
|
||||||
|
// TODO: https://w3c.github.io/ServiceWorker/#terminate-service-worker
|
||||||
|
},
|
||||||
ServiceWorkerMsg::ForwardDOMMessage(msg, scope_url) => {
|
ServiceWorkerMsg::ForwardDOMMessage(msg, scope_url) => {
|
||||||
if let Some(registration) = self.registrations.get_mut(&scope_url) {
|
if let Some(registration) = self.registrations.get_mut(&scope_url) {
|
||||||
if let Some(ref worker) = registration.active_worker {
|
if let Some(ref worker) = registration.active_worker {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue