aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-12-29 11:57:45 -0700
committerbors-servo <metajack+bors@gmail.com>2014-12-29 11:57:45 -0700
commit2c259f477c41331e66beab8bda865971982a1ff4 (patch)
tree12b1b56eec1482d6b6e31e85383a309856a39dc7 /components/script/script_task.rs
parentf76a460c53dfddef74262eceaf4b163b551adc08 (diff)
parent9a7cd3113403fe44a8919f049720b67bfa92c9f1 (diff)
downloadservo-2c259f477c41331e66beab8bda865971982a1ff4.tar.gz
servo-2c259f477c41331e66beab8bda865971982a1ff4.zip
auto merge of #4057 : jdm/servo/refcountdom, r=Ms2ger
This replaces the specialized TrustedXHRAddress and TrustedWorkerAddress code that was used for the same purpose. A non-zero refcount pins the given DOM object's reflector and prevents it from being GCed even when there are no other outstanding references visible to SpiderMonkey. This will enable us to implement asynchronous operations that refer to particular DOM objects (such as "queue a task to fire a simple event named load at the iframe element" from the spec) safely and conveniently, and paves the way for things like asynchronous network responses. Some concerns about the resulting size of XHR progress messages have been expressed, but I believe optimizations to reduce that can be implemented in subsequent PRs. r? @Ms2ger - note in particular the changes to the worker lifetime code. I couldn't figure out how to achieve an identical lifetime to the previous addref/release pairing, and I also was having trouble figuring out why the existing setup was safe. The new implementation now holds the main script task Worker object alive via the TrustedWorkerAddress field in the dedicated worker global scope, which is a significant difference.
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs49
1 files changed, 35 insertions, 14 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 26b5665962e..443bb8c37d6 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -15,6 +15,7 @@ use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, RootCollection, Temporary, OptionalRootable};
+use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap};
use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentSource};
@@ -63,13 +64,14 @@ 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};
use js;
use url::Url;
+use libc;
use libc::size_t;
use std::any::{Any, AnyRefExt};
use std::comm::{channel, Sender, Receiver, Select};
@@ -114,23 +116,41 @@ pub enum ScriptMsg {
DOMMessage(*mut u64, size_t),
/// Posts a message to the Worker object (dispatched to all tasks).
WorkerPostMessage(TrustedWorkerAddress, *mut u64, size_t),
- /// Releases one reference to the Worker object (dispatched to all tasks).
- WorkerRelease(TrustedWorkerAddress),
/// Generic message that encapsulates event handling.
RunnableMsg(Box<Runnable+Send>),
+ /// A DOM object's last pinned reference was removed (dispatched to all tasks).
+ 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);
+ }
+
+ fn clone(&self) -> Box<ScriptChan+Send> {
+ let NonWorkerScriptChan(ref chan) = *self;
+ box NonWorkerScriptChan(chan.clone())
+ }
+}
-impl ScriptChan {
+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))
}
}
@@ -165,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,
@@ -280,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,
@@ -312,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,
@@ -368,6 +388,7 @@ impl ScriptTask {
}
pub fn new_rt_and_cx() -> (js::rust::rt, Rc<Cx>) {
+ LiveDOMReferences::initialize();
let js_runtime = js::rust::rt();
assert!({
let ptr: *mut JSRuntime = (*js_runtime).ptr;
@@ -577,10 +598,10 @@ impl ScriptTask {
panic!("unexpected message"),
ScriptMsg::WorkerPostMessage(addr, data, nbytes) =>
Worker::handle_message(addr, data, nbytes),
- ScriptMsg::WorkerRelease(addr) =>
- Worker::handle_release(addr),
ScriptMsg::RunnableMsg(runnable) =>
runnable.handler(),
+ ScriptMsg::RefcountCleanup(addr) =>
+ LiveDOMReferences::cleanup(self.get_cx(), addr),
}
}