• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/ecma_vm.h"
20 #include "ecmascript/interpreter/interpreter.h"
21 #include "ecmascript/js_api/js_api_tree_set.h"
22 #include "ecmascript/js_api/js_api_tree_set_iterator.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     if (!key->IsString() && !key->IsNumber()) {
226         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
227         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
228         CString errorMsg =
229             "The type of \"key\" must be not null. Received value is: " + ConvertToString(*result);
230         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
231         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
232     }
233     JSHandle<TaggedTreeSet> tset(thread, set->GetTreeSet());
234     return TaggedTreeSet::GetLowerKey(thread, tset, key);
235 }
236 
GetHigherValue(EcmaRuntimeCallInfo * argv)237 JSTaggedValue ContainersTreeSet::GetHigherValue(EcmaRuntimeCallInfo *argv)
238 {
239     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetHigherValue);
240     JSThread *thread = argv->GetThread();
241     [[maybe_unused]] EcmaHandleScope handleScope(thread);
242     // get and check this set
243     JSHandle<JSTaggedValue> self(GetThis(argv));
244     if (!self->IsJSAPITreeSet()) {
245         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
246             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
247         } else {
248             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
249                                                                 "The getHigherValue method cannot be bound");
250             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
251         }
252     }
253 
254     JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
255     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
256     if (!key->IsString() && !key->IsNumber()) {
257         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
258         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
259         CString errorMsg =
260             "The type of \"key\" must be not null. Received value is: " + ConvertToString(*result);
261         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
262         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
263     }
264     JSHandle<TaggedTreeSet> tset(thread, set->GetTreeSet());
265     return TaggedTreeSet::GetHigherKey(thread, tset, key);
266 }
267 
PopFirst(EcmaRuntimeCallInfo * argv)268 JSTaggedValue ContainersTreeSet::PopFirst(EcmaRuntimeCallInfo *argv)
269 {
270     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, PopFirst);
271     JSThread *thread = argv->GetThread();
272     [[maybe_unused]] EcmaHandleScope handleScope(thread);
273     // get and check this set
274     JSHandle<JSTaggedValue> self(GetThis(argv));
275     if (!self->IsJSAPITreeSet()) {
276         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
277             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
278         } else {
279             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
280                                                                 "The popFirst method cannot be bound");
281             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
282         }
283     }
284 
285     JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
286     return JSAPITreeSet::PopFirst(thread, set);
287 }
288 
PopLast(EcmaRuntimeCallInfo * argv)289 JSTaggedValue ContainersTreeSet::PopLast(EcmaRuntimeCallInfo *argv)
290 {
291     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, PopLast);
292     JSThread *thread = argv->GetThread();
293     [[maybe_unused]] EcmaHandleScope handleScope(thread);
294     // get and check this set
295     JSHandle<JSTaggedValue> self(GetThis(argv));
296     if (!self->IsJSAPITreeSet()) {
297         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
298             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
299         } else {
300             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
301                                                                 "The popLast method cannot be bound");
302             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
303         }
304     }
305 
306     JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
307     return JSAPITreeSet::PopLast(thread, set);
308 }
309 
IsEmpty(EcmaRuntimeCallInfo * argv)310 JSTaggedValue ContainersTreeSet::IsEmpty(EcmaRuntimeCallInfo *argv)
311 {
312     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, IsEmpty);
313     JSThread *thread = argv->GetThread();
314     [[maybe_unused]] EcmaHandleScope handleScope(thread);
315     // get and check this set
316     JSHandle<JSTaggedValue> self = GetThis(argv);
317     if (!self->IsJSAPITreeSet()) {
318         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
319             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
320         } else {
321             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
322                                                                 "The isEmpty method cannot be bound");
323             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
324         }
325     }
326     JSHandle<JSAPITreeSet> set = JSHandle<JSAPITreeSet>::Cast(self);
327     return GetTaggedBoolean(set->GetSize() == 0);
328 }
329 
Values(EcmaRuntimeCallInfo * argv)330 JSTaggedValue ContainersTreeSet::Values(EcmaRuntimeCallInfo *argv)
331 {
332     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Values);
333     JSThread *thread = argv->GetThread();
334     [[maybe_unused]] EcmaHandleScope handleScope(thread);
335     JSHandle<JSTaggedValue> self = GetThis(argv);
336     JSHandle<JSTaggedValue> iter = JSAPITreeSetIterator::CreateTreeSetIterator(thread, self, IterationKind::KEY);
337     return iter.GetTaggedValue();
338 }
339 
Entries(EcmaRuntimeCallInfo * argv)340 JSTaggedValue ContainersTreeSet::Entries(EcmaRuntimeCallInfo *argv)
341 {
342     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, Entries);
343     JSThread *thread = argv->GetThread();
344     [[maybe_unused]] EcmaHandleScope handleScope(thread);
345     JSHandle<JSTaggedValue> self = GetThis(argv);
346     JSHandle<JSTaggedValue> iter =
347         JSAPITreeSetIterator::CreateTreeSetIterator(thread, self, IterationKind::KEY_AND_VALUE);
348     return iter.GetTaggedValue();
349 }
350 
ForEach(EcmaRuntimeCallInfo * argv)351 JSTaggedValue ContainersTreeSet::ForEach(EcmaRuntimeCallInfo *argv)
352 {
353     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, ForEach);
354     JSThread *thread = argv->GetThread();
355     [[maybe_unused]] EcmaHandleScope handleScope(thread);
356     // get and check TreeSet object
357     JSHandle<JSTaggedValue> self = GetThis(argv);
358     if (!self->IsJSAPITreeSet()) {
359         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
360             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
361         } else {
362             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
363                                                                 "The forEach method cannot be bound");
364             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
365         }
366     }
367     // get and check callback function
368     JSHandle<JSTaggedValue> func(GetCallArg(argv, 0));
369     if (!func->IsCallable()) {
370         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, func.GetTaggedValue());
371         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
372         CString errorMsg =
373             "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
374         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
375         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
376     }
377     // If thisArg was supplied, let T be thisArg; else let T be undefined.
378     JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 1);
379     JSHandle<JSAPITreeSet> tset = JSHandle<JSAPITreeSet>::Cast(self);
380     JSMutableHandle<TaggedTreeSet> iteratedSet(thread, tset->GetTreeSet());
381     uint32_t elements = iteratedSet->NumberOfElements();
382     JSHandle<TaggedArray> entries = TaggedTreeSet::GetArrayFromSet(thread, iteratedSet);
383     uint32_t index = 0;
384     size_t length = entries->GetLength();
385     const uint32_t argsLength = 3;
386     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
387     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
388     while (index < elements) {
389         int entriesIndex = entries->Get(index).GetInt();
390         key.Update(iteratedSet->GetKey(entriesIndex));
391         // Let funcResult be Call(callbackfn, T, «e, e, S»).
392         EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength);
393         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
394         info->SetCallArg(key.GetTaggedValue(), key.GetTaggedValue(), self.GetTaggedValue());
395         JSTaggedValue ret = JSFunction::Call(info);
396         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ret);
397         // check entries should be update, size will be update by set add and remove.
398         if (tset->GetSize() != static_cast<int>(length)) {
399             iteratedSet.Update(tset->GetTreeSet());
400             entries = TaggedTreeSet::GetArrayFromSet(thread, iteratedSet);
401             elements = iteratedSet->NumberOfElements();
402             length = entries->GetLength();
403         }
404         index++;
405     }
406     return JSTaggedValue::Undefined();
407 }
408 
GetLength(EcmaRuntimeCallInfo * argv)409 JSTaggedValue ContainersTreeSet::GetLength(EcmaRuntimeCallInfo *argv)
410 {
411     ASSERT(argv);
412     BUILTINS_API_TRACE(argv->GetThread(), TreeSet, GetLength);
413     JSThread *thread = argv->GetThread();
414     [[maybe_unused]] EcmaHandleScope handleScope(thread);
415     // get and check this set
416     JSHandle<JSTaggedValue> self(GetThis(argv));
417     if (!self->IsJSAPITreeSet()) {
418         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPITreeSet()) {
419             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
420         } else {
421             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
422                                                                 "The getLength method cannot be bound");
423             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
424         }
425     }
426 
427     int count = JSHandle<JSAPITreeSet>::Cast(self)->GetSize();
428     return JSTaggedValue(count);
429 }
430 }  // namespace panda::ecmascript::containers
431