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