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 23namespace panda::ecmascript::containers { 24JSTaggedValue 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 52JSTaggedValue 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 73JSTaggedValue 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 94JSTaggedValue 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 115JSTaggedValue 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 136JSTaggedValue 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 189JSTaggedValue 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 213JSTaggedValue 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 250JSTaggedValue 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 271JSTaggedValue 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 293JSTaggedValue 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 315JSTaggedValue 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 337JSTaggedValue 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 359JSTaggedValue 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 380JSTaggedValue 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 400JSTaggedValue 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