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(thread).IsJSAPILightWeightSet()) {
61 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
82 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
93 value = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(value)->GetTarget(thread));
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(thread, *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(thread).IsJSAPILightWeightSet()) {
116 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
136 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread, *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(thread, 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(thread).IsJSAPILightWeightSet()) {
168 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
178 value = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(value)->GetTarget(thread));
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(thread, *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(thread, 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(thread).IsJSAPILightWeightSet()) {
201 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
222 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread, 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(thread).IsJSAPILightWeightSet()) {
243 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
263 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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 = "The type of \"minimumCapacity\" must be small integer. Received value is: " +
281 ConvertToString(thread, *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(thread).IsJSAPILightWeightSet()) {
300 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
321 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPILightWeightSet()) {
342 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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() &&
366 JSHandle<JSProxy>::Cast(thisHandle)->GetTarget(thread).IsJSAPILightWeightSet()) {
367 thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget(thread));
368 } else {
369 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
370 "The forEach method cannot be bound");
371 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
372 }
373 }
374
375 if (!callbackFnHandle->IsCallable()) {
376 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue());
377 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
378 CString errorMsg =
379 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(thread, *result);
380 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
381 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
382 }
383 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
384 return JSAPILightWeightSet::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle);
385 }
386
GetIndexOf(EcmaRuntimeCallInfo * argv)387 JSTaggedValue ContainersLightWeightSet::GetIndexOf(EcmaRuntimeCallInfo *argv)
388 {
389 ASSERT(argv != nullptr);
390 JSThread *thread = argv->GetThread();
391 BUILTINS_API_TRACE(thread, LightWeightSet, GetIndexOf);
392 [[maybe_unused]] EcmaHandleScope handleScope(thread);
393 JSHandle<JSTaggedValue> self = GetThis(argv);
394 if (!self->IsJSAPILightWeightSet()) {
395 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
396 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
397 } else {
398 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
399 "The getIndexOf method cannot be bound");
400 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
401 }
402 }
403 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
404 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
405 int32_t result = set->GetIndexOf(thread, value);
406 return JSTaggedValue(result);
407 }
408
Remove(EcmaRuntimeCallInfo * argv)409 JSTaggedValue ContainersLightWeightSet::Remove(EcmaRuntimeCallInfo *argv)
410 {
411 ASSERT(argv != nullptr);
412 JSThread *thread = argv->GetThread();
413 BUILTINS_API_TRACE(thread, LightWeightSet, Remove);
414 [[maybe_unused]] EcmaHandleScope handleScope(thread);
415 JSHandle<JSTaggedValue> self = GetThis(argv);
416 if (!self->IsJSAPILightWeightSet()) {
417 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
418 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
419 } else {
420 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
421 "The remove method cannot be bound");
422 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
423 }
424 }
425 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
426 JSHandle<JSAPILightWeightSet> lightweightset(self);
427 JSAPILightWeightSet::CheckAndCopyValues(thread, lightweightset);
428 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(lightweightset.GetTaggedValue().GetTaggedObject());
429 return set->Remove(thread, key);
430 }
431
RemoveAt(EcmaRuntimeCallInfo * argv)432 JSTaggedValue ContainersLightWeightSet::RemoveAt(EcmaRuntimeCallInfo *argv)
433 {
434 ASSERT(argv != nullptr);
435 JSThread *thread = argv->GetThread();
436 BUILTINS_API_TRACE(thread, LightWeightSet, RemoveAt);
437 [[maybe_unused]] EcmaHandleScope handleScope(thread);
438 JSHandle<JSTaggedValue> self = GetThis(argv);
439 if (!self->IsJSAPILightWeightSet()) {
440 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
441 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
442 } else {
443 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
444 "The removeAt method cannot be bound");
445 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
446 }
447 }
448 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
449 if (value->IsDouble()) {
450 value = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(value->GetDouble()));
451 }
452 if (!value->IsInt()) {
453 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
454 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
455 CString errorMsg =
456 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(thread, *result);
457 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
458 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
459 }
460 JSHandle<JSAPILightWeightSet> lightweightset(self);
461 JSAPILightWeightSet::CheckAndCopyValues(thread, lightweightset);
462 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(lightweightset.GetTaggedValue().GetTaggedObject());
463 return JSTaggedValue(set->RemoveAt(thread, value->GetInt()));
464 }
465
Clear(EcmaRuntimeCallInfo * argv)466 JSTaggedValue ContainersLightWeightSet::Clear(EcmaRuntimeCallInfo *argv)
467 {
468 ASSERT(argv != nullptr);
469 JSThread *thread = argv->GetThread();
470 BUILTINS_API_TRACE(thread, LightWeightSet, Clear);
471 [[maybe_unused]] EcmaHandleScope handleScope(thread);
472 JSHandle<JSTaggedValue> self = GetThis(argv);
473 if (!self->IsJSAPILightWeightSet()) {
474 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
475 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
476 } else {
477 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
478 "The clear method cannot be bound");
479 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
480 }
481 }
482 JSAPILightWeightSet *set = JSAPILightWeightSet::Cast(self->GetTaggedObject());
483 set->Clear(thread);
484 return JSTaggedValue::Undefined();
485 }
486
ToString(EcmaRuntimeCallInfo * argv)487 JSTaggedValue ContainersLightWeightSet::ToString(EcmaRuntimeCallInfo *argv)
488 {
489 ASSERT(argv != nullptr);
490 JSThread *thread = argv->GetThread();
491 BUILTINS_API_TRACE(thread, LightWeightSet, ToString);
492 [[maybe_unused]] EcmaHandleScope handleScope(thread);
493 JSHandle<JSTaggedValue> self = GetThis(argv);
494 if (!self->IsJSAPILightWeightSet()) {
495 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
496 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
497 } else {
498 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
499 "The toString method cannot be bound");
500 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
501 }
502 }
503 JSTaggedValue value = JSAPILightWeightSet::ToString(thread, JSHandle<JSAPILightWeightSet>::Cast(self));
504 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
505 return value;
506 }
507
ToArray(EcmaRuntimeCallInfo * argv)508 JSTaggedValue ContainersLightWeightSet::ToArray(EcmaRuntimeCallInfo *argv)
509 {
510 ASSERT(argv != nullptr);
511 JSThread *thread = argv->GetThread();
512 BUILTINS_API_TRACE(thread, LightWeightSet, ToArray);
513 [[maybe_unused]] EcmaHandleScope handleScope(thread);
514 JSHandle<JSTaggedValue> self = GetThis(argv);
515 if (!self->IsJSAPILightWeightSet()) {
516 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
517 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
518 } else {
519 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
520 "The toArray method cannot be bound");
521 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
522 }
523 }
524 JSHandle<JSAPILightWeightSet> lightweightset = JSHandle<JSAPILightWeightSet>::Cast(self);
525 auto factory = thread->GetEcmaVM()->GetFactory();
526 JSHandle<JSArray> array = factory->NewJSArray();
527
528 uint32_t length = lightweightset->GetLength();
529 array->SetArrayLength(thread, length);
530
531 JSHandle<TaggedArray> srcArray(thread, lightweightset->GetValues(thread));
532
533 if (srcArray.GetTaggedValue().IsCOWArray()) {
534 array->SetElements(thread, srcArray.GetTaggedValue());
535 return array.GetTaggedValue();
536 }
537
538 auto newElements = factory->CopyArray(srcArray, srcArray->GetLength(), srcArray->GetLength(),
539 JSTaggedValue::Hole(), MemSpaceType::NON_MOVABLE);
540 lightweightset->SetValues(thread, newElements.GetTaggedValue());
541 array->SetElements(thread, newElements);
542 return array.GetTaggedValue();
543 }
544
GetSize(EcmaRuntimeCallInfo * argv)545 JSTaggedValue ContainersLightWeightSet::GetSize(EcmaRuntimeCallInfo *argv)
546 {
547 ASSERT(argv != nullptr);
548 JSThread *thread = argv->GetThread();
549 BUILTINS_API_TRACE(thread, LightWeightSet, GetSize);
550 [[maybe_unused]] EcmaHandleScope handleScope(thread);
551 JSHandle<JSTaggedValue> self = GetThis(argv);
552 if (!self->IsJSAPILightWeightSet()) {
553 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPILightWeightSet()) {
554 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
555 } else {
556 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
557 "The getLength method cannot be bound");
558 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
559 }
560 }
561 return JSTaggedValue(JSHandle<JSAPILightWeightSet>::Cast(self)->GetSize());
562 }
563 } // namespace panda::ecmascript::containers
564