Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ServiceWorker: restructure Job Queue, Register flow, to better match spec #26317

Merged
merged 2 commits into from May 21, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

serviceworker: turn-off event-loop, don't assume current scope, clear…

… runtime on shutdown
  • Loading branch information
gterzian committed May 21, 2020
commit bd31860c5dd3a3adcb5ada96c43be88ba73935af
@@ -268,15 +268,12 @@ impl ServiceWorkerGlobalScope {
} = scope_things;

let serialized_worker_url = script_url.to_string();
let origin = GlobalScope::current()
.expect("No current global object")
.origin()
.immutable()
.clone();
let origin = scope_url.origin();
thread::Builder::new()
.name(format!("ServiceWorker for {}", serialized_worker_url))
.spawn(move || {
thread_state::initialize(ThreadState::SCRIPT | ThreadState::IN_WORKER);
let runtime = new_rt_and_cx(None);
let roots = RootCollection::new();
let _stack_roots = ThreadLocalStackRoots::new(&roots);

@@ -298,34 +295,19 @@ impl ServiceWorkerGlobalScope {
.referrer_policy(referrer_policy)
.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
// https://w3c.github.io/ServiceWorker/#service-worker-lifetime
let sw_lifetime_timeout = pref!(dom.serviceworker.timeout_seconds) as u64;
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(
init,
url,
script_url,
devtools_mpsc_port,
runtime,
own_sender,
@@ -334,6 +316,19 @@ impl ServiceWorkerGlobalScope {
swmanager_sender,
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>();

unsafe {
@@ -356,14 +351,15 @@ impl ServiceWorkerGlobalScope {
// until the event loop is destroyed,
// which happens after the closing flag is set to true,
// 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);
}
},
reporter_name,
scope.script_chan(),
CommonScriptMsg::CollectReports,
);
scope.clear_js_runtime();
})
.expect("Thread spawning failed");
}
@@ -390,15 +386,10 @@ impl ServiceWorkerGlobalScope {
}

fn has_timed_out(&self) -> bool {
// Note: this should be included in the `select` inside `run_worker_event_loop`,
// otherwise a block on the select can prevent the timeout.
if self.time_out_port.try_recv().is_ok() {
let _ = self
.swmanager_sender
.send(ServiceWorkerMsg::Timeout(self.scope_url.clone()));
return true;
}
false
// TODO: https://w3c.github.io/ServiceWorker/#service-worker-lifetime
// Since we don't have a shutdown mechanism yet, see #26548
// immediately stop the event-loop after executing the initial script.
true
}

fn handle_script_event(&self, msg: ServiceWorkerScriptMsg) {
@@ -100,7 +100,7 @@ pub struct WorkerGlobalScope {
#[ignore_malloc_size_of = "Arc"]
closing: Option<Arc<AtomicBool>>,
#[ignore_malloc_size_of = "Defined in js"]
runtime: Runtime,
runtime: DomRefCell<Option<Runtime>>,
location: MutNullableDom<WorkerLocation>,
navigator: MutNullableDom<WorkerNavigator>,

@@ -151,7 +151,7 @@ impl WorkerGlobalScope {
worker_type,
worker_url: DomRefCell::new(worker_url),
closing,
runtime,
runtime: DomRefCell::new(Some(runtime)),
location: Default::default(),
navigator: Default::default(),
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 {
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>> {
@@ -175,7 +184,7 @@ impl WorkerGlobalScope {

#[allow(unsafe_code)]
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 {
@@ -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 {
let global_scope = self.upcast::<GlobalScope>();
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()),
};

let result = self.runtime.evaluate_script(
let result = self.runtime.borrow().as_ref().unwrap().evaluate_script(
self.reflector().get_jsobject(),
&source,
url.as_str(),
@@ -401,8 +410,9 @@ impl WorkerGlobalScope {
#[allow(unsafe_code)]
pub fn execute_script(&self, source: DOMString) {
let _aes = AutoEntryScript::new(self.upcast());
rooted!(in(self.runtime.cx()) let mut rval = UndefinedValue());
match self.runtime.evaluate_script(
let cx = self.runtime.borrow().as_ref().unwrap().cx();
rooted!(in(cx) let mut rval = UndefinedValue());
match self.runtime.borrow().as_ref().unwrap().evaluate_script(
self.reflector().get_jsobject(),
&source,
self.worker_url.borrow().as_str(),
@@ -419,7 +429,7 @@ impl WorkerGlobalScope {
println!("evaluate_script failed");
unsafe {
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 {
match msg {
ServiceWorkerMsg::Timeout(scope) => {},
ServiceWorkerMsg::Timeout(_scope) => {
// TODO: https://w3c.github.io/ServiceWorker/#terminate-service-worker
},
ServiceWorkerMsg::ForwardDOMMessage(msg, scope_url) => {
if let Some(registration) = self.registrations.get_mut(&scope_url) {
if let Some(ref worker) = registration.active_worker {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.