mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Force all messages to worker tasks to send a TrustedWorkerAddress along with the ScriptMsg. This ensures that the main-thread Worker object is rooted for as long as there are events in flight or being processed.
This commit is contained in:
parent
2f059c15e7
commit
9a7cd31134
11 changed files with 234 additions and 121 deletions
|
@ -10,7 +10,7 @@
|
|||
use dom::bindings::conversions::FromJSValConvertible;
|
||||
use dom::bindings::js::{JS, JSRef, Root};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
|
||||
use dom::window;
|
||||
use script_task::ScriptChan;
|
||||
|
||||
|
@ -81,7 +81,7 @@ impl<'a> GlobalRef<'a> {
|
|||
|
||||
/// `ScriptChan` used to send messages to the event loop of this global's
|
||||
/// thread.
|
||||
pub fn script_chan<'b>(&'b self) -> &'b ScriptChan {
|
||||
pub fn script_chan(&self) -> Box<ScriptChan+Send> {
|
||||
match *self {
|
||||
GlobalRef::Window(ref window) => window.script_chan(),
|
||||
GlobalRef::Worker(ref worker) => worker.script_chan(),
|
||||
|
|
|
@ -42,32 +42,37 @@ local_data_key!(pub LiveReferences: LiveDOMReferences)
|
|||
/// DOM object is guaranteed to live at least as long as the last outstanding
|
||||
/// `Trusted<T>` instance.
|
||||
pub struct Trusted<T> {
|
||||
cx: *mut JSContext,
|
||||
/// A pointer to the Rust DOM object of type T, but void to allow
|
||||
/// sending `Trusted<T>` between tasks, regardless of T's sendability.
|
||||
ptr: *const libc::c_void,
|
||||
refcount: Arc<Mutex<uint>>,
|
||||
script_chan: ScriptChan,
|
||||
script_chan: Box<ScriptChan + Send>,
|
||||
owner_thread: *const libc::c_void,
|
||||
}
|
||||
|
||||
impl<T: Reflectable> Trusted<T> {
|
||||
/// Create a new `Trusted<T>` instance from an existing DOM pointer. The DOM object will
|
||||
/// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's
|
||||
/// lifetime.
|
||||
pub fn new(cx: *mut JSContext, ptr: JSRef<T>, script_chan: ScriptChan) -> Trusted<T> {
|
||||
pub fn new(cx: *mut JSContext, ptr: JSRef<T>, script_chan: Box<ScriptChan + Send>) -> Trusted<T> {
|
||||
let live_references = LiveReferences.get().unwrap();
|
||||
let refcount = live_references.addref(cx, &*ptr as *const T);
|
||||
Trusted {
|
||||
cx: cx,
|
||||
ptr: &*ptr as *const T as *const libc::c_void,
|
||||
refcount: refcount,
|
||||
script_chan: script_chan,
|
||||
owner_thread: (&*live_references) as *const _ as *const libc::c_void,
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtain a usable DOM pointer from a pinned `Trusted<T>` value. Attempts to use the
|
||||
/// resulting `Temporary<T>` off of the script thread will fail.
|
||||
/// Obtain a usable DOM pointer from a pinned `Trusted<T>` value. Fails if used on
|
||||
/// a different thread than the original value from which this `Trusted<T>` was
|
||||
/// obtained.
|
||||
pub fn to_temporary(&self) -> Temporary<T> {
|
||||
assert!({
|
||||
let live_references = LiveReferences.get().unwrap();
|
||||
self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
|
||||
});
|
||||
unsafe {
|
||||
Temporary::new(JS::from_raw(self.ptr as *const T))
|
||||
}
|
||||
|
@ -82,10 +87,10 @@ impl<T: Reflectable> Clone for Trusted<T> {
|
|||
}
|
||||
|
||||
Trusted {
|
||||
cx: self.cx,
|
||||
ptr: self.ptr,
|
||||
refcount: self.refcount.clone(),
|
||||
script_chan: self.script_chan.clone(),
|
||||
owner_thread: self.owner_thread,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +102,7 @@ impl<T: Reflectable> Drop for Trusted<T> {
|
|||
assert!(*refcount > 0);
|
||||
*refcount -= 1;
|
||||
if *refcount == 0 {
|
||||
let ScriptChan(ref chan) = self.script_chan;
|
||||
chan.send(ScriptMsg::RefcountCleanup(self.ptr));
|
||||
self.script_chan.send(ScriptMsg::RefcountCleanup(self.ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ use dom::bindings::js::JS;
|
|||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler};
|
||||
use dom::node::{Node, TrustedNodeAddress};
|
||||
use script_task::ScriptChan;
|
||||
|
||||
use collections::hash::{Hash, Hasher};
|
||||
use cssparser::RGBA;
|
||||
|
@ -219,6 +220,13 @@ no_jsmanaged_fields!(UntrustedNodeAddress)
|
|||
no_jsmanaged_fields!(LengthOrPercentageOrAuto)
|
||||
no_jsmanaged_fields!(RGBA)
|
||||
|
||||
impl JSTraceable for Box<ScriptChan+Send> {
|
||||
#[inline]
|
||||
fn trace(&self, _trc: *mut JSTracer) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> JSTraceable for &'a str {
|
||||
#[inline]
|
||||
fn trace(&self, _: *mut JSTracer) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue