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