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}