• 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             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