boa_engine/object/builtins/
jssharedarraybuffer.rs

1//! A Rust API wrapper for Boa's `SharedArrayBuffer` Builtin ECMAScript Object
2use crate::{
3    Context, JsResult, JsValue, builtins::array_buffer::SharedArrayBuffer, error::JsNativeError,
4    object::JsObject, value::TryFromJs,
5};
6use boa_gc::{Finalize, Trace};
7use std::{ops::Deref, sync::atomic::Ordering};
8
9/// `JsSharedArrayBuffer` provides a wrapper for Boa's implementation of the ECMAScript `ArrayBuffer` object
10#[derive(Debug, Clone, Trace, Finalize)]
11#[boa_gc(unsafe_no_drop)]
12pub struct JsSharedArrayBuffer {
13    inner: JsObject<SharedArrayBuffer>,
14}
15
16impl From<JsSharedArrayBuffer> for JsObject<SharedArrayBuffer> {
17    #[inline]
18    fn from(value: JsSharedArrayBuffer) -> Self {
19        value.inner
20    }
21}
22
23impl From<JsObject<SharedArrayBuffer>> for JsSharedArrayBuffer {
24    #[inline]
25    fn from(value: JsObject<SharedArrayBuffer>) -> Self {
26        JsSharedArrayBuffer { inner: value }
27    }
28}
29
30impl JsSharedArrayBuffer {
31    /// Creates a new [`JsSharedArrayBuffer`] with `byte_length` bytes of allocated space.
32    #[inline]
33    pub fn new(byte_length: usize, context: &mut Context) -> JsResult<Self> {
34        let inner = SharedArrayBuffer::allocate(
35            &context
36                .intrinsics()
37                .constructors()
38                .shared_array_buffer()
39                .constructor()
40                .into(),
41            byte_length as u64,
42            None,
43            context,
44        )?;
45
46        Ok(Self { inner })
47    }
48
49    /// Creates a [`JsSharedArrayBuffer`] from a shared raw buffer.
50    #[inline]
51    pub fn from_buffer(buffer: SharedArrayBuffer, context: &mut Context) -> Self {
52        let proto = context
53            .intrinsics()
54            .constructors()
55            .shared_array_buffer()
56            .prototype();
57
58        let inner = JsObject::new(context.root_shape(), proto, buffer);
59
60        Self { inner }
61    }
62
63    /// Creates a [`JsSharedArrayBuffer`] from a [`JsObject`], throwing a `TypeError` if the object
64    /// is not a shared array buffer.
65    ///
66    /// This does not clone the fields of the shared array buffer, it only does a shallow clone of
67    /// the object.
68    #[inline]
69    pub fn from_object(object: JsObject) -> JsResult<Self> {
70        object
71            .downcast::<SharedArrayBuffer>()
72            .map(|inner| Self { inner })
73            .map_err(|_| {
74                JsNativeError::typ()
75                    .with_message("object is not a SharedArrayBuffer")
76                    .into()
77            })
78    }
79
80    /// Returns the byte length of the array buffer.
81    #[inline]
82    #[must_use]
83    pub fn byte_length(&self) -> usize {
84        self.borrow().data().len(Ordering::SeqCst)
85    }
86
87    /// Gets the raw buffer of this `JsSharedArrayBuffer`.
88    #[inline]
89    #[must_use]
90    pub fn inner(&self) -> SharedArrayBuffer {
91        self.borrow().data().clone()
92    }
93}
94
95impl From<JsSharedArrayBuffer> for JsObject {
96    #[inline]
97    fn from(o: JsSharedArrayBuffer) -> Self {
98        o.inner.upcast()
99    }
100}
101
102impl From<JsSharedArrayBuffer> for JsValue {
103    #[inline]
104    fn from(o: JsSharedArrayBuffer) -> Self {
105        o.inner.upcast().into()
106    }
107}
108
109impl Deref for JsSharedArrayBuffer {
110    type Target = JsObject<SharedArrayBuffer>;
111
112    #[inline]
113    fn deref(&self) -> &Self::Target {
114        &self.inner
115    }
116}
117
118impl TryFromJs for JsSharedArrayBuffer {
119    fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
120        if let Some(o) = value.as_object() {
121            Self::from_object(o.clone())
122        } else {
123            Err(JsNativeError::typ()
124                .with_message("value is not a SharedArrayBuffer object")
125                .into())
126        }
127    }
128}