• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/containers/containers_private.h"
17 
18 #include "containers_arraylist.h"
19 #include "containers_deque.h"
20 #include "containers_hashmap.h"
21 #include "containers_hashset.h"
22 #include "containers_lightweightmap.h"
23 #include "containers_lightweightset.h"
24 #include "containers_linked_list.h"
25 #include "containers_list.h"
26 #include "containers_plainarray.h"
27 #include "containers_queue.h"
28 #include "containers_stack.h"
29 #include "containers_treemap.h"
30 #include "containers_treeset.h"
31 #include "containers_vector.h"
32 #include "ecmascript/js_api/js_api_arraylist_iterator.h"
33 #include "ecmascript/js_api/js_api_bitvector_iterator.h"
34 #include "ecmascript/js_api/js_api_deque_iterator.h"
35 #include "ecmascript/js_api/js_api_hashmap_iterator.h"
36 #include "ecmascript/js_api/js_api_hashset_iterator.h"
37 #include "ecmascript/js_api/js_api_hashset.h"
38 #include "ecmascript/js_api/js_api_lightweightmap_iterator.h"
39 #include "ecmascript/js_api/js_api_lightweightmap.h"
40 #include "ecmascript/js_api/js_api_lightweightset_iterator.h"
41 #include "ecmascript/js_api/js_api_lightweightset.h"
42 #include "ecmascript/js_api/js_api_linked_list_iterator.h"
43 #include "ecmascript/js_api/js_api_list_iterator.h"
44 #include "ecmascript/js_api/js_api_plain_array_iterator.h"
45 #include "ecmascript/js_api/js_api_queue_iterator.h"
46 #include "ecmascript/js_api/js_api_stack_iterator.h"
47 #include "ecmascript/js_api/js_api_tree_map_iterator.h"
48 #include "ecmascript/js_api/js_api_tree_map.h"
49 #include "ecmascript/js_api/js_api_tree_set_iterator.h"
50 #include "ecmascript/js_api/js_api_tree_set.h"
51 #include "ecmascript/js_api/js_api_vector_iterator.h"
52 #include "ecmascript/builtins/builtins.h"
53 #include "ecmascript/object_fast_operator-inl.h"
54 
55 namespace panda::ecmascript::containers {
Load(EcmaRuntimeCallInfo * msg)56 JSTaggedValue 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 
InitializeContainer(JSThread * thread,const JSHandle<JSObject> & obj,InitializeFunction func,const char * name)147 JSTaggedValue 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 
NewContainerConstructor(JSThread * thread,const JSHandle<JSObject> & prototype,EcmaEntrypoint ctorFunc,const char * name,int length)162 JSHandle<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 
SetFrozenFunction(JSThread * thread,const JSHandle<JSObject> & obj,const char * key,EcmaEntrypoint func,int length,kungfu::BuiltinsStubCSigns::ID builtinId)185 void 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 
SetFrozenConstructor(JSThread * thread,const JSHandle<JSObject> & obj,const char * keyChar,JSHandle<JSTaggedValue> & value)195 void ContainersPrivate::SetFrozenConstructor(JSThread *thread, const JSHandle<JSObject> &obj, const char *keyChar,
196                                              JSHandle<JSTaggedValue> &value)
197 {
198     if (value->IsECMAObject()) {
199         JSObject::PreventExtensions(thread, JSHandle<JSObject>::Cast(value));
200     }
201     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
202     JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyChar));
203     PropertyDescriptor descriptor(thread, value, false, false, false);
204     JSObject::DefineOwnProperty(thread, obj, key, descriptor);
205 }
206 
NewFunction(JSThread * thread,const JSHandle<JSTaggedValue> & key,EcmaEntrypoint func,int length,kungfu::BuiltinsStubCSigns::ID builtinId)207 JSHandle<JSFunction> ContainersPrivate::NewFunction(JSThread *thread, const JSHandle<JSTaggedValue> &key,
208                                                     EcmaEntrypoint func, int length,
209                                                     kungfu::BuiltinsStubCSigns::ID builtinId)
210 {
211     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
212     JSHandle<JSFunction> function =
213         factory->NewJSFunction(thread->GetEcmaVM()->GetGlobalEnv(), reinterpret_cast<void *>(func),
214                                FunctionKind::NORMAL_FUNCTION, builtinId);
215     JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
216     JSHandle<JSFunctionBase> baseFunction(function);
217     JSFunction::SetFunctionName(thread, baseFunction, key, thread->GlobalConstants()->GetHandledUndefined());
218     return function;
219 }
220 
CreateGetter(JSThread * thread,EcmaEntrypoint func,const char * name,int length)221 JSHandle<JSTaggedValue> ContainersPrivate::CreateGetter(JSThread *thread, EcmaEntrypoint func, const char *name,
222                                                         int length)
223 {
224     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
225     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
226     JSHandle<JSFunction> function = factory->NewJSFunction(env, reinterpret_cast<void *>(func));
227     JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
228     JSHandle<JSTaggedValue> funcName(factory->NewFromASCII(name));
229     JSHandle<JSTaggedValue> prefix = thread->GlobalConstants()->GetHandledGetString();
230     JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(function), funcName, prefix);
231     return JSHandle<JSTaggedValue>(function);
232 }
233 
SetGetter(JSThread * thread,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & getter)234 void ContainersPrivate::SetGetter(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
235                                   const JSHandle<JSTaggedValue> &getter)
236 {
237     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
238     JSHandle<AccessorData> accessor = factory->NewAccessorData();
239     accessor->SetGetter(thread, getter);
240     PropertyAttributes attr = PropertyAttributes::DefaultAccessor(false, false, false);
241     JSObject::AddAccessor(thread, JSHandle<JSTaggedValue>::Cast(obj), key, accessor, attr);
242 }
243 
SetFunctionAtSymbol(JSThread * thread,const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & symbol,const char * name,EcmaEntrypoint func,int length)244 void ContainersPrivate::SetFunctionAtSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
245                                             const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &symbol,
246                                             const char *name, EcmaEntrypoint func, int length)
247 {
248     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
249     JSHandle<JSFunction> function = factory->NewJSFunction(env, reinterpret_cast<void *>(func));
250     JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
251     JSHandle<JSTaggedValue> nameString(factory->NewFromASCII(name));
252     JSHandle<JSFunctionBase> baseFunction(function);
253     JSFunction::SetFunctionName(thread, baseFunction, nameString, thread->GlobalConstants()->GetHandledUndefined());
254     PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(function), false, false, false);
255     JSObject::DefineOwnProperty(thread, obj, symbol, descriptor);
256 }
257 
SetStringTagSymbol(JSThread * thread,const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & obj,const char * key)258 void ContainersPrivate::SetStringTagSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
259                                            const JSHandle<JSObject> &obj, const char *key)
260 {
261     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
262     JSHandle<JSTaggedValue> tag(factory->NewFromASCII(key));
263     JSHandle<JSTaggedValue> symbol = env->GetToStringTagSymbol();
264     PropertyDescriptor desc(thread, tag, false, false, false);
265     JSObject::DefineOwnProperty(thread, obj, symbol, desc);
266 }
267 
InitializeArrayList(JSThread * thread)268 JSHandle<JSTaggedValue> ContainersPrivate::InitializeArrayList(JSThread *thread)
269 {
270     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
271     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
272     // ArrayList.prototype
273     JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
274     JSHandle<JSTaggedValue> arrayListFuncPrototypeValue(prototype);
275     // ArrayList.prototype_or_hclass
276     JSHandle<JSHClass> arrayListInstanceClass =
277         factory->NewEcmaHClass(JSAPIArrayList::SIZE, JSType::JS_API_ARRAY_LIST, arrayListFuncPrototypeValue);
278     // ArrayList() = new Function()
279     JSHandle<JSTaggedValue> arrayListFunction(NewContainerConstructor(
280         thread, prototype, ContainersArrayList::ArrayListConstructor, "ArrayList", FuncLength::ZERO));
281     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
282         JSHandle<JSFunction>::Cast(arrayListFunction), arrayListInstanceClass.GetTaggedValue());
283 
284     // "constructor" property on the prototype
285     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
286     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, arrayListFunction);
287     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
288 
289     // ArrayList.prototype methods (excluding constructor and '@@' internal properties)
290     for (const base::BuiltinFunctionEntry &entry: ContainersArrayList::GetArrayListPrototypeFunctions()) {
291         SetFrozenFunction(thread, prototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
292                           entry.GetBuiltinStubId());
293     }
294 
295     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
296     SetStringTagSymbol(thread, env, prototype, "ArrayList");
297 
298     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersArrayList::GetSize, "length",
299                                                         FuncLength::ZERO);
300     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
301     SetGetter(thread, prototype, lengthKey, lengthGetter);
302 
303     SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
304                         ContainersArrayList::GetIteratorObj, FuncLength::ONE);
305     ContainersPrivate::InitializeArrayListIterator(thread, env, globalConst);
306     globalConst->SetConstant(ConstantIndex::ARRAYLIST_FUNCTION_INDEX, arrayListFunction.GetTaggedValue());
307     return arrayListFunction;
308 }
309 
InitializeArrayListIterator(JSThread * thread,const JSHandle<GlobalEnv> & env,GlobalEnvConstants * globalConst)310 void ContainersPrivate::InitializeArrayListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
311                                                     GlobalEnvConstants *globalConst)
312 {
313     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
314     // Iterator.hclass
315     JSHandle<JSHClass> iteratorFuncHClass =
316         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
317     // ArrayListIterator.prototype
318     JSHandle<JSObject> arrayListIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
319     // Iterator.prototype.next()
320     SetFrozenFunction(thread, arrayListIteratorPrototype, "next", JSAPIArrayListIterator::Next, FuncLength::ONE);
321     SetStringTagSymbol(thread, env, arrayListIteratorPrototype, "ArrayList Iterator");
322     globalConst->SetConstant(ConstantIndex::ARRAYLIST_ITERATOR_PROTOTYPE_INDEX,
323                              arrayListIteratorPrototype.GetTaggedValue());
324 }
325 
InitializeLightWeightMap(JSThread * thread)326 JSHandle<JSTaggedValue> ContainersPrivate::InitializeLightWeightMap(JSThread *thread)
327 {
328     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
329     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
330     JSHandle<JSObject> funcPrototype = factory->NewEmptyJSObject();
331     JSHandle<JSTaggedValue> mapFuncPrototypeValue(funcPrototype);
332     JSHandle<JSHClass> lightWeightMapInstanceClass =
333         factory->NewEcmaHClass(JSAPILightWeightMap::SIZE, JSType::JS_API_LIGHT_WEIGHT_MAP, mapFuncPrototypeValue);
334     JSHandle<JSTaggedValue> lightWeightMapFunction(NewContainerConstructor(
335         thread, funcPrototype, ContainersLightWeightMap::LightWeightMapConstructor, "LightWeightMap",
336         FuncLength::ZERO));
337     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
338         JSHandle<JSFunction>::Cast(lightWeightMapFunction), lightWeightMapInstanceClass.GetTaggedValue());
339 
340     // "constructor" property on the prototype
341     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
342     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(funcPrototype), constructorKey, lightWeightMapFunction);
343     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
344 
345     // LightWeightMap.prototype methods (excluding constructor and '@@' internal properties)
346     for (const base::BuiltinFunctionEntry &entry: ContainersLightWeightMap::GetLightWeightMapPrototypeFunctions()) {
347         SetFrozenFunction(thread, funcPrototype, entry.GetName().data(), entry.GetEntrypoint(),
348                           entry.GetLength(), entry.GetBuiltinStubId());
349     }
350 
351     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLightWeightMap::Length, "length",
352                                                         FuncLength::ZERO);
353     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
354     SetGetter(thread, funcPrototype, lengthKey, lengthGetter);
355 
356     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
357     SetFunctionAtSymbol(thread, env, funcPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
358                         ContainersLightWeightMap::Entries, FuncLength::ONE);
359 
360     ContainersPrivate::InitializeLightWeightMapIterator(thread);
361     return lightWeightMapFunction;
362 }
363 
InitializeLightWeightMapIterator(JSThread * thread)364 void ContainersPrivate::InitializeLightWeightMapIterator(JSThread *thread)
365 {
366     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
367     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
368     JSHandle<JSHClass> iteratorClass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR,
369                                                               env->GetIteratorPrototype());
370     JSHandle<JSObject> lightWeightMapIteratorPrototype(factory->NewJSObject(iteratorClass));
371     SetFrozenFunction(thread, lightWeightMapIteratorPrototype, "next", JSAPILightWeightMapIterator::Next,
372                       FuncLength::ONE);
373     SetStringTagSymbol(thread, env, lightWeightMapIteratorPrototype, "LightWeightMap Iterator");
374     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
375     globalConst->SetConstant(ConstantIndex::LIGHTWEIGHTMAP_ITERATOR_PROTOTYPE_INDEX,
376                              lightWeightMapIteratorPrototype.GetTaggedValue());
377 }
378 
InitializeLightWeightSet(JSThread * thread)379 JSHandle<JSTaggedValue> ContainersPrivate::InitializeLightWeightSet(JSThread *thread)
380 {
381     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
382     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
383     // LightWeightSet.prototype
384     JSHandle<JSObject> funcPrototype = factory->NewEmptyJSObject();
385     JSHandle<JSTaggedValue> funcPrototypeValue(funcPrototype);
386     // LightWeightSet.prototype_or_hclass
387     JSHandle<JSHClass> lightweightSetInstanceClass =
388         factory->NewEcmaHClass(JSAPILightWeightSet::SIZE, JSType::JS_API_LIGHT_WEIGHT_SET, funcPrototypeValue);
389     JSHandle<JSTaggedValue> lightweightSetFunction(
390         NewContainerConstructor(thread, funcPrototype, ContainersLightWeightSet::LightWeightSetConstructor,
391                                 "LightWeightSet", FuncLength::ZERO));
392     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
393         JSHandle<JSFunction>::Cast(lightweightSetFunction), lightweightSetInstanceClass.GetTaggedValue());
394     // "constructor" property on the prototype
395     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
396     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(funcPrototype), constructorKey, lightweightSetFunction);
397     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
398 
399     // LightWeightSet.prototype methods (excluding constructor and '@@' internal properties)
400     for (const base::BuiltinFunctionEntry &entry: ContainersLightWeightSet::GetLightWeightSetPrototypeFunctions()) {
401         SetFrozenFunction(thread, funcPrototype, entry.GetName().data(), entry.GetEntrypoint(),
402                           entry.GetLength(), entry.GetBuiltinStubId());
403     }
404 
405     JSHandle<JSTaggedValue> lengthGetter =
406         CreateGetter(thread, ContainersLightWeightSet::GetSize, "length", FuncLength::ZERO);
407 
408     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
409     SetGetter(thread, funcPrototype, lengthKey, lengthGetter);
410     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
411     SetFunctionAtSymbol(thread, env, funcPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
412                         ContainersLightWeightSet::GetIteratorObj, FuncLength::ONE);
413 
414     InitializeLightWeightSetIterator(thread);
415     return lightweightSetFunction;
416 }
417 
InitializeLightWeightSetIterator(JSThread * thread)418 void ContainersPrivate::InitializeLightWeightSetIterator(JSThread *thread)
419 {
420     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
421     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
422     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
423     JSHandle<JSHClass> iteratorClass =
424         JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
425     JSHandle<JSObject> lightWeightSetIteratorPrototype(factory->NewJSObject(iteratorClass));
426     SetFrozenFunction(
427         thread, lightWeightSetIteratorPrototype, "next", JSAPILightWeightSetIterator::Next, FuncLength::ONE);
428     SetStringTagSymbol(thread, env, lightWeightSetIteratorPrototype, "LightWeightSet Iterator");
429     globalConst->SetConstant(ConstantIndex::LIGHTWEIGHTSET_ITERATOR_PROTOTYPE_INDEX,
430                              lightWeightSetIteratorPrototype.GetTaggedValue());
431 }
432 
InitializeTreeMap(JSThread * thread)433 JSHandle<JSTaggedValue> ContainersPrivate::InitializeTreeMap(JSThread *thread)
434 {
435     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
436     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
437     // TreeMap.prototype
438     JSHandle<JSObject> mapFuncPrototype = factory->NewEmptyJSObject();
439     JSHandle<JSTaggedValue> mapFuncPrototypeValue(mapFuncPrototype);
440     // TreeMap.prototype_or_hclass
441     JSHandle<JSHClass> mapInstanceClass =
442         factory->NewEcmaHClass(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, mapFuncPrototypeValue);
443     // TreeMap() = new Function()
444     JSHandle<JSTaggedValue> mapFunction(NewContainerConstructor(
445         thread, mapFuncPrototype, ContainersTreeMap::TreeMapConstructor, "TreeMap", FuncLength::ZERO));
446     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
447         JSHandle<JSFunction>::Cast(mapFunction), mapInstanceClass.GetTaggedValue());
448 
449     // "constructor" property on the prototype
450     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
451     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(mapFuncPrototype), constructorKey, mapFunction);
452     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
453 
454     // TreeMap.prototype methods (excluding constructor and '@@' internal properties)
455     for (const base::BuiltinFunctionEntry &entry: ContainersTreeMap::GetTreeMapPrototypeFunctions()) {
456         SetFrozenFunction(thread, mapFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
457                           entry.GetLength(), entry.GetBuiltinStubId());
458     }
459 
460     // @@ToStringTag
461     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
462     SetStringTagSymbol(thread, env, mapFuncPrototype, "TreeMap");
463     // %TreeMapPrototype% [ @@iterator ]
464     JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
465     JSHandle<JSTaggedValue> entries = globalConst->GetHandledEntriesString();
466     JSHandle<JSTaggedValue> entriesFunc =
467         JSObject::GetMethod(thread, JSHandle<JSTaggedValue>::Cast(mapFuncPrototype), entries);
468     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
469     PropertyDescriptor descriptor(thread, entriesFunc, false, false, false);
470     JSObject::DefineOwnProperty(thread, mapFuncPrototype, iteratorSymbol, descriptor);
471     // length
472     JSHandle<JSTaggedValue> lengthGetter =
473         CreateGetter(thread, ContainersTreeMap::GetLength, "length", FuncLength::ZERO);
474     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
475     SetGetter(thread, mapFuncPrototype, lengthKey, lengthGetter);
476 
477     InitializeTreeMapIterator(thread);
478     return mapFunction;
479 }
480 
InitializeTreeMapIterator(JSThread * thread)481 void ContainersPrivate::InitializeTreeMapIterator(JSThread *thread)
482 {
483     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
484     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
485     // Iterator.hclass
486     JSHandle<JSHClass> iteratorClass =
487         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
488 
489     // TreeMapIterator.prototype
490     JSHandle<JSObject> mapIteratorPrototype(factory->NewJSObject(iteratorClass));
491     // TreeIterator.prototype.next()
492     SetFrozenFunction(thread, mapIteratorPrototype, "next", JSAPITreeMapIterator::Next, FuncLength::ZERO);
493     SetStringTagSymbol(thread, env, mapIteratorPrototype, "TreeMap Iterator");
494     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
495     globalConst->SetConstant(ConstantIndex::TREEMAP_ITERATOR_PROTOTYPE_INDEX, mapIteratorPrototype.GetTaggedValue());
496 }
497 
InitializeTreeSet(JSThread * thread)498 JSHandle<JSTaggedValue> ContainersPrivate::InitializeTreeSet(JSThread *thread)
499 {
500     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
501     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
502     // TreeSet.prototype
503     JSHandle<JSObject> setFuncPrototype = factory->NewEmptyJSObject();
504     JSHandle<JSTaggedValue> setFuncPrototypeValue(setFuncPrototype);
505     // TreeSet.prototype_or_hclass
506     JSHandle<JSHClass> setInstanceClass =
507         factory->NewEcmaHClass(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, setFuncPrototypeValue);
508     // TreeSet() = new Function()
509     JSHandle<JSTaggedValue> setFunction(NewContainerConstructor(
510         thread, setFuncPrototype, ContainersTreeSet::TreeSetConstructor, "TreeSet", FuncLength::ZERO));
511     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
512         JSHandle<JSFunction>::Cast(setFunction), setInstanceClass.GetTaggedValue());
513 
514     // "constructor" property on the prototype
515     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
516     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(setFuncPrototype), constructorKey, setFunction);
517     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
518 
519     // TreeSet.prototype methods (excluding constructor and '@@' internal properties)
520     for (const base::BuiltinFunctionEntry &entry: ContainersTreeSet::GetTreeSetPrototypeFunctions()) {
521         SetFrozenFunction(thread, setFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
522                           entry.GetLength(), entry.GetBuiltinStubId());
523     }
524 
525     // @@ToStringTag
526     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
527     SetStringTagSymbol(thread, env, setFuncPrototype, "TreeSet");
528     // %TreeSetPrototype% [ @@iterator ]
529     JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
530     JSHandle<JSTaggedValue> values(thread, globalConst->GetValuesString());
531     JSHandle<JSTaggedValue> valuesFunc =
532         JSObject::GetMethod(thread, JSHandle<JSTaggedValue>::Cast(setFuncPrototype), values);
533     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
534     PropertyDescriptor descriptor(thread, valuesFunc, false, false, false);
535     JSObject::DefineOwnProperty(thread, setFuncPrototype, iteratorSymbol, descriptor);
536     // length
537     JSHandle<JSTaggedValue> lengthGetter =
538         CreateGetter(thread, ContainersTreeSet::GetLength, "length", FuncLength::ZERO);
539     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
540     SetGetter(thread, setFuncPrototype, lengthKey, lengthGetter);
541 
542     InitializeTreeSetIterator(thread);
543     return setFunction;
544 }
545 
InitializeTreeSetIterator(JSThread * thread)546 void ContainersPrivate::InitializeTreeSetIterator(JSThread *thread)
547 {
548     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
549     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
550     // Iterator.hclass
551     JSHandle<JSHClass> iteratorClass =
552         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
553 
554     // TreeSetIterator.prototype
555     JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
556     // TreeSetIterator.prototype.next()
557     SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPITreeSetIterator::Next, FuncLength::ZERO);
558     SetStringTagSymbol(thread, env, setIteratorPrototype, "TreeSet Iterator");
559     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
560     globalConst->SetConstant(ConstantIndex::TREESET_ITERATOR_PROTOTYPE_INDEX, setIteratorPrototype.GetTaggedValue());
561 }
562 
InitializePlainArray(JSThread * thread)563 JSHandle<JSTaggedValue> ContainersPrivate::InitializePlainArray(JSThread *thread)
564 {
565     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
566     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
567     // PlainArray.prototype
568     JSHandle<JSObject> plainArrayFuncPrototype = factory->NewEmptyJSObject();
569     JSHandle<JSTaggedValue> plainArrayFuncPrototypeValue(plainArrayFuncPrototype);
570     // PlainArray.prototype_or_hclass
571     JSHandle<JSHClass> plainArrayInstanceClass =
572         factory->NewEcmaHClass(JSAPIPlainArray::SIZE, JSType::JS_API_PLAIN_ARRAY, plainArrayFuncPrototypeValue);
573     JSHandle<JSTaggedValue> plainArrayFunction(
574         NewContainerConstructor(thread, plainArrayFuncPrototype, ContainersPlainArray::PlainArrayConstructor,
575                                 "PlainArray", FuncLength::ZERO));
576     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
577         JSHandle<JSFunction>::Cast(plainArrayFunction), plainArrayInstanceClass.GetTaggedValue());
578 
579     // "constructor" property on the prototype
580     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
581     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(plainArrayFuncPrototype), constructorKey,
582                           plainArrayFunction);
583     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
584 
585     // PlainArray.prototype methods (excluding constructor and '@@' internal properties)
586     for (const base::BuiltinFunctionEntry &entry: ContainersPlainArray::GetPlainArrayPrototypeFunctions()) {
587         SetFrozenFunction(thread, plainArrayFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
588                           entry.GetLength(), entry.GetBuiltinStubId());
589     }
590 
591     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersPlainArray::GetSize, "length",
592                                                         FuncLength::ZERO);
593     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
594     SetGetter(thread, plainArrayFuncPrototype, lengthKey, lengthGetter);
595 
596     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
597     SetFunctionAtSymbol(thread, env, plainArrayFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
598                         ContainersPlainArray::GetIteratorObj, FuncLength::ONE);
599     InitializePlainArrayIterator(thread);
600     globalConst->SetConstant(ConstantIndex::PLAIN_ARRAY_FUNCTION_INDEX, plainArrayFunction.GetTaggedValue());
601     return plainArrayFunction;
602 }
603 
InitializePlainArrayIterator(JSThread * thread)604 void ContainersPrivate::InitializePlainArrayIterator(JSThread *thread)
605 {
606     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
607     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
608     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
609     JSHandle<JSHClass> iteratorClass =
610         JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
611     JSHandle<JSObject> plainarrayIteratorPrototype(factory->NewJSObject(iteratorClass));
612     SetFrozenFunction(thread, plainarrayIteratorPrototype, "next", JSAPIPlainArrayIterator::Next, FuncLength::ONE);
613     SetStringTagSymbol(thread, env, plainarrayIteratorPrototype, "PlainArray Iterator");
614     globalConst->SetConstant(ConstantIndex::PLAIN_ARRAY_ITERATOR_PROTOTYPE_INDEX,
615                              plainarrayIteratorPrototype.GetTaggedValue());
616 }
617 
InitializeStack(JSThread * thread)618 JSHandle<JSTaggedValue> ContainersPrivate::InitializeStack(JSThread *thread)
619 {
620     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
621     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
622     // Stack.prototype
623     JSHandle<JSObject> stackFuncPrototype = factory->NewEmptyJSObject();
624     JSHandle<JSTaggedValue> stackFuncPrototypeValue(stackFuncPrototype);
625     // Stack.prototype_or_hclass
626     JSHandle<JSHClass> stackInstanceClass =
627         factory->NewEcmaHClass(JSAPIStack::SIZE, JSType::JS_API_STACK, stackFuncPrototypeValue);
628     // Stack() = new Function()
629     JSHandle<JSTaggedValue> stackFunction(NewContainerConstructor(
630         thread, stackFuncPrototype, ContainersStack::StackConstructor, "Stack", FuncLength::ZERO));
631     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
632         JSHandle<JSFunction>::Cast(stackFunction), stackInstanceClass.GetTaggedValue());
633 
634     // "constructor" property on the prototype
635     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
636     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(stackFuncPrototype), constructorKey, stackFunction);
637     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
638 
639     // Stack.prototype methods (excluding constructor and '@@' internal properties)
640     for (const base::BuiltinFunctionEntry &entry: ContainersStack::GetStackPrototypeFunctions()) {
641         SetFrozenFunction(thread, stackFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
642                           entry.GetLength(), entry.GetBuiltinStubId());
643     }
644 
645     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
646     SetStringTagSymbol(thread, env, stackFuncPrototype, "Stack");
647 
648     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersStack::GetLength, "length", FuncLength::ZERO);
649     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
650     SetGetter(thread, stackFuncPrototype, lengthKey, lengthGetter);
651 
652     SetFunctionAtSymbol(thread, env, stackFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
653                         ContainersStack::Iterator, FuncLength::ONE);
654 
655     ContainersPrivate::InitializeStackIterator(thread, globalConst);
656     return stackFunction;
657 }
658 
InitializeStackIterator(JSThread * thread,GlobalEnvConstants * globalConst)659 void ContainersPrivate::InitializeStackIterator(JSThread *thread, GlobalEnvConstants *globalConst)
660 {
661     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
662     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>(thread, globalConst->
663                         GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
664     // StackIterator.prototype
665     JSHandle<JSObject> stackIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
666     // Iterator.prototype.next()
667     SetFrozenFunction(thread, stackIteratorPrototype, "next", JSAPIStackIterator::Next, FuncLength::ONE);
668     globalConst->SetConstant(ConstantIndex::STACK_ITERATOR_PROTOTYPE_INDEX, stackIteratorPrototype.GetTaggedValue());
669 }
670 
InitializeVector(JSThread * thread)671 JSHandle<JSTaggedValue> ContainersPrivate::InitializeVector(JSThread *thread)
672 {
673     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
674     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
675     // Vector.prototype
676     JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
677     JSHandle<JSTaggedValue> vectorFuncPrototypeValue(prototype);
678     // Vector.prototype_or_hclass
679     JSHandle<JSHClass> vectorInstanceClass =
680         factory->NewEcmaHClass(JSAPIVector::SIZE, JSType::JS_API_VECTOR, vectorFuncPrototypeValue);
681     // Vector() = new Function()
682     JSHandle<JSTaggedValue> vectorFunction(NewContainerConstructor(
683         thread, prototype, ContainersVector::VectorConstructor, "Vector", FuncLength::ZERO));
684     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
685         JSHandle<JSFunction>::Cast(vectorFunction), vectorInstanceClass.GetTaggedValue());
686 
687     // "constructor" property on the prototype
688     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
689     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, vectorFunction);
690     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
691     // Vector.prototype
692     SetFrozenFunction(thread, prototype, "add", ContainersVector::Add, FuncLength::ONE);
693     SetFrozenFunction(thread, prototype, "insert", ContainersVector::Insert, FuncLength::TWO);
694     SetFrozenFunction(thread, prototype, "setLength", ContainersVector::SetLength, FuncLength::ONE);
695     SetFrozenFunction(thread, prototype, "getCapacity", ContainersVector::GetCapacity, FuncLength::ZERO);
696     SetFrozenFunction(thread, prototype, "increaseCapacityTo", ContainersVector::IncreaseCapacityTo, FuncLength::ONE);
697     SetFrozenFunction(thread, prototype, "get", ContainersVector::Get, FuncLength::ONE);
698     SetFrozenFunction(thread, prototype, "getIndexOf", ContainersVector::GetIndexOf, FuncLength::ONE);
699     SetFrozenFunction(thread, prototype, "getIndexFrom", ContainersVector::GetIndexFrom, FuncLength::TWO);
700     SetFrozenFunction(thread, prototype, "isEmpty", ContainersVector::IsEmpty, FuncLength::ZERO);
701     SetFrozenFunction(thread, prototype, "getLastElement", ContainersVector::GetLastElement, FuncLength::ZERO);
702     SetFrozenFunction(thread, prototype, "getLastIndexOf", ContainersVector::GetLastIndexOf, FuncLength::ONE);
703     SetFrozenFunction(thread, prototype, "getLastIndexFrom", ContainersVector::GetLastIndexFrom, FuncLength::TWO);
704     SetFrozenFunction(thread, prototype, "remove", ContainersVector::Remove, FuncLength::ONE);
705     SetFrozenFunction(thread, prototype, "removeByIndex", ContainersVector::RemoveByIndex, FuncLength::ONE);
706     SetFrozenFunction(thread, prototype, "removeByRange", ContainersVector::RemoveByRange, FuncLength::TWO);
707     SetFrozenFunction(thread, prototype, "set", ContainersVector::Set, FuncLength::TWO);
708     SetFrozenFunction(thread, prototype, "subVector", ContainersVector::SubVector, FuncLength::TWO);
709     SetFrozenFunction(thread, prototype, "toString", ContainersVector::ToString, FuncLength::ZERO);
710     SetFrozenFunction(thread, prototype, "forEach", ContainersVector::ForEach, FuncLength::TWO,
711                       BUILTINS_STUB_ID(VectorForEach));
712     SetFrozenFunction(thread, prototype, "replaceAllElements", ContainersVector::ReplaceAllElements, FuncLength::TWO,
713                       BUILTINS_STUB_ID(VectorReplaceAllElements));
714     SetFrozenFunction(thread, prototype, "has", ContainersVector::Has, FuncLength::ONE);
715     SetFrozenFunction(thread, prototype, "sort", ContainersVector::Sort, FuncLength::ZERO);
716     SetFrozenFunction(thread, prototype, "clear", ContainersVector::Clear, FuncLength::ZERO);
717     SetFrozenFunction(thread, prototype, "clone", ContainersVector::Clone, FuncLength::ZERO);
718     SetFrozenFunction(thread, prototype, "copyToArray", ContainersVector::CopyToArray, FuncLength::ONE);
719     SetFrozenFunction(thread, prototype, "convertToArray", ContainersVector::ConvertToArray, FuncLength::ZERO);
720     SetFrozenFunction(thread, prototype, "getFirstElement", ContainersVector::GetFirstElement, FuncLength::ZERO);
721     SetFrozenFunction(thread, prototype, "trimToCurrentLength",
722                       ContainersVector::TrimToCurrentLength, FuncLength::ZERO);
723 
724     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
725     SetStringTagSymbol(thread, env, prototype, "Vector");
726 
727     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersVector::GetSize, "length", FuncLength::ZERO);
728     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
729     SetGetter(thread, prototype, lengthKey, lengthGetter);
730 
731     SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
732                         ContainersVector::GetIteratorObj, FuncLength::ONE);
733 
734     ContainersPrivate::InitializeVectorIterator(thread, env, globalConst);
735     globalConst->SetConstant(ConstantIndex::VECTOR_FUNCTION_INDEX, vectorFunction.GetTaggedValue());
736     return vectorFunction;
737 }
738 
InitializeVectorIterator(JSThread * thread,const JSHandle<GlobalEnv> & env,GlobalEnvConstants * globalConst)739 void ContainersPrivate::InitializeVectorIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
740                                                  GlobalEnvConstants *globalConst)
741 {
742     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
743     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>(thread, globalConst->
744                         GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
745     // VectorIterator.prototype
746     JSHandle<JSObject> vectorIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
747     // Iterator.prototype.next()
748     SetFrozenFunction(thread, vectorIteratorPrototype, "next", JSAPIVectorIterator::Next, FuncLength::ONE);
749     SetStringTagSymbol(thread, env, vectorIteratorPrototype, "Vector Iterator");
750     globalConst->SetConstant(ConstantIndex::VECTOR_ITERATOR_PROTOTYPE_INDEX, vectorIteratorPrototype.GetTaggedValue());
751 }
752 
InitializeBitVector(JSThread * thread)753 JSHandle<JSTaggedValue> ContainersPrivate::InitializeBitVector(JSThread* thread)
754 {
755     auto globalConst = const_cast<GlobalEnvConstants*>(thread->GlobalConstants());
756     auto vm = thread->GetEcmaVM();
757     ObjectFactory* factory = vm->GetFactory();
758     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
759     Builtins builtin(thread, factory, vm);
760     JSHandle<JSObject> sObjPrototype = JSHandle<JSObject>::Cast(env->GetSObjectFunctionPrototype());
761     JSHandle<JSFunction> sFuncPrototype = JSHandle<JSFunction>::Cast(env->GetSFunctionPrototype());
762     builtin.InitializeSharedBitVector(env, sObjPrototype, sFuncPrototype);
763     InitializeBitVectorIterator(thread, env, globalConst);
764     JSHandle<JSTaggedValue> bitVectorFunction = env->GetBitVectorFunction();
765     return bitVectorFunction;
766 }
767 
InitializeBitVectorIterator(JSThread * thread,const JSHandle<GlobalEnv> & env,GlobalEnvConstants * globalConst)768 void ContainersPrivate::InitializeBitVectorIterator(
769     JSThread* thread, const JSHandle<GlobalEnv>& env, GlobalEnvConstants* globalConst)
770 {
771     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
772     JSHandle<JSHClass> iteratorFuncClass = JSHandle<JSHClass>(thread,
773         globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
774     JSHandle<JSObject> bitVectorIteratorPrototype(factory->NewJSObjectWithInit(iteratorFuncClass));
775     // Iterator.prototype.next()
776     SetFrozenFunction(thread, bitVectorIteratorPrototype, "next", JSAPIBitVectorIterator::Next, FuncLength::ONE);
777     SetStringTagSymbol(thread, env, bitVectorIteratorPrototype, "BitVector Iterator");
778     env->SetBitVectorIteratorPrototype(thread, bitVectorIteratorPrototype);
779 }
780 
InitializeQueue(JSThread * thread)781 JSHandle<JSTaggedValue> ContainersPrivate::InitializeQueue(JSThread *thread)
782 {
783     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
784     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
785     // Queue.prototype
786     JSHandle<JSObject> queueFuncPrototype = factory->NewEmptyJSObject();
787     JSHandle<JSTaggedValue> queueFuncPrototypeValue(queueFuncPrototype);
788     // Queue.prototype_or_hclass
789     JSHandle<JSHClass> queueInstanceClass =
790         factory->NewEcmaHClass(JSAPIQueue::SIZE, JSType::JS_API_QUEUE, queueFuncPrototypeValue);
791     // Queue() = new Function()
792     JSHandle<JSTaggedValue> queueFunction(NewContainerConstructor(
793         thread, queueFuncPrototype, ContainersQueue::QueueConstructor, "Queue", FuncLength::ZERO));
794     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
795         JSHandle<JSFunction>::Cast(queueFunction), queueInstanceClass.GetTaggedValue());
796 
797     // "constructor" property on the prototype
798     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
799     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(queueFuncPrototype), constructorKey, queueFunction);
800     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
801 
802     // Queue.prototype methods (excluding constructor and '@@' internal properties)
803     for (const base::BuiltinFunctionEntry &entry: ContainersQueue::GetQueuePrototypeFunctions()) {
804         SetFrozenFunction(thread, queueFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
805                           entry.GetLength(), entry.GetBuiltinStubId());
806     }
807 
808     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
809     SetStringTagSymbol(thread, env, queueFuncPrototype, "Queue");
810 
811     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersQueue::GetSize, "length", FuncLength::ZERO);
812     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
813     SetGetter(thread, queueFuncPrototype, lengthKey, lengthGetter);
814 
815     SetFunctionAtSymbol(thread, env, queueFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
816                         ContainersQueue::GetIteratorObj, FuncLength::ONE);
817 
818     ContainersPrivate::InitializeQueueIterator(thread, env, globalConst);
819     return queueFunction;
820 }
821 
InitializeQueueIterator(JSThread * thread,const JSHandle<GlobalEnv> & env,GlobalEnvConstants * globalConst)822 void ContainersPrivate::InitializeQueueIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
823                                                 GlobalEnvConstants *globalConst)
824 {
825     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
826     JSHandle<JSHClass> iteratorFuncHClass =
827         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
828     // QueueIterator.prototype
829     JSHandle<JSObject> queueIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
830     // Iterator.prototype.next()
831     SetFrozenFunction(thread, queueIteratorPrototype, "next", JSAPIQueueIterator::Next, FuncLength::ONE);
832     SetStringTagSymbol(thread, env, queueIteratorPrototype, "Queue Iterator");
833     globalConst->SetConstant(ConstantIndex::QUEUE_ITERATOR_PROTOTYPE_INDEX, queueIteratorPrototype.GetTaggedValue());
834 }
835 
InitializeDeque(JSThread * thread)836 JSHandle<JSTaggedValue> ContainersPrivate::InitializeDeque(JSThread *thread)
837 {
838     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
839     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
840     // Deque.prototype
841     JSHandle<JSObject> dequeFuncPrototype = factory->NewEmptyJSObject();
842     JSHandle<JSTaggedValue> dequeFuncPrototypeValue(dequeFuncPrototype);
843     // Deque.prototype_or_hclass
844     JSHandle<JSHClass> dequeInstanceClass =
845         factory->NewEcmaHClass(JSAPIDeque::SIZE, JSType::JS_API_DEQUE, dequeFuncPrototypeValue);
846     // Deque() = new Function()
847     JSHandle<JSTaggedValue> dequeFunction(NewContainerConstructor(
848         thread, dequeFuncPrototype, ContainersDeque::DequeConstructor, "Deque", FuncLength::ZERO));
849     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
850         JSHandle<JSFunction>::Cast(dequeFunction), dequeInstanceClass.GetTaggedValue());
851 
852     // "constructor" property on the prototype
853     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
854     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(dequeFuncPrototype), constructorKey, dequeFunction);
855     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
856 
857     // Deque.prototype methods (excluding constructor and '@@' internal properties)
858     for (const base::BuiltinFunctionEntry &entry: ContainersDeque::GetDequePrototypeFunctions()) {
859         SetFrozenFunction(thread, dequeFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
860                           entry.GetBuiltinStubId());
861     }
862 
863     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
864     SetStringTagSymbol(thread, env, dequeFuncPrototype, "Deque");
865 
866     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersDeque::GetSize, "length", FuncLength::ZERO);
867     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
868     SetGetter(thread, dequeFuncPrototype, lengthKey, lengthGetter);
869 
870     SetFunctionAtSymbol(thread, env, dequeFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
871                         ContainersDeque::GetIteratorObj, FuncLength::ONE);
872 
873     ContainersPrivate::InitializeDequeIterator(thread, env, globalConst);
874 
875     return dequeFunction;
876 }
877 
InitializeDequeIterator(JSThread * thread,const JSHandle<GlobalEnv> & env,GlobalEnvConstants * globalConst)878 void ContainersPrivate::InitializeDequeIterator(JSThread *thread, const JSHandle<GlobalEnv> &env,
879                                                 GlobalEnvConstants *globalConst)
880 {
881     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
882     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>(thread, globalConst->
883                         GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
884     JSHandle<JSObject> dequeIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
885     SetFrozenFunction(thread, dequeIteratorPrototype, "next", JSAPIDequeIterator::Next, FuncLength::ONE);
886     SetStringTagSymbol(thread, env, dequeIteratorPrototype, "Deque Iterator");
887     globalConst->SetConstant(ConstantIndex::DEQUE_ITERATOR_PROTOTYPE_INDEX, dequeIteratorPrototype.GetTaggedValue());
888 }
889 
InitializeList(JSThread * thread)890 JSHandle<JSTaggedValue> ContainersPrivate::InitializeList(JSThread *thread)
891 {
892     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
893     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
894     JSHandle<JSObject> listFuncPrototype = factory->NewEmptyJSObject();
895     JSHandle<JSTaggedValue> listFuncPrototypeValue(listFuncPrototype);
896     JSHandle<JSHClass> listInstanceClass =
897         factory->NewEcmaHClass(JSAPIList::SIZE, JSType::JS_API_LIST, listFuncPrototypeValue);
898     JSHandle<JSTaggedValue> listFunction(NewContainerConstructor(
899         thread, listFuncPrototype, ContainersList::ListConstructor, "List", FuncLength::ZERO));
900     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
901         JSHandle<JSFunction>::Cast(listFunction), listInstanceClass.GetTaggedValue());
902 
903     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
904     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(listFuncPrototype), constructorKey, listFunction);
905     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
906 
907     // List.prototype methods (excluding constructor and '@@' internal properties)
908     for (const base::BuiltinFunctionEntry &entry: ContainersList::GetListPrototypeFunctions()) {
909         SetFrozenFunction(thread, listFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
910                           entry.GetBuiltinStubId());
911     }
912 
913     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersList::Length, "length", FuncLength::ZERO);
914     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
915     SetGetter(thread, listFuncPrototype, lengthKey, lengthGetter);
916 
917     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
918     SetFunctionAtSymbol(thread, env, listFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
919                         ContainersList::GetIteratorObj, FuncLength::ONE);
920 
921     InitializeListIterator(thread, env);
922     globalConst->SetConstant(ConstantIndex::LIST_FUNCTION_INDEX, listFunction.GetTaggedValue());
923     return listFunction;
924 }
925 
InitializeLinkedList(JSThread * thread)926 JSHandle<JSTaggedValue> ContainersPrivate::InitializeLinkedList(JSThread *thread)
927 {
928     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
929     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
930     JSHandle<JSObject> linkedListFuncPrototype = factory->NewEmptyJSObject();
931     JSHandle<JSTaggedValue> linkedListFuncPrototypeValue(linkedListFuncPrototype);
932     JSHandle<JSHClass> linkedListInstanceClass =
933         factory->NewEcmaHClass(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, linkedListFuncPrototypeValue);
934     JSHandle<JSTaggedValue> linkedListFunction(NewContainerConstructor(
935         thread, linkedListFuncPrototype, ContainersLinkedList::LinkedListConstructor, "LinkedList", FuncLength::ZERO));
936     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
937         JSHandle<JSFunction>::Cast(linkedListFunction), linkedListInstanceClass.GetTaggedValue());
938 
939     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
940     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(linkedListFuncPrototype), constructorKey, linkedListFunction);
941     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
942 
943     // LinkedList.prototype methods (excluding constructor and '@@' internal properties)
944     for (const base::BuiltinFunctionEntry &entry: ContainersLinkedList::GetLinkedListPrototypeFunctions()) {
945         SetFrozenFunction(thread, linkedListFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
946                           entry.GetBuiltinStubId());
947     }
948 
949     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLinkedList::Length, "length",
950                                                         FuncLength::ZERO);
951     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
952     SetGetter(thread, linkedListFuncPrototype, lengthKey, lengthGetter);
953 
954     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
955     SetFunctionAtSymbol(thread, env, linkedListFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
956                         ContainersLinkedList::GetIteratorObj, FuncLength::ONE);
957 
958     InitializeLinkedListIterator(thread, env);
959     globalConst->SetConstant(ConstantIndex::LINKED_LIST_FUNCTION_INDEX, linkedListFunction.GetTaggedValue());
960     return linkedListFunction;
961 }
962 
InitializeLinkedListIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)963 void ContainersPrivate::InitializeLinkedListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
964 {
965     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
966     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
967     JSHandle<JSHClass> iteratorClass =
968         JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
969     JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
970     SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPILinkedListIterator::Next, FuncLength::ONE);
971     SetStringTagSymbol(thread, env, setIteratorPrototype, "linkedlist Iterator");
972     globalConst->SetConstant(ConstantIndex::LINKED_LIST_ITERATOR_PROTOTYPE_INDEX,
973         setIteratorPrototype.GetTaggedValue());
974 }
975 
InitializeListIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)976 void ContainersPrivate::InitializeListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
977 {
978     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
979     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
980     JSHandle<JSHClass> iteratorClass =
981         JSHandle<JSHClass>(thread, globalConst->GetHandledJSAPIIteratorFuncHClass().GetObject<JSHClass>());
982     JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
983     SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPIListIterator::Next, FuncLength::ONE);
984     SetStringTagSymbol(thread, env, setIteratorPrototype, "list Iterator");
985     globalConst->SetConstant(ConstantIndex::LIST_ITERATOR_PROTOTYPE_INDEX, setIteratorPrototype.GetTaggedValue());
986 }
987 
InitializeHashMap(JSThread * thread)988 JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashMap(JSThread *thread)
989 {
990     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
991     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
992     // HashMap.prototype
993     JSHandle<JSObject> hashMapFuncPrototype = factory->NewEmptyJSObject();
994     JSHandle<JSTaggedValue> hashMapFuncPrototypeValue(hashMapFuncPrototype);
995     // HashMap.prototype_or_hclass
996     JSHandle<JSHClass> hashMapInstanceClass =
997         factory->NewEcmaHClass(JSAPIHashMap::SIZE, JSType::JS_API_HASH_MAP, hashMapFuncPrototypeValue);
998 
999     JSHandle<JSTaggedValue> hashMapFunction(NewContainerConstructor(
1000         thread, hashMapFuncPrototype, ContainersHashMap::HashMapConstructor, "HashMap", FuncLength::ZERO));
1001     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1002         JSHandle<JSFunction>::Cast(hashMapFunction), hashMapInstanceClass.GetTaggedValue());
1003 
1004     // "constructor" property on the prototype
1005     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1006     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(hashMapFuncPrototype), constructorKey, hashMapFunction);
1007     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1008 
1009     // HashMap.prototype methods (excluding constructor and '@@' internal properties)
1010     for (const base::BuiltinFunctionEntry &entry: ContainersHashMap::GetHashMapPrototypeFunctions()) {
1011         SetFrozenFunction(thread, hashMapFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
1012                           entry.GetLength(), entry.GetBuiltinStubId());
1013     }
1014 
1015     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1016     // @@ToStringTag
1017     SetStringTagSymbol(thread, env, hashMapFuncPrototype, "HashMap");
1018     // %HashMapPrototype% [ @@iterator ]
1019     SetFunctionAtSymbol(thread, env, hashMapFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1020                         ContainersHashMap::GetIteratorObj, FuncLength::ONE);
1021 
1022     JSHandle<JSTaggedValue> lengthGetter =
1023         CreateGetter(thread, ContainersHashMap::GetLength, "length", FuncLength::ZERO);
1024     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1025     SetGetter(thread, hashMapFuncPrototype, lengthKey, lengthGetter);
1026     InitializeHashMapIterator(thread);
1027     return hashMapFunction;
1028 }
1029 
InitializeHashMapIterator(JSThread * thread)1030 void ContainersPrivate::InitializeHashMapIterator(JSThread *thread)
1031 {
1032     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1033     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1034     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1035     JSHandle<JSHClass> iteratorFuncHClass =
1036         JSHandle<JSHClass>::Cast(globalConst->GetHandledJSAPIIteratorFuncHClass());
1037     // HashMapIterator.prototype
1038     JSHandle<JSObject> hashMapIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1039     // HashMapIterator.prototype.next()
1040     SetFrozenFunction(thread, hashMapIteratorPrototype, "next", JSAPIHashMapIterator::Next, FuncLength::ZERO);
1041     SetStringTagSymbol(thread, env, hashMapIteratorPrototype, "HashMap Iterator");
1042 
1043     globalConst->SetConstant(ConstantIndex::HASHMAP_ITERATOR_PROTOTYPE_INDEX,
1044                              hashMapIteratorPrototype.GetTaggedValue());
1045 }
1046 
InitializeHashSet(JSThread * thread)1047 JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashSet(JSThread *thread)
1048 {
1049     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1050     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1051     // HashSet.prototype
1052     JSHandle<JSObject> hashSetFuncPrototype = factory->NewEmptyJSObject();
1053     JSHandle<JSTaggedValue> hashSetFuncPrototypeValue(hashSetFuncPrototype);
1054     // HashSet.prototype_or_hclass
1055     JSHandle<JSHClass> hashSetInstanceClass =
1056         factory->NewEcmaHClass(JSAPIHashSet::SIZE, JSType::JS_API_HASH_SET, hashSetFuncPrototypeValue);
1057 
1058     JSHandle<JSTaggedValue> hashSetFunction(NewContainerConstructor(
1059         thread, hashSetFuncPrototype, ContainersHashSet::HashSetConstructor, "HashSet", FuncLength::ZERO));
1060     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1061         JSHandle<JSFunction>::Cast(hashSetFunction), hashSetInstanceClass.GetTaggedValue());
1062 
1063     // "constructor" property on the prototype
1064     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1065     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(hashSetFuncPrototype), constructorKey, hashSetFunction);
1066     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1067 
1068     // HashSet.prototype methods (excluding constructor and '@@' internal properties)
1069     for (const base::BuiltinFunctionEntry &entry: ContainersHashSet::GetHashSetPrototypeFunctions()) {
1070         SetFrozenFunction(thread, hashSetFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
1071                           entry.GetLength(), entry.GetBuiltinStubId());
1072     }
1073 
1074     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1075     // @@ToStringTag
1076     SetStringTagSymbol(thread, env, hashSetFuncPrototype, "HashSet");
1077     // %HashSetPrototype% [ @@iterator ]
1078     SetFunctionAtSymbol(thread, env, hashSetFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1079                         ContainersHashSet::GetIteratorObj, FuncLength::ONE);
1080 
1081     JSHandle<JSTaggedValue> lengthGetter =
1082         CreateGetter(thread, ContainersHashSet::GetLength, "length", FuncLength::ZERO);
1083     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1084     SetGetter(thread, hashSetFuncPrototype, lengthKey, lengthGetter);
1085     InitializeHashSetIterator(thread);
1086     return hashSetFunction;
1087 }
1088 
InitializeHashSetIterator(JSThread * thread)1089 void ContainersPrivate::InitializeHashSetIterator(JSThread *thread)
1090 {
1091     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1092     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1093     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1094     JSHandle<JSHClass> iteratorFuncHClass =
1095         JSHandle<JSHClass>::Cast(globalConst->GetHandledJSAPIIteratorFuncHClass());
1096 
1097     // HashSetIterator.prototype
1098     JSHandle<JSObject> hashSetIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1099     // HashSetIterator.prototype.next()
1100     SetFrozenFunction(thread, hashSetIteratorPrototype, "next", JSAPIHashSetIterator::Next, FuncLength::ZERO);
1101     SetStringTagSymbol(thread, env, hashSetIteratorPrototype, "HashSet Iterator");
1102     globalConst->SetConstant(ConstantIndex::HASHSET_ITERATOR_PROTOTYPE_INDEX,
1103                              hashSetIteratorPrototype.GetTaggedValue());
1104 }
1105 }  // namespace panda::ecmascript::containers
1106