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 "containers_hashmap.h"
17
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_api/js_api_hashmap_iterator.h"
21 #include "ecmascript/js_function.h"
22
23 namespace panda::ecmascript::containers {
HashMapConstructor(EcmaRuntimeCallInfo *argv)24 JSTaggedValue ContainersHashMap::HashMapConstructor(EcmaRuntimeCallInfo *argv)
25 {
26 ASSERT(argv != nullptr);
27 JSThread *thread = argv->GetThread();
28 BUILTINS_API_TRACE(thread, HashMap, Constructor);
29 [[maybe_unused]] EcmaHandleScope handleScope(thread);
30 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
31
32 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
33 if (newTarget->IsUndefined()) {
34 JSTaggedValue error =
35 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
36 "The HashMap's constructor cannot be directly invoked");
37 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
38 }
39
40 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
41 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
42 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
43
44 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(obj);
45 JSTaggedValue hashMapArray = TaggedHashArray::Create(thread);
46 hashMap->SetTable(thread, hashMapArray);
47 hashMap->SetSize(0);
48
49 return hashMap.GetTaggedValue();
50 }
51
Keys(EcmaRuntimeCallInfo *argv)52 JSTaggedValue ContainersHashMap::Keys(EcmaRuntimeCallInfo *argv)
53 {
54 ASSERT(argv != nullptr);
55 JSThread *thread = argv->GetThread();
56 BUILTINS_API_TRACE(thread, HashMap, Keys);
57 [[maybe_unused]] EcmaHandleScope handleScope(thread);
58 JSHandle<JSTaggedValue> self = GetThis(argv);
59 if (!self->IsJSAPIHashMap()) {
60 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
61 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
62 } else {
63 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
64 "The keys method cannot be bound");
65 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
66 }
67 }
68 JSHandle<JSTaggedValue> iter =
69 JSAPIHashMapIterator::CreateHashMapIterator(thread, self, IterationKind::KEY);
70 return iter.GetTaggedValue();
71 }
72
Values(EcmaRuntimeCallInfo *argv)73 JSTaggedValue ContainersHashMap::Values(EcmaRuntimeCallInfo *argv)
74 {
75 ASSERT(argv != nullptr);
76 JSThread *thread = argv->GetThread();
77 BUILTINS_API_TRACE(thread, HashMap, Values);
78 [[maybe_unused]] EcmaHandleScope handleScope(thread);
79 JSHandle<JSTaggedValue> self = GetThis(argv);
80 if (!self->IsJSAPIHashMap()) {
81 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
82 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
83 } else {
84 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
85 "The values method cannot be bound");
86 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
87 }
88 }
89 JSHandle<JSTaggedValue> iter =
90 JSAPIHashMapIterator::CreateHashMapIterator(thread, self, IterationKind::VALUE);
91 return iter.GetTaggedValue();
92 }
93
GetIteratorObj(EcmaRuntimeCallInfo *argv)94 JSTaggedValue ContainersHashMap::GetIteratorObj(EcmaRuntimeCallInfo *argv)
95 {
96 ASSERT(argv != nullptr);
97 JSThread *thread = argv->GetThread();
98 BUILTINS_API_TRACE(thread, HashMap, GetIteratorObj);
99 [[maybe_unused]] EcmaHandleScope handleScope(thread);
100 JSHandle<JSTaggedValue> self = GetThis(argv);
101 if (!self->IsJSAPIHashMap()) {
102 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
103 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
104 } else {
105 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
106 "The Symbol.iterator method cannot be bound");
107 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
108 }
109 }
110 JSHandle<JSTaggedValue> iter =
111 JSAPIHashMapIterator::CreateHashMapIterator(thread, self, IterationKind::KEY_AND_VALUE);
112 return iter.GetTaggedValue();
113 }
114
Entries(EcmaRuntimeCallInfo *argv)115 JSTaggedValue ContainersHashMap::Entries(EcmaRuntimeCallInfo *argv)
116 {
117 ASSERT(argv != nullptr);
118 JSThread *thread = argv->GetThread();
119 BUILTINS_API_TRACE(thread, HashMap, Entries);
120 [[maybe_unused]] EcmaHandleScope handleScope(thread);
121 JSHandle<JSTaggedValue> self = GetThis(argv);
122 if (!self->IsJSAPIHashMap()) {
123 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
124 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
125 } else {
126 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
127 "The entries method cannot be bound");
128 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
129 }
130 }
131 JSHandle<JSTaggedValue> iter =
132 JSAPIHashMapIterator::CreateHashMapIterator(thread, self, IterationKind::KEY_AND_VALUE);
133 return iter.GetTaggedValue();
134 }
135
ForEach(EcmaRuntimeCallInfo *argv)136 JSTaggedValue ContainersHashMap::ForEach(EcmaRuntimeCallInfo *argv)
137 {
138 ASSERT(argv != nullptr);
139 JSThread *thread = argv->GetThread();
140 BUILTINS_API_TRACE(thread, HashMap, ForEach);
141 [[maybe_unused]] EcmaHandleScope handleScope(thread);
142 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
143 if (!thisHandle->IsJSAPIHashMap()) {
144 if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPIHashMap()) {
145 thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
146 } else {
147 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
148 "The forEach method cannot be bound");
149 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
150 }
151 }
152 JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
153 if (!callbackFnHandle->IsCallable()) {
154 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle);
155 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
156 CString errorMsg =
157 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
158 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
159 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
160 }
161 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
162 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(thisHandle);
163 JSHandle<TaggedHashArray> table(thread, hashMap->GetTable());
164 uint32_t len = table->GetLength();
165 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
166 JSMutableHandle<TaggedQueue> queue(thread, factory->NewTaggedQueue(0));
167 JSMutableHandle<TaggedNode> node(thread, JSTaggedValue::Undefined());
168 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
169 JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
170 uint32_t index = 0;
171 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
172 while (index < len) {
173 node.Update(TaggedHashArray::GetCurrentNode(thread, queue, table, index));
174 if (!node.GetTaggedValue().IsHole()) {
175 key.Update(node->GetKey());
176 value.Update(node->GetValue());
177 EcmaRuntimeCallInfo *info =
178 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle,
179 thisArgHandle, undefined, 3); // 3: three args
180 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
181 info->SetCallArg(value.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
182 JSTaggedValue funcResult = JSFunction::Call(info);
183 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
184 }
185 }
186 return JSTaggedValue::Undefined();
187 }
188
Set(EcmaRuntimeCallInfo *argv)189 JSTaggedValue ContainersHashMap::Set(EcmaRuntimeCallInfo *argv)
190 {
191 ASSERT(argv != nullptr);
192 JSThread *thread = argv->GetThread();
193 BUILTINS_API_TRACE(thread, HashMap, Set);
194 [[maybe_unused]] EcmaHandleScope handleScope(thread);
195 JSHandle<JSTaggedValue> self = GetThis(argv);
196 if (!self->IsJSAPIHashMap()) {
197 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
198 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
199 } else {
200 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
201 "The set method cannot be bound");
202 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
203 }
204 }
205 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
206 JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
207 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
208 JSAPIHashMap::Set(thread, hashMap, key, value);
209 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
210 return hashMap.GetTaggedValue();
211 }
212
SetAll(EcmaRuntimeCallInfo *argv)213 JSTaggedValue ContainersHashMap::SetAll(EcmaRuntimeCallInfo *argv)
214 {
215 ASSERT(argv != nullptr);
216 JSThread *thread = argv->GetThread();
217 BUILTINS_API_TRACE(thread, HashMap, SetAll);
218 [[maybe_unused]] EcmaHandleScope handleScope(thread);
219 JSHandle<JSTaggedValue> self = GetThis(argv);
220 if (!self->IsJSAPIHashMap()) {
221 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
222 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
223 } else {
224 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
225 "The setAll method cannot be bound");
226 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
227 }
228 }
229
230 JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
231 if (!obj->IsJSAPIHashMap()) {
232 if (obj->IsJSProxy() && JSHandle<JSProxy>::Cast(obj)->GetTarget().IsJSAPIHashMap()) {
233 obj = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(obj)->GetTarget());
234 } else {
235 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, obj);
236 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
237 CString errorMsg =
238 "The type of \"map\" must be HashMap. Received value is: " + ConvertToString(*result);
239 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
240 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
241 }
242 }
243
244 JSHandle<JSAPIHashMap> targetMap = JSHandle<JSAPIHashMap>::Cast(self);
245 JSHandle<JSAPIHashMap> sourceMap = JSHandle<JSAPIHashMap>::Cast(obj);
246 JSAPIHashMap::SetAll(thread, targetMap, sourceMap);
247 return self.GetTaggedValue();
248 }
249
Get(EcmaRuntimeCallInfo *argv)250 JSTaggedValue ContainersHashMap::Get(EcmaRuntimeCallInfo *argv)
251 {
252 ASSERT(argv != nullptr);
253 JSThread *thread = argv->GetThread();
254 BUILTINS_API_TRACE(thread, HashMap, Get);
255 [[maybe_unused]] EcmaHandleScope handleScope(thread);
256 JSHandle<JSTaggedValue> self = GetThis(argv);
257 if (!self->IsJSAPIHashMap()) {
258 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
259 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
260 } else {
261 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
262 "The get method cannot be bound");
263 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
264 }
265 }
266 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
267 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
268 return hashMap->Get(thread, key.GetTaggedValue());
269 }
270
Remove(EcmaRuntimeCallInfo *argv)271 JSTaggedValue ContainersHashMap::Remove(EcmaRuntimeCallInfo *argv)
272 {
273 ASSERT(argv != nullptr);
274 JSThread *thread = argv->GetThread();
275 BUILTINS_API_TRACE(thread, HashMap, Remove);
276 [[maybe_unused]] EcmaHandleScope handleScope(thread);
277 JSHandle<JSTaggedValue> self = GetThis(argv);
278
279 if (!self->IsJSAPIHashMap()) {
280 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
281 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
282 } else {
283 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
284 "The remove method cannot be bound");
285 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
286 }
287 }
288 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
289 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
290 return JSAPIHashMap::Remove(thread, hashMap, key.GetTaggedValue());
291 }
292
HasKey(EcmaRuntimeCallInfo *argv)293 JSTaggedValue ContainersHashMap::HasKey(EcmaRuntimeCallInfo *argv)
294 {
295 ASSERT(argv != nullptr);
296 JSThread *thread = argv->GetThread();
297 BUILTINS_API_TRACE(thread, HashMap, HasKey);
298 [[maybe_unused]] EcmaHandleScope handleScope(thread);
299 JSHandle<JSTaggedValue> self = GetThis(argv);
300
301 if (!self->IsJSAPIHashMap()) {
302 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
303 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
304 } else {
305 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
306 "The hasKey method cannot be bound");
307 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
308 }
309 }
310 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
311 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
312 return hashMap->HasKey(thread, key.GetTaggedValue());
313 }
314
HasValue(EcmaRuntimeCallInfo *argv)315 JSTaggedValue ContainersHashMap::HasValue(EcmaRuntimeCallInfo *argv)
316 {
317 ASSERT(argv != nullptr);
318 JSThread *thread = argv->GetThread();
319 BUILTINS_API_TRACE(thread, HashMap, HasValue);
320 [[maybe_unused]] EcmaHandleScope handleScope(thread);
321 JSHandle<JSTaggedValue> self = GetThis(argv);
322
323 if (!self->IsJSAPIHashMap()) {
324 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
325 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
326 } else {
327 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
328 "The hasValue method cannot be bound");
329 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
330 }
331 }
332 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
333 JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
334 return JSAPIHashMap::HasValue(thread, hashMap, value);
335 }
336
Replace(EcmaRuntimeCallInfo *argv)337 JSTaggedValue ContainersHashMap::Replace(EcmaRuntimeCallInfo *argv)
338 {
339 ASSERT(argv != nullptr);
340 JSThread *thread = argv->GetThread();
341 BUILTINS_API_TRACE(thread, HashMap, Replace);
342 [[maybe_unused]] EcmaHandleScope handleScope(thread);
343 JSHandle<JSTaggedValue> self = GetThis(argv);
344 if (!self->IsJSAPIHashMap()) {
345 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
346 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
347 } else {
348 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
349 "The replace method cannot be bound");
350 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
351 }
352 }
353 JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
354 JSHandle<JSTaggedValue> newValue = GetCallArg(argv, 1);
355 JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
356 return JSTaggedValue(jsHashMap->Replace(thread, key.GetTaggedValue(), newValue.GetTaggedValue()));
357 }
358
Clear(EcmaRuntimeCallInfo *argv)359 JSTaggedValue ContainersHashMap::Clear(EcmaRuntimeCallInfo *argv)
360 {
361 ASSERT(argv != nullptr);
362 JSThread *thread = argv->GetThread();
363 BUILTINS_API_TRACE(thread, HashMap, Clear);
364 [[maybe_unused]] EcmaHandleScope handleScope(thread);
365 JSHandle<JSTaggedValue> self = GetThis(argv);
366 if (!self->IsJSAPIHashMap()) {
367 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
368 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
369 } else {
370 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
371 "The clear method cannot be bound");
372 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
373 }
374 }
375 JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
376 jsHashMap->Clear(thread);
377 return JSTaggedValue::Undefined();
378 }
379
GetLength(EcmaRuntimeCallInfo *argv)380 JSTaggedValue ContainersHashMap::GetLength(EcmaRuntimeCallInfo *argv)
381 {
382 ASSERT(argv != nullptr);
383 JSThread *thread = argv->GetThread();
384 BUILTINS_API_TRACE(thread, HashMap, GetLength);
385 [[maybe_unused]] EcmaHandleScope handleScope(thread);
386 JSHandle<JSTaggedValue> self = GetThis(argv);
387 if (!self->IsJSAPIHashMap()) {
388 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
389 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
390 } else {
391 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
392 "The getLength method cannot be bound");
393 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
394 }
395 }
396 JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
397 return jsHashMap->GetLength();
398 }
399
IsEmpty(EcmaRuntimeCallInfo *argv)400 JSTaggedValue ContainersHashMap::IsEmpty(EcmaRuntimeCallInfo *argv)
401 {
402 ASSERT(argv != nullptr);
403 JSThread *thread = argv->GetThread();
404 BUILTINS_API_TRACE(thread, HashMap, IsEmpty);
405 [[maybe_unused]] EcmaHandleScope handleScope(thread);
406 JSHandle<JSTaggedValue> self = GetThis(argv);
407 if (!self->IsJSAPIHashMap()) {
408 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
409 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
410 } else {
411 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
412 "The isEmpty method cannot be bound");
413 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
414 }
415 }
416 JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
417 return jsHashMap->IsEmpty();
418 }
419 } // namespace panda::ecmascript::containers
420