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