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