14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_shared_map.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter.h" 194514f5e3Sopenharmony_ci#include "ecmascript/js_function.h" 204514f5e3Sopenharmony_ci#include "ecmascript/linked_hash_table.h" 214514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/concurrent_api_scope.h" 224514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_shared_map.h" 234514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_shared_map_iterator.h" 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins { 264514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Constructor(EcmaRuntimeCallInfo *argv) 274514f5e3Sopenharmony_ci{ 284514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Constructor); 294514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 304514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 314514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 324514f5e3Sopenharmony_ci // 1. If NewTarget is undefined, throw exception 334514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv); 344514f5e3Sopenharmony_ci if (newTarget->IsUndefined()) { 354514f5e3Sopenharmony_ci JSTaggedValue error = containers::ContainerError::BusinessError( 364514f5e3Sopenharmony_ci thread, containers::ErrorFlag::IS_NULL_ERROR, "The ArkTS Map's constructor cannot be directly invoked."); 374514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 384514f5e3Sopenharmony_ci } 394514f5e3Sopenharmony_ci // 2.Let Map be OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", «[[MapData]]» ). 404514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> constructor = GetConstructor(argv); 414514f5e3Sopenharmony_ci ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap()); 424514f5e3Sopenharmony_ci JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget); 434514f5e3Sopenharmony_ci // 3.returnIfAbrupt() 444514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 454514f5e3Sopenharmony_ci ASSERT(obj.GetTaggedValue().IsInSharedHeap()); 464514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map = JSHandle<JSSharedMap>::Cast(obj); 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ci // 4.Set map’s [[MapData]] internal slot to a new empty List. 494514f5e3Sopenharmony_ci JSHandle<LinkedHashMap> linkedMap = LinkedHashMap::Create(thread, 504514f5e3Sopenharmony_ci LinkedHashMap::MIN_CAPACITY, MemSpaceKind::SHARED); 514514f5e3Sopenharmony_ci map->SetLinkedMap(thread, linkedMap); 524514f5e3Sopenharmony_ci // add data into set from iterable 534514f5e3Sopenharmony_ci // 5.If iterable is not present, let iterable be undefined. 544514f5e3Sopenharmony_ci // 6.If iterable is either undefined or null, let iter be undefined. 554514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> iterable = GetCallArg(argv, 0); 564514f5e3Sopenharmony_ci if (iterable->IsUndefined() || iterable->IsNull()) { 574514f5e3Sopenharmony_ci return map.GetTaggedValue(); 584514f5e3Sopenharmony_ci } 594514f5e3Sopenharmony_ci if (!iterable->IsECMAObject()) { 604514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "iterable is not object", JSTaggedValue::Exception()); 614514f5e3Sopenharmony_ci } 624514f5e3Sopenharmony_ci // Let adder be Get(map, "set"). 634514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> adderKey = thread->GlobalConstants()->GetHandledSetString(); 644514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> adder = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(map), adderKey).GetValue(); 654514f5e3Sopenharmony_ci // ReturnIfAbrupt(adder). 664514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, adder.GetTaggedValue()); 674514f5e3Sopenharmony_ci return AddEntriesFromIterable(thread, obj, iterable, adder, factory); 684514f5e3Sopenharmony_ci} 694514f5e3Sopenharmony_ci 704514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Set(EcmaRuntimeCallInfo *argv) 714514f5e3Sopenharmony_ci{ 724514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Set); 734514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 744514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 754514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 764514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 774514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 784514f5e3Sopenharmony_ci "The set method cannot be bound."); 794514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key = GetCallArg(argv, 0); 824514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = GetCallArg(argv, 1); 834514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 844514f5e3Sopenharmony_ci JSSharedMap::Set(thread, map, key, value); 854514f5e3Sopenharmony_ci return map.GetTaggedValue(); 864514f5e3Sopenharmony_ci} 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Clear(EcmaRuntimeCallInfo *argv) 894514f5e3Sopenharmony_ci{ 904514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Clear); 914514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 924514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 934514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 944514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 954514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 964514f5e3Sopenharmony_ci "The clear method cannot be bound."); 974514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 984514f5e3Sopenharmony_ci } 994514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 1004514f5e3Sopenharmony_ci JSSharedMap::Clear(thread, map); 1014514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 1024514f5e3Sopenharmony_ci} 1034514f5e3Sopenharmony_ci 1044514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Delete(EcmaRuntimeCallInfo *argv) 1054514f5e3Sopenharmony_ci{ 1064514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Delete); 1074514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1084514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1094514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 1104514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 1114514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 1124514f5e3Sopenharmony_ci "The delete method cannot be bound."); 1134514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1144514f5e3Sopenharmony_ci } 1154514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 1164514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key = GetCallArg(argv, 0); 1174514f5e3Sopenharmony_ci bool flag = JSSharedMap::Delete(thread, map, key); 1184514f5e3Sopenharmony_ci return GetTaggedBoolean(flag); 1194514f5e3Sopenharmony_ci} 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Has(EcmaRuntimeCallInfo *argv) 1224514f5e3Sopenharmony_ci{ 1234514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Has); 1244514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1254514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1264514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self(GetThis(argv)); 1274514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 1284514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 1294514f5e3Sopenharmony_ci "The has method cannot be bound."); 1304514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1314514f5e3Sopenharmony_ci } 1324514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 1334514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key = GetCallArg(argv, 0); 1344514f5e3Sopenharmony_ci bool flag = JSSharedMap::Has(thread, map, key.GetTaggedValue()); 1354514f5e3Sopenharmony_ci return GetTaggedBoolean(flag); 1364514f5e3Sopenharmony_ci} 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Get(EcmaRuntimeCallInfo *argv) 1394514f5e3Sopenharmony_ci{ 1404514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Get); 1414514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1424514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1434514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self(GetThis(argv)); 1444514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 1454514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 1464514f5e3Sopenharmony_ci "The get method cannot be bound."); 1474514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 1504514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key = GetCallArg(argv, 0); 1514514f5e3Sopenharmony_ci JSTaggedValue value = JSSharedMap::Get(thread, map, key.GetTaggedValue()); 1524514f5e3Sopenharmony_ci return value; 1534514f5e3Sopenharmony_ci} 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::ForEach(EcmaRuntimeCallInfo *argv) 1564514f5e3Sopenharmony_ci{ 1574514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1584514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, SharedMap, ForEach); 1594514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1604514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 1614514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 1624514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 1634514f5e3Sopenharmony_ci "The forEach method cannot be bound."); 1644514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 1654514f5e3Sopenharmony_ci } 1664514f5e3Sopenharmony_ci [[maybe_unused]] ConcurrentApiScope<JSSharedMap> scope(thread, self); 1674514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); 1684514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 1694514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> func(GetCallArg(argv, 0)); 1704514f5e3Sopenharmony_ci if (!func->IsCallable()) { 1714514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not Callable", JSTaggedValue::Exception()); 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> thisArg = GetCallArg(argv, 1); 1744514f5e3Sopenharmony_ci JSMutableHandle<LinkedHashMap> hashMap(thread, map->GetLinkedMap()); 1754514f5e3Sopenharmony_ci const uint32_t argsLength = 3; 1764514f5e3Sopenharmony_ci int index = 0; 1774514f5e3Sopenharmony_ci int totalElements = hashMap->NumberOfElements() + hashMap->NumberOfDeletedElements(); 1784514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 1794514f5e3Sopenharmony_ci // Repeat for each e that is an element of entries, in original insertion order 1804514f5e3Sopenharmony_ci while (index < totalElements) { 1814514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key(thread, hashMap->GetKey(index++)); 1824514f5e3Sopenharmony_ci if (!key->IsHole()) { 1834514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value(thread, hashMap->GetValue(index - 1)); 1844514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo( 1854514f5e3Sopenharmony_ci thread, func, thisArg, undefined, argsLength); 1864514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1874514f5e3Sopenharmony_ci info->SetCallArg(value.GetTaggedValue(), key.GetTaggedValue(), map.GetTaggedValue()); 1884514f5e3Sopenharmony_ci JSTaggedValue ret = JSFunction::Call(info); 1894514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ret); 1904514f5e3Sopenharmony_ci } 1914514f5e3Sopenharmony_ci } 1924514f5e3Sopenharmony_ci 1934514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 1944514f5e3Sopenharmony_ci} 1954514f5e3Sopenharmony_ci 1964514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Species(EcmaRuntimeCallInfo *argv) 1974514f5e3Sopenharmony_ci{ 1984514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Species); 1994514f5e3Sopenharmony_ci return GetThis(argv).GetTaggedValue(); 2004514f5e3Sopenharmony_ci} 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::GetSize(EcmaRuntimeCallInfo *argv) 2034514f5e3Sopenharmony_ci{ 2044514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, GetSize); 2054514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2064514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2074514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self(GetThis(argv)); 2084514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 2094514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not SharedMap", JSTaggedValue::Exception()); 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci JSHandle<JSSharedMap> map(self); 2124514f5e3Sopenharmony_ci uint32_t size = JSSharedMap::GetSize(thread, map); 2134514f5e3Sopenharmony_ci return JSTaggedValue(size); 2144514f5e3Sopenharmony_ci} 2154514f5e3Sopenharmony_ci 2164514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Entries(EcmaRuntimeCallInfo *argv) 2174514f5e3Sopenharmony_ci{ 2184514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Entries); 2194514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2204514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2214514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 2224514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 2234514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 2244514f5e3Sopenharmony_ci "The entries method cannot be bound."); 2254514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> iter = JSSharedMapIterator::CreateMapIterator(thread, self, IterationKind::KEY_AND_VALUE); 2284514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2294514f5e3Sopenharmony_ci return iter.GetTaggedValue(); 2304514f5e3Sopenharmony_ci} 2314514f5e3Sopenharmony_ci 2324514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Keys(EcmaRuntimeCallInfo *argv) 2334514f5e3Sopenharmony_ci{ 2344514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Keys); 2354514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2364514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2374514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 2384514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 2394514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 2404514f5e3Sopenharmony_ci "The keys method cannot be bound."); 2414514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2424514f5e3Sopenharmony_ci } 2434514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> iter = JSSharedMapIterator::CreateMapIterator(thread, self, IterationKind::KEY); 2444514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2454514f5e3Sopenharmony_ci return iter.GetTaggedValue(); 2464514f5e3Sopenharmony_ci} 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::Values(EcmaRuntimeCallInfo *argv) 2494514f5e3Sopenharmony_ci{ 2504514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), SharedMap, Values); 2514514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2524514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2534514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> self = GetThis(argv); 2544514f5e3Sopenharmony_ci if (!self->IsJSSharedMap()) { 2554514f5e3Sopenharmony_ci auto error = containers::ContainerError::BusinessError(thread, containers::ErrorFlag::BIND_ERROR, 2564514f5e3Sopenharmony_ci "The values method cannot be bound."); 2574514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 2584514f5e3Sopenharmony_ci } 2594514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> iter = JSSharedMapIterator::CreateMapIterator(thread, self, IterationKind::VALUE); 2604514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2614514f5e3Sopenharmony_ci return iter.GetTaggedValue(); 2624514f5e3Sopenharmony_ci} 2634514f5e3Sopenharmony_ci 2644514f5e3Sopenharmony_ciJSTaggedValue BuiltinsSharedMap::AddEntriesFromIterable(JSThread *thread, const JSHandle<JSObject> &target, 2654514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &iterable, const JSHandle<JSTaggedValue> &adder, ObjectFactory *factory) 2664514f5e3Sopenharmony_ci{ 2674514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, SharedMap, AddEntriesFromIterable); 2684514f5e3Sopenharmony_ci // If IsCallable(adder) is false, throw a TypeError exception 2694514f5e3Sopenharmony_ci if (!adder->IsCallable()) { 2704514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "adder is not callable", adder.GetTaggedValue()); 2714514f5e3Sopenharmony_ci } 2724514f5e3Sopenharmony_ci // Let iter be GetIterator(iterable). 2734514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> iter(JSIterator::GetIterator(thread, iterable)); 2744514f5e3Sopenharmony_ci // ReturnIfAbrupt(iter). 2754514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, iter.GetTaggedValue()); 2764514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> keyIndex(thread, JSTaggedValue(0)); 2774514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> valueIndex(thread, JSTaggedValue(1)); 2784514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> next = JSIterator::IteratorStep(thread, iter); 2794514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, next.GetTaggedValue()); 2804514f5e3Sopenharmony_ci while (!next->IsFalse()) { 2814514f5e3Sopenharmony_ci // Let nextValue be IteratorValue(next). 2824514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> nextValue(JSIterator::IteratorValue(thread, next)); 2834514f5e3Sopenharmony_ci // ReturnIfAbrupt(nextValue). 2844514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, next.GetTaggedValue()); 2854514f5e3Sopenharmony_ci 2864514f5e3Sopenharmony_ci // If Type(nextItem) is not Object 2874514f5e3Sopenharmony_ci if (!nextValue->IsECMAObject()) { 2884514f5e3Sopenharmony_ci JSHandle<JSObject> typeError = factory->GetJSError(ErrorType::TYPE_ERROR, 2894514f5e3Sopenharmony_ci "nextItem is not Object", StackCheck::NO); 2904514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> record( 2914514f5e3Sopenharmony_ci factory->NewCompletionRecord(CompletionRecordType::THROW, JSHandle<JSTaggedValue>(typeError))); 2924514f5e3Sopenharmony_ci JSTaggedValue ret = JSIterator::IteratorClose(thread, iter, record).GetTaggedValue(); 2934514f5e3Sopenharmony_ci if (!thread->HasPendingException()) { 2944514f5e3Sopenharmony_ci THROW_NEW_ERROR_AND_RETURN_VALUE(thread, typeError.GetTaggedValue(), ret); 2954514f5e3Sopenharmony_ci } 2964514f5e3Sopenharmony_ci return ret; 2974514f5e3Sopenharmony_ci } 2984514f5e3Sopenharmony_ci // Let k be Get(nextItem, "0"). 2994514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> key = JSTaggedValue::GetProperty(thread, nextValue, keyIndex).GetValue(); 3004514f5e3Sopenharmony_ci // If k is an abrupt completion, return IteratorClose(iter, k). 3014514f5e3Sopenharmony_ci if (thread->HasPendingException()) { 3024514f5e3Sopenharmony_ci return JSIterator::IteratorCloseAndReturn(thread, iter); 3034514f5e3Sopenharmony_ci } 3044514f5e3Sopenharmony_ci // Let v be Get(nextItem, "1"). 3054514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = JSTaggedValue::GetProperty(thread, nextValue, valueIndex).GetValue(); 3064514f5e3Sopenharmony_ci // If v is an abrupt completion, return IteratorClose(iter, v). 3074514f5e3Sopenharmony_ci if (thread->HasPendingException()) { 3084514f5e3Sopenharmony_ci return JSIterator::IteratorCloseAndReturn(thread, iter); 3094514f5e3Sopenharmony_ci } 3104514f5e3Sopenharmony_ci const uint32_t argsLength = 2; // 2: key and value pair 3114514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 3124514f5e3Sopenharmony_ci EcmaRuntimeCallInfo *info = 3134514f5e3Sopenharmony_ci EcmaInterpreter::NewRuntimeCallInfo(thread, adder, JSHandle<JSTaggedValue>(target), undefined, argsLength); 3144514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, next.GetTaggedValue()); 3154514f5e3Sopenharmony_ci info->SetCallArg(key.GetTaggedValue(), value.GetTaggedValue()); 3164514f5e3Sopenharmony_ci JSFunction::Call(info); 3174514f5e3Sopenharmony_ci // If status is an abrupt completion, return IteratorClose(iter, status). 3184514f5e3Sopenharmony_ci if (thread->HasPendingException()) { 3194514f5e3Sopenharmony_ci return JSIterator::IteratorCloseAndReturn(thread, iter); 3204514f5e3Sopenharmony_ci } 3214514f5e3Sopenharmony_ci // Let next be IteratorStep(iter). 3224514f5e3Sopenharmony_ci next = JSIterator::IteratorStep(thread, iter); 3234514f5e3Sopenharmony_ci // ReturnIfAbrupt(next). 3244514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, next.GetTaggedValue()); 3254514f5e3Sopenharmony_ci } 3264514f5e3Sopenharmony_ci return target.GetTaggedValue(); 3274514f5e3Sopenharmony_ci} 3284514f5e3Sopenharmony_ci} // namespace panda::ecmascript::builtins 329