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