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