• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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