mirror of
https://github.com/servo/servo.git
synced 2025-06-22 08:08:59 +01:00
auto merge of #4607 : Ms2ger/servo/clone, r=jdm
This commit is contained in:
commit
a07c3eadb3
5 changed files with 76 additions and 65 deletions
54
components/script/dom/bindings/structuredclone.rs
Normal file
54
components/script/dom/bindings/structuredclone.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue