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