auto merge of #4607 : Ms2ger/servo/clone, r=jdm

This commit is contained in:
bors-servo 2015-01-10 09:18:45 -07:00
commit a07c3eadb3
5 changed files with 76 additions and 65 deletions

View file

@ -0,0 +1,54 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::error::Fallible;
use dom::bindings::error::Error::DataClone;
use dom::bindings::global::GlobalRef;
use js::glue::JS_STRUCTURED_CLONE_VERSION;
use js::jsapi::JSContext;
use js::jsapi::{JS_WriteStructuredClone, JS_ClearPendingException};
use js::jsapi::JS_ReadStructuredClone;
use js::jsval::{JSVal, UndefinedValue};
use libc::size_t;
use std::ptr;
#[allow(raw_pointer_deriving)]
#[deriving(Copy)]
pub struct StructuredCloneData {
pub data: *mut u64,
pub nbytes: size_t,
}
impl StructuredCloneData {
pub fn write(cx: *mut JSContext, message: JSVal)
-> Fallible<StructuredCloneData> {
let mut data = ptr::null_mut();
let mut nbytes = 0;
let result = unsafe {
JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
ptr::null(), ptr::null_mut())
};
if result == 0 {
unsafe { JS_ClearPendingException(cx); }
return Err(DataClone);
}
Ok(StructuredCloneData {
data: data,
nbytes: nbytes,
})
}
pub fn read(self, global: GlobalRef) -> JSVal {
let mut message = UndefinedValue();
unsafe {
assert!(JS_ReadStructuredClone(
global.get_cx(), self.data as *const u64, self.nbytes,
JS_STRUCTURED_CLONE_VERSION, &mut message,
ptr::null(), ptr::null_mut()) != 0);
}
message
}
}

View file

