1 /*
2 * Copyright (c) 2022-2024 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_lightweightmap.h"
17
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_api/js_api_lightweightmap.h"
21 #include "ecmascript/js_api/js_api_lightweightmap_iterator.h"
22 #include "ecmascript/js_array.h"
23 #include "ecmascript/js_function.h"
24 #include "ecmascript/object_factory.h"
25 #include "ecmascript/tagged_array-inl.h"
26
27 namespace panda::ecmascript::containers {
LightWeightMapConstructor(EcmaRuntimeCallInfo * argv)28 JSTaggedValue ContainersLightWeightMap::LightWeightMapConstructor(EcmaRuntimeCallInfo *argv)
29 {
30 ASSERT(argv != nullptr);
31 JSThread *thread = argv->GetThread();
32 BUILTINS_API_TRACE(thread, LightWeightMap, Constructor);
33 [[maybe_unused]] EcmaHandleScope handleScope(thread);
34 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
35 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
36 if (newTarget->IsUndefined()) {
37 JSTaggedValue error =
38 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
39 "The LightWeightMap's constructor cannot be directly invoked");
40 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
41 }
42 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
43 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
44 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
45 JSHandle<JSAPILightWeightMap> lwMap = JSHandle<JSAPILightWeightMap>::Cast(obj);
46 JSHandle<TaggedArray> hashArray = factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH);
47 JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH);
48 JSHandle<TaggedArray> valueArray = factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH);
49 lwMap->SetHashes(thread, hashArray.GetTaggedValue());
50 lwMap->SetKeys(thread, keyArray.GetTaggedValue());
51 lwMap->SetValues(thread, valueArray.GetTaggedValue());
52
53 return lwMap.GetTaggedValue();
54 }
55
Length(EcmaRuntimeCallInfo * argv)56 JSTaggedValue ContainersLightWeightMap::Length(EcmaRuntimeCallInfo *argv)
57 {
58 ASSERT(argv != nullptr);
59 JSThread *thread = argv->GetThread();
60 BUILTINS_API_TRACE(thread, LightWeightMap, Length);
61 [[maybe_unused]] EcmaHandleScope handleScope(thread);
62 JSHandle<JSTaggedValue> self = GetThis(argv);
63
64 if (!self->IsJSAPILightWeightMap()) {
65 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
66 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
67 } else {
68 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
69 "The getLength method cannot be bound");
70 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
71 }
72 }
73
74 return JSTaggedValue(JSHandle<JSAPILightWeightMap>::Cast(self)->GetLength());
75 }
76
HasAll(EcmaRuntimeCallInfo * argv)77 JSTaggedValue ContainersLightWeightMap::HasAll(EcmaRuntimeCallInfo *argv)
78 {
79 ASSERT(argv != nullptr);
80 JSThread *thread = argv->GetThread();
81 BUILTINS_API_TRACE(thread, LightWeightMap, HasAll);
82 [[maybe_unused]] EcmaHandleScope handleScope(thread);
83 JSHandle<JSTaggedValue> self = GetThis(argv);
84
85 if (!self->IsJSAPILightWeightMap()) {
86 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
87 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
88 } else {
89 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
90 "The hasAll method cannot be bound");
91 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
92 }
93 }
94
95 JSHandle<JSTaggedValue> lightWeightMap(GetCallArg(argv, 0));
96 if (!lightWeightMap->IsJSAPILightWeightMap()) {
97 if (lightWeightMap->IsJSProxy() &&
98 JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget().IsJSAPILightWeightMap()) {
99 lightWeightMap = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget());
100 } else {
101 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, lightWeightMap.GetTaggedValue());
102 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
103 CString errorMsg =
104 "The type of \"map\" must be LightWeightMap. Received value is: " + ConvertToString(*result);
105 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
106 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
107 }
108 }
109
110 return JSAPILightWeightMap::HasAll(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
111 JSHandle<JSAPILightWeightMap>::Cast(lightWeightMap));
112 }
113
HasKey(EcmaRuntimeCallInfo * argv)114 JSTaggedValue ContainersLightWeightMap::HasKey(EcmaRuntimeCallInfo *argv)
115 {
116 ASSERT(argv != nullptr);
117 JSThread *thread = argv->GetThread();
118 BUILTINS_API_TRACE(thread, LightWeightMap, HasKey);
119 [[maybe_unused]] EcmaHandleScope handleScope(thread);
120 JSHandle<JSTaggedValue> self = GetThis(argv);
121
122 if (!self->IsJSAPILightWeightMap()) {
123 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
124 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
125 } else {
126 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
127 "The hasKey method cannot be bound");
128 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
129 }
130 }
131 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
132
133 return JSAPILightWeightMap::HasKey(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key);
134 }
135
HasValue(EcmaRuntimeCallInfo * argv)136 JSTaggedValue ContainersLightWeightMap::HasValue(EcmaRuntimeCallInfo *argv)
137 {
138 ASSERT(argv != nullptr);
139 JSThread *thread = argv->GetThread();
140 BUILTINS_API_TRACE(thread, LightWeightMap, HasValue);
141 [[maybe_unused]] EcmaHandleScope handleScope(thread);
142 JSHandle<JSTaggedValue> self = GetThis(argv);
143
144 if (!self->IsJSAPILightWeightMap()) {
145 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
146 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
147 } else {
148 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
149 "The hasValue method cannot be bound");
150 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
151 }
152 }
153
154 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
155 return JSAPILightWeightMap::HasValue(thread, JSHandle<JSAPILightWeightMap>::Cast(self), value);
156 }
157
IncreaseCapacityTo(EcmaRuntimeCallInfo * argv)158 JSTaggedValue ContainersLightWeightMap::IncreaseCapacityTo(EcmaRuntimeCallInfo *argv)
159 {
160 ASSERT(argv != nullptr);
161 JSThread *thread = argv->GetThread();
162 BUILTINS_API_TRACE(thread, LightWeightMap, IncreaseCapacityTo);
163 [[maybe_unused]] EcmaHandleScope handleScope(thread);
164 JSHandle<JSTaggedValue> self = GetThis(argv);
165
166 if (!self->IsJSAPILightWeightMap()) {
167 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
168 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
169 } else {
170 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
171 "The increaseCapacityTo method cannot be bound");
172 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
173 }
174 }
175
176 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
177
178 // for case like Math.foor(1.3), it gives double 1.0;
179 if (index->IsDouble()) {
180 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
181 }
182
183 if (!index->IsInt()) {
184 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
185 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
186 CString errorMsg =
187 "The type of \"minimumCapacity\" must be small integer. Received value is: " + ConvertToString(*result);
188 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
189 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
190 }
191 JSAPILightWeightMap::IncreaseCapacityTo(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
192 index->GetInt());
193
194 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
195 return JSTaggedValue::Undefined();
196 }
197
Entries(EcmaRuntimeCallInfo * argv)198 JSTaggedValue ContainersLightWeightMap::Entries(EcmaRuntimeCallInfo *argv)
199 {
200 ASSERT(argv != nullptr);
201 JSThread *thread = argv->GetThread();
202 BUILTINS_API_TRACE(thread, LightWeightMap, Entries);
203 [[maybe_unused]] EcmaHandleScope handleScope(thread);
204 JSHandle<JSTaggedValue> self = GetThis(argv);
205 JSHandle<JSTaggedValue> iter =
206 JSAPILightWeightMapIterator::CreateLightWeightMapIterator(thread, self, IterationKind::KEY_AND_VALUE);
207 return iter.GetTaggedValue();
208 }
209
Get(EcmaRuntimeCallInfo * argv)210 JSTaggedValue ContainersLightWeightMap::Get(EcmaRuntimeCallInfo *argv)
211 {
212 ASSERT(argv != nullptr);
213 JSThread *thread = argv->GetThread();
214 BUILTINS_API_TRACE(thread, LightWeightMap, Get);
215 [[maybe_unused]] EcmaHandleScope handleScope(thread);
216 JSHandle<JSTaggedValue> self = GetThis(argv);
217
218 if (!self->IsJSAPILightWeightMap()) {
219 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
220 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
221 } else {
222 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
223 "The get method cannot be bound");
224 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
225 }
226 }
227
228 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
229
230 return JSAPILightWeightMap::Get(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key);
231 }
232
GetIndexOfKey(EcmaRuntimeCallInfo * argv)233 JSTaggedValue ContainersLightWeightMap::GetIndexOfKey(EcmaRuntimeCallInfo *argv)
234 {
235 ASSERT(argv != nullptr);
236 JSThread *thread = argv->GetThread();
237 BUILTINS_API_TRACE(thread, LightWeightMap, GetIndexOfKey);
238 [[maybe_unused]] EcmaHandleScope handleScope(thread);
239 JSHandle<JSTaggedValue> self = GetThis(argv);
240
241 if (!self->IsJSAPILightWeightMap()) {
242 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
243 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
244 } else {
245 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
246 "The getIndexOfKey method cannot be bound");
247 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
248 }
249 }
250
251 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
252
253 int32_t index = JSAPILightWeightMap::GetIndexOfKey(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key);
254 return JSTaggedValue(index);
255 }
256
GetIndexOfValue(EcmaRuntimeCallInfo * argv)257 JSTaggedValue ContainersLightWeightMap::GetIndexOfValue(EcmaRuntimeCallInfo *argv)
258 {
259 ASSERT(argv != nullptr);
260 JSThread *thread = argv->GetThread();
261 BUILTINS_API_TRACE(thread, LightWeightMap, GetIndexOfValue);
262 [[maybe_unused]] EcmaHandleScope handleScope(thread);
263 JSHandle<JSTaggedValue> self = GetThis(argv);
264
265 if (!self->IsJSAPILightWeightMap()) {
266 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
267 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
268 } else {
269 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
270 "The getIndexOfValue method cannot be bound");
271 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
272 }
273 }
274
275 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
276
277 int32_t index = JSAPILightWeightMap::GetIndexOfValue(thread, JSHandle<JSAPILightWeightMap>::Cast(self), value);
278 return JSTaggedValue(index);
279 }
280
IsEmpty(EcmaRuntimeCallInfo * argv)281 JSTaggedValue ContainersLightWeightMap::IsEmpty(EcmaRuntimeCallInfo *argv)
282 {
283 ASSERT(argv != nullptr);
284 JSThread *thread = argv->GetThread();
285 BUILTINS_API_TRACE(thread, LightWeightMap, IsEmpty);
286 [[maybe_unused]] EcmaHandleScope handleScope(thread);
287 JSHandle<JSTaggedValue> self = GetThis(argv);
288
289 if (!self->IsJSAPILightWeightMap()) {
290 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
291 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
292 } else {
293 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
294 "The isEmpty method cannot be bound");
295 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
296 }
297 }
298 return JSHandle<JSAPILightWeightMap>::Cast(self)->IsEmpty();
299 }
300
GetKeyAt(EcmaRuntimeCallInfo * argv)301 JSTaggedValue ContainersLightWeightMap::GetKeyAt(EcmaRuntimeCallInfo *argv)
302 {
303 ASSERT(argv != nullptr);
304 JSThread *thread = argv->GetThread();
305 BUILTINS_API_TRACE(thread, LightWeightMap, GetKeyAt);
306 [[maybe_unused]] EcmaHandleScope handleScope(thread);
307 JSHandle<JSTaggedValue> self = GetThis(argv);
308
309 if (!self->IsJSAPILightWeightMap()) {
310 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
311 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
312 } else {
313 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
314 "The getKeyAt method cannot be bound");
315 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
316 }
317 }
318
319 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
320
321 if (index->IsDouble()) {
322 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
323 }
324 if (!index->IsInt()) {
325 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
326 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
327 CString errorMsg =
328 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
329 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
330 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
331 }
332
333 return JSAPILightWeightMap::GetKeyAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
334 index->GetInt());
335 }
336
Keys(EcmaRuntimeCallInfo * argv)337 JSTaggedValue ContainersLightWeightMap::Keys(EcmaRuntimeCallInfo *argv)
338 {
339 ASSERT(argv != nullptr);
340 JSThread *thread = argv->GetThread();
341 BUILTINS_API_TRACE(thread, LightWeightMap, Keys);
342 [[maybe_unused]] EcmaHandleScope handleScope(thread);
343 JSHandle<JSTaggedValue> self = GetThis(argv);
344 JSHandle<JSTaggedValue> iter =
345 JSAPILightWeightMapIterator::CreateLightWeightMapIterator(thread, self, IterationKind::KEY);
346 return iter.GetTaggedValue();
347 }
348
SetAll(EcmaRuntimeCallInfo * argv)349 JSTaggedValue ContainersLightWeightMap::SetAll(EcmaRuntimeCallInfo *argv)
350 {
351 ASSERT(argv != nullptr);
352 JSThread *thread = argv->GetThread();
353 BUILTINS_API_TRACE(thread, LightWeightMap, SetAll);
354 [[maybe_unused]] EcmaHandleScope handleScope(thread);
355 JSHandle<JSTaggedValue> self = GetThis(argv);
356
357 if (!self->IsJSAPILightWeightMap()) {
358 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
359 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
360 } else {
361 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
362 "The setAll method cannot be bound");
363 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
364 }
365 }
366
367 JSHandle<JSTaggedValue> lightWeightMap(GetCallArg(argv, 0));
368
369 if (!lightWeightMap->IsJSAPILightWeightMap()) {
370 if (lightWeightMap->IsJSProxy() &&
371 JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget().IsJSAPILightWeightMap()) {
372 lightWeightMap = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget());
373 } else {
374 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, lightWeightMap.GetTaggedValue());
375 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
376 CString errorMsg =
377 "The type of \"map\" must be LightWeightMap. Received value is: " + ConvertToString(*result);
378 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
379 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
380 }
381 }
382
383 JSAPILightWeightMap::SetAll(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
384 JSHandle<JSAPILightWeightMap>::Cast(lightWeightMap));
385 return JSTaggedValue::True();
386 }
387
Set(EcmaRuntimeCallInfo * argv)388 JSTaggedValue ContainersLightWeightMap::Set(EcmaRuntimeCallInfo *argv)
389 {
390 ASSERT(argv != nullptr);
391 JSThread *thread = argv->GetThread();
392 BUILTINS_API_TRACE(thread, LightWeightMap, Set);
393 [[maybe_unused]] EcmaHandleScope handleScope(thread);
394 JSHandle<JSTaggedValue> self = GetThis(argv);
395
396 if (!self->IsJSAPILightWeightMap()) {
397 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
398 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
399 } else {
400 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
401 "The set method cannot be bound");
402 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
403 }
404 }
405
406 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
407 JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
408 JSHandle<JSAPILightWeightMap> lightWeightMap = JSHandle<JSAPILightWeightMap>::Cast(self);
409 JSAPILightWeightMap::Set(thread, lightWeightMap, key, value);
410
411 return lightWeightMap.GetTaggedValue();
412 }
413
Remove(EcmaRuntimeCallInfo * argv)414 JSTaggedValue ContainersLightWeightMap::Remove(EcmaRuntimeCallInfo *argv)
415 {
416 ASSERT(argv != nullptr);
417 JSThread *thread = argv->GetThread();
418 BUILTINS_API_TRACE(thread, LightWeightMap, Remove);
419 [[maybe_unused]] EcmaHandleScope handleScope(thread);
420 JSHandle<JSTaggedValue> self = GetThis(argv);
421
422 if (!self->IsJSAPILightWeightMap()) {
423 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
424 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
425 } else {
426 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
427 "The remove method cannot be bound");
428 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
429 }
430 }
431 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
432
433 return JSAPILightWeightMap::Remove(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key);
434 }
435
RemoveAt(EcmaRuntimeCallInfo * argv)436 JSTaggedValue ContainersLightWeightMap::RemoveAt(EcmaRuntimeCallInfo *argv)
437 {
438 ASSERT(argv != nullptr);
439 JSThread *thread = argv->GetThread();
440 BUILTINS_API_TRACE(thread, LightWeightMap, RemoveAt);
441 [[maybe_unused]] EcmaHandleScope handleScope(thread);
442 JSHandle<JSTaggedValue> self = GetThis(argv);
443
444 if (!self->IsJSAPILightWeightMap()) {
445 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
446 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
447 } else {
448 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
449 "The removeAt method cannot be bound");
450 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
451 }
452 }
453
454 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
455
456 if (index->IsDouble()) {
457 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
458 }
459 if (!index->IsInt()) {
460 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
461 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
462 CString errorMsg =
463 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
464 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
465 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
466 }
467
468 return JSAPILightWeightMap::RemoveAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
469 index->GetInt());
470 }
471
Clear(EcmaRuntimeCallInfo * argv)472 JSTaggedValue ContainersLightWeightMap::Clear(EcmaRuntimeCallInfo *argv)
473 {
474 ASSERT(argv != nullptr);
475 JSThread *thread = argv->GetThread();
476 BUILTINS_API_TRACE(thread, LightWeightMap, Clear);
477 [[maybe_unused]] EcmaHandleScope handleScope(thread);
478 JSHandle<JSTaggedValue> self = GetThis(argv);
479
480 if (!self->IsJSAPILightWeightMap()) {
481 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
482 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
483 } else {
484 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
485 "The clear method cannot be bound");
486 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
487 }
488 }
489
490 JSAPILightWeightMap::Clear(thread, JSHandle<JSAPILightWeightMap>::Cast(self));
491 return JSTaggedValue::Undefined();
492 }
493
SetValueAt(EcmaRuntimeCallInfo * argv)494 JSTaggedValue ContainersLightWeightMap::SetValueAt(EcmaRuntimeCallInfo *argv)
495 {
496 ASSERT(argv != nullptr);
497 JSThread *thread = argv->GetThread();
498 BUILTINS_API_TRACE(thread, LightWeightMap, SetValueAt);
499 [[maybe_unused]] EcmaHandleScope handleScope(thread);
500 JSHandle<JSTaggedValue> self = GetThis(argv);
501
502 if (!self->IsJSAPILightWeightMap()) {
503 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
504 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
505 } else {
506 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
507 "The setValueAt method cannot be bound");
508 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
509 }
510 }
511
512 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
513 JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
514 if (index->IsDouble()) {
515 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
516 }
517 if (!index->IsInt()) {
518 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
519 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
520 CString errorMsg =
521 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
522 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
523 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
524 }
525
526 return JSAPILightWeightMap::SetValueAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
527 index->GetInt(), value);
528 }
529
ForEach(EcmaRuntimeCallInfo * argv)530 JSTaggedValue ContainersLightWeightMap::ForEach(EcmaRuntimeCallInfo *argv)
531 {
532 ASSERT(argv != nullptr);
533 JSThread *thread = argv->GetThread();
534 BUILTINS_API_TRACE(thread, LightWeightMap, ForEach);
535 [[maybe_unused]] EcmaHandleScope handleScope(thread);
536 // get and check lightweightmap object
537 JSHandle<JSTaggedValue> self = GetThis(argv);
538 if (!self->IsJSAPILightWeightMap()) {
539 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
540 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
541 } else {
542 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
543 "The forEach method cannot be bound");
544 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
545 }
546 }
547 // get and check callback function
548 JSHandle<JSTaggedValue> func(GetCallArg(argv, 0));
549 if (!func->IsCallable()) {
550 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, func.GetTaggedValue());
551 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
552 CString errorMsg =
553 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
554 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
555 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
556 }
557 // If thisArg was supplied, let T be thisArg; else let T be undefined.
558 JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 1);
559 JSHandle<JSAPILightWeightMap> tmap = JSHandle<JSAPILightWeightMap>::Cast(self);
560 JSMutableHandle<TaggedArray> keys(thread, tmap->GetKeys());
561 JSMutableHandle<TaggedArray> values(thread, tmap->GetValues());
562
563 uint32_t index = 0;
564 uint32_t length = tmap->GetSize();
565 const uint32_t argsLength = 3;
566 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
567 while (index < length) {
568 // ignore the hash value is required to determine the true index
569 // Let funcResult be Call(callbackfn, T, «e, e, S»).
570 EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength);
571 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
572 info->SetCallArg(values->Get(index), keys->Get(index), self.GetTaggedValue());
573 JSTaggedValue ret = JSFunction::Call(info);
574 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ret);
575
576 // check entries should be update, size will be update in tmap set or remove.
577 if (tmap->GetSize() != length) {
578 keys.Update(tmap->GetKeys());
579 values.Update(tmap->GetValues());
580 length = tmap->GetSize();
581 }
582 index++;
583 }
584 return JSTaggedValue::Undefined();
585 }
586
ToString(EcmaRuntimeCallInfo * argv)587 JSTaggedValue ContainersLightWeightMap::ToString(EcmaRuntimeCallInfo *argv)
588 {
589 ASSERT(argv != nullptr);
590 JSThread *thread = argv->GetThread();
591 BUILTINS_API_TRACE(thread, LightWeightMap, ToString);
592 [[maybe_unused]] EcmaHandleScope handleScope(thread);
593 JSHandle<JSTaggedValue> self = GetThis(argv);
594
595 if (!self->IsJSAPILightWeightMap()) {
596 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
597 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
598 } else {
599 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
600 "The toString method cannot be bound");
601 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
602 }
603 }
604
605 return JSAPILightWeightMap::ToString(thread, JSHandle<JSAPILightWeightMap>::Cast(self));
606 }
607
GetValueAt(EcmaRuntimeCallInfo * argv)608 JSTaggedValue ContainersLightWeightMap::GetValueAt(EcmaRuntimeCallInfo *argv)
609 {
610 ASSERT(argv != nullptr);
611 JSThread *thread = argv->GetThread();
612 BUILTINS_API_TRACE(thread, LightWeightMap, GetValueAt);
613 [[maybe_unused]] EcmaHandleScope handleScope(thread);
614 JSHandle<JSTaggedValue> self = GetThis(argv);
615
616 if (!self->IsJSAPILightWeightMap()) {
617 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
618 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
619 } else {
620 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
621 "The getValueAt method cannot be bound");
622 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
623 }
624 }
625 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
626 if (index->IsDouble()) {
627 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
628 }
629 if (!index->IsInt()) {
630 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
631 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
632 CString errorMsg =
633 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
634 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
635 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
636 }
637
638 if (index->IsDouble()) {
639 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
640 }
641 return JSAPILightWeightMap::GetValueAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
642 index->GetInt());
643 }
644
Values(EcmaRuntimeCallInfo * argv)645 JSTaggedValue ContainersLightWeightMap::Values(EcmaRuntimeCallInfo *argv)
646 {
647 ASSERT(argv != nullptr);
648 JSThread *thread = argv->GetThread();
649 BUILTINS_API_TRACE(thread, LightWeightMap, Keys);
650 [[maybe_unused]] EcmaHandleScope handleScope(thread);
651 JSHandle<JSTaggedValue> self = GetThis(argv);
652 JSHandle<JSTaggedValue> iter =
653 JSAPILightWeightMapIterator::CreateLightWeightMapIterator(thread, self, IterationKind::VALUE);
654 return iter.GetTaggedValue();
655 }
656 } // namespace panda::ecmascript::containers
657