boa_engine/object/builtins/
jsset.rs1use std::ops::Deref;
3
4use boa_gc::{Finalize, Trace};
5
6use crate::{
7 builtins::{iterable::IteratorHint, set::ordered_set::OrderedSet, Set},
8 error::JsNativeError,
9 object::{JsFunction, JsObject, JsSetIterator},
10 value::TryFromJs,
11 Context, JsResult, JsValue,
12};
13
14#[derive(Debug, Clone, Trace, Finalize)]
16pub struct JsSet {
17 inner: JsObject,
18}
19
20impl JsSet {
21 #[inline]
26 pub fn new(context: &mut Context) -> Self {
27 let inner = Set::set_create(None, context);
28
29 Self { inner }
30 }
31
32 #[inline]
36 pub fn size(&self) -> JsResult<usize> {
37 Set::get_size(&self.inner.clone().into())
38 }
39
40 pub fn add<T>(&self, value: T, context: &mut Context) -> JsResult<JsValue>
45 where
46 T: Into<JsValue>,
47 {
48 self.add_items(&[value.into()], context)
49 }
50
51 #[inline]
56 pub fn add_items(&self, items: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
57 Set::add(&self.inner.clone().into(), items, context)
58 }
59
60 #[inline]
65 pub fn clear(&self, context: &mut Context) -> JsResult<JsValue> {
66 Set::clear(&self.inner.clone().into(), &[JsValue::Null], context)
67 }
68
69 pub fn delete<T>(&self, value: T, context: &mut Context) -> JsResult<bool>
75 where
76 T: Into<JsValue>,
77 {
78 match Set::delete(&self.inner.clone().into(), &[value.into()], context)? {
80 JsValue::Boolean(bool) => Ok(bool),
81 _ => unreachable!("`delete` must always return a bool"),
82 }
83 }
84
85 pub fn has<T>(&self, value: T, context: &mut Context) -> JsResult<bool>
90 where
91 T: Into<JsValue>,
92 {
93 match Set::has(&self.inner.clone().into(), &[value.into()], context)? {
95 JsValue::Boolean(bool) => Ok(bool),
96 _ => unreachable!("`has` must always return a bool"),
97 }
98 }
99
100 #[inline]
105 pub fn values(&self, context: &mut Context) -> JsResult<JsSetIterator> {
106 let iterator_object = Set::values(&self.inner.clone().into(), &[JsValue::Null], context)?
107 .get_iterator(IteratorHint::Sync, context)?;
108
109 JsSetIterator::from_object(iterator_object.iterator().clone())
110 }
111
112 #[inline]
118 pub fn keys(&self, context: &mut Context) -> JsResult<JsSetIterator> {
119 let iterator_object = Set::values(&self.inner.clone().into(), &[JsValue::Null], context)?
120 .get_iterator(IteratorHint::Sync, context)?;
121
122 JsSetIterator::from_object(iterator_object.iterator().clone())
123 }
124
125 #[inline]
131 pub fn for_each(
132 &self,
133 callback: JsFunction,
134 this_arg: JsValue,
135 context: &mut Context,
136 ) -> JsResult<JsValue> {
137 Set::for_each(
138 &self.inner.clone().into(),
139 &[callback.into(), this_arg],
140 context,
141 )
142 }
143
144 #[inline]
146 pub fn from_object(object: JsObject) -> JsResult<Self> {
147 if object.is::<OrderedSet>() {
148 Ok(Self { inner: object })
149 } else {
150 Err(JsNativeError::typ()
151 .with_message("Object is not a Set")
152 .into())
153 }
154 }
155
156 pub fn from_iter<I>(elements: I, context: &mut Context) -> Self
158 where
159 I: IntoIterator<Item = JsValue>,
160 {
161 let inner = Set::create_set_from_list(elements, context);
162 Self { inner }
163 }
164}
165
166impl From<JsSet> for JsObject {
167 #[inline]
168 fn from(o: JsSet) -> Self {
169 o.inner.clone()
170 }
171}
172
173impl From<JsSet> for JsValue {
174 #[inline]
175 fn from(o: JsSet) -> Self {
176 o.inner.clone().into()
177 }
178}
179
180impl Deref for JsSet {
181 type Target = JsObject;
182 #[inline]
183 fn deref(&self) -> &Self::Target {
184 &self.inner
185 }
186}
187
188impl TryFromJs for JsSet {
189 fn try_from_js(value: &JsValue, _context: &mut Context) -> JsResult<Self> {
190 match value {
191 JsValue::Object(o) => Self::from_object(o.clone()),
192 _ => Err(JsNativeError::typ()
193 .with_message("value is not a Set object")
194 .into()),
195 }
196 }
197}