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