Skip to main content

boa_engine/object/builtins/
jsweakmap.rs

1//! A Rust API wrapper for the `WeakMap` Builtin ECMAScript Object
2use std::ops::Deref;
3
4use boa_gc::{Finalize, Trace};
5
6use crate::{
7    Context, JsResult, JsValue,
8    builtins::weak_map::{NativeWeakMap, WeakMap},
9    error::JsNativeError,
10    object::JsObject,
11    value::TryFromJs,
12};
13
14/// `JsWeakMap` provides a wrapper for Boa's implementation of the ECMAScript `WeakMap` object.
15#[derive(Debug, Clone, Trace, Finalize)]
16pub struct JsWeakMap {
17    inner: JsObject,
18}
19
20impl JsWeakMap {
21    /// Creates a new empty `WeakMap`.
22    ///
23    /// More information:
24    ///  - [MDN documentation][mdn]
25    ///
26    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/WeakMap
27    #[inline]
28    pub fn new(context: &mut Context) -> Self {
29        Self {
30            inner: JsObject::from_proto_and_data_with_shared_shape(
31                context.root_shape(),
32                context.intrinsics().constructors().weak_map().prototype(),
33                NativeWeakMap::new(),
34            )
35            .upcast(),
36        }
37    }
38
39    /// Returns the value associated with the specified key in the `WeakMap`,
40    /// or `undefined` if the key is not present.
41    ///
42    /// More information:
43    ///  - [MDN documentation][mdn]
44    ///
45    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/get
46    #[inline]
47    pub fn get(&self, key: &JsObject, context: &mut Context) -> JsResult<JsValue> {
48        WeakMap::get(&self.inner.clone().into(), &[key.clone().into()], context)
49    }
50
51    /// Inserts a key-value pair into the `WeakMap`.
52    ///
53    /// More information:
54    ///  - [MDN documentation][mdn]
55    ///
56    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/set
57    #[inline]
58    pub fn set(&self, key: &JsObject, value: JsValue, context: &mut Context) -> JsResult<JsValue> {
59        WeakMap::set(
60            &self.inner.clone().into(),
61            &[key.clone().into(), value],
62            context,
63        )
64    }
65
66    /// Returns `true` if the specified key exists in the `WeakMap`.
67    ///
68    /// More information:
69    ///  - [MDN documentation][mdn]
70    ///
71    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/has
72    #[inline]
73    pub fn has(&self, key: &JsObject, context: &mut Context) -> JsResult<bool> {
74        WeakMap::has(&self.inner.clone().into(), &[key.clone().into()], context)
75            .map(|v| v.as_boolean().unwrap_or(false))
76    }
77
78    /// Removes the element associated with the specified key.
79    /// Returns `true` if the element existed, `false` otherwise.
80    ///
81    /// More information:
82    ///  - [MDN documentation][mdn]
83    ///
84    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/delete
85    #[inline]
86    pub fn delete(&self, key: &JsObject, context: &mut Context) -> JsResult<bool> {
87        WeakMap::delete(&self.inner.clone().into(), &[key.clone().into()], context)
88            .map(|v| v.as_boolean().unwrap_or(false))
89    }
90
91    /// Returns the value associated with the key if it exists; otherwise inserts
92    /// the provided default value and returns it.
93    ///
94    /// More information:
95    ///  - [MDN documentation][mdn]
96    ///
97    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/getOrInsert
98    #[inline]
99    pub fn get_or_insert(
100        &self,
101        key: &JsObject,
102        default: JsValue,
103        context: &mut Context,
104    ) -> JsResult<JsValue> {
105        WeakMap::get_or_insert(
106            &self.inner.clone().into(),
107            &[key.clone().into(), default],
108            context,
109        )
110    }
111
112    /// Returns the value associated with the key if it exists; otherwise calls
113    /// the provided callback with the key, inserts the result, and returns it.
114    ///
115    /// More information:
116    ///  - [MDN documentation][mdn]
117    ///
118    /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap/getOrInsertComputed
119    #[inline]
120    pub fn get_or_insert_computed(
121        &self,
122        key: &JsObject,
123        callback: JsValue,
124        context: &mut Context,
125    ) -> JsResult<JsValue> {
126        WeakMap::get_or_insert_computed(
127            &self.inner.clone().into(),
128            &[key.clone().into(), callback],
129            context,
130        )
131    }
132
133    /// Creates a `JsWeakMap` from a `JsObject`, or returns the original object as `Err`
134    /// if it is not a `WeakMap`.
135    #[inline]
136    pub fn from_object(object: JsObject) -> Result<Self, JsObject> {
137        if object.downcast_ref::<NativeWeakMap>().is_some() {
138            Ok(Self { inner: object })
139        } else {
140            Err(object)
141        }
142    }
143}
144
145impl From<JsWeakMap> for JsObject {
146    #[inline]
147    fn from(o: JsWeakMap) -> Self {
148        o.inner.clone()
149    }
150}
151
152impl From<JsWeakMap> for JsValue {
153    #[inline]
154    fn from(o: JsWeakMap) -> Self {
155        o.inner.clone().into()
156    }
157}
158
159impl Deref for JsWeakMap {
160    type Target = JsObject;
161    #[inline]
162    fn deref(&self) -> &Self::Target {
163        &self.inner
164    }
165}
166
167impl TryFromJs for JsWeakMap {
168    fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
169        if let Some(o) = value.as_object()
170            && let Ok(weak_map) = Self::from_object(o.clone())
171        {
172            Ok(weak_map)
173        } else {
174            Err(JsNativeError::typ()
175                .with_message("value is not a WeakMap object")
176                .into())
177        }
178    }
179}