diff options
author | Josh Matthews <josh@joshmatthews.net> | 2017-01-12 18:05:54 -0500 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2017-01-13 09:59:57 -0500 |
commit | 3f35c3eee22cb52de04dea764e529517f6bfef0d (patch) | |
tree | caa59c9b7955f2dc6730eac3289b3232ea681a89 /components/script/dom/bindings/callback.rs | |
parent | 550df86ac88ff12ad3964d08b6a678ae0d1b4436 (diff) | |
download | servo-3f35c3eee22cb52de04dea764e529517f6bfef0d.tar.gz servo-3f35c3eee22cb52de04dea764e529517f6bfef0d.zip |
Add a permanent root to WebIDL callbacks, ensuring they are always safe to store.
Diffstat (limited to 'components/script/dom/bindings/callback.rs')
-rw-r--r-- | components/script/dom/bindings/callback.rs | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/components/script/dom/bindings/callback.rs b/components/script/dom/bindings/callback.rs index 067b498a35d..e260195f7ef 100644 --- a/components/script/dom/bindings/callback.rs +++ b/components/script/dom/bindings/callback.rs @@ -5,16 +5,16 @@ //! Base classes to work with IDL callbacks. use dom::bindings::error::{Error, Fallible, report_pending_exception}; -use dom::bindings::js::Root; +use dom::bindings::js::{Root, MutHeapJSVal}; use dom::bindings::reflector::DomObject; use dom::bindings::settings_stack::AutoEntryScript; use dom::globalscope::GlobalScope; use js::jsapi::{Heap, MutableHandleObject}; -use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject}; -use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment}; +use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject, AddRawValueRoot}; +use js::jsapi::{JSCompartment, JS_EnterCompartment, JS_LeaveCompartment, RemoveRawValueRoot}; use js::jsapi::JSAutoCompartment; use js::jsapi::JS_GetProperty; -use js::jsval::{JSVal, UndefinedValue}; +use js::jsval::{JSVal, UndefinedValue, ObjectValue}; use std::default::Default; use std::ffi::CString; use std::mem::drop; @@ -33,22 +33,52 @@ pub enum ExceptionHandling { /// A common base class for representing IDL callback function and /// callback interface types. -#[derive(Default, JSTraceable)] +#[derive(JSTraceable)] +#[must_root] pub struct CallbackObject { /// The underlying `JSObject`. callback: Heap<*mut JSObject>, + permanent_js_root: MutHeapJSVal, +} + +impl Default for CallbackObject { + #[allow(unrooted_must_root)] + fn default() -> CallbackObject { + CallbackObject::new() + } } impl CallbackObject { + #[allow(unrooted_must_root)] fn new() -> CallbackObject { CallbackObject { callback: Heap::default(), + permanent_js_root: MutHeapJSVal::new(), } } pub fn get(&self) -> *mut JSObject { self.callback.get() } + + #[allow(unsafe_code)] + unsafe fn init(&mut self, cx: *mut JSContext, callback: *mut JSObject) { + self.callback.set(callback); + self.permanent_js_root.set(ObjectValue(callback)); + assert!(AddRawValueRoot(cx, self.permanent_js_root.get_unsafe(), + b"CallbackObject::root\n" as *const _ as *const _)); + } +} + +impl Drop for CallbackObject { + #[allow(unsafe_code)] + fn drop(&mut self) { + unsafe { + let cx = GlobalScope::from_object(self.callback.get()).get_cx(); + RemoveRawValueRoot(cx, self.permanent_js_root.get_unsafe()); + } + } + } impl PartialEq for CallbackObject { @@ -62,7 +92,7 @@ impl PartialEq for CallbackObject { /// callback interface types. pub trait CallbackContainer { /// Create a new CallbackContainer object for the given `JSObject`. - fn new(callback: *mut JSObject) -> Rc<Self>; + unsafe fn new(cx: *mut JSContext, callback: *mut JSObject) -> Rc<Self>; /// Returns the underlying `CallbackObject`. fn callback_holder(&self) -> &CallbackObject; /// Returns the underlying `JSObject`. @@ -74,12 +104,14 @@ pub trait CallbackContainer { /// A common base class for representing IDL callback function types. #[derive(JSTraceable, PartialEq)] +#[must_root] pub struct CallbackFunction { object: CallbackObject, } impl CallbackFunction { /// Create a new `CallbackFunction` for this object. + #[allow(unrooted_must_root)] pub fn new() -> CallbackFunction { CallbackFunction { object: CallbackObject::new(), @@ -93,14 +125,17 @@ impl CallbackFunction { /// Initialize the callback function with a value. /// Should be called once this object is done moving. - pub fn init(&mut self, callback: *mut JSObject) { - self.object.callback.set(callback); + pub unsafe fn init(&mut self, cx: *mut JSContext, callback: *mut JSObject) { + self.object.init(cx, callback); } } + + /// A common base class for representing IDL callback interface types. #[derive(JSTraceable, PartialEq)] +#[must_root] pub struct CallbackInterface { object: CallbackObject, } @@ -120,8 +155,8 @@ impl CallbackInterface { /// Initialize the callback function with a value. /// Should be called once this object is done moving. - pub fn init(&mut self, callback: *mut JSObject) { - self.object.callback.set(callback); + pub unsafe fn init(&mut self, cx: *mut JSContext, callback: *mut JSObject) { + self.object.init(cx, callback); } /// Returns the property with the given `name`, if it is a callable object, |