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_lightweightmap.h"
17
18 #include "ecmascript/base/array_helper.h"
19 #include "ecmascript/base/number_helper.h"
20 #include "ecmascript/base/typed_array_helper.h"
21 #include "ecmascript/base/typed_array_helper-inl.h"
22 #include "ecmascript/containers/containers_errors.h"
23 #include "ecmascript/ecma_vm.h"
24 #include "ecmascript/interpreter/interpreter.h"
25 #include "ecmascript/js_api/js_api_lightweightmap.h"
26 #include "ecmascript/js_api/js_api_lightweightmap_iterator.h"
27 #include "ecmascript/js_array.h"
28 #include "ecmascript/object_factory.h"
29 #include "ecmascript/tagged_array-inl.h"
30
31 namespace panda::ecmascript::containers {
LightWeightMapConstructor(EcmaRuntimeCallInfo * argv)32 JSTaggedValue ContainersLightWeightMap::LightWeightMapConstructor(EcmaRuntimeCallInfo *argv)
33 {
34 ASSERT(argv != nullptr);
35 JSThread *thread = argv->GetThread();
36 BUILTINS_API_TRACE(thread, LightWeightMap, Constructor);
37 [[maybe_unused]] EcmaHandleScope handleScope(thread);
38 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
39 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
40 if (newTarget->IsUndefined()) {
41 JSTaggedValue error =
42 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
43 "The LightWeightMap's constructor cannot be directly invoked");
44 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
45 }
46 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
47 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
48 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
49 JSHandle<JSAPILightWeightMap> lwMap = JSHandle<JSAPILightWeightMap>::Cast(obj);
50 JSHandle<TaggedArray> hashArray = factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH);
51 JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH);
52 JSHandle<TaggedArray> valueArray = factory->NewTaggedArray(JSAPILightWeightMap::DEFAULT_CAPACITY_LENGTH);
53 lwMap->SetHashes(thread, hashArray.GetTaggedValue());
54 lwMap->SetKeys(thread, keyArray.GetTaggedValue());
55 lwMap->SetValues(thread, valueArray.GetTaggedValue());
56
57 return lwMap.GetTaggedValue();
58 }
59
Length(EcmaRuntimeCallInfo * argv)60 JSTaggedValue ContainersLightWeightMap::Length(EcmaRuntimeCallInfo *argv)
61 {
62 ASSERT(argv != nullptr);
63 JSThread *thread = argv->GetThread();
64 BUILTINS_API_TRACE(thread, LightWeightMap, Length);
65 [[maybe_unused]] EcmaHandleScope handleScope(thread);
66 JSHandle<JSTaggedValue> self = GetThis(argv);
67
68 if (!self->IsJSAPILightWeightMap()) {
69 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
70 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
71 } else {
72 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
73 "The length method cannot be bound");
74 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
75 }
76 }
77
78 return JSTaggedValue(JSHandle<JSAPILightWeightMap>::Cast(self)->GetLength());
79 }
80
HasAll(EcmaRuntimeCallInfo * argv)81 JSTaggedValue ContainersLightWeightMap::HasAll(EcmaRuntimeCallInfo *argv)
82 {
83 ASSERT(argv != nullptr);
84 JSThread *thread = argv->GetThread();
85 BUILTINS_API_TRACE(thread, LightWeightMap, HasAll);
86 [[maybe_unused]] EcmaHandleScope handleScope(thread);
87 JSHandle<JSTaggedValue> self = GetThis(argv);
88
89 if (!self->IsJSAPILightWeightMap()) {
90 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
91 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
92 } else {
93 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
94 "The hasAll method cannot be bound");
95 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
96 }
97 }
98
99 JSHandle<JSTaggedValue> lightWeightMap(GetCallArg(argv, 0));
100 if (!lightWeightMap->IsJSAPILightWeightMap()) {
101 if (lightWeightMap->IsJSProxy() &&
102 JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget().IsJSAPILightWeightMap()) {
103 lightWeightMap = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget());
104 } else {
105 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, lightWeightMap.GetTaggedValue());
106 CString errorMsg =
107 "The type of \"map\" must be LightWeightMap. Received value is: " + ConvertToString(*result);
108 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
109 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
110 }
111 }
112
113 return JSAPILightWeightMap::HasAll(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
114 JSHandle<JSAPILightWeightMap>::Cast(lightWeightMap));
115 }
116
HasKey(EcmaRuntimeCallInfo * argv)117 JSTaggedValue ContainersLightWeightMap::HasKey(EcmaRuntimeCallInfo *argv)
118 {
119 ASSERT(argv != nullptr);
120 JSThread *thread = argv->GetThread();
121 BUILTINS_API_TRACE(thread, LightWeightMap, HasKey);
122 [[maybe_unused]] EcmaHandleScope handleScope(thread);
123 JSHandle<JSTaggedValue> self = GetThis(argv);
124
125 if (!self->IsJSAPILightWeightMap()) {
126 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
127 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
128 } else {
129 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
130 "The hasKey method cannot be bound");
131 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
132 }
133 }
134 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
135
136 return JSAPILightWeightMap::HasKey(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key);
137 }
138
HasValue(EcmaRuntimeCallInfo * argv)139 JSTaggedValue ContainersLightWeightMap::HasValue(EcmaRuntimeCallInfo *argv)
140 {
141 ASSERT(argv != nullptr);
142 JSThread *thread = argv->GetThread();
143 BUILTINS_API_TRACE(thread, LightWeightMap, HasValue);
144 [[maybe_unused]] EcmaHandleScope handleScope(thread);
145 JSHandle<JSTaggedValue> self = GetThis(argv);
146
147 if (!self->IsJSAPILightWeightMap()) {
148 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
149 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
150 } else {
151 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
152 "The hasValue method cannot be bound");
153 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
154 }
155 }
156
157 JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
158 return JSAPILightWeightMap::HasValue(thread, JSHandle<JSAPILightWeightMap>::Cast(self), value);
159 }
160
IncreaseCapacityTo(EcmaRuntimeCallInfo * argv)161 JSTaggedValue ContainersLightWeightMap::IncreaseCapacityTo(EcmaRuntimeCallInfo *argv)
162 {
163 ASSERT(argv != nullptr);
164 JSThread *thread = argv->GetThread();
165 BUILTINS_API_TRACE(thread, LightWeightMap, IncreaseCapacityTo);
166 [[maybe_unused]] EcmaHandleScope handleScope(thread);
167 JSHandle<JSTaggedValue> self = GetThis(argv);
168
169 if (!self->IsJSAPILightWeightMap()) {
170 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
171 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
172 } else {
173 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
174 "The increaseCapacityTo method cannot be bound");
175 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
176 }
177 }
178
179 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
180
181 if (!index->IsInt()) {
182 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
183 CString errorMsg =
184 "The type of \"minimumCapacity\" must be number. 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.GetTaggedValue().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->IsInt()) {
319 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
320 CString errorMsg =
321 "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
322 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
323 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
324 }
325
326 return JSAPILightWeightMap::GetKeyAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
327 index->GetInt());
328 }
329
Keys(EcmaRuntimeCallInfo * argv)330 JSTaggedValue ContainersLightWeightMap::Keys(EcmaRuntimeCallInfo *argv)
331 {
332 ASSERT(argv != nullptr);
333 JSThread *thread = argv->GetThread();
334 BUILTINS_API_TRACE(thread, LightWeightMap, Keys);
335 [[maybe_unused]] EcmaHandleScope handleScope(thread);
336 JSHandle<JSTaggedValue> self = GetThis(argv);
337 JSHandle<JSTaggedValue> iter =
338 JSAPILightWeightMapIterator::CreateLightWeightMapIterator(thread, self, IterationKind::KEY);
339 return iter.GetTaggedValue();
340 }
341
SetAll(EcmaRuntimeCallInfo * argv)342 JSTaggedValue ContainersLightWeightMap::SetAll(EcmaRuntimeCallInfo *argv)
343 {
344 ASSERT(argv != nullptr);
345 JSThread *thread = argv->GetThread();
346 BUILTINS_API_TRACE(thread, LightWeightMap, SetAll);
347 [[maybe_unused]] EcmaHandleScope handleScope(thread);
348 JSHandle<JSTaggedValue> self = GetThis(argv);
349
350 if (!self->IsJSAPILightWeightMap()) {
351 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
352 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
353 } else {
354 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
355 "The setAll method cannot be bound");
356 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
357 }
358 }
359
360 JSHandle<JSTaggedValue> lightWeightMap(GetCallArg(argv, 0));
361
362 if (!lightWeightMap->IsJSAPILightWeightMap()) {
363 if (lightWeightMap->IsJSProxy() &&
364 JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget().IsJSAPILightWeightMap()) {
365 lightWeightMap = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(lightWeightMap)->GetTarget());
366 } else {
367 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, lightWeightMap.GetTaggedValue());
368 CString errorMsg =
369 "The type of \"map\" must be LightWeightMap. Received value is: " + ConvertToString(*result);
370 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
371 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
372 }
373 }
374
375 JSAPILightWeightMap::SetAll(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
376 JSHandle<JSAPILightWeightMap>::Cast(lightWeightMap));
377 return JSTaggedValue::True();
378 }
379
Set(EcmaRuntimeCallInfo * argv)380 JSTaggedValue ContainersLightWeightMap::Set(EcmaRuntimeCallInfo *argv)
381 {
382 ASSERT(argv != nullptr);
383 JSThread *thread = argv->GetThread();
384 BUILTINS_API_TRACE(thread, LightWeightMap, Set);
385 [[maybe_unused]] EcmaHandleScope handleScope(thread);
386 JSHandle<JSTaggedValue> self = GetThis(argv);
387
388 if (!self->IsJSAPILightWeightMap()) {
389 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
390 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
391 } else {
392 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
393 "The set method cannot be bound");
394 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
395 }
396 }
397
398 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
399 JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
400
401 JSAPILightWeightMap::Set(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key, value);
402 return JSTaggedValue::True();
403 }
404
Remove(EcmaRuntimeCallInfo * argv)405 JSTaggedValue ContainersLightWeightMap::Remove(EcmaRuntimeCallInfo *argv)
406 {
407 ASSERT(argv != nullptr);
408 JSThread *thread = argv->GetThread();
409 BUILTINS_API_TRACE(thread, LightWeightMap, Remove);
410 [[maybe_unused]] EcmaHandleScope handleScope(thread);
411 JSHandle<JSTaggedValue> self = GetThis(argv);
412
413 if (!self->IsJSAPILightWeightMap()) {
414 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
415 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
416 } else {
417 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
418 "The remove method cannot be bound");
419 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
420 }
421 }
422 JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
423
424 return JSAPILightWeightMap::Remove(thread, JSHandle<JSAPILightWeightMap>::Cast(self), key);
425 }
426
RemoveAt(EcmaRuntimeCallInfo * argv)427 JSTaggedValue ContainersLightWeightMap::RemoveAt(EcmaRuntimeCallInfo *argv)
428 {
429 ASSERT(argv != nullptr);
430 JSThread *thread = argv->GetThread();
431 BUILTINS_API_TRACE(thread, LightWeightMap, RemoveAt);
432 [[maybe_unused]] EcmaHandleScope handleScope(thread);
433 JSHandle<JSTaggedValue> self = GetThis(argv);
434
435 if (!self->IsJSAPILightWeightMap()) {
436 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
437 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
438 } else {
439 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
440 "The removeAt method cannot be bound");
441 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
442 }
443 }
444
445 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
446 if (!index->IsInt()) {
447 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
448 CString errorMsg =
449 "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
450 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
451 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
452 }
453
454 return JSAPILightWeightMap::RemoveAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
455 index->GetInt());
456 }
457
Clear(EcmaRuntimeCallInfo * argv)458 JSTaggedValue ContainersLightWeightMap::Clear(EcmaRuntimeCallInfo *argv)
459 {
460 ASSERT(argv != nullptr);
461 JSThread *thread = argv->GetThread();
462 BUILTINS_API_TRACE(thread, LightWeightMap, Clear);
463 [[maybe_unused]] EcmaHandleScope handleScope(thread);
464 JSHandle<JSTaggedValue> self = GetThis(argv);
465
466 if (!self->IsJSAPILightWeightMap()) {
467 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
468 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
469 } else {
470 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
471 "The clear method cannot be bound");
472 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
473 }
474 }
475
476 JSAPILightWeightMap::Clear(thread, JSHandle<JSAPILightWeightMap>::Cast(self));
477 return JSTaggedValue::True();
478 }
479
SetValueAt(EcmaRuntimeCallInfo * argv)480 JSTaggedValue ContainersLightWeightMap::SetValueAt(EcmaRuntimeCallInfo *argv)
481 {
482 ASSERT(argv != nullptr);
483 JSThread *thread = argv->GetThread();
484 BUILTINS_API_TRACE(thread, LightWeightMap, SetValueAt);
485 [[maybe_unused]] EcmaHandleScope handleScope(thread);
486 JSHandle<JSTaggedValue> self = GetThis(argv);
487
488 if (!self->IsJSAPILightWeightMap()) {
489 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
490 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
491 } else {
492 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
493 "The setValueAt method cannot be bound");
494 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
495 }
496 }
497
498 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
499 JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
500 if (!index->IsInt()) {
501 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
502 CString errorMsg =
503 "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
504 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
505 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
506 }
507
508 return JSAPILightWeightMap::SetValueAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
509 index->GetInt(), value);
510 }
511
ForEach(EcmaRuntimeCallInfo * argv)512 JSTaggedValue ContainersLightWeightMap::ForEach(EcmaRuntimeCallInfo *argv)
513 {
514 ASSERT(argv != nullptr);
515 JSThread *thread = argv->GetThread();
516 BUILTINS_API_TRACE(thread, LightWeightMap, ForEach);
517 [[maybe_unused]] EcmaHandleScope handleScope(thread);
518 // get and check lightweightmap object
519 JSHandle<JSTaggedValue> self = GetThis(argv);
520 if (!self->IsJSAPILightWeightMap()) {
521 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
522 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
523 } else {
524 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
525 "The forEach method cannot be bound");
526 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
527 }
528 }
529 // get and check callback function
530 JSHandle<JSTaggedValue> func(GetCallArg(argv, 0));
531 if (!func->IsCallable()) {
532 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, func.GetTaggedValue());
533 CString errorMsg =
534 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
535 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
536 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
537 }
538 // If thisArg was supplied, let T be thisArg; else let T be undefined.
539 JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 1);
540 JSHandle<JSAPILightWeightMap> tmap = JSHandle<JSAPILightWeightMap>::Cast(self);
541 JSMutableHandle<TaggedArray> keys(thread, tmap->GetKeys());
542 JSMutableHandle<TaggedArray> values(thread, tmap->GetValues());
543
544 int index = 0;
545 int32_t length = tmap->GetSize();
546 const int32_t argsLength = 3;
547 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
548 while (index < length) {
549 // ignore the hash value is required to determine the true index
550 // Let funcResult be Call(callbackfn, T, «e, e, S»).
551 EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisArg, undefined, argsLength);
552 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
553 info->SetCallArg(values->Get(index), keys->Get(index), self.GetTaggedValue());
554 JSTaggedValue ret = JSFunction::Call(info);
555 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ret);
556
557 // check entries should be update, size will be update in tmap set or remove.
558 if (tmap->GetSize() != length) {
559 keys.Update(tmap->GetKeys());
560 values.Update(tmap->GetValues());
561 length = tmap->GetSize();
562 }
563 index++;
564 }
565 return JSTaggedValue::Undefined();
566 }
567
ToString(EcmaRuntimeCallInfo * argv)568 JSTaggedValue ContainersLightWeightMap::ToString(EcmaRuntimeCallInfo *argv)
569 {
570 ASSERT(argv != nullptr);
571 JSThread *thread = argv->GetThread();
572 BUILTINS_API_TRACE(thread, LightWeightMap, ToString);
573 [[maybe_unused]] EcmaHandleScope handleScope(thread);
574 JSHandle<JSTaggedValue> self = GetThis(argv);
575
576 if (!self->IsJSAPILightWeightMap()) {
577 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
578 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
579 } else {
580 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
581 "The toString method cannot be bound");
582 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
583 }
584 }
585
586 return JSAPILightWeightMap::ToString(thread, JSHandle<JSAPILightWeightMap>::Cast(self));
587 }
588
GetValueAt(EcmaRuntimeCallInfo * argv)589 JSTaggedValue ContainersLightWeightMap::GetValueAt(EcmaRuntimeCallInfo *argv)
590 {
591 ASSERT(argv != nullptr);
592 JSThread *thread = argv->GetThread();
593 BUILTINS_API_TRACE(thread, LightWeightMap, GetValueAt);
594 [[maybe_unused]] EcmaHandleScope handleScope(thread);
595 JSHandle<JSTaggedValue> self = GetThis(argv);
596
597 if (!self->IsJSAPILightWeightMap()) {
598 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILightWeightMap()) {
599 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
600 } else {
601 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
602 "The getValueAt method cannot be bound");
603 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
604 }
605 }
606 JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
607 if (!index->IsInt()) {
608 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index);
609 CString errorMsg =
610 "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
611 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
612 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
613 }
614
615 return JSAPILightWeightMap::GetValueAt(thread, JSHandle<JSAPILightWeightMap>::Cast(self),
616 index->GetInt());
617 }
618
Values(EcmaRuntimeCallInfo * argv)619 JSTaggedValue ContainersLightWeightMap::Values(EcmaRuntimeCallInfo *argv)
620 {
621 ASSERT(argv != nullptr);
622 JSThread *thread = argv->GetThread();
623 BUILTINS_API_TRACE(thread, LightWeightMap, Keys);
624 [[maybe_unused]] EcmaHandleScope handleScope(thread);
625 JSHandle<JSTaggedValue> self = GetThis(argv);
626 JSHandle<JSTaggedValue> iter =
627 JSAPILightWeightMapIterator::CreateLightWeightMapIterator(thread, self, IterationKind::VALUE);
628 return iter.GetTaggedValue();
629 }
630 } // namespace panda::ecmascript::containers
631