mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Allow refcounting arbitrary DOM objects in concert with the GC to enable safe, asynchronous/cross-task references to pinned objects.
This commit is contained in:
parent
c4b93d30e4
commit
2f059c15e7
8 changed files with 210 additions and 154 deletions
|
@ -9,7 +9,8 @@ use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
|||
use dom::bindings::error::{Fallible, ErrorResult};
|
||||
use dom::bindings::error::Error::{Syntax, DataClone};
|
||||
use dom::bindings::global::{GlobalRef, GlobalField};
|
||||
use dom::bindings::js::{JS, JSRef, Temporary};
|
||||
use dom::bindings::js::{JSRef, Temporary};
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::bindings::utils::{Reflectable, reflect_dom_object};
|
||||
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
||||
|
@ -20,17 +21,16 @@ use script_task::{ScriptChan, ScriptMsg};
|
|||
use servo_util::str::DOMString;
|
||||
|
||||
use js::glue::JS_STRUCTURED_CLONE_VERSION;
|
||||
use js::jsapi::{JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot, JSTracer};
|
||||
use js::jsapi::JSContext;
|
||||
use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException};
|
||||
use js::jsval::{JSVal, UndefinedValue};
|
||||
use url::UrlParser;
|
||||
|
||||
use libc::{c_void, size_t};
|
||||
use libc::size_t;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
|
||||
pub struct TrustedWorkerAddress(pub *const c_void);
|
||||
no_jsmanaged_fields!(TrustedWorkerAddress)
|
||||
pub type TrustedWorkerAddress = Trusted<Worker>;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct Worker {
|
||||
|
@ -71,7 +71,7 @@ impl Worker {
|
|||
let (receiver, sender) = ScriptChan::new();
|
||||
|
||||
let worker = Worker::new(global, sender.clone()).root();
|
||||
let worker_ref = worker.addref();
|
||||
let worker_ref = Trusted::new(global.get_cx(), *worker, global.script_chan().clone());
|
||||
|
||||
DedicatedWorkerGlobalScope::run_worker_scope(
|
||||
worker_url, worker_ref, resource_task, global.script_chan().clone(),
|
||||
|
@ -82,7 +82,7 @@ impl Worker {
|
|||
|
||||
pub fn handle_message(address: TrustedWorkerAddress,
|
||||
data: *mut u64, nbytes: size_t) {
|
||||
let worker = unsafe { JS::from_trusted_worker_address(address).root() };
|
||||
let worker = address.to_temporary().root();
|
||||
|
||||
let global = worker.global.root();
|
||||
|
||||
|
@ -99,38 +99,6 @@ impl Worker {
|
|||
}
|
||||
}
|
||||
|
||||
impl Worker {
|
||||
// Creates a trusted address to the object, and roots it. Always pair this with a release()
|
||||
pub fn addref(&self) -> TrustedWorkerAddress {
|
||||
let refcount = self.refcount.get();
|
||||
if refcount == 0 {
|
||||
let cx = self.global.root().root_ref().get_cx();
|
||||
unsafe {
|
||||
JS_AddObjectRoot(cx, self.reflector().rootable());
|
||||
}
|
||||
}
|
||||
self.refcount.set(refcount + 1);
|
||||
TrustedWorkerAddress(self as *const Worker as *const c_void)
|
||||
}
|
||||
|
||||
pub fn release(&self) {
|
||||
let refcount = self.refcount.get();
|
||||
assert!(refcount > 0)
|
||||
self.refcount.set(refcount - 1);
|
||||
if refcount == 1 {
|
||||
let cx = self.global.root().root_ref().get_cx();
|
||||
unsafe {
|
||||
JS_RemoveObjectRoot(cx, self.reflector().rootable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_release(address: TrustedWorkerAddress) {
|
||||
let worker = unsafe { JS::from_trusted_worker_address(address).root() };
|
||||
worker.release();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WorkerMethods for JSRef<'a, Worker> {
|
||||
fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult {
|
||||
let mut data = ptr::null_mut();
|
||||
|
@ -144,9 +112,9 @@ impl<'a> WorkerMethods for JSRef<'a, Worker> {
|
|||
return Err(DataClone);
|
||||
}
|
||||
|
||||
self.addref();
|
||||
let addr = Trusted::new(cx, self, self.global.root().root_ref().script_chan().clone());
|
||||
let ScriptChan(ref sender) = self.sender;
|
||||
sender.send(ScriptMsg::DOMMessage(data, nbytes));
|
||||
sender.send(ScriptMsg::DOMMessage(addr, data, nbytes));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue