diff options
author | yvt <i@yvt.jp> | 2021-07-13 23:08:23 +0900 |
---|---|---|
committer | yvt <i@yvt.jp> | 2021-07-13 23:08:23 +0900 |
commit | f884506dfbced3daa115317de8090c99b9d3f34b (patch) | |
tree | d8b5b175a45d307c0255bdf20fb0d68b7be29f19 /components/script/dom | |
parent | b77ee8721b9cede9acaa0a6064a36491ed9083f2 (diff) | |
download | servo-f884506dfbced3daa115317de8090c99b9d3f34b.tar.gz servo-f884506dfbced3daa115317de8090c99b9d3f34b.zip |
refactor(script): auto ref-count `ServoJSPrincipals`
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/interface.rs | 2 | ||||
-rw-r--r-- | components/script/dom/bindings/principals.rs | 96 |
2 files changed, 86 insertions, 12 deletions
diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index 2b4fcd67f3a..e22b897ac6e 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -155,7 +155,7 @@ pub unsafe fn create_global_object( rval.set(JS_NewGlobalObject( *cx, class, - principal.0, + principal.as_raw(), OnNewGlobalHookOption::DontFireOnNewGlobalHook, &*options, )); diff --git a/components/script/dom/bindings/principals.rs b/components/script/dom/bindings/principals.rs index 010fb28b39f..afaf02c74fe 100644 --- a/components/script/dom/bindings/principals.rs +++ b/components/script/dom/bindings/principals.rs @@ -1,23 +1,97 @@ -use js::glue::{ - CreateRustJSPrincipals, DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, - JSPrincipalsCallbacks, +use js::{ + glue::{ + CreateRustJSPrincipals, DestroyRustJSPrincipals, GetRustJSPrincipalsPrivate, + JSPrincipalsCallbacks, + }, + jsapi::{JSPrincipals, JS_DropPrincipals, JS_HoldPrincipals}, + rust::Runtime, }; -use js::jsapi::JSPrincipals; use servo_url::MutableOrigin; +use std::{marker::PhantomData, ops::Deref, ptr::NonNull}; -// TODO: RAII ref-counting -pub struct ServoJSPrincipals(pub *mut JSPrincipals); +/// An owned reference to Servo's `JSPrincipals` instance. +#[repr(transparent)] +pub struct ServoJSPrincipals(NonNull<JSPrincipals>); impl ServoJSPrincipals { pub fn new(origin: &MutableOrigin) -> Self { - let private: Box<MutableOrigin> = Box::new(origin.clone()); - Self(unsafe { CreateRustJSPrincipals(&PRINCIPALS_CALLBACKS, Box::into_raw(private) as _) }) + unsafe { + let private: Box<MutableOrigin> = Box::new(origin.clone()); + let raw = CreateRustJSPrincipals(&PRINCIPALS_CALLBACKS, Box::into_raw(private) as _); + // The created `JSPrincipals` object has an initial reference + // count of zero, so the following code will set it to one + Self::from_raw_nonnull(NonNull::new_unchecked(raw)) + } } + /// Construct `Self` from a raw `*mut JSPrincipals`, incrementing its + /// reference count. + #[inline] + pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self { + JS_HoldPrincipals(raw.as_ptr()); + Self(raw) + } + + #[inline] pub unsafe fn origin(&self) -> MutableOrigin { - let origin = GetRustJSPrincipalsPrivate(self.0) as *mut MutableOrigin; + let origin = GetRustJSPrincipalsPrivate(self.0.as_ptr()) as *mut MutableOrigin; (*origin).clone() } + + #[inline] + pub fn as_raw_nonnull(&self) -> NonNull<JSPrincipals> { + self.0 + } + + #[inline] + pub fn as_raw(&self) -> *mut JSPrincipals { + self.0.as_ptr() + } +} + +impl Clone for ServoJSPrincipals { + #[inline] + fn clone(&self) -> Self { + unsafe { Self::from_raw_nonnull(self.as_raw_nonnull()) } + } +} + +impl Drop for ServoJSPrincipals { + #[inline] + fn drop(&mut self) { + unsafe { JS_DropPrincipals(Runtime::get(), self.as_raw()) }; + } +} + +/// A borrowed reference to Servo's `JSPrincipals` instance. +#[derive(Clone, Copy)] +pub struct ServoJSPrincipalsRef<'a>(NonNull<JSPrincipals>, PhantomData<&'a ()>); + +impl ServoJSPrincipalsRef<'_> { + /// Construct `Self` from a raw `NonNull<JSPrincipals>`. + #[inline] + pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self { + Self(raw, PhantomData) + } + + /// Construct `Self` from a raw `*mut JSPrincipals`. + /// + /// # Safety + /// + /// The behavior is undefined if `raw` is null. + #[inline] + pub unsafe fn from_raw_unchecked(raw: *mut JSPrincipals) -> Self { + Self::from_raw_nonnull(NonNull::new_unchecked(raw)) + } +} + +impl Deref for ServoJSPrincipalsRef<'_> { + type Target = ServoJSPrincipals; + + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { &*(&self.0 as *const NonNull<JSPrincipals> as *const ServoJSPrincipals) } + } } pub unsafe extern "C" fn destroy_servo_jsprincipal(principals: *mut JSPrincipals) { @@ -36,8 +110,8 @@ unsafe extern "C" fn principals_is_system_or_addon_principal(_: *mut JSPrincipal //TODO is same_origin_domain equivalent to subsumes for our purposes pub unsafe extern "C" fn subsumes(obj: *mut JSPrincipals, other: *mut JSPrincipals) -> bool { - let obj = ServoJSPrincipals(obj); - let other = ServoJSPrincipals(other); + let obj = ServoJSPrincipalsRef::from_raw_unchecked(obj); + let other = ServoJSPrincipalsRef::from_raw_unchecked(other); let obj_origin = obj.origin(); let other_origin = other.origin(); obj_origin.same_origin_domain(&other_origin) |