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_lightweightset.h"
17
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/js_api/js_api_lightweightset.h"
20 #include "ecmascript/js_api/js_api_lightweightset_iterator.h"
21 #include "ecmascript/js_array.h"
22
23 namespace panda::ecmascript::containers {
LightWeightSetConstructor(EcmaRuntimeCallInfo * argv)24 JSTaggedValue ContainersLightWeightSet::LightWeightSetConstructor(EcmaRuntimeCallInfo *argv)
25 {
26 ASSERT(argv != nullptr);
27 JSThread *thread = argv->GetThread();
28 BUILTINS_API_TRACE(thread, LightWeightSet, Constructor);
29 [[maybe_unused]] EcmaHandleScope handleScope(thread);
30 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
31 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
32 if (newTarget->IsUndefined()) {
33 JSTaggedValue error =
34 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
35 "The LightWeightSet's constructor cannot be directly invoked");
36 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
37 }
38 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
39 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
40 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
41 JSHandle<JSAPILightWeightSet> lightweightSet = JSHandle<JSAPILightWeightSet>::Cast(obj);
42
43 JSHandle<TaggedArray> hashes =
44 JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
45 JSHandle<TaggedArray> values =
46 JSAPILightWeightSet::CreateSlot(thread, JSAPILightWeightSet::DEFAULT_CAPACITY_LENGTH);
47 lightweightSet->SetHashes(thread, hashes);
48 lightweightSet->SetValues(thread, values);
49 return obj.GetTaggedValue();
50 }
51
Add(EcmaRuntimeCallInfo * argv)52 JSTaggedValue ContainersLightWeightSet::Add(EcmaRuntimeCallInfo *argv)
53 {
54 ASSERT(argv != nullptr);
55 JSThread *thread = argv->GetThread();
56 BUILTINS_API_TRACE(thread, LightWeightSet, Add);
57 [[maybe_unused]] EcmaHandleScope handleScope(thread);
58 JSHandle<JSTaggedValue> self = GetThis(argv);
59 if (!self->IsJSAPILightWeightSet()) {
60 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
61 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
62 } else {
63 JSTaggedValue error = ContainerError::BusinessError(thread, BIND_ERROR,
64 "The add method cannot be bound");
65 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
66 }
67 }
68 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
69 bool flag = JSAPILightWeightSet::Add(thread, JSHandle<JSAPILightWeightSet>::Cast(self), value);
70 return JSTaggedValue(flag);
71 }
72
AddAll(EcmaRuntimeCallInfo * argv)73 JSTaggedValue ContainersLightWeightSet::AddAll(EcmaRuntimeCallInfo *argv)
74 {
75 ASSERT(argv != nullptr);
76 JSThread *thread = argv->GetThread();
77 BUILTINS_API_TRACE(thread, LightWeightSet, AddAll);
78 [[maybe_unused]] EcmaHandleScope handleScope(thread);
79 JSHandle<JSTaggedValue> self = GetThis(argv);
80 if (!self->IsJSAPILightWeightSet()) {
81 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
82 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
83 } else {
84 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
85 "The addAll method cannot be bound");
86 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
87 }
88 }
89
90 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
91 if (!value->IsJSAPILightWeightSet()) {
92 if (value->IsJSProxy() && JSHandle<JSProxy>::Cast(value)->GetTarget().IsJSAPILightWeightSet()) {
93 value = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(value)->GetTarget());
94 } else {
95 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
96 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
97 CString errorMsg =
98 "The type of \"set\" must be LightWeightSet. Received value is: " + ConvertToString(*result);
99 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
100 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
101 }
102 }
103
104 return JSTaggedValue(JSAPILightWeightSet::AddAll(thread, JSHandle<JSAPILightWeightSet>::Cast(self), value));
105 }
106
IsEmpty(EcmaRuntimeCallInfo * argv)107 JSTaggedValue ContainersLightWeightSet::IsEmpty(EcmaRuntimeCallInfo *argv)
108 {
109 ASSERT(argv != nullptr);
110 JSThread *thread = argv->GetThread();
111 BUILTINS_API_TRACE(thread, LightWeightSet, IsEmpty);
112 [[maybe_unused]] EcmaHandleScope handleScope(thread);
113 JSHandle<JSTaggedValue> self = GetThis(argv);
114 if (!self->IsJSAPILightWeightSet()) {
115 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
116 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
117 } else {
118 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
119 "The isEmpty method cannot be bound");
120 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
121 }
122 }
123 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
124 return JSTaggedValue(set->IsEmpty());
125 }
126
GetValueAt(EcmaRuntimeCallInfo * argv)127 JSTaggedValue ContainersLightWeightSet::GetValueAt(EcmaRuntimeCallInfo *argv)
128 {
129 ASSERT(argv != nullptr);
130 JSThread *thread = argv->GetThread();
131 BUILTINS_API_TRACE(thread, LightWeightSet, GetValueAt);
132 [[maybe_unused]] EcmaHandleScope handleScope(thread);
133 JSHandle<JSTaggedValue> self = GetThis(argv);
134 if (!self->IsJSAPILightWeightSet()) {
135 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
136 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
137 } else {
138 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
139 "The getValueAt method cannot be bound");
140 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
141 }
142 }
143 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
144 if (value->IsDouble()) {
145 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble()));
146 }
147 if (!value->IsInt()) {
148 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
149 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
150 CString errorMsg =
151 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
152 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
153 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
154 }
155 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
156 return set->GetValueAt(value->GetInt());
157 }
158
HasAll(EcmaRuntimeCallInfo * argv)159 JSTaggedValue ContainersLightWeightSet::HasAll(EcmaRuntimeCallInfo *argv)
160 {
161 ASSERT(argv != nullptr);
162 JSThread *thread = argv->GetThread();
163 BUILTINS_API_TRACE(thread, LightWeightSet, HasAll);
164 [[maybe_unused]] EcmaHandleScope handleScope(thread);
165 JSHandle<JSTaggedValue> self = GetThis(argv);
166 if (!self->IsJSAPILightWeightSet()) {
167 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
168 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
169 } else {
170 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
171 "The hasAll method cannot be bound");
172 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
173 }
174 }
175 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
176 if (!value->IsJSAPILightWeightSet()) {
177 if (value->IsJSProxy() && JSHandle<JSProxy>::Cast(value)->GetTarget().IsJSAPILightWeightSet()) {
178 value = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(value)->GetTarget());
179 } else {
180 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
181 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
182 CString errorMsg =
183 "The type of \"set\" must be LightWeightSet. Received value is: " + ConvertToString(*result);
184 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
185 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
186 }
187 }
188 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
189 return JSTaggedValue(set->HasAll(value));
190 }
191
Has(EcmaRuntimeCallInfo * argv)192 JSTaggedValue ContainersLightWeightSet::Has(EcmaRuntimeCallInfo *argv)
193 {
194 ASSERT(argv != nullptr);
195 JSThread *thread = argv->GetThread();
196 BUILTINS_API_TRACE(thread, LightWeightSet, Has);
197 [[maybe_unused]] EcmaHandleScope handleScope(thread);
198 JSHandle<JSTaggedValue> self = GetThis(argv);
199 if (!self->IsJSAPILightWeightSet()) {
200 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
201 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
202 } else {
203 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
204 "The has method cannot be bound");
205 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
206 }
207 }
208 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
209 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
210 return JSTaggedValue(set->Has(thread, value));
211 }
212
HasHash(EcmaRuntimeCallInfo * argv)213 JSTaggedValue ContainersLightWeightSet::HasHash(EcmaRuntimeCallInfo *argv)
214 {
215 ASSERT(argv != nullptr);
216 JSThread *thread = argv->GetThread();
217 BUILTINS_API_TRACE(thread, LightWeightSet, HasHash);
218 [[maybe_unused]] EcmaHandleScope handleScope(thread);
219 JSHandle<JSTaggedValue> self = GetThis(argv);
220 if (!self->IsJSAPILightWeightSet()) {
221 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
222 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
223 } else {
224 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
225 "The hasHash method cannot be bound");
226 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
227 }
228 }
229 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
230 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
231 return JSTaggedValue(set->HasHash(value));
232 }
233
Equal(EcmaRuntimeCallInfo * argv)234 JSTaggedValue ContainersLightWeightSet::Equal(EcmaRuntimeCallInfo *argv)
235 {
236 ASSERT(argv != nullptr);
237 JSThread *thread = argv->GetThread();
238 BUILTINS_API_TRACE(thread, LightWeightSet, Equal);
239 [[maybe_unused]] EcmaHandleScope handleScope(thread);
240 JSHandle<JSTaggedValue> self = GetThis(argv);
241 if (!self->IsJSAPILightWeightSet()) {
242 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
243 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
244 } else {
245 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
246 "The equal method cannot be bound");
247 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
248 }
249 }
250 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
251 return JSTaggedValue(JSAPILightWeightSet::Equal(thread, JSHandle<JSAPILightWeightSet>::Cast(self), value));
252 }
253
IncreaseCapacityTo(EcmaRuntimeCallInfo * argv)254 JSTaggedValue ContainersLightWeightSet::IncreaseCapacityTo(EcmaRuntimeCallInfo *argv)
255 {
256 ASSERT(argv != nullptr);
257 JSThread *thread = argv->GetThread();
258 BUILTINS_API_TRACE(thread, LightWeightSet, IncreaseCapacityTo);
259 [[maybe_unused]] EcmaHandleScope handleScope(thread);
260 JSHandle<JSTaggedValue> self = GetThis(argv);
261 if (!self->IsJSAPILightWeightSet()) {
262 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
263 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
264 } else {
265 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
266 "The increaseCapacityTo method cannot be bound");
267 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
268 }
269 }
270 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
271
272 // for case like Math.foor(1.3), it gives double 1.0;
273 if (value->IsDouble()) {
274 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble()));
275 }
276
277 if (!value->IsInt()) {
278 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
279 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
280 CString errorMsg =
281 "The type of \"minimumCapacity\" must be small integer. Received value is: " + ConvertToString(*result);
282 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
283 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
284 }
285 int32_t minCapacity = value->GetInt();
286 JSAPILightWeightSet::IncreaseCapacityTo(thread, JSHandle<JSAPILightWeightSet>::Cast(self), minCapacity);
287 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
288 return JSTaggedValue::Undefined();
289 }
290
GetIteratorObj(EcmaRuntimeCallInfo * argv)291 JSTaggedValue ContainersLightWeightSet::GetIteratorObj(EcmaRuntimeCallInfo *argv)
292 {
293 ASSERT(argv != nullptr);
294 JSThread *thread = argv->GetThread();
295 BUILTINS_API_TRACE(thread, LightWeightSet, GetIteratorObj);
296 [[maybe_unused]] EcmaHandleScope handleScope(thread);
297 JSHandle<JSTaggedValue> self = GetThis(argv);
298 if (!self->IsJSAPILightWeightSet()) {
299 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
300 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
301 } else {
302 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
303 "The Symbol.iterator method cannot be bound");
304 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
305 }
306 }
307 JSHandle<JSTaggedValue> iter =
308 JSAPILightWeightSet::GetIteratorObj(thread, JSHandle<JSAPILightWeightSet>::Cast(self), IterationKind::VALUE);
309 return iter.GetTaggedValue();
310 }
311
Values(EcmaRuntimeCallInfo * argv)312 JSTaggedValue ContainersLightWeightSet::Values(EcmaRuntimeCallInfo *argv)
313 {
314 ASSERT(argv != nullptr);
315 JSThread *thread = argv->GetThread();
316 BUILTINS_API_TRACE(thread, LightWeightSet, Values);
317 [[maybe_unused]] EcmaHandleScope handleScope(thread);
318 JSHandle<JSTaggedValue> self = GetThis(argv);
319 if (!self->IsJSAPILightWeightSet()) {
320 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
321 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
322 } else {
323 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
324 "The values method cannot be bound");
325 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
326 }
327 }
328 JSHandle<JSTaggedValue> iter =
329 JSAPILightWeightSet::GetIteratorObj(thread, JSHandle<JSAPILightWeightSet>::Cast(self), IterationKind::VALUE);
330 return iter.GetTaggedValue();
331 }
332
Entries(EcmaRuntimeCallInfo * argv)333 JSTaggedValue ContainersLightWeightSet::Entries(EcmaRuntimeCallInfo *argv)
334 {
335 ASSERT(argv != nullptr);
336 JSThread *thread = argv->GetThread();
337 BUILTINS_API_TRACE(thread, LightWeightSet, Entries);
338 [[maybe_unused]] EcmaHandleScope handleScope(thread);
339 JSHandle<JSTaggedValue> self = GetThis(argv);
340 if (!self->IsJSAPILightWeightSet()) {
341 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
342 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
343 } else {
344 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
345 "The entries method cannot be bound");
346 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
347 }
348 }
349 JSHandle<JSTaggedValue> iter =
350 JSAPILightWeightSet::GetIteratorObj(thread, JSHandle<JSAPILightWeightSet>::Cast(self),
351 IterationKind::KEY_AND_VALUE);
352 return iter.GetTaggedValue();
353 }
354
ForEach(EcmaRuntimeCallInfo * argv)355 JSTaggedValue ContainersLightWeightSet::ForEach(EcmaRuntimeCallInfo *argv)
356 {
357 ASSERT(argv != nullptr);
358 JSThread *thread = argv->GetThread();
359 BUILTINS_API_TRACE(thread, LightWeightSet, ForEach);
360 [[maybe_unused]] EcmaHandleScope handleScope(thread);
361 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
362 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
363
364 if (!thisHandle->IsJSAPILightWeightSet()) {
365 if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPILightWeightSet()) {
366 thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
367 } else {
368 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
369 "The forEach method cannot be bound");
370 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
371 }
372 }
373
374 if (!callbackFnHandle->IsCallable()) {
375 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue());
376 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
377 CString errorMsg =
378 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
379 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
380 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
381 }
382 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
383 return JSAPILightWeightSet::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle);
384 }
385
GetIndexOf(EcmaRuntimeCallInfo * argv)386 JSTaggedValue ContainersLightWeightSet::GetIndexOf(EcmaRuntimeCallInfo *argv)
387 {
388 ASSERT(argv != nullptr);
389 JSThread *thread = argv->GetThread();
390 BUILTINS_API_TRACE(thread, LightWeightSet, GetIndexOf);
391 [[maybe_unused]] EcmaHandleScope handleScope(thread);
392 JSHandle<JSTaggedValue> self = GetThis(argv);
393 if (!self->IsJSAPILightWeightSet()) {
394 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
395 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
396 } else {
397 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
398 "The getIndexOf method cannot be bound");
399 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
400 }
401 }
402 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
403 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
404 int32_t result = set->GetIndexOf(thread, value);
405 return JSTaggedValue(result);
406 }
407
Remove(EcmaRuntimeCallInfo * argv)408 JSTaggedValue ContainersLightWeightSet::Remove(EcmaRuntimeCallInfo *argv)
409 {
410 ASSERT(argv != nullptr);
411 JSThread *thread = argv->GetThread();
412 BUILTINS_API_TRACE(thread, LightWeightSet, Remove);
413 [[maybe_unused]] EcmaHandleScope handleScope(thread);
414 JSHandle<JSTaggedValue> self = GetThis(argv);
415 if (!self->IsJSAPILightWeightSet()) {
416 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
417 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
418 } else {
419 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
420 "The remove method cannot be bound");
421 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
422 }
423 }
424 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
425 JSHandle<JSAPILightWeightSet> lightweightset(self);
426 JSAPILightWeightSet::CheckAndCopyValues(thread, lightweightset);
427 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(lightweightset.GetTaggedValue().GetTaggedObject());
428 return set->Remove(thread, key);
429 }
430
RemoveAt(EcmaRuntimeCallInfo * argv)431 JSTaggedValue ContainersLightWeightSet::RemoveAt(EcmaRuntimeCallInfo *argv)
432 {
433 ASSERT(argv != nullptr);
434 JSThread *thread = argv->GetThread();
435 BUILTINS_API_TRACE(thread, LightWeightSet, RemoveAt);
436 [[maybe_unused]] EcmaHandleScope handleScope(thread);
437 JSHandle<JSTaggedValue> self = GetThis(argv);
438 if (!self->IsJSAPILightWeightSet()) {
439 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
440 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
441 } else {
442 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
443 "The removeAt method cannot be bound");
444 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
445 }
446 }
447 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
448 if (value->IsDouble()) {
449 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble()));
450 }
451 if (!value->IsInt()) {
452 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
453 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
454 CString errorMsg =
455 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
456 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
457 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
458 }
459 JSHandle<JSAPILightWeightSet> lightweightset(self);
460 JSAPILightWeightSet::CheckAndCopyValues(thread, lightweightset);
461 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(lightweightset.GetTaggedValue().GetTaggedObject());
462 return JSTaggedValue(set->RemoveAt(thread, value->GetInt()));
463 }
464
Clear(EcmaRuntimeCallInfo * argv)465 JSTaggedValue ContainersLightWeightSet::Clear(EcmaRuntimeCallInfo *argv)
466 {
467 ASSERT(argv != nullptr);
468 JSThread *thread = argv->GetThread();
469 BUILTINS_API_TRACE(thread, LightWeightSet, Clear);
470 [[maybe_unused]] EcmaHandleScope handleScope(thread);
471 JSHandle<JSTaggedValue> self = GetThis(argv);
472 if (!self->IsJSAPILightWeightSet()) {
473 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
474 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
475 } else {
476 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
477 "The clear method cannot be bound");
478 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
479 }
480 }
481 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
482 set->Clear(thread);
483 return JSTaggedValue::Undefined();
484 }
485
ToString(EcmaRuntimeCallInfo * argv)486 JSTaggedValue ContainersLightWeightSet::ToString(EcmaRuntimeCallInfo *argv)
487 {
488 ASSERT(argv != nullptr);
489 JSThread *thread = argv->GetThread();
490 BUILTINS_API_TRACE(thread, LightWeightSet, ToString);
491 [[maybe_unused]] EcmaHandleScope handleScope(thread);
492 JSHandle<JSTaggedValue> self = GetThis(argv);
493 if (!self->IsJSAPILightWeightSet()) {
494 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
495 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
496 } else {
497 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
498 "The toString method cannot be bound");
499 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
500 }
501 }
502 JSTaggedValue value = JSAPILightWeightSet::ToString(thread, JSHandle<JSAPILightWeightSet>::Cast(self));
503 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
504 return value;
505 }
506
ToArray(EcmaRuntimeCallInfo * argv)507 JSTaggedValue ContainersLightWeightSet::ToArray(EcmaRuntimeCallInfo *argv)
508 {
509 ASSERT(argv != nullptr);
510 JSThread *thread = argv->GetThread();
511 BUILTINS_API_TRACE(thread, LightWeightSet, ToArray);
512 [[maybe_unused]] EcmaHandleScope handleScope(thread);
513 JSHandle<JSTaggedValue> self = GetThis(argv);
514 if (!self->IsJSAPILightWeightSet()) {
515 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
516 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
517 } else {
518 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
519 "The toArray method cannot be bound");
520 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
521 }
522 }
523 JSHandle<JSAPILightWeightSet> lightweightset = JSHandle<JSAPILightWeightSet>::Cast(self);
524 auto factory = thread->GetEcmaVM()->GetFactory();
525 JSHandle<JSArray> array = factory->NewJSArray();
526
527 uint32_t length = lightweightset->GetLength();
528 array->SetArrayLength(thread, length);
529
530 JSHandle<TaggedArray> srcArray(thread, lightweightset->GetValues());
531
532 if (srcArray.GetTaggedValue().IsCOWArray()) {
533 array->SetElements(thread, srcArray.GetTaggedValue());
534 return array.GetTaggedValue();
535 }
536
537 auto newElements = factory->CopyArray(srcArray, srcArray->GetLength(), srcArray->GetLength(),
538 JSTaggedValue::Hole(), MemSpaceType::NON_MOVABLE);
539 lightweightset->SetValues(thread, newElements.GetTaggedValue());
540 array->SetElements(thread, newElements);
541 return array.GetTaggedValue();
542 }
543
GetSize(EcmaRuntimeCallInfo * argv)544 JSTaggedValue ContainersLightWeightSet::GetSize(EcmaRuntimeCallInfo *argv)
545 {
546 ASSERT(argv != nullptr);
547 JSThread *thread = argv->GetThread();
548 BUILTINS_API_TRACE(thread, LightWeightSet, GetSize);
549 [[maybe_unused]] EcmaHandleScope handleScope(thread);
550 JSHandle<JSTaggedValue> self = GetThis(argv);
551 if (!self->IsJSAPILightWeightSet()) {
552 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightSet()) {
553 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
554 } else {
555 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
556 "The getLength method cannot be bound");
557 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
558 }
559 }
560 return JSTaggedValue(JSHandle<JSAPILightWeightSet>::Cast(self)->GetSize());
561 }
562 } // namespace panda::ecmascript::containers
563