Skip to main content

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    /// Crate a new [`ServoJSPrincipals`] with the given [`MutableOrigin`]. Note that the
24    /// resulting value will hold a **shared** mutable reference to `origin`, so any changes to
25    /// `origin`'s `host` will be reflected in the return value's internal state.
26    pub fn new<D: DomTypes>(origin: &MutableOrigin) -> Self {
27        unsafe {
28            let private: Box<MutableOrigin> = Box::new(origin.clone());
29            let raw = CreateRustJSPrincipals(
30                <D as DomHelpers<D>>::principals_callbacks(),
31                Box::into_raw(private) as _,
32            );
33            // The created `JSPrincipals` object has an initial reference
34            // count of zero, so the following code will set it to one
35            Self::from_raw_nonnull(NonNull::new_unchecked(raw))
36        }
37    }
38
39    /// Construct `Self` from a raw `*mut JSPrincipals`, incrementing its
40    /// reference count.
41    ///
42    /// # Safety
43    /// `raw` must point to a valid JSPrincipals value.
44    #[inline]
45    pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
46        JS_HoldPrincipals(raw.as_ptr());
47        Self(raw)
48    }
49
50    #[inline]
51    pub fn origin(&self) -> MutableOrigin {
52        unsafe {
53            let origin = GetRustJSPrincipalsPrivate(self.0.as_ptr()) as *mut MutableOrigin;
54            (*origin).clone()
55        }
56    }
57
58    #[inline]
59    pub fn as_raw_nonnull(&self) -> NonNull<JSPrincipals> {
60        self.0
61    }
62
63    #[inline]
64    pub fn as_raw(&self) -> *mut JSPrincipals {
65        self.0.as_ptr()
66    }
67}
68
69impl Clone for ServoJSPrincipals {
70    #[inline]
71    fn clone(&self) -> Self {
72        unsafe { Self::from_raw_nonnull(self.as_raw_nonnull()) }
73    }
74}
75
76impl Drop for ServoJSPrincipals {
77    #[inline]
78    fn drop(&mut self) {
79        if let Some(cx) = Runtime::get() {
80            unsafe { JS_DropPrincipals(cx.as_ptr(), self.as_raw()) };
81        }
82    }
83}
84
85/// A borrowed reference to Servo's `JSPrincipals` instance. Does not update the
86/// reference count on creation and deletion.
87pub struct ServoJSPrincipalsRef<'a>(ManuallyDrop<ServoJSPrincipals>, PhantomData<&'a ()>);
88
89impl ServoJSPrincipalsRef<'_> {
90    /// Construct `Self` from a raw `NonNull<JSPrincipals>`.
91    ///
92    /// # Safety
93    ///
94    /// `ServoJSPrincipalsRef` does not update the reference count of the
95    /// wrapped `JSPrincipals` object. It's up to the caller to ensure the
96    /// returned `ServoJSPrincipalsRef` object or any clones are not used past
97    /// the lifetime of the wrapped object.
98    #[inline]
99    pub unsafe fn from_raw_nonnull(raw: NonNull<JSPrincipals>) -> Self {
100        // Don't use `ServoJSPrincipals::from_raw_nonnull`; we don't want to
101        // update the reference count
102        Self(ManuallyDrop::new(ServoJSPrincipals(raw)), PhantomData)
103    }
104
105    /// Construct `Self` from a raw `*mut JSPrincipals`.
106    ///
107    /// # Safety
108    ///
109    /// The behavior is undefined if `raw` is null. See also
110    /// [`Self::from_raw_nonnull`].
111    #[inline]
112    pub unsafe fn from_raw_unchecked(raw: *mut JSPrincipals) -> Self {
113        Self::from_raw_nonnull(NonNull::new_unchecked(raw))
114    }
115}
116
117impl Clone for ServoJSPrincipalsRef<'_> {
118    #[inline]
119    fn clone(&self) -> Self {
120        Self(ManuallyDrop::new(ServoJSPrincipals(self.0.0)), PhantomData)
121    }
122}
123
124impl Deref for ServoJSPrincipalsRef<'_> {
125    type Target = ServoJSPrincipals;
126
127    #[inline]
128    fn deref(&self) -> &Self::Target {
129        &self.0
130    }
131}