1 /*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/containers/containers_treeset.h"
17
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_api/js_api_tree_set.h"
21 #include "ecmascript/js_api/js_api_tree_set_iterator.h"
22 #include "ecmascript/js_function.h"
23 #include "ecmascript/object_factory.h"
24 #include "ecmascript/tagged_array-inl.h"
25 #include "ecmascript/tagged_tree.h"
26
27 namespace panda::ecmascript::containers {
TreeSetConstructor(EcmaRuntimeCallInfo * argv)28 JSTaggedValue ContainersTreeSet::TreeSetConstructor(EcmaRuntimeCallInfo *argv)
29 {
30 ASSERT(argv);
31 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Constructor);
32 JSThread *thread = argv->GetThread();
33 [[maybe_unused]] EcmaHandleScope handleScope(thread);
34 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
35
36 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
37 if (newTarget->IsUndefined()) {
38 JSTaggedValue error =
39 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
40 "The TreeSet's constructor cannot be directly invoked");
41 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
42 }
43 // new TreeSet
44 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
45 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
46 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
47
48 // Set set’s internal slot with a new empty List.
49 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(obj);
50 JSTaggedValue internal = TaggedTreeSet::Create(thread);
51 set->SetTreeSet(thread, internal);
52
53 // If comparefn was supplied, let compare be comparefn; else let compare be hole.
54 JSHandle<JSTaggedValue> compareFn(GetCallArg(argv, 0));
55 if (compareFn->IsUndefined() || compareFn->IsNull()) {
56 return set.GetTaggedValue();
57 }
58 if (!compareFn->IsCallable()) {
59 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, compareFn.GetTaggedValue());
60 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
61 CString errorMsg =
62 "The type of \"comparefn\" must be callable. Received value is: " + ConvertToString(*result);
63 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
64 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
65 }
66
67 TaggedTreeSet::Cast(internal.GetTaggedObject())->SetCompare(thread, compareFn.GetTaggedValue());
68 return set.GetTaggedValue();
69 }
70
Add(EcmaRuntimeCallInfo * argv)71 JSTaggedValue ContainersTreeSet::Add(EcmaRuntimeCallInfo *argv)
72 {
73 ASSERT(argv);
74 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Add);
75 JSThread *thread = argv->GetThread();
76 [[maybe_unused]] EcmaHandleScope handleScope(thread);
77 // get and check this set
78 JSHandle<JSTaggedValue> self = GetThis(argv);
79 if (!self->IsJSAPITreeSet()) {
80 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
81 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
82 } else {
83 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
84 "The add method cannot be bound");
85 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
86 }
87 }
88
89 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
90 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
91 JSAPITreeSet::Add(thread, set, value);
92 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
93 return JSTaggedValue::True();
94 }
95
Remove(EcmaRuntimeCallInfo * argv)96 JSTaggedValue ContainersTreeSet::Remove(EcmaRuntimeCallInfo *argv)
97 {
98 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Remove);
99 JSThread *thread = argv->GetThread();
100 [[maybe_unused]] EcmaHandleScope handleScope(thread);
101 // get and check this set
102 JSHandle<JSTaggedValue> self = GetThis(argv);
103 if (!self->IsJSAPITreeSet()) {
104 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
105 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
106 } else {
107 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
108 "The remove method cannot be bound");
109 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
110 }
111 }
112
113 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
114 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
115 return GetTaggedBoolean(JSAPITreeSet::Delete(thread, set, key));
116 }
117
Has(EcmaRuntimeCallInfo * argv)118 JSTaggedValue ContainersTreeSet::Has(EcmaRuntimeCallInfo *argv)
119 {
120 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Has);
121 JSThread *thread = argv->GetThread();
122 [[maybe_unused]] EcmaHandleScope handleScope(thread);
123 // get and check this set
124 JSHandle<JSTaggedValue> self(GetThis(argv));
125 if (!self->IsJSAPITreeSet()) {
126 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
127 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
128 } else {
129 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
130 "The has method cannot be bound");
131 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
132 }
133 }
134
135 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
136 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
137
138 bool flag = JSAPITreeSet::Has(thread, JSHandle<JSAPITreeSet>::Cast(set), key);
139 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
140 return GetTaggedBoolean(flag);
141 }
142
GetFirstValue(EcmaRuntimeCallInfo * argv)143 JSTaggedValue ContainersTreeSet::GetFirstValue(EcmaRuntimeCallInfo *argv)
144 {
145 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetFirstValue);
146 JSThread *thread = argv->GetThread();
147 [[maybe_unused]] EcmaHandleScope handleScope(thread);
148 // get and check this set
149 JSHandle<JSTaggedValue> self(GetThis(argv));
150 if (!self->IsJSAPITreeSet()) {
151 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
152 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
153 } else {
154 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
155 "The getFirstValue method cannot be bound");
156 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
157 }
158 }
159
160 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
161 return TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())->GetFirstKey();
162 }
163
GetLastValue(EcmaRuntimeCallInfo * argv)164 JSTaggedValue ContainersTreeSet::GetLastValue(EcmaRuntimeCallInfo *argv)
165 {
166 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetLastValue);
167 JSThread *thread = argv->GetThread();
168 [[maybe_unused]] EcmaHandleScope handleScope(thread);
169 // get and check this set
170 JSHandle<JSTaggedValue> self(GetThis(argv));
171 if (!self->IsJSAPITreeSet()) {
172 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
173 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
174 } else {
175 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
176 "The getLastValue method cannot be bound");
177 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
178 }
179 }
180
181 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
182 return TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())->GetLastKey();
183 }
184
Clear(EcmaRuntimeCallInfo * argv)185 JSTaggedValue ContainersTreeSet::Clear(EcmaRuntimeCallInfo *argv)
186 {
187 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Clear);
188 JSThread *thread = argv->GetThread();
189 [[maybe_unused]] EcmaHandleScope handleScope(thread);
190 // get and check this set
191 JSHandle<JSTaggedValue> self(GetThis(argv));
192 if (!self->IsJSAPITreeSet()) {
193 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
194 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
195 } else {
196 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
197 "The clear method cannot be bound");
198 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
199 }
200 }
201
202 JSAPITreeSet::Clear(thread, JSHandle<JSAPITreeSet>::Cast(self));
203 return JSTaggedValue::Undefined();
204 }
205
GetLowerValue(EcmaRuntimeCallInfo * argv)206 JSTaggedValue ContainersTreeSet::GetLowerValue(EcmaRuntimeCallInfo *argv)
207 {
208 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetLowerValue);
209 JSThread *thread = argv->GetThread();
210 [[maybe_unused]] EcmaHandleScope handleScope(thread);
211 // get and check this set
212 JSHandle<JSTaggedValue> self(GetThis(argv));
213 if (!self->IsJSAPITreeSet()) {
214 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
215 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
216 } else {
217 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
218 "The getLowerValue method cannot be bound");
219 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
220 }
221 }
222
223 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
224 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
225 JSHandle<TaggedTreeSet> tset(thread, set->GetTreeSet());
226 return TaggedTreeSet::GetLowerKey(thread, tset, key);
227 }
228
GetHigherValue(EcmaRuntimeCallInfo * argv)229 JSTaggedValue ContainersTreeSet::GetHigherValue(EcmaRuntimeCallInfo *argv)
230 {
231 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetHigherValue);
232 JSThread *thread = argv->GetThread();
233 [[maybe_unused]] EcmaHandleScope handleScope(thread);
234 // get and check this set
235 JSHandle<JSTaggedValue> self(GetThis(argv));
236 if (!self->IsJSAPITreeSet()) {
237 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
238 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
239 } else {
240 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
241 "The getHigherValue method cannot be bound");
242 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
243 }
244 }
245
246 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
247 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
248 JSHandle<TaggedTreeSet> tset(thread, set->GetTreeSet());
249 return TaggedTreeSet::GetHigherKey(thread, tset, key);
250 }
251
PopFirst(EcmaRuntimeCallInfo * argv)252 JSTaggedValue ContainersTreeSet::PopFirst(EcmaRuntimeCallInfo *argv)
253 {
254 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, PopFirst);
255 JSThread *thread = argv->GetThread();
256 [[maybe_unused]] EcmaHandleScope handleScope(thread);
257 // get and check this set
258 JSHandle<JSTaggedValue> self(GetThis(argv));
259 if (!self->IsJSAPITreeSet()) {
260 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
261 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
262 } else {
263 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
264 "The popFirst method cannot be bound");
265 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
266 }
267 }
268
269 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
270 return JSAPITreeSet::PopFirst(thread, set);
271 }
272
PopLast(EcmaRuntimeCallInfo * argv)273 JSTaggedValue ContainersTreeSet::PopLast(EcmaRuntimeCallInfo *argv)
274 {
275 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, PopLast);
276 JSThread *thread = argv->GetThread();
277 [[maybe_unused]] EcmaHandleScope handleScope(thread);
278 // get and check this set
279 JSHandle<JSTaggedValue> self(GetThis(argv));
280 if (!self->IsJSAPITreeSet()) {
281 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
282 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
283 } else {
284 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
285 "The popLast method cannot be bound");
286 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
287 }
288 }
289
290 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
291 return JSAPITreeSet::PopLast(thread, set);
292 }
293
IsEmpty(EcmaRuntimeCallInfo * argv)294 JSTaggedValue ContainersTreeSet::IsEmpty(EcmaRuntimeCallInfo *argv)
295 {
296 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, IsEmpty);
297 JSThread *thread = argv->GetThread();
298 [[maybe_unused]] EcmaHandleScope handleScope(thread);
299 // get and check this set
300 JSHandle<JSTaggedValue> self = GetThis(argv);
301 if (!self->IsJSAPITreeSet()) {
302 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
303 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
304 } else {
305 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
306 "The isEmpty method cannot be bound");
307 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
308 }
309 }
310 JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
311 return GetTaggedBoolean(set->GetSize() == 0);
312 }
313
Values(EcmaRuntimeCallInfo * argv)314 JSTaggedValue ContainersTreeSet::Values(EcmaRuntimeCallInfo *argv)
315 {
316 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Values);
317 JSThread *thread = argv->GetThread();
318 [[maybe_unused]] EcmaHandleScope handleScope(thread);
319 JSHandle<JSTaggedValue> self = GetThis(argv);
320 JSHandle<JSTaggedValue> iter = JSAPITreeSetIterator::CreateTreeSetIterator(thread, self, IterationKind::KEY);
321 return iter.GetTaggedValue();
322 }
323
Entries(EcmaRuntimeCallInfo * argv)324 JSTaggedValue ContainersTreeSet::Entries(EcmaRuntimeCallInfo *argv)
325 {
326 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Entries);
327 JSThread *thread = argv->GetThread();
328 [[maybe_unused]] EcmaHandleScope handleScope(thread);
329 JSHandle<JSTaggedValue> self = GetThis(argv);
330 JSHandle<JSTaggedValue> iter =
331 JSAPITreeSetIterator::CreateTreeSetIterator(thread, self, IterationKind::KEY_AND_VALUE);
332 return iter.GetTaggedValue();
333 }
334
ForEach(EcmaRuntimeCallInfo * argv)335 JSTaggedValue ContainersTreeSet::ForEach(EcmaRuntimeCallInfo *argv)
336 {
337 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, ForEach);
338 JSThread *thread = argv->GetThread();
339 [[maybe_unused]] EcmaHandleScope handleScope(thread);
340 // get and check TreeSet object
341 JSHandle<JSTaggedValue> self = GetThis(argv);
342 if (!self->IsJSAPITreeSet()) {
343 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
344 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
345 } else {
346 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
347 "The forEach method cannot be bound");
348 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
349 }
350 }
351 // get and check callback function
352 JSHandle<JSTaggedValue> func(GetCallArg(argv, 0));
353 if (!func->IsCallable()) {
354 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, func.GetTaggedValue());
355 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
356 CString errorMsg =
357 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
358 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
359 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
360 }
361 // If thisArg was supplied, let T be thisArg; else let T be undefined.
362 JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 1);
363 JSHandle<JSAPITreeSet> tset = JSHandle<JSAPITreeSet>::Cast(self);
364 JSMutableHandle<TaggedTreeSet> iteratedSet(thread, tset->GetTreeSet());
365 uint32_t elements = iteratedSet->NumberOfElements();
366 JSHandle<TaggedArray> entries = TaggedTreeSet::GetArrayFromSet(thread, iteratedSet);
367 uint32_t index = 0;
368 size_t length = entries->GetLength();
369 const uint32_t argsLength = 3;
370 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
371 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
372 while (index < elements) {
373 int entriesIndex = entries->Get(index).GetInt();
374 key.Update(iteratedSet->GetKey(entriesIndex));
375 // Let funcResult be Call(callbackfn, T, «e, e, S»).
376 EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength);
377 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
378 info->SetCallArg(key.GetTaggedValue(), key.GetTaggedValue(), self.GetTaggedValue());
379 JSTaggedValue ret = JSFunction::Call(info);
380 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ret);
381 // check entries should be update, size will be update by set add and remove.
382 if (tset->GetSize() != static_cast<int>(length)) {
383 iteratedSet.Update(tset->GetTreeSet());
384 entries = TaggedTreeSet::GetArrayFromSet(thread, iteratedSet);
385 elements = iteratedSet->NumberOfElements();
386 length = entries->GetLength();
387 }
388 index++;
389 }
390 return JSTaggedValue::Undefined();
391 }
392
GetLength(EcmaRuntimeCallInfo * argv)393 JSTaggedValue ContainersTreeSet::GetLength(EcmaRuntimeCallInfo *argv)
394 {
395 ASSERT(argv);
396 BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetLength);
397 JSThread *thread = argv->GetThread();
398 [[maybe_unused]] EcmaHandleScope handleScope(thread);
399 // get and check this set
400 JSHandle<JSTaggedValue> self(GetThis(argv));
401 if (!self->IsJSAPITreeSet()) {
402 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
403 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
404 } else {
405 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
406 "The getLength method cannot be bound");
407 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
408 }
409 }
410
411 int count = JSHandle<JSAPITreeSet>::Cast(self)->GetSize();
412 return JSTaggedValue(count);
413 }
414 } // namespace panda::ecmascript::containers
415