• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "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         CString errorMsg =
142             "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
143         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
144         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
145     }
146     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
147     JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(thisHandle);
148     JSHandle<TaggedHashArray> table(thread, hashMap->GetTable());
149     uint32_t len = table->GetLength();
150     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
151     JSMutableHandle<TaggedQueue> queue(thread, factory->NewTaggedQueue(0));
152     JSMutableHandle<TaggedNode> node(thread, JSTaggedValue::Undefined());
153     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
154     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
155     uint32_t index = 0;
156     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
157     while (index < len) {
158         node.Update(TaggedHashArray::GetCurrentNode(thread, queue, table, index));
159         if (!node.GetTaggedValue().IsHole()) {
160             key.Update(node->GetKey());
161             value.Update(node->GetValue());
162             EcmaRuntimeCallInfo *info =
163                 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle,
164                                                     thisArgHandle, undefined, 3); // 3: three args
165             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
166             info->SetCallArg(value.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
167             JSTaggedValue funcResult = JSFunction::Call(info);
168             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
169         }
170     }
171     return JSTaggedValue::Undefined();
172 }
173 
Set(EcmaRuntimeCallInfo * argv)174 JSTaggedValue ContainersHashMap::Set(EcmaRuntimeCallInfo *argv)
175 {
176     ASSERT(argv != nullptr);
177     JSThread *thread = argv->GetThread();
178     BUILTINS_API_TRACE(thread, HashMap, Set);
179     [[maybe_unused]] EcmaHandleScope handleScope(thread);
180     JSHandle<JSTaggedValue> self = GetThis(argv);
181     if (!self->IsJSAPIHashMap()) {
182         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
183             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
184         } else {
185             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
186                                                                 "The set method cannot be bound");
187             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
188         }
189     }
190     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
191     JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
192     JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
193     JSAPIHashMap::Set(thread, hashMap, key, value);
194     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
195     return hashMap.GetTaggedValue();
196 }
197 
SetAll(EcmaRuntimeCallInfo * argv)198 JSTaggedValue ContainersHashMap::SetAll(EcmaRuntimeCallInfo *argv)
199 {
200     ASSERT(argv != nullptr);
201     JSThread *thread = argv->GetThread();
202     BUILTINS_API_TRACE(thread, HashMap, SetAll);
203     [[maybe_unused]] EcmaHandleScope handleScope(thread);
204     JSHandle<JSTaggedValue> self = GetThis(argv);
205     if (!self->IsJSAPIHashMap()) {
206         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
207             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
208         } else {
209             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
210                                                                 "The setAll method cannot be bound");
211             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
212         }
213     }
214 
215     JSHandle<JSTaggedValue> obj = GetCallArg(argv, 0);
216     if (!obj->IsJSAPIHashMap()) {
217         if (obj->IsJSProxy() && JSHandle<JSProxy>::Cast(obj)->GetTarget().IsJSAPIHashMap()) {
218             obj = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(obj)->GetTarget());
219         } else {
220             JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, obj);
221             CString errorMsg =
222                 "The type of \"map\" must be HashMap. Received value is: " + ConvertToString(*result);
223             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
224             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
225         }
226     }
227 
228     JSHandle<JSAPIHashMap> targetMap = JSHandle<JSAPIHashMap>::Cast(self);
229     JSHandle<JSAPIHashMap> sourceMap = JSHandle<JSAPIHashMap>::Cast(obj);
230     JSAPIHashMap::SetAll(thread, targetMap, sourceMap);
231     return self.GetTaggedValue();
232 }
233 
Get(EcmaRuntimeCallInfo * argv)234 JSTaggedValue ContainersHashMap::Get(EcmaRuntimeCallInfo *argv)
235 {
236     ASSERT(argv != nullptr);
237     JSThread *thread = argv->GetThread();
238     BUILTINS_API_TRACE(thread, HashMap, Get);
239     [[maybe_unused]] EcmaHandleScope handleScope(thread);
240     JSHandle<JSTaggedValue> self = GetThis(argv);
241     if (!self->IsJSAPIHashMap()) {
242         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
243             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
244         } else {
245             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
246                                                                 "The get method cannot be bound");
247             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
248         }
249     }
250     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
251     JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
252     return hashMap->Get(thread, key.GetTaggedValue());
253 }
254 
Remove(EcmaRuntimeCallInfo * argv)255 JSTaggedValue ContainersHashMap::Remove(EcmaRuntimeCallInfo *argv)
256 {
257     ASSERT(argv != nullptr);
258     JSThread *thread = argv->GetThread();
259     BUILTINS_API_TRACE(thread, HashMap, Remove);
260     [[maybe_unused]] EcmaHandleScope handleScope(thread);
261     JSHandle<JSTaggedValue> self = GetThis(argv);
262 
263     if (!self->IsJSAPIHashMap()) {
264         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
265             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
266         } else {
267             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
268                                                                 "The remove method cannot be bound");
269             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
270         }
271     }
272     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
273     JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
274     return JSAPIHashMap::Remove(thread, hashMap, key.GetTaggedValue());
275 }
276 
HasKey(EcmaRuntimeCallInfo * argv)277 JSTaggedValue ContainersHashMap::HasKey(EcmaRuntimeCallInfo *argv)
278 {
279     ASSERT(argv != nullptr);
280     JSThread *thread = argv->GetThread();
281     BUILTINS_API_TRACE(thread, HashMap, HasKey);
282     [[maybe_unused]] EcmaHandleScope handleScope(thread);
283     JSHandle<JSTaggedValue> self = GetThis(argv);
284 
285     if (!self->IsJSAPIHashMap()) {
286         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
287             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
288         } else {
289             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
290                                                                 "The hasKey method cannot be bound");
291             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
292         }
293     }
294     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
295     JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
296     return hashMap->HasKey(thread, key.GetTaggedValue());
297 }
298 
HasValue(EcmaRuntimeCallInfo * argv)299 JSTaggedValue ContainersHashMap::HasValue(EcmaRuntimeCallInfo *argv)
300 {
301     ASSERT(argv != nullptr);
302     JSThread *thread = argv->GetThread();
303     BUILTINS_API_TRACE(thread, HashMap, HasValue);
304     [[maybe_unused]] EcmaHandleScope handleScope(thread);
305     JSHandle<JSTaggedValue> self = GetThis(argv);
306 
307     if (!self->IsJSAPIHashMap()) {
308         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
309             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
310         } else {
311             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
312                                                                 "The hasValue method cannot be bound");
313             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
314         }
315     }
316     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
317     JSHandle<JSAPIHashMap> hashMap = JSHandle<JSAPIHashMap>::Cast(self);
318     return JSAPIHashMap::HasValue(thread, hashMap, value);
319 }
320 
Replace(EcmaRuntimeCallInfo * argv)321 JSTaggedValue ContainersHashMap::Replace(EcmaRuntimeCallInfo *argv)
322 {
323     ASSERT(argv != nullptr);
324     JSThread *thread = argv->GetThread();
325     BUILTINS_API_TRACE(thread, HashMap, Replace);
326     [[maybe_unused]] EcmaHandleScope handleScope(thread);
327     JSHandle<JSTaggedValue> self = GetThis(argv);
328     if (!self->IsJSAPIHashMap()) {
329         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
330             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
331         } else {
332             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
333                                                                 "The replace method cannot be bound");
334             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
335         }
336     }
337     JSHandle<JSTaggedValue> key = GetCallArg(argv, 0);
338     JSHandle<JSTaggedValue> newValue = GetCallArg(argv, 1);
339     JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
340     return jsHashMap->Replace(thread, key.GetTaggedValue(), newValue.GetTaggedValue());
341 }
342 
Clear(EcmaRuntimeCallInfo * argv)343 JSTaggedValue ContainersHashMap::Clear(EcmaRuntimeCallInfo *argv)
344 {
345     ASSERT(argv != nullptr);
346     JSThread *thread = argv->GetThread();
347     BUILTINS_API_TRACE(thread, HashMap, Clear);
348     [[maybe_unused]] EcmaHandleScope handleScope(thread);
349     JSHandle<JSTaggedValue> self = GetThis(argv);
350     if (!self->IsJSAPIHashMap()) {
351         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
352             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
353         } else {
354             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
355                                                                 "The clear method cannot be bound");
356             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
357         }
358     }
359     JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
360     jsHashMap->Clear(thread);
361     return JSTaggedValue::Undefined();
362 }
363 
GetLength(EcmaRuntimeCallInfo * argv)364 JSTaggedValue ContainersHashMap::GetLength(EcmaRuntimeCallInfo *argv)
365 {
366     ASSERT(argv != nullptr);
367     JSThread *thread = argv->GetThread();
368     BUILTINS_API_TRACE(thread, HashMap, GetLength);
369     [[maybe_unused]] EcmaHandleScope handleScope(thread);
370     JSHandle<JSTaggedValue> self = GetThis(argv);
371     if (!self->IsJSAPIHashMap()) {
372         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
373             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
374         } else {
375             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
376                                                                 "The getLength method cannot be bound");
377             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
378         }
379     }
380     JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
381     return jsHashMap->GetLength();
382 }
383 
IsEmpty(EcmaRuntimeCallInfo * argv)384 JSTaggedValue ContainersHashMap::IsEmpty(EcmaRuntimeCallInfo *argv)
385 {
386     ASSERT(argv != nullptr);
387     JSThread *thread = argv->GetThread();
388     BUILTINS_API_TRACE(thread, HashMap, IsEmpty);
389     [[maybe_unused]] EcmaHandleScope handleScope(thread);
390     JSHandle<JSTaggedValue> self = GetThis(argv);
391     if (!self->IsJSAPIHashMap()) {
392         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIHashMap()) {
393             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
394         } else {
395             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
396                                                                 "The isEmpty method cannot be bound");
397             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
398         }
399     }
400     JSHandle<JSAPIHashMap> jsHashMap = JSHandle<JSAPIHashMap>::Cast(self);
401     return jsHashMap->IsEmpty();
402 }
403 } // namespace panda::ecmascript::containers
404