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 "ecmascript/containers/containers_private.h"
17
18#include "containers_arraylist.h"
19#include "containers_bitvector.h"
20#include "containers_deque.h"
21#include "containers_hashmap.h"
22#include "containers_hashset.h"
23#include "containers_lightweightmap.h"
24#include "containers_lightweightset.h"
25#include "containers_linked_list.h"
26#include "containers_list.h"
27#include "containers_plainarray.h"
28#include "containers_queue.h"
29#include "containers_stack.h"
30#include "containers_treemap.h"
31#include "containers_treeset.h"
32#include "containers_vector.h"
33#include "ecmascript/js_api/js_api_arraylist_iterator.h"
34#include "ecmascript/js_api/js_api_bitvector_iterator.h"
35#include "ecmascript/js_api/js_api_deque_iterator.h"
36#include "ecmascript/js_api/js_api_hashmap_iterator.h"
37#include "ecmascript/js_api/js_api_hashset_iterator.h"
38#include "ecmascript/js_api/js_api_hashset.h"
39#include "ecmascript/js_api/js_api_lightweightmap_iterator.h"
40#include "ecmascript/js_api/js_api_lightweightmap.h"
41#include "ecmascript/js_api/js_api_lightweightset_iterator.h"
42#include "ecmascript/js_api/js_api_lightweightset.h"
43#include "ecmascript/js_api/js_api_linked_list_iterator.h"
44#include "ecmascript/js_api/js_api_list_iterator.h"
45#include "ecmascript/js_api/js_api_plain_array_iterator.h"
46#include "ecmascript/js_api/js_api_queue_iterator.h"
47#include "ecmascript/js_api/js_api_stack_iterator.h"
48#include "ecmascript/js_api/js_api_tree_map_iterator.h"
49#include "ecmascript/js_api/js_api_tree_map.h"
50#include "ecmascript/js_api/js_api_tree_set_iterator.h"
51#include "ecmascript/js_api/js_api_tree_set.h"
52#include "ecmascript/js_api/js_api_vector_iterator.h"
53#include "ecmascript/object_fast_operator-inl.h"
54
55namespace panda::ecmascript::containers {
56JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg)
57{
58    ASSERT(msg != nullptr);
59    JSThread *thread = msg->GetThread();
60    [[maybe_unused]] EcmaHandleScope handleScope(thread);
61    JSHandle<JSTaggedValue> argv = GetCallArg(msg, 0);
62    JSHandle<JSObject> thisValue(GetThis(msg));
63
64    uint32_t tag = 0;
65    if (!JSTaggedValue::ToElementIndex(argv.GetTaggedValue(), &tag) || tag >= ContainerTag::END) {
66        THROW_TYPE_ERROR_AND_RETURN(thread, "Incorrect input parameters", JSTaggedValue::Exception());
67    }
68
69    // Lazy set an undefinedIteratorResult to global constants
70    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
71    JSHandle<JSTaggedValue> undefinedHandle = globalConst->GetHandledUndefined();
72    JSHandle<JSObject> undefinedIteratorResult = JSIterator::CreateIterResultObject(thread, undefinedHandle, true);
73    globalConst->SetConstant(ConstantIndex::UNDEFINED_INTERATOR_RESULT_INDEX, undefinedIteratorResult.GetTaggedValue());
74
75    JSTaggedValue res = JSTaggedValue::Undefined();
76    switch (tag) {
77        case ContainerTag::ArrayList: {
78            res = InitializeContainer(thread, thisValue, InitializeArrayList, "ArrayListConstructor");
79            break;
80        }
81        case ContainerTag::Deque: {
82            res = InitializeContainer(thread, thisValue, InitializeDeque, "DequeConstructor");
83            break;
84        }
85        case ContainerTag::LightWeightMap: {
86            res = InitializeContainer(thread, thisValue, InitializeLightWeightMap, "LightWeightMapConstructor");
87            break;
88        }
89        case ContainerTag::LightWeightSet: {
90            res = InitializeContainer(thread, thisValue, InitializeLightWeightSet, "LightWeightSetConstructor");
91            break;
92        }
93        case ContainerTag::PlainArray: {
94            res = InitializeContainer(thread, thisValue, InitializePlainArray, "PlainArrayConstructor");
95            break;
96        }
97        case ContainerTag::Queue: {
98            res = InitializeContainer(thread, thisValue, InitializeQueue, "QueueConstructor");
99            break;
100        }
101        case ContainerTag::Stack: {
102            res = InitializeContainer(thread, thisValue, InitializeStack, "StackConstructor");
103            break;
104        }
105        case ContainerTag::TreeMap: {
106            res = InitializeContainer(thread, thisValue, InitializeTreeMap, "TreeMapConstructor");
107            break;
108        }
109        case ContainerTag::TreeSet: {
110            res = InitializeContainer(thread, thisValue, InitializeTreeSet, "TreeSetConstructor");
111            break;
112        }
113        case ContainerTag::Vector: {
114            res = InitializeContainer(thread, thisValue, InitializeVector, "VectorConstructor");
115            break;
116        }
117        case ContainerTag::BitVector: {
118            res = InitializeContainer(thread, thisValue, InitializeBitVector, "BitVectorConstructor");
119            break;
120        }
121        case ContainerTag::List: {
122            res = InitializeContainer(thread, thisValue, InitializeList, "ListConstructor");
123            break;
124        }
125        case ContainerTag::LinkedList: {
126            res = InitializeContainer(thread, thisValue, InitializeLinkedList, "LinkedListConstructor");
127            break;
128        }
129        case ContainerTag::HashMap: {
130            res = InitializeContainer(thread, thisValue, InitializeHashMap, "HashMapConstructor");
131            break;
132        }
133        case ContainerTag::HashSet: {
134            res = InitializeContainer(thread, thisValue, InitializeHashSet, "HashSetConstructor");
135            break;
136        }
137        case ContainerTag::END:
138            break;
139        default:
140            LOG_ECMA(FATAL) << "this branch is unreachable";
141            UNREACHABLE();
142    }
143
144    return res;
145}
146
147JSTaggedValue ContainersPrivate::InitializeContainer(JSThread *thread, const JSHandle<JSObject> &obj,
148                                                     InitializeFunction func, const char *name)
149{
150    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
151    JSHandle<JSTaggedValue> key(factory->NewFromASCII(name));
152    JSTaggedValue value = ObjectFastOperator::GetPropertyByName<ObjectFastOperator::Status::UseOwn>
153        (thread, obj.GetTaggedValue(), key.GetTaggedValue());
154    if (!value.IsUndefined()) {
155        return value;
156    }
157    JSHandle<JSTaggedValue> map = func(thread);
158    SetFrozenConstructor(thread, obj, name, map);
159    return map.GetTaggedValue();
160}
161
162JSHandle<JSFunction> ContainersPrivate::NewContainerConstructor(JSThread *thread, const JSHandle<JSObject> &prototype,
163                                                                EcmaEntrypoint ctorFunc, const char *name, int length)
164{
165    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
166    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
167    JSHandle<JSFunction> ctor =
168        factory->NewJSFunction(env, reinterpret_cast<void *>(ctorFunc), FunctionKind::BUILTIN_CONSTRUCTOR);
169
170    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
171    JSFunction::SetFunctionLength(thread, ctor, JSTaggedValue(length));
172    JSHandle<JSTaggedValue> nameString(factory->NewFromASCII(name));
173    JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(ctor), nameString,
174                                globalConst->GetHandledUndefined());
175    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
176    PropertyDescriptor descriptor1(thread, JSHandle<JSTaggedValue>::Cast(ctor), true, false, true);
177    JSObject::DefineOwnProperty(thread, prototype, constructorKey, descriptor1);
178
179    /* set "prototype" in constructor */
180    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread, ctor, prototype.GetTaggedValue());
181
182    return ctor;
183}
184
185void ContainersPrivate::SetFrozenFunction(JSThread *thread, const JSHandle<JSObject> &obj, const char *key,
186                                          EcmaEntrypoint func, int length, kungfu::BuiltinsStubCSigns::ID builtinId)
187{
188    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
189    JSHandle<JSTaggedValue> keyString(factory->NewFromASCII(key));
190    JSHandle<JSFunction> function = NewFunction(thread, keyString, func, length, builtinId);
191    PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>(function), false, false, false);
192    JSObject::DefineOwnProperty(thread, obj, keyString, descriptor);
193}
194
195void ContainersPrivate::SetFrozenConstructor(JSThread *thread, const JSHandle<JSObject> &obj, const char *keyChar,
196                                             JSHandle<JSTaggedValue> &value)
197{
198    JSObject::PreventExtensions(thread, JSHandle<JSObject>::Cast(value));
199    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
200    JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyChar));
201    PropertyDescriptor descriptor(thread, value, false, false, false);
202    JSObject::DefineOwnProperty(thread, obj, key, descriptor);
203}
204
205JSHandle<JSFunction> ContainersPrivate::NewFunction(JSThread *thread, const JSHandle<JSTaggedValue> &key,
206                                                    EcmaEntrypoint func, int length,
207                                                    kungfu::BuiltinsStubCSigns::ID builtinId)
208{
209    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
210    JSHandle<JSFunction> function =
211        factory->NewJSFunction(thread->GetEcmaVM()->GetGlobalEnv(), reinterpret_cast<void *>(func),
212                               FunctionKind::NORMAL_FUNCTION, builtinId);
213    JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
214    JSHandle<JSFunctionBase> baseFunction(function);
215    JSFunction::SetFunctionName(thread, baseFunction, key, thread->GlobalConstants()->GetHandledUndefined());
216    return function;
217}
218
219JSHandle<JSTaggedValue> ContainersPrivate::CreateGetter(JSThread *thread, EcmaEntrypoint func, const char *name,
220                                                        int length)
221{
222    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
223    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
224    JSHandle<JSFunction> function = factory->NewJSFunction(env, reinterpret_cast<void *>(func));
225    JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
226    JSHandle<JSTaggedValue> funcName(factory->NewFromASCII(name));
227    JSHandle<JSTaggedValue> prefix = thread->GlobalConstants()->GetHandledGetString();
228    JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(function), funcName, prefix);
229    return JSHandle<JSTaggedValue>(function);
230}
231
232void ContainersPrivate::SetGetter(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
233                                  const JSHandle<JSTaggedValue> &getter)
234{
235    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
236    JSHandle<AccessorData> accessor = factory->NewAccessorData();
237    accessor->SetGetter(thread, getter);
238    PropertyAttributes attr = PropertyAttributes::DefaultAccessor(false, false, false);
239    JSObject::AddAccessor(thread, JSHandle<JSTaggedValue>::Cast(obj), key, accessor, attr);
240}
241
242void ContainersPrivate::SetFunctionAtSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
243                                            const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &symbol,
244                                            const char *name, EcmaEntrypoint func, int length)
245{
246    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
247    JSHandle<JSFunction> function = factory->NewJSFunction(env, reinterpret_cast<void *>(func));
248    JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
249    JSHandle<JSTaggedValue> nameString(factory->NewFromASCII(name));
250    JSHandle<JSFunctionBase> baseFunction(function);
251    JSFunction::SetFunctionName(thread, baseFunction, nameString, thread->GlobalConstants()->GetHandledUndefined());
252    PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(function), false, false, false);
253    JSObject::DefineOwnProperty(thread, obj, symbol, descriptor);
254}
255
256void ContainersPrivate::SetStringTagSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
257                                           const JSHandle<JSObject> &obj, const char *key)
258{
259    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
260    JSHandle<JSTaggedValue> tag(factory->NewFromASCII(key));
261    JSHandle<JSTaggedValue> symbol = env->GetToStringTagSymbol();
262    PropertyDescriptor desc(thread, tag, false, false, false);
263    JSObject::DefineOwnProperty(thread, obj, symbol, desc);
264}
265
266JSHandle<JSTaggedValue> ContainersPrivate::InitializeArrayList(JSThread *thread)
267{
268    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
269    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
270    // ArrayList.prototype
271    JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
272    JSHandle<JSTaggedValue> arrayListFuncPrototypeValue(prototype);
273    // ArrayList.prototype_or_hclass
274    JSHandle<JSHClass> arrayListInstanceClass =
275        factory->NewEcmaHClass(JSAPIArrayList::SIZE, JSType::JS_API_ARRAY_LIST, arrayListFuncPrototypeValue);
276    // ArrayList() = new Function()
277    JSHandle<JSTaggedValue> arrayListFunction(NewContainerConstructor(
278        thread, prototype, ContainersArrayList::ArrayListConstructor, "ArrayList", FuncLength::ZERO));
279    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
280        JSHandle<JSFunction>::Cast(arrayListFunction), arrayListInstanceClass.GetTaggedValue());
281
282    // "constructor" property on the prototype
283    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
284    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, arrayListFunction);
285    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
286
287    // ArrayList.prototype
288    SetFrozenFunction(thread, prototype, "add", ContainersArrayList::Add, FuncLength::ONE);
289    SetFrozenFunction(thread, prototype, "insert", ContainersArrayList::Insert, FuncLength::TWO);
290    SetFrozenFunction(thread, prototype, "clear", ContainersArrayList::Clear, FuncLength::ZERO);
291    SetFrozenFunction(thread, prototype, "clone", ContainersArrayList::Clone, FuncLength::ZERO);
292    SetFrozenFunction(thread, prototype, "has", ContainersArrayList::Has, FuncLength::ONE);
293    SetFrozenFunction(thread, prototype, "getCapacity", ContainersArrayList::GetCapacity, FuncLength::ZERO);
294    SetFrozenFunction(thread, prototype, "increaseCapacityTo",
295                      ContainersArrayList::IncreaseCapacityTo, FuncLength::ONE);
296    SetFrozenFunction(thread, prototype, "trimToCurrentLength",
297                      ContainersArrayList::TrimToCurrentLength, FuncLength::ZERO);
298    SetFrozenFunction(thread, prototype, "getIndexOf", ContainersArrayList::GetIndexOf, FuncLength::ONE);
299    SetFrozenFunction(thread, prototype, "isEmpty", ContainersArrayList::IsEmpty, FuncLength::ZERO);
300    SetFrozenFunction(thread, prototype, "getLastIndexOf", ContainersArrayList::GetLastIndexOf, FuncLength::ONE);
301    SetFrozenFunction(thread, prototype, "removeByIndex", ContainersArrayList::RemoveByIndex, FuncLength::ONE);
302    SetFrozenFunction(thread, prototype, "remove", ContainersArrayList::Remove, FuncLength::ONE);
303    SetFrozenFunction(thread, prototype, "removeByRange", ContainersArrayList::RemoveByRange, FuncLength::TWO);
304    SetFrozenFunction(thread, prototype, "replaceAllElements", ContainersArrayList::ReplaceAllElements,
305        FuncLength::TWO, BUILTINS_STUB_ID(ArrayListReplaceAllElements));
306    SetFrozenFunction(thread, prototype, "sort", ContainersArrayList::Sort, FuncLength::ONE);
307    SetFrozenFunction(thread, prototype, "subArrayList", ContainersArrayList::SubArrayList, FuncLength::TWO);
308    SetFrozenFunction(thread, prototype, "convertToArray", ContainersArrayList::ConvertToArray, FuncLength::ZERO);
309    SetFrozenFunction(thread, prototype, "forEach", ContainersArrayList::ForEach, FuncLength::TWO,
310        BUILTINS_STUB_ID(ArrayListForEach));
311
312    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
313    SetStringTagSymbol(thread, env, prototype, "ArrayList");
314
315    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersArrayList::GetSize, "length",
316                                                        FuncLength::ZERO);
317    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
318    SetGetter(thread, prototype, lengthKey, lengthGetter);
319
320    SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
321                        ContainersArrayList::GetIteratorObj, FuncLength::ONE);
322    ContainersPrivate::InitializeArrayListIterator(thread, env, globalConst);
323    globalConst->SetConstant(ConstantIndex::ARRAYLIST_FUNCTION_INDEX, arrayListFunction.GetTaggedValue());
324    return arrayListFunction;
325}
326
327void ContainersPrivate::InitializeArrayListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
328                                                    GlobalEnvConstants *globalConst)
329{
330    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
331    // Iterator.hclass
332    JSHandle<JSHClass> iteratorFuncHClass =
333        factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
334    // ArrayListIterator.prototype
335    JSHandle<JSObject> arrayListIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
336    // Iterator.prototype.next()
337    SetFrozenFunction(thread, arrayListIteratorPrototype, "next", JSAPIArrayListIterator::Next, FuncLength::ONE);
338    SetStringTagSymbol(thread, env, arrayListIteratorPrototype, "ArrayList Iterator");
339    globalConst->SetConstant(ConstantIndex::ARRAYLIST_ITERATOR_PROTOTYPE_INDEX,
340                             arrayListIteratorPrototype.GetTaggedValue());
341}
342
343JSHandle<JSTaggedValue> ContainersPrivate::InitializeLightWeightMap(JSThread *thread)
344{
345    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
346    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
347    JSHandle<JSObject> funcPrototype = factory->NewEmptyJSObject();
348    JSHandle<JSTaggedValue> mapFuncPrototypeValue(funcPrototype);
349    JSHandle<JSHClass> lightWeightMapInstanceClass =
350        factory->NewEcmaHClass(JSAPILightWeightMap::SIZE, JSType::JS_API_LIGHT_WEIGHT_MAP, mapFuncPrototypeValue);
351    JSHandle<JSTaggedValue> lightWeightMapFunction(NewContainerConstructor(
352        thread, funcPrototype, ContainersLightWeightMap::LightWeightMapConstructor, "LightWeightMap",
353        FuncLength::ZERO));
354    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
355        JSHandle<JSFunction>::Cast(lightWeightMapFunction), lightWeightMapInstanceClass.GetTaggedValue());
356
357    // "constructor" property on the prototype
358    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
359    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(funcPrototype), constructorKey, lightWeightMapFunction);
360    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
361
362    // LightWeightMap.prototype.add()
363    SetFrozenFunction(thread, funcPrototype, "hasAll", ContainersLightWeightMap::HasAll, FuncLength::ONE);
364    SetFrozenFunction(thread, funcPrototype, "hasKey", ContainersLightWeightMap::HasKey, FuncLength::ONE);
365    SetFrozenFunction(thread, funcPrototype, "hasValue", ContainersLightWeightMap::HasValue, FuncLength::ONE);
366    SetFrozenFunction(thread, funcPrototype, "increaseCapacityTo", ContainersLightWeightMap::IncreaseCapacityTo,
367                      FuncLength::ONE);
368    SetFrozenFunction(thread, funcPrototype, "entries", ContainersLightWeightMap::Entries, FuncLength::ONE);
369    SetFrozenFunction(thread, funcPrototype, "get", ContainersLightWeightMap::Get, FuncLength::ONE);
370    SetFrozenFunction(thread, funcPrototype, "getIndexOfKey", ContainersLightWeightMap::GetIndexOfKey, FuncLength::ONE);
371    SetFrozenFunction(thread, funcPrototype, "getIndexOfValue", ContainersLightWeightMap::GetIndexOfValue,
372                      FuncLength::ONE);
373    SetFrozenFunction(thread, funcPrototype, "isEmpty", ContainersLightWeightMap::IsEmpty, FuncLength::ONE);
374    SetFrozenFunction(thread, funcPrototype, "getKeyAt", ContainersLightWeightMap::GetKeyAt, FuncLength::ONE);
375    SetFrozenFunction(thread, funcPrototype, "keys", ContainersLightWeightMap::Keys, FuncLength::ONE);
376    SetFrozenFunction(thread, funcPrototype, "setAll", ContainersLightWeightMap::SetAll, FuncLength::ONE);
377    SetFrozenFunction(thread, funcPrototype, "set", ContainersLightWeightMap::Set, FuncLength::ONE);
378    SetFrozenFunction(thread, funcPrototype, "remove", ContainersLightWeightMap::Remove, FuncLength::ONE);
379    SetFrozenFunction(thread, funcPrototype, "removeAt", ContainersLightWeightMap::RemoveAt, FuncLength::ONE);
380    SetFrozenFunction(thread, funcPrototype, "clear", ContainersLightWeightMap::Clear, FuncLength::ONE);
381    SetFrozenFunction(thread, funcPrototype, "setValueAt", ContainersLightWeightMap::SetValueAt, FuncLength::ONE);
382    SetFrozenFunction(thread, funcPrototype, "forEach", ContainersLightWeightMap::ForEach, FuncLength::ONE,
383                      BUILTINS_STUB_ID(LightWeightMapForEach));
384    SetFrozenFunction(thread, funcPrototype, "toString", ContainersLightWeightMap::ToString, FuncLength::ONE);
385    SetFrozenFunction(thread, funcPrototype, "getValueAt", ContainersLightWeightMap::GetValueAt, FuncLength::ONE);
386    SetFrozenFunction(thread, funcPrototype, "values", ContainersLightWeightMap::Values, FuncLength::ONE);
387
388    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLightWeightMap::Length, "length",
389                                                        FuncLength::ZERO);
390    JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
391    SetGetter(thread, funcPrototype, lengthKey, lengthGetter);
392
393    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
394    SetFunctionAtSymbol(thread, env, funcPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
395                        ContainersLightWeightMap::Entries, FuncLength::ONE);
396
397    ContainersPrivate::InitializeLightWeightMapIterator(thread);
398    return lightWeightMapFunction;
399}
400
401void ContainersPrivate::InitializeLightWeightMapIterator(JSThread *thread)
402{
403    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
404    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
405    JSHandle<JSHClass> iteratorClass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR,
406                                                              env->GetIteratorPrototype());
407    JSHandle<JSObject> lightWeightMapIteratorPrototype(factory->NewJSObject(iteratorClass));
408    SetFrozenFunction(thread, lightWeightMapIteratorPrototype, "next", JSAPILightWeightMapIterator::Next,
409                      FuncLength::ONE);
410    SetStringTagSymbol(thread, env, lightWeightMapIteratorPrototype, "LightWeightMap Iterator");
411    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
412    globalConst->SetConstant(ConstantIndex::LIGHTWEIGHTMAP_ITERATOR_PROTOTYPE_INDEX,
413                             lightWeightMapIteratorPrototype.GetTaggedValue());
414}
415
416JSHandle<JSTaggedValue> ContainersPrivate::InitializeLightWeightSet(JSThread *thread)
417{
418    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
419    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
420    // LightWeightSet.prototype
421    JSHandle<JSObject> funcPrototype = factory->NewEmptyJSObject();
422    JSHandle<JSTaggedValue> funcPrototypeValue(funcPrototype);
423    // LightWeightSet.prototype_or_hclass
424    JSHandle<JSHClass> lightweightSetInstanceClass =
425        factory->NewEcmaHClass(JSAPILightWeightSet::SIZE, JSType::JS_API_LIGHT_WEIGHT_SET, funcPrototypeValue);
426    JSHandle<JSTaggedValue> lightweightSetFunction(
427        NewContainerConstructor(thread, funcPrototype, ContainersLightWeightSet::LightWeightSetConstructor,
428                                "LightWeightSet", FuncLength::ZERO));
429    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
430        JSHandle<JSFunction>::Cast(lightweightSetFunction), lightweightSetInstanceClass.GetTaggedValue());
431    // "constructor" property on the prototype
432    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
433    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(funcPrototype), constructorKey, lightweightSetFunction);
434    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
435    SetFrozenFunction(thread, funcPrototype, "add", ContainersLightWeightSet::Add, FuncLength::ONE);
436    SetFrozenFunction(thread, funcPrototype, "addAll", ContainersLightWeightSet::AddAll, FuncLength::ONE);
437    SetFrozenFunction(thread, funcPrototype, "isEmpty", ContainersLightWeightSet::IsEmpty, FuncLength::ONE);
438    SetFrozenFunction(thread, funcPrototype, "getValueAt", ContainersLightWeightSet::GetValueAt, FuncLength::ONE);
439    SetFrozenFunction(thread, funcPrototype, "hasAll", ContainersLightWeightSet::HasAll, FuncLength::ONE);
440    SetFrozenFunction(thread, funcPrototype, "has", ContainersLightWeightSet::Has, FuncLength::ONE);
441    SetFrozenFunction(thread, funcPrototype, "equal", ContainersLightWeightSet::Equal, FuncLength::ONE);
442    SetFrozenFunction(thread, funcPrototype, "increaseCapacityTo",
443                      ContainersLightWeightSet::IncreaseCapacityTo, FuncLength::ONE);
444    SetFrozenFunction(thread, funcPrototype, "forEach", ContainersLightWeightSet::ForEach, FuncLength::ONE,
445                      BUILTINS_STUB_ID(LightWeightSetForEach));
446    SetFrozenFunction(thread, funcPrototype, "getIndexOf", ContainersLightWeightSet::GetIndexOf, FuncLength::ONE);
447    SetFrozenFunction(thread, funcPrototype, "remove", ContainersLightWeightSet::Remove, FuncLength::ZERO);
448    SetFrozenFunction(thread, funcPrototype, "removeAt", ContainersLightWeightSet::RemoveAt, FuncLength::ZERO);
449    SetFrozenFunction(thread, funcPrototype, "clear", ContainersLightWeightSet::Clear, FuncLength::ONE);
450    SetFrozenFunction(thread, funcPrototype, "toString", ContainersLightWeightSet::ToString, FuncLength::ZERO);
451    SetFrozenFunction(thread, funcPrototype, "toArray", ContainersLightWeightSet::ToArray, FuncLength::ONE);
452    SetFrozenFunction(thread, funcPrototype, "values", ContainersLightWeightSet::Values, FuncLength::ONE);
453    SetFrozenFunction(thread, funcPrototype, "entries", ContainersLightWeightSet::Entries, FuncLength::ZERO);
454    JSHandle<JSTaggedValue> lengthGetter =
455        CreateGetter(thread, ContainersLightWeightSet::GetSize, "length", FuncLength::ZERO);
456
457    JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
458    SetGetter(thread, funcPrototype, lengthKey, lengthGetter);
459    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
460    SetFunctionAtSymbol(thread, env, funcPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
461                        ContainersLightWeightSet::GetIteratorObj, FuncLength::ONE);
462
463    InitializeLightWeightSetIterator(thread);
464    return lightweightSetFunction;
465}
466
467void ContainersPrivate::InitializeLightWeightSetIterator(JSThread *thread)
468{
469    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
470    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
471    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
472    JSHandle<JSHClass> iteratorClass =
473        JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
474    JSHandle<JSObject> lightWeightSetIteratorPrototype(factory->NewJSObject(iteratorClass));
475    SetFrozenFunction(
476        thread, lightWeightSetIteratorPrototype, "next", JSAPILightWeightSetIterator::Next, FuncLength::ONE);
477    SetStringTagSymbol(thread, env, lightWeightSetIteratorPrototype, "LightWeightSet Iterator");
478    globalConst->SetConstant(ConstantIndex::LIGHTWEIGHTSET_ITERATOR_PROTOTYPE_INDEX,
479                             lightWeightSetIteratorPrototype.GetTaggedValue());
480}
481
482JSHandle<JSTaggedValue> ContainersPrivate::InitializeTreeMap(JSThread *thread)
483{
484    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
485    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
486    // TreeMap.prototype
487    JSHandle<JSObject> mapFuncPrototype = factory->NewEmptyJSObject();
488    JSHandle<JSTaggedValue> mapFuncPrototypeValue(mapFuncPrototype);
489    // TreeMap.prototype_or_hclass
490    JSHandle<JSHClass> mapInstanceClass =
491        factory->NewEcmaHClass(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, mapFuncPrototypeValue);
492    // TreeMap() = new Function()
493    JSHandle<JSTaggedValue> mapFunction(NewContainerConstructor(
494        thread, mapFuncPrototype, ContainersTreeMap::TreeMapConstructor, "TreeMap", FuncLength::ZERO));
495    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
496        JSHandle<JSFunction>::Cast(mapFunction), mapInstanceClass.GetTaggedValue());
497
498    // "constructor" property on the prototype
499    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
500    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(mapFuncPrototype), constructorKey, mapFunction);
501    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
502    // TreeMap.prototype
503    SetFrozenFunction(thread, mapFuncPrototype, "set", ContainersTreeMap::Set, FuncLength::TWO);
504    SetFrozenFunction(thread, mapFuncPrototype, "get", ContainersTreeMap::Get, FuncLength::ONE);
505    SetFrozenFunction(thread, mapFuncPrototype, "remove", ContainersTreeMap::Remove, FuncLength::ONE);
506    SetFrozenFunction(thread, mapFuncPrototype, "hasKey", ContainersTreeMap::HasKey, FuncLength::ONE);
507    SetFrozenFunction(thread, mapFuncPrototype, "hasValue", ContainersTreeMap::HasValue, FuncLength::ONE);
508    SetFrozenFunction(thread, mapFuncPrototype, "getFirstKey", ContainersTreeMap::GetFirstKey, FuncLength::ZERO);
509    SetFrozenFunction(thread, mapFuncPrototype, "getLastKey", ContainersTreeMap::GetLastKey, FuncLength::ZERO);
510    SetFrozenFunction(thread, mapFuncPrototype, "setAll", ContainersTreeMap::SetAll, FuncLength::ONE);
511    SetFrozenFunction(thread, mapFuncPrototype, "clear", ContainersTreeMap::Clear, FuncLength::ZERO);
512    SetFrozenFunction(thread, mapFuncPrototype, "getLowerKey", ContainersTreeMap::GetLowerKey, FuncLength::ONE);
513    SetFrozenFunction(thread, mapFuncPrototype, "getHigherKey", ContainersTreeMap::GetHigherKey, FuncLength::ONE);
514    SetFrozenFunction(thread, mapFuncPrototype, "keys", ContainersTreeMap::Keys, FuncLength::ZERO);
515    SetFrozenFunction(thread, mapFuncPrototype, "values", ContainersTreeMap::Values, FuncLength::ZERO);
516    SetFrozenFunction(thread, mapFuncPrototype, "replace", ContainersTreeMap::Replace, FuncLength::TWO);
517    SetFrozenFunction(thread, mapFuncPrototype, "forEach", ContainersTreeMap::ForEach, FuncLength::ONE);
518    SetFrozenFunction(thread, mapFuncPrototype, "entries", ContainersTreeMap::Entries, FuncLength::ZERO);
519    SetFrozenFunction(thread, mapFuncPrototype, "isEmpty", ContainersTreeMap::IsEmpty, FuncLength::ZERO);
520
521    // @@ToStringTag
522    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
523    SetStringTagSymbol(thread, env, mapFuncPrototype, "TreeMap");
524    // %TreeMapPrototype% [ @@iterator ]
525    JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
526    JSHandle<JSTaggedValue> entries = globalConst->GetHandledEntriesString();
527    JSHandle<JSTaggedValue> entriesFunc =
528        JSObject::GetMethod(thread, JSHandle<JSTaggedValue>::Cast(mapFuncPrototype), entries);
529    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
530    PropertyDescriptor descriptor(thread, entriesFunc, false, false, false);
531    JSObject::DefineOwnProperty(thread, mapFuncPrototype, iteratorSymbol, descriptor);
532    // length
533    JSHandle<JSTaggedValue> lengthGetter =
534        CreateGetter(thread, ContainersTreeMap::GetLength, "length", FuncLength::ZERO);
535    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
536    SetGetter(thread, mapFuncPrototype, lengthKey, lengthGetter);
537
538    InitializeTreeMapIterator(thread);
539    return mapFunction;
540}
541
542void ContainersPrivate::InitializeTreeMapIterator(JSThread *thread)
543{
544    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
545    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
546    // Iterator.hclass
547    JSHandle<JSHClass> iteratorClass =
548        factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
549
550    // TreeMapIterator.prototype
551    JSHandle<JSObject> mapIteratorPrototype(factory->NewJSObject(iteratorClass));
552    // TreeIterator.prototype.next()
553    SetFrozenFunction(thread, mapIteratorPrototype, "next", JSAPITreeMapIterator::Next, FuncLength::ZERO);
554    SetStringTagSymbol(thread, env, mapIteratorPrototype, "TreeMap Iterator");
555    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
556    globalConst->SetConstant(ConstantIndex::TREEMAP_ITERATOR_PROTOTYPE_INDEX, mapIteratorPrototype.GetTaggedValue());
557}
558
559JSHandle<JSTaggedValue> ContainersPrivate::InitializeTreeSet(JSThread *thread)
560{
561    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
562    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
563    // TreeSet.prototype
564    JSHandle<JSObject> setFuncPrototype = factory->NewEmptyJSObject();
565    JSHandle<JSTaggedValue> setFuncPrototypeValue(setFuncPrototype);
566    // TreeSet.prototype_or_hclass
567    JSHandle<JSHClass> setInstanceClass =
568        factory->NewEcmaHClass(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, setFuncPrototypeValue);
569    // TreeSet() = new Function()
570    JSHandle<JSTaggedValue> setFunction(NewContainerConstructor(
571        thread, setFuncPrototype, ContainersTreeSet::TreeSetConstructor, "TreeSet", FuncLength::ZERO));
572    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
573        JSHandle<JSFunction>::Cast(setFunction), setInstanceClass.GetTaggedValue());
574
575    // "constructor" property on the prototype
576    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
577    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(setFuncPrototype), constructorKey, setFunction);
578    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
579    // TreeSet.prototype
580    SetFrozenFunction(thread, setFuncPrototype, "add", ContainersTreeSet::Add, FuncLength::TWO);
581    SetFrozenFunction(thread, setFuncPrototype, "remove", ContainersTreeSet::Remove, FuncLength::ONE);
582    SetFrozenFunction(thread, setFuncPrototype, "has", ContainersTreeSet::Has, FuncLength::ONE);
583    SetFrozenFunction(thread, setFuncPrototype, "getFirstValue", ContainersTreeSet::GetFirstValue, FuncLength::ZERO);
584    SetFrozenFunction(thread, setFuncPrototype, "getLastValue", ContainersTreeSet::GetLastValue, FuncLength::ZERO);
585    SetFrozenFunction(thread, setFuncPrototype, "clear", ContainersTreeSet::Clear, FuncLength::ZERO);
586    SetFrozenFunction(thread, setFuncPrototype, "getLowerValue", ContainersTreeSet::GetLowerValue, FuncLength::ONE);
587    SetFrozenFunction(thread, setFuncPrototype, "getHigherValue", ContainersTreeSet::GetHigherValue, FuncLength::ONE);
588    SetFrozenFunction(thread, setFuncPrototype, "popFirst", ContainersTreeSet::PopFirst, FuncLength::ZERO);
589    SetFrozenFunction(thread, setFuncPrototype, "popLast", ContainersTreeSet::PopLast, FuncLength::ZERO);
590    SetFrozenFunction(thread, setFuncPrototype, "isEmpty", ContainersTreeSet::IsEmpty, FuncLength::TWO);
591    SetFrozenFunction(thread, setFuncPrototype, "values", ContainersTreeSet::Values, FuncLength::ZERO);
592    SetFrozenFunction(thread, setFuncPrototype, "forEach", ContainersTreeSet::ForEach, FuncLength::ONE);
593    SetFrozenFunction(thread, setFuncPrototype, "entries", ContainersTreeSet::Entries, FuncLength::ZERO);
594
595    // @@ToStringTag
596    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
597    SetStringTagSymbol(thread, env, setFuncPrototype, "TreeSet");
598    // %TreeSetPrototype% [ @@iterator ]
599    JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
600    JSHandle<JSTaggedValue> values(thread, globalConst->GetValuesString());
601    JSHandle<JSTaggedValue> valuesFunc =
602        JSObject::GetMethod(thread, JSHandle<JSTaggedValue>::Cast(setFuncPrototype), values);
603    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
604    PropertyDescriptor descriptor(thread, valuesFunc, false, false, false);
605    JSObject::DefineOwnProperty(thread, setFuncPrototype, iteratorSymbol, descriptor);
606    // length
607    JSHandle<JSTaggedValue> lengthGetter =
608        CreateGetter(thread, ContainersTreeSet::GetLength, "length", FuncLength::ZERO);
609    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
610    SetGetter(thread, setFuncPrototype, lengthKey, lengthGetter);
611
612    InitializeTreeSetIterator(thread);
613    return setFunction;
614}
615
616void ContainersPrivate::InitializeTreeSetIterator(JSThread *thread)
617{
618    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
619    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
620    // Iterator.hclass
621    JSHandle<JSHClass> iteratorClass =
622        factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
623
624    // TreeSetIterator.prototype
625    JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
626    // TreeSetIterator.prototype.next()
627    SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPITreeSetIterator::Next, FuncLength::ZERO);
628    SetStringTagSymbol(thread, env, setIteratorPrototype, "TreeSet Iterator");
629    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
630    globalConst->SetConstant(ConstantIndex::TREESET_ITERATOR_PROTOTYPE_INDEX, setIteratorPrototype.GetTaggedValue());
631}
632
633JSHandle<JSTaggedValue> ContainersPrivate::InitializePlainArray(JSThread *thread)
634{
635    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
636    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
637    // PlainArray.prototype
638    JSHandle<JSObject> plainArrayFuncPrototype = factory->NewEmptyJSObject();
639    JSHandle<JSTaggedValue> plainArrayFuncPrototypeValue(plainArrayFuncPrototype);
640    // PlainArray.prototype_or_hclass
641    JSHandle<JSHClass> plainArrayInstanceClass =
642        factory->NewEcmaHClass(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, plainArrayFuncPrototypeValue);
643    JSHandle<JSTaggedValue> plainArrayFunction(
644        NewContainerConstructor(thread, plainArrayFuncPrototype, ContainersPlainArray::PlainArrayConstructor,
645                                "PlainArray", FuncLength::ZERO));
646    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
647        JSHandle<JSFunction>::Cast(plainArrayFunction), plainArrayInstanceClass.GetTaggedValue());
648
649    // "constructor" property on the prototype
650    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
651    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(plainArrayFuncPrototype), constructorKey,
652                          plainArrayFunction);
653    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
654    // PlainArray.prototype.add()
655    SetFrozenFunction(thread, plainArrayFuncPrototype, "add", ContainersPlainArray::Add, FuncLength::ONE);
656    SetFrozenFunction(thread, plainArrayFuncPrototype, "clear", ContainersPlainArray::Clear, FuncLength::ONE);
657    SetFrozenFunction(thread, plainArrayFuncPrototype, "clone", ContainersPlainArray::Clone, FuncLength::ONE);
658    SetFrozenFunction(thread, plainArrayFuncPrototype, "has", ContainersPlainArray::Has, FuncLength::ONE);
659    SetFrozenFunction(thread, plainArrayFuncPrototype, "get", ContainersPlainArray::Get, FuncLength::ONE);
660    SetFrozenFunction(thread, plainArrayFuncPrototype, "forEach", ContainersPlainArray::ForEach, FuncLength::ONE,
661                      BUILTINS_STUB_ID(PlainArrayForEach));
662    SetFrozenFunction(thread, plainArrayFuncPrototype, "toString", ContainersPlainArray::ToString,
663                      FuncLength::ZERO);
664    SetFrozenFunction(thread, plainArrayFuncPrototype, "getIndexOfKey", ContainersPlainArray::GetIndexOfKey,
665                      FuncLength::ZERO);
666    SetFrozenFunction(thread, plainArrayFuncPrototype, "getIndexOfValue", ContainersPlainArray::GetIndexOfValue,
667                      FuncLength::ZERO);
668    SetFrozenFunction(thread, plainArrayFuncPrototype, "isEmpty", ContainersPlainArray::IsEmpty, FuncLength::ZERO);
669    SetFrozenFunction(thread, plainArrayFuncPrototype, "getKeyAt",
670                      ContainersPlainArray::GetKeyAt, FuncLength::ZERO);
671    SetFrozenFunction(thread, plainArrayFuncPrototype, "remove", ContainersPlainArray::Remove, FuncLength::ZERO);
672    SetFrozenFunction(thread, plainArrayFuncPrototype, "removeAt", ContainersPlainArray::RemoveAt,
673                      FuncLength::ZERO);
674    SetFrozenFunction(thread, plainArrayFuncPrototype, "removeRangeFrom", ContainersPlainArray::RemoveRangeFrom,
675                      FuncLength::ZERO);
676    SetFrozenFunction(thread, plainArrayFuncPrototype, "setValueAt", ContainersPlainArray::SetValueAt,
677                      FuncLength::ZERO);
678    SetFrozenFunction(thread, plainArrayFuncPrototype, "getValueAt", ContainersPlainArray::GetValueAt,
679                      FuncLength::ZERO);
680
681    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersPlainArray::GetSize, "length",
682                                                        FuncLength::ZERO);
683    JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
684    SetGetter(thread, plainArrayFuncPrototype, lengthKey, lengthGetter);
685
686    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
687    SetFunctionAtSymbol(thread, env, plainArrayFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
688                        ContainersPlainArray::GetIteratorObj, FuncLength::ONE);
689    InitializePlainArrayIterator(thread);
690    globalConst->SetConstant(ConstantIndex::PLAIN_ARRAY_FUNCTION_INDEX, plainArrayFunction.GetTaggedValue());
691    return plainArrayFunction;
692}
693
694void ContainersPrivate::InitializePlainArrayIterator(JSThread *thread)
695{
696    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
697    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
698    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
699    JSHandle<JSHClass> iteratorClass =
700        JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
701    JSHandle<JSObject> plainarrayIteratorPrototype(factory->NewJSObject(iteratorClass));
702    SetFrozenFunction(thread, plainarrayIteratorPrototype, "next", JSAPIPlainArrayIterator::Next, FuncLength::ONE);
703    SetStringTagSymbol(thread, env, plainarrayIteratorPrototype, "PlainArray Iterator");
704    globalConst->SetConstant(ConstantIndex::PLAIN_ARRAY_ITERATOR_PROTOTYPE_INDEX,
705                             plainarrayIteratorPrototype.GetTaggedValue());
706}
707
708JSHandle<JSTaggedValue> ContainersPrivate::InitializeStack(JSThread *thread)
709{
710    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
711    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
712    // Stack.prototype
713    JSHandle<JSObject> stackFuncPrototype = factory->NewEmptyJSObject();
714    JSHandle<JSTaggedValue> stackFuncPrototypeValue(stackFuncPrototype);
715    // Stack.prototype_or_hclass
716    JSHandle<JSHClass> stackInstanceClass =
717        factory->NewEcmaHClass(JSAPIStack::SIZE, JSType::JS_API_STACK, stackFuncPrototypeValue);
718    // Stack() = new Function()
719    JSHandle<JSTaggedValue> stackFunction(NewContainerConstructor(
720        thread, stackFuncPrototype, ContainersStack::StackConstructor, "Stack", FuncLength::ZERO));
721    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
722        JSHandle<JSFunction>::Cast(stackFunction), stackInstanceClass.GetTaggedValue());
723
724    // "constructor" property on the prototype
725    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
726    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(stackFuncPrototype), constructorKey, stackFunction);
727    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
728    // Stack.prototype.push()
729    SetFrozenFunction(thread, stackFuncPrototype, "push", ContainersStack::Push, FuncLength::ONE);
730    // Stack.prototype.empty()
731    SetFrozenFunction(thread, stackFuncPrototype, "isEmpty", ContainersStack::IsEmpty, FuncLength::ONE);
732    // Stack.prototype.peek()
733    SetFrozenFunction(thread, stackFuncPrototype, "peek", ContainersStack::Peek, FuncLength::ONE);
734    // Stack.prototype.pop()
735    SetFrozenFunction(thread, stackFuncPrototype, "pop", ContainersStack::Pop, FuncLength::ONE);
736    // Stack.prototype.search()
737    SetFrozenFunction(thread, stackFuncPrototype, "locate", ContainersStack::Locate, FuncLength::ONE);
738    // Stack.prototype.forEach()
739    SetFrozenFunction(thread, stackFuncPrototype, "forEach", ContainersStack::ForEach, FuncLength::ONE,
740                      BUILTINS_STUB_ID(StackForEach));
741    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
742    SetStringTagSymbol(thread, env, stackFuncPrototype, "Stack");
743
744    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersStack::GetLength, "length", FuncLength::ZERO);
745    JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
746    SetGetter(thread, stackFuncPrototype, lengthKey, lengthGetter);
747
748    SetFunctionAtSymbol(thread, env, stackFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
749                        ContainersStack::Iterator, FuncLength::ONE);
750
751    ContainersPrivate::InitializeStackIterator(thread, globalConst);
752    return stackFunction;
753}
754
755void ContainersPrivate::InitializeStackIterator(JSThread *thread, GlobalEnvConstants *globalConst)
756{
757    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
758    JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>(thread, globalConst->
759                        GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
760    // StackIterator.prototype
761    JSHandle<JSObject> stackIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
762    // Iterator.prototype.next()
763    SetFrozenFunction(thread, stackIteratorPrototype, "next", JSAPIStackIterator::Next, FuncLength::ONE);
764    globalConst->SetConstant(ConstantIndex::STACK_ITERATOR_PROTOTYPE_INDEX, stackIteratorPrototype.GetTaggedValue());
765}
766
767JSHandle<JSTaggedValue> ContainersPrivate::InitializeVector(JSThread *thread)
768{
769    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
770    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
771    // Vector.prototype
772    JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
773    JSHandle<JSTaggedValue> vectorFuncPrototypeValue(prototype);
774    // Vector.prototype_or_hclass
775    JSHandle<JSHClass> vectorInstanceClass =
776        factory->NewEcmaHClass(JSAPIVector::SIZE, JSType::JS_API_VECTOR, vectorFuncPrototypeValue);
777    // Vector() = new Function()
778    JSHandle<JSTaggedValue> vectorFunction(NewContainerConstructor(
779        thread, prototype, ContainersVector::VectorConstructor, "Vector", FuncLength::ZERO));
780    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
781        JSHandle<JSFunction>::Cast(vectorFunction), vectorInstanceClass.GetTaggedValue());
782
783    // "constructor" property on the prototype
784    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
785    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, vectorFunction);
786    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
787    // Vector.prototype
788    SetFrozenFunction(thread, prototype, "add", ContainersVector::Add, FuncLength::ONE);
789    SetFrozenFunction(thread, prototype, "insert", ContainersVector::Insert, FuncLength::TWO);
790    SetFrozenFunction(thread, prototype, "setLength", ContainersVector::SetLength, FuncLength::ONE);
791    SetFrozenFunction(thread, prototype, "getCapacity", ContainersVector::GetCapacity, FuncLength::ZERO);
792    SetFrozenFunction(thread, prototype, "increaseCapacityTo", ContainersVector::IncreaseCapacityTo, FuncLength::ONE);
793    SetFrozenFunction(thread, prototype, "get", ContainersVector::Get, FuncLength::ONE);
794    SetFrozenFunction(thread, prototype, "getIndexOf", ContainersVector::GetIndexOf, FuncLength::ONE);
795    SetFrozenFunction(thread, prototype, "getIndexFrom", ContainersVector::GetIndexFrom, FuncLength::TWO);
796    SetFrozenFunction(thread, prototype, "isEmpty", ContainersVector::IsEmpty, FuncLength::ZERO);
797    SetFrozenFunction(thread, prototype, "getLastElement", ContainersVector::GetLastElement, FuncLength::ZERO);
798    SetFrozenFunction(thread, prototype, "getLastIndexOf", ContainersVector::GetLastIndexOf, FuncLength::ONE);
799    SetFrozenFunction(thread, prototype, "getLastIndexFrom", ContainersVector::GetLastIndexFrom, FuncLength::TWO);
800    SetFrozenFunction(thread, prototype, "remove", ContainersVector::Remove, FuncLength::ONE);
801    SetFrozenFunction(thread, prototype, "removeByIndex", ContainersVector::RemoveByIndex, FuncLength::ONE);
802    SetFrozenFunction(thread, prototype, "removeByRange", ContainersVector::RemoveByRange, FuncLength::TWO);
803    SetFrozenFunction(thread, prototype, "set", ContainersVector::Set, FuncLength::TWO);
804    SetFrozenFunction(thread, prototype, "subVector", ContainersVector::SubVector, FuncLength::TWO);
805    SetFrozenFunction(thread, prototype, "toString", ContainersVector::ToString, FuncLength::ZERO);
806    SetFrozenFunction(thread, prototype, "forEach", ContainersVector::ForEach, FuncLength::TWO,
807                      BUILTINS_STUB_ID(VectorForEach));
808    SetFrozenFunction(thread, prototype, "replaceAllElements", ContainersVector::ReplaceAllElements, FuncLength::TWO,
809                      BUILTINS_STUB_ID(VectorReplaceAllElements));
810    SetFrozenFunction(thread, prototype, "has", ContainersVector::Has, FuncLength::ONE);
811    SetFrozenFunction(thread, prototype, "sort", ContainersVector::Sort, FuncLength::ZERO);
812    SetFrozenFunction(thread, prototype, "clear", ContainersVector::Clear, FuncLength::ZERO);
813    SetFrozenFunction(thread, prototype, "clone", ContainersVector::Clone, FuncLength::ZERO);
814    SetFrozenFunction(thread, prototype, "copyToArray", ContainersVector::CopyToArray, FuncLength::ONE);
815    SetFrozenFunction(thread, prototype, "convertToArray", ContainersVector::ConvertToArray, FuncLength::ZERO);
816    SetFrozenFunction(thread, prototype, "getFirstElement", ContainersVector::GetFirstElement, FuncLength::ZERO);
817    SetFrozenFunction(thread, prototype, "trimToCurrentLength",
818                      ContainersVector::TrimToCurrentLength, FuncLength::ZERO);
819
820    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
821    SetStringTagSymbol(thread, env, prototype, "Vector");
822
823    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersVector::GetSize, "length", FuncLength::ZERO);
824    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
825    SetGetter(thread, prototype, lengthKey, lengthGetter);
826
827    SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
828                        ContainersVector::GetIteratorObj, FuncLength::ONE);
829
830    ContainersPrivate::InitializeVectorIterator(thread, env, globalConst);
831    globalConst->SetConstant(ConstantIndex::VECTOR_FUNCTION_INDEX, vectorFunction.GetTaggedValue());
832    return vectorFunction;
833}
834
835void ContainersPrivate::InitializeVectorIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
836                                                 GlobalEnvConstants *globalConst)
837{
838    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
839    JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>(thread, globalConst->
840                        GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
841    // VectorIterator.prototype
842    JSHandle<JSObject> vectorIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
843    // Iterator.prototype.next()
844    SetFrozenFunction(thread, vectorIteratorPrototype, "next", JSAPIVectorIterator::Next, FuncLength::ONE);
845    SetStringTagSymbol(thread, env, vectorIteratorPrototype, "Vector Iterator");
846    globalConst->SetConstant(ConstantIndex::VECTOR_ITERATOR_PROTOTYPE_INDEX, vectorIteratorPrototype.GetTaggedValue());
847}
848
849JSHandle<JSTaggedValue> ContainersPrivate::InitializeBitVector(JSThread* thread)
850{
851    auto globalConst = const_cast<GlobalEnvConstants*>(thread->GlobalConstants());
852    ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
853    // BitVector.prototype
854    JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
855    JSHandle<JSTaggedValue> bitVectorFuncPrototypeValue(prototype);
856    // BitVector.prototype_or_hclass
857    JSHandle<JSHClass> bitVectorInstanceClass =
858        factory->NewEcmaHClass(JSAPIBitVector::SIZE, JSType::JS_API_BITVECTOR, bitVectorFuncPrototypeValue);
859    // BitVector() = new Function()
860    JSHandle<JSTaggedValue> bitVectorFunction(NewContainerConstructor(
861        thread, prototype, ContainersBitVector::BitVectorConstructor, "BitVector", FuncLength::ONE));
862    JSFunction::SetFunctionPrototypeOrInstanceHClass(
863        thread, JSHandle<JSFunction>::Cast(bitVectorFunction), bitVectorInstanceClass.GetTaggedValue());
864
865    // "constructor" property on the prototype
866    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
867    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, bitVectorFunction);
868    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
869
870    // BitVector.prototype
871    SetFrozenFunction(thread, prototype, "push", ContainersBitVector::Push, FuncLength::ONE);
872    SetFrozenFunction(thread, prototype, "pop", ContainersBitVector::Pop, FuncLength::ZERO);
873    SetFrozenFunction(thread, prototype, "has", ContainersBitVector::Has, FuncLength::THREE);
874    SetFrozenFunction(thread, prototype, "setBitsByRange", ContainersBitVector::SetBitsByRange, FuncLength::THREE);
875    SetFrozenFunction(thread, prototype, "getBitsByRange", ContainersBitVector::GetBitsByRange, FuncLength::TWO);
876    SetFrozenFunction(thread, prototype, "setAllBits", ContainersBitVector::SetAllBits, FuncLength::ONE);
877    SetFrozenFunction(thread, prototype, "resize", ContainersBitVector::Resize, FuncLength::ONE);
878    SetFrozenFunction(
879        thread, prototype, "getBitCountByRange", ContainersBitVector::GetBitCountByRange, FuncLength::THREE);
880    SetFrozenFunction(thread, prototype, "getIndexOf", ContainersBitVector::GetIndexOf, FuncLength::THREE);
881    SetFrozenFunction(thread, prototype, "getLastIndexOf", ContainersBitVector::GetLastIndexOf, FuncLength::THREE);
882    SetFrozenFunction(thread, prototype, "flipBitByIndex", ContainersBitVector::FlipBitByIndex, FuncLength::ONE);
883    SetFrozenFunction(thread, prototype, "flipBitsByRange", ContainersBitVector::FlipBitsByRange, FuncLength::TWO);
884    SetFrozenFunction(thread, prototype, "values", ContainersBitVector::GetIteratorObj, FuncLength::ZERO);
885
886    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
887    SetStringTagSymbol(thread, env, prototype, "BitVector");
888
889    JSHandle<JSTaggedValue> lengthGetter =
890        CreateGetter(thread, ContainersBitVector::GetSize, "length", FuncLength::ZERO);
891    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
892    SetGetter(thread, prototype, lengthKey, lengthGetter);
893
894    SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
895                        ContainersBitVector::GetIteratorObj, FuncLength::ONE);
896    ContainersPrivate::InitializeBitVectorIterator(thread, env, globalConst);
897
898    globalConst->SetConstant(ConstantIndex::BITVECTOR_FUNCTION_INDEX, bitVectorFunction.GetTaggedValue());
899    return bitVectorFunction;
900}
901
902void ContainersPrivate::InitializeBitVectorIterator(
903    JSThread* thread, const JSHandle<GlobalEnv>& env, GlobalEnvConstants* globalConst)
904{
905    ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
906    JSHandle<JSHClass> iteratorFuncHClass =
907        JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
908    // BitVectorIterator.prototype
909    JSHandle<JSObject> bitVectorIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
910    // Iterator.prototype.next()
911    SetFrozenFunction(thread, bitVectorIteratorPrototype, "next", JSAPIBitVectorIterator::Next, FuncLength::ONE);
912    SetStringTagSymbol(thread, env, bitVectorIteratorPrototype, "BitVector Iterator");
913    globalConst->SetConstant(
914        ConstantIndex::BITVECTOR_ITERATOR_PROTOTYPE_INDEX, bitVectorIteratorPrototype.GetTaggedValue());
915}
916
917JSHandle<JSTaggedValue> ContainersPrivate::InitializeQueue(JSThread *thread)
918{
919    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
920    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
921    // Queue.prototype
922    JSHandle<JSObject> queueFuncPrototype = factory->NewEmptyJSObject();
923    JSHandle<JSTaggedValue> queueFuncPrototypeValue(queueFuncPrototype);
924    // Queue.prototype_or_hclass
925    JSHandle<JSHClass> queueInstanceClass =
926        factory->NewEcmaHClass(JSAPIQueue::SIZE, JSType::JS_API_QUEUE, queueFuncPrototypeValue);
927    // Queue() = new Function()
928    JSHandle<JSTaggedValue> queueFunction(NewContainerConstructor(
929        thread, queueFuncPrototype, ContainersQueue::QueueConstructor, "Queue", FuncLength::ZERO));
930    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
931        JSHandle<JSFunction>::Cast(queueFunction), queueInstanceClass.GetTaggedValue());
932
933    // "constructor" property on the prototype
934    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
935    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(queueFuncPrototype), constructorKey, queueFunction);
936    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
937    // Queue.prototype.add()
938    SetFrozenFunction(thread, queueFuncPrototype, "add", ContainersQueue::Add, FuncLength::ONE);
939    SetFrozenFunction(thread, queueFuncPrototype, "getFirst", ContainersQueue::GetFirst, FuncLength::ZERO);
940    SetFrozenFunction(thread, queueFuncPrototype, "pop", ContainersQueue::Pop, FuncLength::ZERO);
941    SetFrozenFunction(thread, queueFuncPrototype, "forEach", ContainersQueue::ForEach, FuncLength::TWO,
942                      BUILTINS_STUB_ID(QueueForEach));
943
944    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
945    SetStringTagSymbol(thread, env, queueFuncPrototype, "Queue");
946
947    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersQueue::GetSize, "length", FuncLength::ZERO);
948    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
949    SetGetter(thread, queueFuncPrototype, lengthKey, lengthGetter);
950
951    SetFunctionAtSymbol(thread, env, queueFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
952                        ContainersQueue::GetIteratorObj, FuncLength::ONE);
953
954    ContainersPrivate::InitializeQueueIterator(thread, env, globalConst);
955    return queueFunction;
956}
957
958void ContainersPrivate::InitializeQueueIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
959                                                GlobalEnvConstants *globalConst)
960{
961    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
962    JSHandle<JSHClass> iteratorFuncHClass =
963        factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
964    // QueueIterator.prototype
965    JSHandle<JSObject> queueIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
966    // Iterator.prototype.next()
967    SetFrozenFunction(thread, queueIteratorPrototype, "next", JSAPIQueueIterator::Next, FuncLength::ONE);
968    SetStringTagSymbol(thread, env, queueIteratorPrototype, "Queue Iterator");
969    globalConst->SetConstant(ConstantIndex::QUEUE_ITERATOR_PROTOTYPE_INDEX, queueIteratorPrototype.GetTaggedValue());
970}
971
972JSHandle<JSTaggedValue> ContainersPrivate::InitializeDeque(JSThread *thread)
973{
974    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
975    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
976    // Deque.prototype
977    JSHandle<JSObject> dequeFuncPrototype = factory->NewEmptyJSObject();
978    JSHandle<JSTaggedValue> dequeFuncPrototypeValue(dequeFuncPrototype);
979    // Deque.prototype_or_hclass
980    JSHandle<JSHClass> dequeInstanceClass =
981        factory->NewEcmaHClass(JSAPIDeque::SIZE, JSType::JS_API_DEQUE, dequeFuncPrototypeValue);
982    // Deque() = new Function()
983    JSHandle<JSTaggedValue> dequeFunction(NewContainerConstructor(
984        thread, dequeFuncPrototype, ContainersDeque::DequeConstructor, "Deque", FuncLength::ZERO));
985    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
986        JSHandle<JSFunction>::Cast(dequeFunction), dequeInstanceClass.GetTaggedValue());
987
988    // "constructor" property on the prototype
989    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
990    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(dequeFuncPrototype), constructorKey, dequeFunction);
991    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
992    SetFrozenFunction(thread, dequeFuncPrototype, "insertFront", ContainersDeque::InsertFront, FuncLength::ONE);
993    SetFrozenFunction(thread, dequeFuncPrototype, "insertEnd", ContainersDeque::InsertEnd, FuncLength::ONE);
994    SetFrozenFunction(thread, dequeFuncPrototype, "getFirst", ContainersDeque::GetFirst, FuncLength::ZERO);
995    SetFrozenFunction(thread, dequeFuncPrototype, "getLast", ContainersDeque::GetLast, FuncLength::ZERO);
996    SetFrozenFunction(thread, dequeFuncPrototype, "has", ContainersDeque::Has, FuncLength::ONE);
997    SetFrozenFunction(thread, dequeFuncPrototype, "popFirst", ContainersDeque::PopFirst, FuncLength::ZERO);
998    SetFrozenFunction(thread, dequeFuncPrototype, "popLast", ContainersDeque::PopLast, FuncLength::ZERO);
999    SetFrozenFunction(thread, dequeFuncPrototype, "forEach", ContainersDeque::ForEach, FuncLength::TWO,
1000                      BUILTINS_STUB_ID(DequeForEach));
1001
1002    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1003    SetStringTagSymbol(thread, env, dequeFuncPrototype, "Deque");
1004
1005    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersDeque::GetSize, "length", FuncLength::ZERO);
1006    JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
1007    SetGetter(thread, dequeFuncPrototype, lengthKey, lengthGetter);
1008
1009    SetFunctionAtSymbol(thread, env, dequeFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1010                        ContainersDeque::GetIteratorObj, FuncLength::ONE);
1011
1012    ContainersPrivate::InitializeDequeIterator(thread, env, globalConst);
1013
1014    return dequeFunction;
1015}
1016
1017void ContainersPrivate::InitializeDequeIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
1018                                                GlobalEnvConstants *globalConst)
1019{
1020    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1021    JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>(thread, globalConst->
1022                        GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
1023    JSHandle<JSObject> dequeIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1024    SetFrozenFunction(thread, dequeIteratorPrototype, "next", JSAPIDequeIterator::Next, FuncLength::ONE);
1025    SetStringTagSymbol(thread, env, dequeIteratorPrototype, "Deque Iterator");
1026    globalConst->SetConstant(ConstantIndex::DEQUE_ITERATOR_PROTOTYPE_INDEX, dequeIteratorPrototype.GetTaggedValue());
1027}
1028
1029JSHandle<JSTaggedValue> ContainersPrivate::InitializeList(JSThread *thread)
1030{
1031    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1032    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1033    JSHandle<JSObject> listFuncPrototype = factory->NewEmptyJSObject();
1034    JSHandle<JSTaggedValue> listFuncPrototypeValue(listFuncPrototype);
1035    JSHandle<JSHClass> listInstanceClass =
1036        factory->NewEcmaHClass(JSAPIList::SIZE, JSType::JS_API_LIST, listFuncPrototypeValue);
1037    JSHandle<JSTaggedValue> listFunction(NewContainerConstructor(
1038        thread, listFuncPrototype, ContainersList::ListConstructor, "List", FuncLength::ZERO));
1039    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1040        JSHandle<JSFunction>::Cast(listFunction), listInstanceClass.GetTaggedValue());
1041
1042    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1043    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(listFuncPrototype), constructorKey, listFunction);
1044    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1045    SetFrozenFunction(thread, listFuncPrototype, "add", ContainersList::Add, FuncLength::ONE);
1046    SetFrozenFunction(thread, listFuncPrototype, "getFirst", ContainersList::GetFirst, FuncLength::ONE);
1047    SetFrozenFunction(thread, listFuncPrototype, "getLast", ContainersList::GetLast, FuncLength::ONE);
1048    SetFrozenFunction(thread, listFuncPrototype, "insert", ContainersList::Insert, FuncLength::ONE);
1049    SetFrozenFunction(thread, listFuncPrototype, "clear", ContainersList::Clear, FuncLength::ONE);
1050    SetFrozenFunction(thread, listFuncPrototype, "removeByIndex", ContainersList::RemoveByIndex, FuncLength::ONE);
1051    SetFrozenFunction(thread, listFuncPrototype, "remove", ContainersList::Remove, FuncLength::ONE);
1052    SetFrozenFunction(thread, listFuncPrototype, "has", ContainersList::Has, FuncLength::ONE);
1053    SetFrozenFunction(thread, listFuncPrototype, "isEmpty", ContainersList::IsEmpty, FuncLength::ONE);
1054    SetFrozenFunction(thread, listFuncPrototype, "get", ContainersList::Get, FuncLength::ONE);
1055    SetFrozenFunction(thread, listFuncPrototype, "getIndexOf", ContainersList::GetIndexOf, FuncLength::ONE);
1056    SetFrozenFunction(thread, listFuncPrototype, "getLastIndexOf", ContainersList::GetLastIndexOf, FuncLength::ONE);
1057    SetFrozenFunction(thread, listFuncPrototype, "set", ContainersList::Set, FuncLength::ONE);
1058    SetFrozenFunction(thread, listFuncPrototype, "forEach", ContainersList::ForEach, FuncLength::ONE,
1059                      BUILTINS_STUB_ID(ListForEach));
1060    SetFrozenFunction(thread, listFuncPrototype, "replaceAllElements", ContainersList::ReplaceAllElements,
1061                      FuncLength::ONE);
1062    SetFrozenFunction(thread, listFuncPrototype, "equal", ContainersList::Equal, FuncLength::ONE);
1063    SetFrozenFunction(thread, listFuncPrototype, "sort", ContainersList::Sort, FuncLength::ONE);
1064    SetFrozenFunction(thread, listFuncPrototype, "convertToArray", ContainersList::ConvertToArray, FuncLength::ONE);
1065    SetFrozenFunction(thread, listFuncPrototype, "getSubList", ContainersList::GetSubList, FuncLength::ONE);
1066
1067    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersList::Length, "length", FuncLength::ZERO);
1068    JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
1069    SetGetter(thread, listFuncPrototype, lengthKey, lengthGetter);
1070
1071    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1072    SetFunctionAtSymbol(thread, env, listFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1073                        ContainersList::GetIteratorObj, FuncLength::ONE);
1074
1075    InitializeListIterator(thread, env);
1076    globalConst->SetConstant(ConstantIndex::LIST_FUNCTION_INDEX, listFunction.GetTaggedValue());
1077    return listFunction;
1078}
1079
1080JSHandle<JSTaggedValue> ContainersPrivate::InitializeLinkedList(JSThread *thread)
1081{
1082    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1083    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1084    JSHandle<JSObject> linkedListFuncPrototype = factory->NewEmptyJSObject();
1085    JSHandle<JSTaggedValue> linkedListFuncPrototypeValue(linkedListFuncPrototype);
1086    JSHandle<JSHClass> linkedListInstanceClass =
1087        factory->NewEcmaHClass(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, linkedListFuncPrototypeValue);
1088    JSHandle<JSTaggedValue> linkedListFunction(NewContainerConstructor(
1089        thread, linkedListFuncPrototype, ContainersLinkedList::LinkedListConstructor, "LinkedList", FuncLength::ZERO));
1090    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1091        JSHandle<JSFunction>::Cast(linkedListFunction), linkedListInstanceClass.GetTaggedValue());
1092
1093    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1094    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(linkedListFuncPrototype), constructorKey, linkedListFunction);
1095    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1096    SetFrozenFunction(thread, linkedListFuncPrototype, "add", ContainersLinkedList::Add, FuncLength::ONE);
1097    SetFrozenFunction(thread, linkedListFuncPrototype, "insert", ContainersLinkedList::Insert, FuncLength::ONE);
1098    SetFrozenFunction(thread, linkedListFuncPrototype, "clear", ContainersLinkedList::Clear, FuncLength::ONE);
1099    SetFrozenFunction(thread, linkedListFuncPrototype, "clone", ContainersLinkedList::Clone, FuncLength::ONE);
1100    SetFrozenFunction(thread, linkedListFuncPrototype, "removeFirst", ContainersLinkedList::RemoveFirst,
1101                      FuncLength::ONE);
1102    SetFrozenFunction(thread, linkedListFuncPrototype, "removeLast", ContainersLinkedList::RemoveLast, FuncLength::ONE);
1103    SetFrozenFunction(thread, linkedListFuncPrototype, "removeFirstFound", ContainersLinkedList::RemoveFirstFound,
1104                      FuncLength::ONE);
1105    SetFrozenFunction(thread, linkedListFuncPrototype, "removeByIndex", ContainersLinkedList::RemoveByIndex,
1106                      FuncLength::ONE);
1107    SetFrozenFunction(thread, linkedListFuncPrototype, "remove", ContainersLinkedList::Remove, FuncLength::ONE);
1108    SetFrozenFunction(thread, linkedListFuncPrototype, "removeLastFound", ContainersLinkedList::RemoveLastFound,
1109                      FuncLength::ONE);
1110    SetFrozenFunction(thread, linkedListFuncPrototype, "has", ContainersLinkedList::Has, FuncLength::ONE);
1111    SetFrozenFunction(thread, linkedListFuncPrototype, "get", ContainersLinkedList::Get, FuncLength::ONE);
1112    SetFrozenFunction(thread, linkedListFuncPrototype, "addFirst", ContainersLinkedList::AddFirst, FuncLength::ONE);
1113    SetFrozenFunction(thread, linkedListFuncPrototype, "getFirst", ContainersLinkedList::GetFirst, FuncLength::ONE);
1114    SetFrozenFunction(thread, linkedListFuncPrototype, "getLast", ContainersLinkedList::GetLast, FuncLength::ONE);
1115    SetFrozenFunction(thread, linkedListFuncPrototype, "getIndexOf", ContainersLinkedList::GetIndexOf, FuncLength::ONE);
1116    SetFrozenFunction(thread, linkedListFuncPrototype, "getLastIndexOf", ContainersLinkedList::GetLastIndexOf,
1117                      FuncLength::ONE);
1118    SetFrozenFunction(thread, linkedListFuncPrototype, "convertToArray", ContainersLinkedList::ConvertToArray,
1119                      FuncLength::ONE);
1120    SetFrozenFunction(thread, linkedListFuncPrototype, "set", ContainersLinkedList::Set, FuncLength::ONE);
1121    SetFrozenFunction(thread, linkedListFuncPrototype, "forEach", ContainersLinkedList::ForEach, FuncLength::ONE,
1122                      BUILTINS_STUB_ID(LinkedListForEach));
1123
1124    JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLinkedList::Length, "length",
1125                                                        FuncLength::ZERO);
1126    JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
1127    SetGetter(thread, linkedListFuncPrototype, lengthKey, lengthGetter);
1128
1129    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1130    SetFunctionAtSymbol(thread, env, linkedListFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1131                        ContainersLinkedList::GetIteratorObj, FuncLength::ONE);
1132
1133    InitializeLinkedListIterator(thread, env);
1134    globalConst->SetConstant(ConstantIndex::LINKED_LIST_FUNCTION_INDEX, linkedListFunction.GetTaggedValue());
1135    return linkedListFunction;
1136}
1137
1138void ContainersPrivate::InitializeLinkedListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
1139{
1140    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1141    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1142    JSHandle<JSHClass> iteratorClass =
1143        JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
1144    JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
1145    SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPILinkedListIterator::Next, FuncLength::ONE);
1146    SetStringTagSymbol(thread, env, setIteratorPrototype, "linkedlist Iterator");
1147    globalConst->SetConstant(ConstantIndex::LINKED_LIST_ITERATOR_PROTOTYPE_INDEX,
1148        setIteratorPrototype.GetTaggedValue());
1149}
1150
1151void ContainersPrivate::InitializeListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
1152{
1153    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1154    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1155    JSHandle<JSHClass> iteratorClass =
1156        JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
1157    JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
1158    SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPIListIterator::Next, FuncLength::ONE);
1159    SetStringTagSymbol(thread, env, setIteratorPrototype, "list Iterator");
1160    globalConst->SetConstant(ConstantIndex::LIST_ITERATOR_PROTOTYPE_INDEX, setIteratorPrototype.GetTaggedValue());
1161}
1162
1163JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashMap(JSThread *thread)
1164{
1165    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1166    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1167    // HashMap.prototype
1168    JSHandle<JSObject> hashMapFuncPrototype = factory->NewEmptyJSObject();
1169    JSHandle<JSTaggedValue> hashMapFuncPrototypeValue(hashMapFuncPrototype);
1170    // HashMap.prototype_or_hclass
1171    JSHandle<JSHClass> hashMapInstanceClass =
1172        factory->NewEcmaHClass(JSAPIHashMap::SIZE, JSType::JS_API_HASH_MAP, hashMapFuncPrototypeValue);
1173
1174    JSHandle<JSTaggedValue> hashMapFunction(NewContainerConstructor(
1175        thread, hashMapFuncPrototype, ContainersHashMap::HashMapConstructor, "HashMap", FuncLength::ZERO));
1176    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1177        JSHandle<JSFunction>::Cast(hashMapFunction), hashMapInstanceClass.GetTaggedValue());
1178
1179    // "constructor" property on the prototype
1180    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1181    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(hashMapFuncPrototype), constructorKey, hashMapFunction);
1182    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1183    // HashMap.prototype.set()
1184    SetFrozenFunction(thread, hashMapFuncPrototype, "set", ContainersHashMap::Set, FuncLength::TWO);
1185     // HashMap.prototype.setall()
1186    SetFrozenFunction(thread, hashMapFuncPrototype, "setAll", ContainersHashMap::SetAll, FuncLength::ONE);
1187    // HashMap.prototype.isEmpty()
1188    SetFrozenFunction(thread, hashMapFuncPrototype, "isEmpty", ContainersHashMap::IsEmpty, FuncLength::ZERO);
1189    // HashMap.prototype.remove()
1190    SetFrozenFunction(thread, hashMapFuncPrototype, "remove", ContainersHashMap::Remove, FuncLength::ONE);
1191     // HashMap.prototype.clear()
1192    SetFrozenFunction(thread, hashMapFuncPrototype, "clear", ContainersHashMap::Clear, FuncLength::ZERO);
1193    // HashMap.prototype.get()
1194    SetFrozenFunction(thread, hashMapFuncPrototype, "get", ContainersHashMap::Get, FuncLength::ONE);
1195    // HashMap.prototype.forEach()
1196    SetFrozenFunction(thread, hashMapFuncPrototype, "forEach", ContainersHashMap::ForEach, FuncLength::TWO,
1197                      BUILTINS_STUB_ID(HashMapForEach));
1198    // HashMap.prototype.hasKey()
1199    SetFrozenFunction(thread, hashMapFuncPrototype, "hasKey", ContainersHashMap::HasKey, FuncLength::ONE);
1200     // HashMap.prototype.hasValue()
1201    SetFrozenFunction(thread, hashMapFuncPrototype, "hasValue", ContainersHashMap::HasValue, FuncLength::ONE);
1202     // HashMap.prototype.replace()
1203    SetFrozenFunction(thread, hashMapFuncPrototype, "replace", ContainersHashMap::Replace, FuncLength::TWO);
1204    // HashMap.prototype.keys()
1205    SetFrozenFunction(thread, hashMapFuncPrototype, "keys", ContainersHashMap::Keys, FuncLength::ZERO);
1206    // HashMap.prototype.Values()
1207    SetFrozenFunction(thread, hashMapFuncPrototype, "values", ContainersHashMap::Values, FuncLength::ZERO);
1208    // HashMap.prototype.keys()
1209    SetFrozenFunction(thread, hashMapFuncPrototype, "entries", ContainersHashMap::Entries, FuncLength::ZERO);
1210    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1211    // @@ToStringTag
1212    SetStringTagSymbol(thread, env, hashMapFuncPrototype, "HashMap");
1213    // %HashMapPrototype% [ @@iterator ]
1214    SetFunctionAtSymbol(thread, env, hashMapFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1215                        ContainersHashMap::GetIteratorObj, FuncLength::ONE);
1216
1217    JSHandle<JSTaggedValue> lengthGetter =
1218        CreateGetter(thread, ContainersHashMap::GetLength, "length", FuncLength::ZERO);
1219    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1220    SetGetter(thread, hashMapFuncPrototype, lengthKey, lengthGetter);
1221    InitializeHashMapIterator(thread);
1222    return hashMapFunction;
1223}
1224
1225void ContainersPrivate::InitializeHashMapIterator(JSThread *thread)
1226{
1227    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1228    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1229    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1230    JSHandle<JSHClass> iteratorFuncHClass =
1231        JSHandle<JSHClass>::Cast(globalConst->GetHandledJSAPIIteratorFuncHClass());
1232    // HashMapIterator.prototype
1233    JSHandle<JSObject> hashMapIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1234    // HashMapIterator.prototype.next()
1235    SetFrozenFunction(thread, hashMapIteratorPrototype, "next", JSAPIHashMapIterator::Next, FuncLength::ZERO);
1236    SetStringTagSymbol(thread, env, hashMapIteratorPrototype, "HashMap Iterator");
1237
1238    globalConst->SetConstant(ConstantIndex::HASHMAP_ITERATOR_PROTOTYPE_INDEX,
1239                             hashMapIteratorPrototype.GetTaggedValue());
1240}
1241
1242JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashSet(JSThread *thread)
1243{
1244    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1245    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1246    // HashSet.prototype
1247    JSHandle<JSObject> hashSetFuncPrototype = factory->NewEmptyJSObject();
1248    JSHandle<JSTaggedValue> hashSetFuncPrototypeValue(hashSetFuncPrototype);
1249    // HashSet.prototype_or_hclass
1250    JSHandle<JSHClass> hashSetInstanceClass =
1251        factory->NewEcmaHClass(JSAPIHashSet::SIZE, JSType::JS_API_HASH_SET, hashSetFuncPrototypeValue);
1252
1253    JSHandle<JSTaggedValue> hashSetFunction(NewContainerConstructor(
1254        thread, hashSetFuncPrototype, ContainersHashSet::HashSetConstructor, "HashSet", FuncLength::ZERO));
1255    JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1256        JSHandle<JSFunction>::Cast(hashSetFunction), hashSetInstanceClass.GetTaggedValue());
1257
1258    // "constructor" property on the prototype
1259    JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1260    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(hashSetFuncPrototype), constructorKey, hashSetFunction);
1261    RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1262    SetFrozenFunction(thread, hashSetFuncPrototype, "isEmpty", ContainersHashSet::IsEmpty, FuncLength::ZERO);
1263    SetFrozenFunction(thread, hashSetFuncPrototype, "has", ContainersHashSet::Has, FuncLength::ONE);
1264    SetFrozenFunction(thread, hashSetFuncPrototype, "add", ContainersHashSet::Add, FuncLength::ONE);
1265    SetFrozenFunction(thread, hashSetFuncPrototype, "has", ContainersHashSet::Has, FuncLength::ONE);
1266    SetFrozenFunction(thread, hashSetFuncPrototype, "remove", ContainersHashSet::Remove, FuncLength::ONE);
1267    SetFrozenFunction(thread, hashSetFuncPrototype, "clear", ContainersHashSet::Clear, FuncLength::ZERO);
1268    SetFrozenFunction(thread, hashSetFuncPrototype, "values", ContainersHashSet::Values, FuncLength::ZERO);
1269    SetFrozenFunction(thread, hashSetFuncPrototype, "entries", ContainersHashSet::Entries, FuncLength::ZERO);
1270    SetFrozenFunction(thread, hashSetFuncPrototype, "forEach", ContainersHashSet::ForEach, FuncLength::TWO,
1271                      BUILTINS_STUB_ID(HashSetForEach));
1272
1273    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1274    // @@ToStringTag
1275    SetStringTagSymbol(thread, env, hashSetFuncPrototype, "HashSet");
1276    // %HashSetPrototype% [ @@iterator ]
1277    SetFunctionAtSymbol(thread, env, hashSetFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1278                        ContainersHashSet::GetIteratorObj, FuncLength::ONE);
1279
1280    JSHandle<JSTaggedValue> lengthGetter =
1281        CreateGetter(thread, ContainersHashSet::GetLength, "length", FuncLength::ZERO);
1282    JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1283    SetGetter(thread, hashSetFuncPrototype, lengthKey, lengthGetter);
1284    InitializeHashSetIterator(thread);
1285    return hashSetFunction;
1286}
1287
1288void ContainersPrivate::InitializeHashSetIterator(JSThread *thread)
1289{
1290    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1291    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1292    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1293    JSHandle<JSHClass> iteratorFuncHClass =
1294        JSHandle<JSHClass>::Cast(globalConst->GetHandledJSAPIIteratorFuncHClass());
1295
1296    // HashSetIterator.prototype
1297    JSHandle<JSObject> hashSetIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1298    // HashSetIterator.prototype.next()
1299    SetFrozenFunction(thread, hashSetIteratorPrototype, "next", JSAPIHashSetIterator::Next, FuncLength::ZERO);
1300    SetStringTagSymbol(thread, env, hashSetIteratorPrototype, "HashSet Iterator");
1301    globalConst->SetConstant(ConstantIndex::HASHSET_ITERATOR_PROTOTYPE_INDEX,
1302                             hashSetIteratorPrototype.GetTaggedValue());
1303}
1304}  // namespace panda::ecmascript::containers
1305