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