• 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         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