@ -9,10 +9,10 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast};
use dom::bindings::error::ErrorResult; use dom::bindings::error::ErrorResult;
use dom::bindings::error::Error::DataClone;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary, RootCollection}; use dom::bindings::js::{JSRef, Temporary, RootCollection};
use dom::bindings::refcounted::LiveDOMReferences; use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
@ -27,13 +27,11 @@ use servo_util::task::spawn_named;
use servo_util::task_state; use servo_util::task_state;
use servo_util::task_state::{SCRIPT, IN_WORKER}; use servo_util::task_state::{SCRIPT, IN_WORKER};
use js::glue::JS_STRUCTURED_CLONE_VERSION; use js::jsapi::JSContext;
use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException}; use js::jsval::JSVal;
use js::jsval::{JSVal, UndefinedValue};
use js::rust::Cx; use js::rust::Cx;
use std::rc::Rc; use std::rc::Rc;
use std::ptr;
use url::Url; use url::Url;
/// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with /// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with
@ -197,20 +195,12 @@ trait PrivateDedicatedWorkerGlobalScopeHelpers {
} }
impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> { impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> {
#[allow(unsafe_blocks)]
fn handle_event(self, msg: ScriptMsg) { fn handle_event(self, msg: ScriptMsg) {
match msg { match msg {
ScriptMsg::DOMMessage(data, nbytes) => { ScriptMsg::DOMMessage(data) => {
let mut message = UndefinedValue();
let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self); let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self);
unsafe {
assert!(JS_ReadStructuredClone(
scope.get_cx(), data as *const u64, nbytes,
JS_STRUCTURED_CLONE_VERSION, &mut message,
ptr::null(), ptr::null_mut()) != 0);
}
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let message = data.read(GlobalRef::Worker(scope));
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message); MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message);
}, },
ScriptMsg::RunnableMsg(runnable) => { ScriptMsg::RunnableMsg(runnable) => {
@ -230,21 +220,11 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerG
} }
impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalScope> { impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalScope> {
#[allow(unsafe_blocks)]
fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult {
let mut data = ptr::null_mut(); let data = try!(StructuredCloneData::write(cx, message));
let mut nbytes = 0;
let result = unsafe {
JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
ptr::null(), ptr::null_mut())
};
if result == 0 {
unsafe { JS_ClearPendingException(cx); }
return Err(DataClone);
}
let worker = self.worker.borrow().as_ref().unwrap().clone(); let worker = self.worker.borrow().as_ref().unwrap().clone();
self.parent_sender.send(ScriptMsg::RunnableMsg(box WorkerMessageHandler::new(worker, data, nbytes))); self.parent_sender.send(ScriptMsg::RunnableMsg(
box WorkerMessageHandler::new(worker, data)));
Ok(()) Ok(())
} }

View file

@ -7,10 +7,11 @@ use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::error::Error::{Syntax, DataClone}; use dom::bindings::error::Error::Syntax;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflectable, reflect_dom_object}; use dom::bindings::utils::{Reflectable, reflect_dom_object};
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
@ -20,15 +21,11 @@ use script_task::{ScriptChan, ScriptMsg, Runnable};
use servo_util::str::DOMString; use servo_util::str::DOMString;
use js::glue::JS_STRUCTURED_CLONE_VERSION;
use js::jsapi::JSContext; use js::jsapi::JSContext;
use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException}; use js::jsval::JSVal;
use js::jsval::{JSVal, UndefinedValue};
use url::UrlParser; use url::UrlParser;
use libc::size_t;
use std::cell::Cell; use std::cell::Cell;
use std::ptr;
pub type TrustedWorkerAddress = Trusted<Worker>; pub type TrustedWorkerAddress = Trusted<Worker>;
@ -80,42 +77,23 @@ impl Worker {
Ok(Temporary::from_rooted(worker.r())) Ok(Temporary::from_rooted(worker.r()))
} }
#[allow(unsafe_blocks)]
pub fn handle_message(address: TrustedWorkerAddress, pub fn handle_message(address: TrustedWorkerAddress,
data: *mut u64, nbytes: size_t) { data: StructuredCloneData) {
let worker = address.to_temporary().root(); let worker = address.to_temporary().root();
let global = worker.r().global.root(); let global = worker.r().global.root();
let mut message = UndefinedValue();
unsafe {
assert!(JS_ReadStructuredClone(
global.r().get_cx(), data as *const u64, nbytes,
JS_STRUCTURED_CLONE_VERSION, &mut message,
ptr::null(), ptr::null_mut()) != 0);
}
let target: JSRef<EventTarget> = EventTargetCast::from_ref(worker.r()); let target: JSRef<EventTarget> = EventTargetCast::from_ref(worker.r());
let message = data.read(global.r());
MessageEvent::dispatch_jsval(target, global.r(), message); MessageEvent::dispatch_jsval(target, global.r(), message);
} }
} }
impl<'a> WorkerMethods for JSRef<'a, Worker> { impl<'a> WorkerMethods for JSRef<'a, Worker> {
#[allow(unsafe_blocks)]
fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult {
let mut data = ptr::null_mut(); let data = try!(StructuredCloneData::write(cx, message));
let mut nbytes = 0;
let result = unsafe {
JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
ptr::null(), ptr::null_mut())
};
if result == 0 {
unsafe { JS_ClearPendingException(cx); }
return Err(DataClone);
}
let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone()); let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone());
self.sender.send((address, ScriptMsg::DOMMessage(data, nbytes))); self.sender.send((address, ScriptMsg::DOMMessage(data)));
Ok(()) Ok(())
} }
@ -124,22 +102,20 @@ impl<'a> WorkerMethods for JSRef<'a, Worker> {
pub struct WorkerMessageHandler { pub struct WorkerMessageHandler {
addr: TrustedWorkerAddress, addr: TrustedWorkerAddress,
data: *mut u64, data: StructuredCloneData,
nbytes: size_t
} }
impl WorkerMessageHandler { impl WorkerMessageHandler {
pub fn new(addr: TrustedWorkerAddress, data: *mut u64, nbytes: size_t) -> WorkerMessageHandler { pub fn new(addr: TrustedWorkerAddress, data: StructuredCloneData) -> WorkerMessageHandler {
WorkerMessageHandler { WorkerMessageHandler {
addr: addr, addr: addr,
data: data, data: data,
nbytes: nbytes,
} }
} }
} }
impl Runnable for WorkerMessageHandler { impl Runnable for WorkerMessageHandler {
fn handler(&self){ fn handler(&self){
Worker::handle_message(self.addr.clone(), self.data, self.nbytes); Worker::handle_message(self.addr.clone(), self.data);
} }
} }

View file

@ -64,6 +64,7 @@ pub mod dom {
pub mod conversions; pub mod conversions;
mod proxyhandler; mod proxyhandler;
pub mod str; pub mod str;
pub mod structuredclone;
pub mod trace; pub mod trace;
/// Generated JS-Rust bindings. /// Generated JS-Rust bindings.

View file

@ -19,6 +19,7 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
use dom::bindings::js::{RootCollection, RootCollectionPtr}; use dom::bindings::js::{RootCollection, RootCollectionPtr};
use dom::bindings::refcounted::{LiveDOMReferences, Trusted}; use dom::bindings::refcounted::{LiveDOMReferences, Trusted};
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap}; use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap};
use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentSource}; use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentSource};
@ -77,7 +78,6 @@ use js;
use url::Url; use url::Url;
use libc; use libc;
use libc::size_t;
use std::any::{Any, AnyRefExt}; use std::any::{Any, AnyRefExt};
use std::cell::Cell; use std::cell::Cell;
use std::comm::{channel, Sender, Receiver, Select}; use std::comm::{channel, Sender, Receiver, Select};
@ -120,7 +120,7 @@ pub enum ScriptMsg {
ExitWindow(PipelineId), ExitWindow(PipelineId),
/// Message sent through Worker.postMessage (only dispatched to /// Message sent through Worker.postMessage (only dispatched to
/// DedicatedWorkerGlobalScope). /// DedicatedWorkerGlobalScope).
DOMMessage(*mut u64, size_t), DOMMessage(StructuredCloneData),
/// Generic message that encapsulates event handling. /// Generic message that encapsulates event handling.
RunnableMsg(Box<Runnable+Send>), RunnableMsg(Box<Runnable+Send>),
/// A DOM object's last pinned reference was removed (dispatched to all tasks). /// A DOM object's last pinned reference was removed (dispatched to all tasks).