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:
Josh Matthews 2014-12-02 16:54:43 -08:00
parent 2f059c15e7
commit 9a7cd31134
11 changed files with 234 additions and 121 deletions

View file

@ -64,7 +64,7 @@ use geom::point::Point2D;
use hyper::header::{Header, HeaderFormat};
use hyper::header::common::util as header_util;
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_SetGCZeal, JS_DEFAULT_ZEAL_FREQ, JS_GC};
use js::jsapi::{JSContext, JSRuntime, JSTracer};
use js::jsapi::{JSContext, JSRuntime};
use js::jsapi::{JS_SetGCParameter, JSGC_MAX_BYTES};
use js::jsapi::{JS_SetGCCallback, JSGCStatus, JSGC_BEGIN, JSGC_END};
use js::rust::{Cx, RtUtils};
@ -113,7 +113,7 @@ pub enum ScriptMsg {
ExitWindow(PipelineId),
/// Message sent through Worker.postMessage (only dispatched to
/// DedicatedWorkerGlobalScope).
DOMMessage(TrustedWorkerAddress, *mut u64, size_t),
DOMMessage(*mut u64, size_t),
/// Posts a message to the Worker object (dispatched to all tasks).
WorkerPostMessage(TrustedWorkerAddress, *mut u64, size_t),
/// Generic message that encapsulates event handling.
@ -122,17 +122,35 @@ pub enum ScriptMsg {
RefcountCleanup(*const libc::c_void),
}
/// A cloneable interface for communicating with an event loop.
pub trait ScriptChan {
/// Send a message to the associated event loop.
fn send(&self, msg: ScriptMsg);
/// Clone this handle.
fn clone(&self) -> Box<ScriptChan+Send>;
}
/// Encapsulates internal communication within the script task.
#[deriving(Clone)]
pub struct ScriptChan(pub Sender<ScriptMsg>);
#[jstraceable]
pub struct NonWorkerScriptChan(pub Sender<ScriptMsg>);
no_jsmanaged_fields!(ScriptChan)
impl ScriptChan for NonWorkerScriptChan {
fn send(&self, msg: ScriptMsg) {
let NonWorkerScriptChan(ref chan) = *self;
chan.send(msg);
}
impl ScriptChan {
fn clone(&self) -> Box<ScriptChan+Send> {
let NonWorkerScriptChan(ref chan) = *self;
box NonWorkerScriptChan(chan.clone())
}
}
impl NonWorkerScriptChan {
/// Creates a new script chan.
pub fn new() -> (Receiver<ScriptMsg>, ScriptChan) {
pub fn new() -> (Receiver<ScriptMsg>, Box<NonWorkerScriptChan>) {
let (chan, port) = channel();
(port, ScriptChan(chan))
(port, box NonWorkerScriptChan(chan))
}
}
@ -167,7 +185,7 @@ pub struct ScriptTask {
port: Receiver<ScriptMsg>,
/// A channel to hand out to script task-based entities that need to be able to enqueue
/// events in the event queue.
chan: ScriptChan,
chan: NonWorkerScriptChan,
/// A channel to hand out to tasks that need to respond to a message from the script task.
control_chan: ScriptControlChan,
@ -282,7 +300,7 @@ impl ScriptTaskFactory for ScriptTask {
box compositor as Box<ScriptListener>,
layout_chan,
script_port,
ScriptChan(script_chan),
NonWorkerScriptChan(script_chan),
control_chan,
control_port,
constellation_chan,
@ -314,7 +332,7 @@ impl ScriptTask {
compositor: Box<ScriptListener+'static>,
layout_chan: LayoutChan,
port: Receiver<ScriptMsg>,
chan: ScriptChan,
chan: NonWorkerScriptChan,
control_chan: ScriptControlChan,
control_port: Receiver<ConstellationControlMsg>,
constellation_chan: ConstellationChan,
@ -583,7 +601,7 @@ impl ScriptTask {
ScriptMsg::RunnableMsg(runnable) =>
runnable.handler(),
ScriptMsg::RefcountCleanup(addr) =>
LiveDOMReferences::cleanup(self.js_context.borrow().as_ref().unwrap().ptr, addr),
LiveDOMReferences::cleanup(self.get_cx(), addr),
}
}