From 57aaa60fa5c3c0da1458271d21a1cab1c6a778c4 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 10 Jan 2015 15:39:47 +0100 Subject: [PATCH 1/3] Create a StructuredCloneData struct to encapsulate the result of a structured clone. --- .../script/dom/bindings/structuredclone.rs | 12 +++++++++++ .../script/dom/dedicatedworkerglobalscope.rs | 12 ++++++++--- components/script/dom/worker.rs | 20 ++++++++++--------- components/script/lib.rs | 1 + components/script/script_task.rs | 4 ++-- 5 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 components/script/dom/bindings/structuredclone.rs diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs new file mode 100644 index 00000000000..aad4a50a149 --- /dev/null +++ b/components/script/dom/bindings/structuredclone.rs @@ -0,0 +1,12 @@ +/* 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 libc::size_t; + +#[allow(raw_pointer_deriving)] +#[deriving(Copy)] +pub struct StructuredCloneData { + pub data: *mut u64, + pub nbytes: size_t, +} diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 6f8242086f0..8cc5e5c6dda 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -13,6 +13,7 @@ use dom::bindings::error::Error::DataClone; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JSRef, Temporary, RootCollection}; use dom::bindings::refcounted::LiveDOMReferences; +use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::utils::Reflectable; use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::messageevent::MessageEvent; @@ -200,12 +201,12 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerG #[allow(unsafe_blocks)] fn handle_event(self, msg: ScriptMsg) { match msg { - ScriptMsg::DOMMessage(data, nbytes) => { + ScriptMsg::DOMMessage(data) => { let mut message = UndefinedValue(); let scope: JSRef = WorkerGlobalScopeCast::from_ref(self); unsafe { assert!(JS_ReadStructuredClone( - scope.get_cx(), data as *const u64, nbytes, + scope.get_cx(), data.data as *const u64, data.nbytes, JS_STRUCTURED_CLONE_VERSION, &mut message, ptr::null(), ptr::null_mut()) != 0); } @@ -242,9 +243,14 @@ impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalSc unsafe { JS_ClearPendingException(cx); } return Err(DataClone); } + let data = StructuredCloneData { + data: data, + nbytes: nbytes, + }; 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(()) } diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index d3681900db3..98392cb6a11 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -11,6 +11,7 @@ use dom::bindings::error::Error::{Syntax, DataClone}; use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::refcounted::Trusted; +use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::trace::JSTraceable; use dom::bindings::utils::{Reflectable, reflect_dom_object}; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; @@ -26,7 +27,6 @@ use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPending use js::jsval::{JSVal, UndefinedValue}; use url::UrlParser; -use libc::size_t; use std::cell::Cell; use std::ptr; @@ -82,7 +82,7 @@ impl Worker { #[allow(unsafe_blocks)] pub fn handle_message(address: TrustedWorkerAddress, - data: *mut u64, nbytes: size_t) { + data: StructuredCloneData) { let worker = address.to_temporary().root(); let global = worker.r().global.root(); @@ -90,7 +90,7 @@ impl Worker { let mut message = UndefinedValue(); unsafe { assert!(JS_ReadStructuredClone( - global.r().get_cx(), data as *const u64, nbytes, + global.r().get_cx(), data.data as *const u64, data.nbytes, JS_STRUCTURED_CLONE_VERSION, &mut message, ptr::null(), ptr::null_mut()) != 0); } @@ -113,9 +113,13 @@ impl<'a> WorkerMethods for JSRef<'a, Worker> { unsafe { JS_ClearPendingException(cx); } return Err(DataClone); } + let data = StructuredCloneData { + data: data, + nbytes: nbytes, + }; 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(()) } @@ -124,22 +128,20 @@ impl<'a> WorkerMethods for JSRef<'a, Worker> { pub struct WorkerMessageHandler { addr: TrustedWorkerAddress, - data: *mut u64, - nbytes: size_t + data: StructuredCloneData, } impl WorkerMessageHandler { - pub fn new(addr: TrustedWorkerAddress, data: *mut u64, nbytes: size_t) -> WorkerMessageHandler { + pub fn new(addr: TrustedWorkerAddress, data: StructuredCloneData) -> WorkerMessageHandler { WorkerMessageHandler { addr: addr, data: data, - nbytes: nbytes, } } } impl Runnable for WorkerMessageHandler { fn handler(&self){ - Worker::handle_message(self.addr.clone(), self.data, self.nbytes); + Worker::handle_message(self.addr.clone(), self.data); } } diff --git a/components/script/lib.rs b/components/script/lib.rs index bd4b19745a4..50661a60ca1 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -64,6 +64,7 @@ pub mod dom { pub mod conversions; mod proxyhandler; pub mod str; + pub mod structuredclone; pub mod trace; /// Generated JS-Rust bindings. diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 1c4af120334..4783d8539f4 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -19,6 +19,7 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable}; use dom::bindings::js::{RootCollection, RootCollectionPtr}; use dom::bindings::refcounted::{LiveDOMReferences, Trusted}; +use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::trace::JSTraceable; use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap}; use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentSource}; @@ -77,7 +78,6 @@ use js; use url::Url; use libc; -use libc::size_t; use std::any::{Any, AnyRefExt}; use std::cell::Cell; use std::comm::{channel, Sender, Receiver, Select}; @@ -120,7 +120,7 @@ pub enum ScriptMsg { ExitWindow(PipelineId), /// Message sent through Worker.postMessage (only dispatched to /// DedicatedWorkerGlobalScope). - DOMMessage(*mut u64, size_t), + DOMMessage(StructuredCloneData), /// Generic message that encapsulates event handling. RunnableMsg(Box), /// A DOM object's last pinned reference was removed (dispatched to all tasks). From 5978b21abf0939491527fa55503c4c01363f8bbf Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 10 Jan 2015 16:23:35 +0100 Subject: [PATCH 2/3] Implement StructuredCloneData::write. --- .../script/dom/bindings/structuredclone.rs | 28 +++++++++++++++++++ .../script/dom/dedicatedworkerglobalscope.rs | 20 ++----------- components/script/dom/worker.rs | 21 ++------------ 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index aad4a50a149..018ac30e340 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -2,7 +2,15 @@ * 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 js::jsapi::JSContext; +use js::jsapi::{JS_WriteStructuredClone, JS_ClearPendingException}; +use js::jsval::JSVal; + use libc::size_t; +use std::ptr; #[allow(raw_pointer_deriving)] #[deriving(Copy)] @@ -10,3 +18,23 @@ pub struct StructuredCloneData { pub data: *mut u64, pub nbytes: size_t, } + +impl StructuredCloneData { + pub fn write(cx: *mut JSContext, message: JSVal) + -> Fallible { + 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, + }) + } +} diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 8cc5e5c6dda..23ef0089274 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -9,7 +9,6 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; use dom::bindings::error::ErrorResult; -use dom::bindings::error::Error::DataClone; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JSRef, Temporary, RootCollection}; use dom::bindings::refcounted::LiveDOMReferences; @@ -29,7 +28,7 @@ use servo_util::task_state; use servo_util::task_state::{SCRIPT, IN_WORKER}; use js::glue::JS_STRUCTURED_CLONE_VERSION; -use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException}; +use js::jsapi::{JSContext, JS_ReadStructuredClone}; use js::jsval::{JSVal, UndefinedValue}; use js::rust::Cx; @@ -231,23 +230,8 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerG } impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalScope> { - #[allow(unsafe_blocks)] fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { - 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); - } - let data = StructuredCloneData { - data: data, - nbytes: nbytes, - }; - + let data = try!(StructuredCloneData::write(cx, message)); let worker = self.worker.borrow().as_ref().unwrap().clone(); self.parent_sender.send(ScriptMsg::RunnableMsg( box WorkerMessageHandler::new(worker, data))); diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 98392cb6a11..60675fa4b8a 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::InheritTypes::EventTargetCast; 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::js::{JSRef, Temporary}; use dom::bindings::refcounted::Trusted; @@ -23,7 +23,7 @@ use servo_util::str::DOMString; use js::glue::JS_STRUCTURED_CLONE_VERSION; use js::jsapi::JSContext; -use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException}; +use js::jsapi::JS_ReadStructuredClone; use js::jsval::{JSVal, UndefinedValue}; use url::UrlParser; @@ -101,23 +101,8 @@ impl Worker { } impl<'a> WorkerMethods for JSRef<'a, Worker> { - #[allow(unsafe_blocks)] fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { - 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); - } - let data = StructuredCloneData { - data: data, - nbytes: nbytes, - }; - + let data = try!(StructuredCloneData::write(cx, message)); let address = Trusted::new(cx, self, self.global.root().r().script_chan().clone()); self.sender.send((address, ScriptMsg::DOMMessage(data))); Ok(()) From 14ff55443fc872f0806a6267655689d48002a3b3 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 10 Jan 2015 16:30:27 +0100 Subject: [PATCH 3/3] Implement StructuredCloneData::read. --- .../script/dom/bindings/structuredclone.rs | 16 +++++++++++++++- .../script/dom/dedicatedworkerglobalscope.rs | 16 +++------------- components/script/dom/worker.rs | 17 +++-------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs index 018ac30e340..843b7bea30c 100644 --- a/components/script/dom/bindings/structuredclone.rs +++ b/components/script/dom/bindings/structuredclone.rs @@ -4,10 +4,13 @@ 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::jsval::JSVal; +use js::jsapi::JS_ReadStructuredClone; +use js::jsval::{JSVal, UndefinedValue}; use libc::size_t; use std::ptr; @@ -37,4 +40,15 @@ impl StructuredCloneData { 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 + } } diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 23ef0089274..1403344dad2 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -27,13 +27,11 @@ use servo_util::task::spawn_named; use servo_util::task_state; use servo_util::task_state::{SCRIPT, IN_WORKER}; -use js::glue::JS_STRUCTURED_CLONE_VERSION; -use js::jsapi::{JSContext, JS_ReadStructuredClone}; -use js::jsval::{JSVal, UndefinedValue}; +use js::jsapi::JSContext; +use js::jsval::JSVal; use js::rust::Cx; use std::rc::Rc; -use std::ptr; use url::Url; /// 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> { - #[allow(unsafe_blocks)] fn handle_event(self, msg: ScriptMsg) { match msg { ScriptMsg::DOMMessage(data) => { - let mut message = UndefinedValue(); let scope: JSRef = WorkerGlobalScopeCast::from_ref(self); - unsafe { - assert!(JS_ReadStructuredClone( - scope.get_cx(), data.data as *const u64, data.nbytes, - JS_STRUCTURED_CLONE_VERSION, &mut message, - ptr::null(), ptr::null_mut()) != 0); - } - let target: JSRef = EventTargetCast::from_ref(self); + let message = data.read(GlobalRef::Worker(scope)); MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message); }, ScriptMsg::RunnableMsg(runnable) => { diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 60675fa4b8a..3822e4e538c 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -21,14 +21,11 @@ use script_task::{ScriptChan, ScriptMsg, Runnable}; use servo_util::str::DOMString; -use js::glue::JS_STRUCTURED_CLONE_VERSION; use js::jsapi::JSContext; -use js::jsapi::JS_ReadStructuredClone; -use js::jsval::{JSVal, UndefinedValue}; +use js::jsval::JSVal; use url::UrlParser; use std::cell::Cell; -use std::ptr; pub type TrustedWorkerAddress = Trusted; @@ -80,22 +77,14 @@ impl Worker { Ok(Temporary::from_rooted(worker.r())) } - #[allow(unsafe_blocks)] pub fn handle_message(address: TrustedWorkerAddress, data: StructuredCloneData) { let worker = address.to_temporary().root(); let global = worker.r().global.root(); - - let mut message = UndefinedValue(); - unsafe { - assert!(JS_ReadStructuredClone( - global.r().get_cx(), data.data as *const u64, data.nbytes, - JS_STRUCTURED_CLONE_VERSION, &mut message, - ptr::null(), ptr::null_mut()) != 0); - } - let target: JSRef = EventTargetCast::from_ref(worker.r()); + + let message = data.read(global.r()); MessageEvent::dispatch_jsval(target, global.r(), message); } }