• 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_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