script_bindings/
principals.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::marker::PhantomData;
6use std::mem::ManuallyDrop;
7use std::ops::Deref;
8use std::ptr::NonNull;
9
10use js::glue::{CreateRustJSPrincipals, GetRustJSPrincipalsPrivate};
11use js::jsapi::{JS_DropPrincipals, JS_HoldPrincipals, JSPrincipals};
12use js::rust::Runtime;
13use servo_url::MutableOrigin;
14
15use crate::DomTypes;
16use crate::interfaces::DomHelpers;
17
18/// An owned reference to Servo's `JSPrincipals` instance.
19#[repr(transparent)]
20pub struct ServoJSPrincipals(NonNull<JSPrincipals>);
21
22impl ServoJSPrincipals {
23    pub fn new<D: DomTypes>(origin: &MutableOrigin) -> Self {
24        unsafe {
25            let private: Box<MutableOrigin> = Box::new(origin.clone());
26            let raw = CreateRustJSPrincipals(
27                <D as DomHelpers<D>>::principals_callbacks(),
28                Box::into_raw(private) as _,
29            );
30            // The created `JSPrincipals` object has an initial reference
31            // count of zero, so the following code will set it to one
32            Self::from_raw_nonnull(NonNull::new_unchecked(raw))
33        }
34    }
35
36    /// Construct `Self` from a raw `*mut JSPrincipals`, incrementing its
37    /// reference count.
38    ///
39    /// # Safety
40    /// `raw` must point to a valid JSPrincipals value.
41    #[inline]
42    pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
43        JS_HoldPrincipals(raw.as_ptr());
44        Self(raw)
45    }
46
47    #[inline]
48    pub fn origin(&self) -> MutableOrigin {
49        unsafe {
50            let origin = GetRustJSPrincipalsPrivate(self.0.as_ptr()) as *mut MutableOrigin;
51            (*origin).clone()
52        }
53    }
54
55    #[inline]
56    pub fn as_raw_nonnull(&self) -> NonNull<JSPrincipals> {
57        self.0
58    }
59
60    #[inline]
61    pub fn as_raw(&self) -> *mut JSPrincipals {
62        self.0.as_ptr()
63    }
64}
65
66impl Clone for ServoJSPrincipals {
67    #[inline]
68    fn clone(&self) -> Self {
69        unsafe { Self::from_raw_nonnull(self.as_raw_nonnull()) }
70    }
71}
72
73impl Drop for ServoJSPrincipals {
74    #[inline]
75    fn drop(&mut self) {
76        if let Some(cx) = Runtime::get() {
77            unsafe { JS_DropPrincipals(cx.as_ptr(), self.as_raw()) };
78        }
79    }
80}
81
82/// A borrowed reference to Servo's `JSPrincipals` instance. Does not update the
83/// reference count on creation and deletion.
84pub struct ServoJSPrincipalsRef<'a>(ManuallyDrop<ServoJSPrincipals>, PhantomData<&'a ()>);
85
86impl ServoJSPrincipalsRef<'_> {
87    /// Construct `Self` from a raw `NonNull<JSPrincipals>`.
88    ///
89    /// # Safety
90    ///
91    /// `ServoJSPrincipalsRef` does not update the reference count of the
92    /// wrapped `JSPrincipals` object. It's up to the caller to ensure the
93    /// returned `ServoJSPrincipalsRef` object or any clones are not used past
94    /// the lifetime of the wrapped object.
95    #[inline]
96    pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
97        // Don't use `ServoJSPrincipals::from_raw_nonnull`; we don't want to
98        // update the reference count
99        Self(ManuallyDrop::new(ServoJSPrincipals(raw)), PhantomData)
100    }
101
102    /// Construct `Self` from a raw `*mut JSPrincipals`.
103    ///
104    /// # Safety
105    ///
106    /// The behavior is undefined if `raw` is null. See also
107    /// [`Self::from_raw_nonnull`].
108    #[inline]
109    pub unsafe fn from_raw_unchecked(raw: *mut JSPrincipals) -> Self {
110        Self::from_raw_nonnull(NonNull::new_unchecked(raw))
111    }
112}
113
114impl Clone for ServoJSPrincipalsRef<'_> {
115    #[inline]
116    fn clone(&self) -> Self {
117        Self(ManuallyDrop::new(ServoJSPrincipals(self.0.0)), PhantomData)
118    }
119}
120
121impl Deref for ServoJSPrincipalsRef<'_> {
122    type Target = ServoJSPrincipals;
123
124    #[inline]
125    fn deref(&self) -> &Self::Target {
126        &self.0
127    }
128}