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