• 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_buffer.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_buffer.h"
36 #include "ecmascript/js_api/js_api_deque_iterator.h"
37 #include "ecmascript/js_api/js_api_hashmap_iterator.h"
38 #include "ecmascript/js_api/js_api_hashset_iterator.h"
39 #include "ecmascript/js_api/js_api_hashset.h"
40 #include "ecmascript/js_api/js_api_lightweightmap_iterator.h"
41 #include "ecmascript/js_api/js_api_lightweightmap.h"
42 #include "ecmascript/js_api/js_api_lightweightset_iterator.h"
43 #include "ecmascript/js_api/js_api_lightweightset.h"
44 #include "ecmascript/js_api/js_api_linked_list_iterator.h"
45 #include "ecmascript/js_api/js_api_list_iterator.h"
46 #include "ecmascript/js_api/js_api_plain_array_iterator.h"
47 #include "ecmascript/js_api/js_api_queue_iterator.h"
48 #include "ecmascript/js_api/js_api_stack_iterator.h"
49 #include "ecmascript/js_api/js_api_tree_map_iterator.h"
50 #include "ecmascript/js_api/js_api_tree_map.h"
51 #include "ecmascript/js_api/js_api_tree_set_iterator.h"
52 #include "ecmascript/js_api/js_api_tree_set.h"
53 #include "ecmascript/js_api/js_api_vector_iterator.h"
54 #include "ecmascript/builtins/builtins.h"
55 #include "ecmascript/object_fast_operator-inl.h"
56 #include <numeric>
57 
58 namespace panda::ecmascript::containers {
Load(EcmaRuntimeCallInfo * msg)59 JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg)
60 {
61     ASSERT(msg != nullptr);
62     JSThread *thread = msg->GetThread();
63     [[maybe_unused]] EcmaHandleScope handleScope(thread);
64     JSHandle<JSTaggedValue> argv = GetCallArg(msg, 0);
65     JSHandle<JSObject> thisValue(GetThis(msg));
66 
67     uint32_t tag = 0;
68     if (!JSTaggedValue::ToElementIndex(thread, argv.GetTaggedValue(), &tag) || tag >= ContainerTag::END) {
69         THROW_TYPE_ERROR_AND_RETURN(thread, "Incorrect input parameters", JSTaggedValue::Exception());
70     }
71 
72     // Lazy set an undefinedIteratorResult to global constants
73     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
74     JSHandle<JSTaggedValue> undefinedHandle = globalConst->GetHandledUndefined();
75     JSHandle<JSObject> undefinedIteratorResult = JSIterator::CreateIterResultObject(thread, undefinedHandle, true);
76     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
77     env->SetUndefinedIteratorResult(thread, undefinedIteratorResult);
78 
79     JSTaggedValue res = JSTaggedValue::Undefined();
80     switch (tag) {
81         case ContainerTag::ArrayList: {
82             res = InitializeContainer(thread, thisValue, InitializeArrayList, "ArrayListConstructor");
83             break;
84         }
85         case ContainerTag::Deque: {
86             res = InitializeContainer(thread, thisValue, InitializeDeque, "DequeConstructor");
87             break;
88         }
89         case ContainerTag::LightWeightMap: {
90             res = InitializeContainer(thread, thisValue, InitializeLightWeightMap, "LightWeightMapConstructor");
91             break;
92         }
93         case ContainerTag::LightWeightSet: {
94             res = InitializeContainer(thread, thisValue, InitializeLightWeightSet, "LightWeightSetConstructor");
95             break;
96         }
97         case ContainerTag::PlainArray: {
98             res = InitializeContainer(thread, thisValue, InitializePlainArray, "PlainArrayConstructor");
99             break;
100         }
101         case ContainerTag::Queue: {
102             res = InitializeContainer(thread, thisValue, InitializeQueue, "QueueConstructor");
103             break;
104         }
105         case ContainerTag::Stack: {
106             res = InitializeContainer(thread, thisValue, InitializeStack, "StackConstructor");
107             break;
108         }
109         case ContainerTag::TreeMap: {
110             res = InitializeContainer(thread, thisValue, InitializeTreeMap, "TreeMapConstructor");
111             break;
112         }
113         case ContainerTag::TreeSet: {
114             res = InitializeContainer(thread, thisValue, InitializeTreeSet, "TreeSetConstructor");
115             break;
116         }
117         case ContainerTag::Vector: {
118             res = InitializeContainer(thread, thisValue, InitializeVector, "VectorConstructor");
119             break;
120         }
121         case ContainerTag::BitVector: {
122             res = InitializeContainer(thread, thisValue, InitializeBitVector, "BitVectorConstructor");
123             break;
124         }
125         case ContainerTag::List: {
126             res = InitializeContainer(thread, thisValue, InitializeList, "ListConstructor");
127             break;
128         }
129         case ContainerTag::LinkedList: {
130             res = InitializeContainer(thread, thisValue, InitializeLinkedList, "LinkedListConstructor");
131             break;
132         }
133         case ContainerTag::HashMap: {
134             res = InitializeContainer(thread, thisValue, InitializeHashMap, "HashMapConstructor");
135             break;
136         }
137         case ContainerTag::HashSet: {
138             res = InitializeContainer(thread, thisValue, InitializeHashSet, "HashSetConstructor");
139             break;
140         }
141         case ContainerTag::FastBuffer: {
142             res = InitializeContainer(thread, thisValue, InitializeBuffer, "BufferConstructor");
143             break;
144         }
145         case ContainerTag::END:
146             break;
147         default:
148             LOG_ECMA(FATAL) << "this branch is unreachable";
149             UNREACHABLE();
150     }
151 
152     return res;
153 }
154 
InitializeContainer(JSThread * thread,const JSHandle<JSObject> & obj,InitializeFunction func,const char * name)155 JSTaggedValue ContainersPrivate::InitializeContainer(JSThread *thread, const JSHandle<JSObject> &obj,
156                                                      InitializeFunction func, const char *name)
157 {
158     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
159     JSHandle<JSTaggedValue> key(factory->NewFromASCII(name));
160     JSTaggedValue value = ObjectFastOperator::GetPropertyByName<ObjectFastOperator::Status::UseOwn>
161         (thread, obj.GetTaggedValue(), key.GetTaggedValue());
162     if (!value.IsUndefined()) {
163         return value;
164     }
165     JSHandle<JSTaggedValue> map = func(thread);
166     SetFrozenConstructor(thread, obj, name, map);
167     return map.GetTaggedValue();
168 }
169 
NewContainerConstructor(JSThread * thread,const JSHandle<JSObject> & prototype,EcmaEntrypoint ctorFunc,const char * name,int length)170 JSHandle<JSFunction> ContainersPrivate::NewContainerConstructor(JSThread *thread, const JSHandle<JSObject> &prototype,
171                                                                 EcmaEntrypoint ctorFunc, const char *name, int length)
172 {
173     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
174     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
175     JSHandle<JSFunction> ctor =
176         factory->NewJSBuiltinFunction(env, reinterpret_cast<void *>(ctorFunc), FunctionKind::BUILTIN_CONSTRUCTOR);
177 
178     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
179     JSFunction::SetFunctionLength(thread, ctor, JSTaggedValue(length));
180     JSHandle<JSTaggedValue> nameString(factory->NewFromASCII(name));
181     JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(ctor), nameString,
182                                 globalConst->GetHandledUndefined());
183     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
184     PropertyDescriptor descriptor1(thread, JSHandle<JSTaggedValue>::Cast(ctor), true, false, true);
185     JSObject::DefineOwnProperty(thread, prototype, constructorKey, descriptor1);
186 
187     /* set "prototype" in constructor */
188     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread, ctor, prototype.GetTaggedValue());
189 
190     return ctor;
191 }
192 
SetFrozenFunction(JSThread * thread,const JSHandle<JSObject> & obj,const char * key,EcmaEntrypoint func,int length,kungfu::BuiltinsStubCSigns::ID builtinId)193 void ContainersPrivate::SetFrozenFunction(JSThread *thread, const JSHandle<JSObject> &obj, const char *key,
194                                           EcmaEntrypoint func, int length, kungfu::BuiltinsStubCSigns::ID builtinId)
195 {
196     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
197     JSHandle<JSTaggedValue> keyString(factory->NewFromASCII(key));
198     JSHandle<JSFunction> function = NewFunction(thread, keyString, func, length, builtinId);
199     PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>(function), false, false, false);
200     JSObject::DefineOwnProperty(thread, obj, keyString, descriptor);
201 }
202 
SetFrozenConstructor(JSThread * thread,const JSHandle<JSObject> & obj,const char * keyChar,JSHandle<JSTaggedValue> & value)203 void ContainersPrivate::SetFrozenConstructor(JSThread *thread, const JSHandle<JSObject> &obj, const char *keyChar,
204                                              JSHandle<JSTaggedValue> &value)
205 {
206     if (value->IsECMAObject()) {
207         JSObject::PreventExtensions(thread, JSHandle<JSObject>::Cast(value));
208     }
209     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
210     JSHandle<JSTaggedValue> key(factory->NewFromASCII(keyChar));
211     PropertyDescriptor descriptor(thread, value, false, false, false);
212     JSObject::DefineOwnProperty(thread, obj, key, descriptor);
213 }
214 
NewFunction(JSThread * thread,const JSHandle<JSTaggedValue> & key,EcmaEntrypoint func,int length,kungfu::BuiltinsStubCSigns::ID builtinId)215 JSHandle<JSFunction> ContainersPrivate::NewFunction(JSThread *thread, const JSHandle<JSTaggedValue> &key,
216                                                     EcmaEntrypoint func, int length,
217                                                     kungfu::BuiltinsStubCSigns::ID builtinId)
218 {
219     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
220     JSHandle<JSFunction> function =
221         factory->NewJSBuiltinFunction(thread->GetEcmaVM()->GetGlobalEnv(), reinterpret_cast<void *>(func),
222                                       FunctionKind::NORMAL_FUNCTION, builtinId);
223     JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
224     JSHandle<JSFunctionBase> baseFunction(function);
225     JSFunction::SetFunctionName(thread, baseFunction, key, thread->GlobalConstants()->GetHandledUndefined());
226     return function;
227 }
228 
CreateGetter(JSThread * thread,EcmaEntrypoint func,const char * name,int length)229 JSHandle<JSTaggedValue> ContainersPrivate::CreateGetter(JSThread *thread, EcmaEntrypoint func, const char *name,
230                                                         int length)
231 {
232     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
233     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
234     JSHandle<JSFunction> function = factory->NewJSBuiltinFunction(env, reinterpret_cast<void *>(func));
235     JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
236     JSHandle<JSTaggedValue> funcName(factory->NewFromASCII(name));
237     JSHandle<JSTaggedValue> prefix = thread->GlobalConstants()->GetHandledGetString();
238     JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(function), funcName, prefix);
239     return JSHandle<JSTaggedValue>(function);
240 }
241 
SetGetter(JSThread * thread,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & getter)242 void ContainersPrivate::SetGetter(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key,
243                                   const JSHandle<JSTaggedValue> &getter)
244 {
245     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
246     JSHandle<AccessorData> accessor = factory->NewAccessorData();
247     accessor->SetGetter(thread, getter);
248     PropertyAttributes attr = PropertyAttributes::DefaultAccessor(false, false, false);
249     JSObject::AddAccessor(thread, JSHandle<JSTaggedValue>::Cast(obj), key, accessor, attr);
250 }
251 
SetFunctionAtSymbol(JSThread * thread,const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & symbol,const char * name,EcmaEntrypoint func,int length)252 void ContainersPrivate::SetFunctionAtSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
253                                             const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &symbol,
254                                             const char *name, EcmaEntrypoint func, int length)
255 {
256     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
257     JSHandle<JSFunction> function = factory->NewJSBuiltinFunction(env, reinterpret_cast<void *>(func));
258     JSFunction::SetFunctionLength(thread, function, JSTaggedValue(length));
259     JSHandle<JSTaggedValue> nameString(factory->NewFromASCII(name));
260     JSHandle<JSFunctionBase> baseFunction(function);
261     JSFunction::SetFunctionName(thread, baseFunction, nameString, thread->GlobalConstants()->GetHandledUndefined());
262     PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(function), false, false, false);
263     JSObject::DefineOwnProperty(thread, obj, symbol, descriptor);
264 }
265 
SetStringTagSymbol(JSThread * thread,const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & obj,const char * key)266 void ContainersPrivate::SetStringTagSymbol(JSThread *thread, const JSHandle<GlobalEnv> &env,
267                                            const JSHandle<JSObject> &obj, const char *key)
268 {
269     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
270     JSHandle<JSTaggedValue> tag(factory->NewFromASCII(key));
271     JSHandle<JSTaggedValue> symbol = env->GetToStringTagSymbol();
272     PropertyDescriptor desc(thread, tag, false, false, false);
273     JSObject::DefineOwnProperty(thread, obj, symbol, desc);
274 }
275 
InitializeArrayList(JSThread * thread)276 JSHandle<JSTaggedValue> ContainersPrivate::InitializeArrayList(JSThread *thread)
277 {
278     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
279     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
280     // ArrayList.prototype
281     JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
282     JSHandle<JSTaggedValue> arrayListFuncPrototypeValue(prototype);
283     // ArrayList.prototype_or_hclass
284     JSHandle<JSHClass> arrayListInstanceClass =
285         factory->NewEcmaHClass(JSAPIArrayList::SIZE, JSType::JS_API_ARRAY_LIST, arrayListFuncPrototypeValue);
286     // ArrayList() = new Function()
287     JSHandle<JSTaggedValue> arrayListFunction(NewContainerConstructor(
288         thread, prototype, ContainersArrayList::ArrayListConstructor, "ArrayList", FuncLength::ZERO));
289     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
290         JSHandle<JSFunction>::Cast(arrayListFunction), arrayListInstanceClass.GetTaggedValue());
291 
292     // "constructor" property on the prototype
293     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
294     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, arrayListFunction);
295     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
296 
297     // ArrayList.prototype methods (excluding constructor and '@@' internal properties)
298     for (const base::BuiltinFunctionEntry &entry: ContainersArrayList::GetArrayListPrototypeFunctions()) {
299         SetFrozenFunction(thread, prototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
300                           entry.GetBuiltinStubId());
301     }
302 
303     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
304     SetStringTagSymbol(thread, env, prototype, "ArrayList");
305 
306     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersArrayList::GetSize, "length",
307                                                         FuncLength::ZERO);
308     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
309     SetGetter(thread, prototype, lengthKey, lengthGetter);
310 
311     SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
312                         ContainersArrayList::GetIteratorObj, FuncLength::ONE);
313     ContainersPrivate::InitializeArrayListIterator(thread, env);
314     env->SetArrayListFunction(thread, arrayListFunction);
315     return arrayListFunction;
316 }
317 
InitializeArrayListIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)318 void ContainersPrivate::InitializeArrayListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
319 {
320     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
321     // Iterator.hclass
322     JSHandle<JSHClass> iteratorFuncHClass =
323         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
324     // ArrayListIterator.prototype
325     JSHandle<JSObject> arrayListIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
326     // Iterator.prototype.next()
327     SetFrozenFunction(thread, arrayListIteratorPrototype, "next", JSAPIArrayListIterator::Next, FuncLength::ONE);
328     SetStringTagSymbol(thread, env, arrayListIteratorPrototype, "ArrayList Iterator");
329     env->SetArrayListIteratorPrototype(thread, arrayListIteratorPrototype);
330 }
331 
InitializeLightWeightMap(JSThread * thread)332 JSHandle<JSTaggedValue> ContainersPrivate::InitializeLightWeightMap(JSThread *thread)
333 {
334     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
335     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
336     JSHandle<JSObject> funcPrototype = factory->NewEmptyJSObject();
337     JSHandle<JSTaggedValue> mapFuncPrototypeValue(funcPrototype);
338     JSHandle<JSHClass> lightWeightMapInstanceClass =
339         factory->NewEcmaHClass(JSAPILightWeightMap::SIZE, JSType::JS_API_LIGHT_WEIGHT_MAP, mapFuncPrototypeValue);
340     JSHandle<JSTaggedValue> lightWeightMapFunction(NewContainerConstructor(
341         thread, funcPrototype, ContainersLightWeightMap::LightWeightMapConstructor, "LightWeightMap",
342         FuncLength::ZERO));
343     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
344         JSHandle<JSFunction>::Cast(lightWeightMapFunction), lightWeightMapInstanceClass.GetTaggedValue());
345 
346     // "constructor" property on the prototype
347     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
348     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(funcPrototype), constructorKey, lightWeightMapFunction);
349     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
350 
351     // LightWeightMap.prototype methods (excluding constructor and '@@' internal properties)
352     for (const base::BuiltinFunctionEntry &entry: ContainersLightWeightMap::GetLightWeightMapPrototypeFunctions()) {
353         SetFrozenFunction(thread, funcPrototype, entry.GetName().data(), entry.GetEntrypoint(),
354                           entry.GetLength(), entry.GetBuiltinStubId());
355     }
356 
357     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLightWeightMap::Length, "length",
358                                                         FuncLength::ZERO);
359     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
360     SetGetter(thread, funcPrototype, lengthKey, lengthGetter);
361 
362     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
363     SetFunctionAtSymbol(thread, env, funcPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
364                         ContainersLightWeightMap::Entries, FuncLength::ONE);
365 
366     ContainersPrivate::InitializeLightWeightMapIterator(thread);
367     return lightWeightMapFunction;
368 }
369 
InitializeLightWeightMapIterator(JSThread * thread)370 void ContainersPrivate::InitializeLightWeightMapIterator(JSThread *thread)
371 {
372     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
373     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
374     JSHandle<JSHClass> iteratorClass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR,
375                                                               env->GetIteratorPrototype());
376     JSHandle<JSObject> lightWeightMapIteratorPrototype(factory->NewJSObject(iteratorClass));
377     SetFrozenFunction(thread, lightWeightMapIteratorPrototype, "next", JSAPILightWeightMapIterator::Next,
378                       FuncLength::ONE);
379     SetStringTagSymbol(thread, env, lightWeightMapIteratorPrototype, "LightWeightMap Iterator");
380     env->SetLightWeightMapIteratorPrototype(thread, lightWeightMapIteratorPrototype);
381 }
382 
InitializeLightWeightSet(JSThread * thread)383 JSHandle<JSTaggedValue> ContainersPrivate::InitializeLightWeightSet(JSThread *thread)
384 {
385     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
386     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
387     // LightWeightSet.prototype
388     JSHandle<JSObject> funcPrototype = factory->NewEmptyJSObject();
389     JSHandle<JSTaggedValue> funcPrototypeValue(funcPrototype);
390     // LightWeightSet.prototype_or_hclass
391     JSHandle<JSHClass> lightweightSetInstanceClass =
392         factory->NewEcmaHClass(JSAPILightWeightSet::SIZE, JSType::JS_API_LIGHT_WEIGHT_SET, funcPrototypeValue);
393     JSHandle<JSTaggedValue> lightweightSetFunction(
394         NewContainerConstructor(thread, funcPrototype, ContainersLightWeightSet::LightWeightSetConstructor,
395                                 "LightWeightSet", FuncLength::ZERO));
396     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
397         JSHandle<JSFunction>::Cast(lightweightSetFunction), lightweightSetInstanceClass.GetTaggedValue());
398     // "constructor" property on the prototype
399     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
400     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(funcPrototype), constructorKey, lightweightSetFunction);
401     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
402 
403     // LightWeightSet.prototype methods (excluding constructor and '@@' internal properties)
404     for (const base::BuiltinFunctionEntry &entry: ContainersLightWeightSet::GetLightWeightSetPrototypeFunctions()) {
405         SetFrozenFunction(thread, funcPrototype, entry.GetName().data(), entry.GetEntrypoint(),
406                           entry.GetLength(), entry.GetBuiltinStubId());
407     }
408 
409     JSHandle<JSTaggedValue> lengthGetter =
410         CreateGetter(thread, ContainersLightWeightSet::GetSize, "length", FuncLength::ZERO);
411 
412     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
413     SetGetter(thread, funcPrototype, lengthKey, lengthGetter);
414     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
415     SetFunctionAtSymbol(thread, env, funcPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
416                         ContainersLightWeightSet::GetIteratorObj, FuncLength::ONE);
417 
418     InitializeLightWeightSetIterator(thread);
419     return lightweightSetFunction;
420 }
421 
InitializeLightWeightSetIterator(JSThread * thread)422 void ContainersPrivate::InitializeLightWeightSetIterator(JSThread *thread)
423 {
424     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
425     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
426 
427     JSHandle<JSHClass> iteratorClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
428     JSHandle<JSObject> lightWeightSetIteratorPrototype(factory->NewJSObject(iteratorClass));
429     SetFrozenFunction(
430         thread, lightWeightSetIteratorPrototype, "next", JSAPILightWeightSetIterator::Next, FuncLength::ONE);
431     SetStringTagSymbol(thread, env, lightWeightSetIteratorPrototype, "LightWeightSet Iterator");
432     env->SetLightWeightSetIteratorPrototype(thread, lightWeightSetIteratorPrototype);
433 }
434 
InitializeTreeMap(JSThread * thread)435 JSHandle<JSTaggedValue> ContainersPrivate::InitializeTreeMap(JSThread *thread)
436 {
437     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
438     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
439     // TreeMap.prototype
440     JSHandle<JSObject> mapFuncPrototype = factory->NewEmptyJSObject();
441     JSHandle<JSTaggedValue> mapFuncPrototypeValue(mapFuncPrototype);
442     // TreeMap.prototype_or_hclass
443     JSHandle<JSHClass> mapInstanceClass =
444         factory->NewEcmaHClass(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, mapFuncPrototypeValue);
445     // TreeMap() = new Function()
446     JSHandle<JSTaggedValue> mapFunction(NewContainerConstructor(
447         thread, mapFuncPrototype, ContainersTreeMap::TreeMapConstructor, "TreeMap", FuncLength::ZERO));
448     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
449         JSHandle<JSFunction>::Cast(mapFunction), mapInstanceClass.GetTaggedValue());
450 
451     // "constructor" property on the prototype
452     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
453     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(mapFuncPrototype), constructorKey, mapFunction);
454     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
455 
456     // TreeMap.prototype methods (excluding constructor and '@@' internal properties)
457     for (const base::BuiltinFunctionEntry &entry: ContainersTreeMap::GetTreeMapPrototypeFunctions()) {
458         SetFrozenFunction(thread, mapFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
459                           entry.GetLength(), entry.GetBuiltinStubId());
460     }
461 
462     // @@ToStringTag
463     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
464     SetStringTagSymbol(thread, env, mapFuncPrototype, "TreeMap");
465     // %TreeMapPrototype% [ @@iterator ]
466     JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
467     JSHandle<JSTaggedValue> entries = globalConst->GetHandledEntriesString();
468     JSHandle<JSTaggedValue> entriesFunc =
469         JSObject::GetMethod(thread, JSHandle<JSTaggedValue>::Cast(mapFuncPrototype), entries);
470     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
471     PropertyDescriptor descriptor(thread, entriesFunc, false, false, false);
472     JSObject::DefineOwnProperty(thread, mapFuncPrototype, iteratorSymbol, descriptor);
473     // length
474     JSHandle<JSTaggedValue> lengthGetter =
475         CreateGetter(thread, ContainersTreeMap::GetLength, "length", FuncLength::ZERO);
476     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
477     SetGetter(thread, mapFuncPrototype, lengthKey, lengthGetter);
478 
479     InitializeTreeMapIterator(thread);
480     return mapFunction;
481 }
482 
InitializeTreeMapIterator(JSThread * thread)483 void ContainersPrivate::InitializeTreeMapIterator(JSThread *thread)
484 {
485     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
486     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
487     // Iterator.hclass
488     JSHandle<JSHClass> iteratorClass =
489         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
490 
491     // TreeMapIterator.prototype
492     JSHandle<JSObject> mapIteratorPrototype(factory->NewJSObject(iteratorClass));
493     // TreeIterator.prototype.next()
494     SetFrozenFunction(thread, mapIteratorPrototype, "next", JSAPITreeMapIterator::Next, FuncLength::ZERO);
495     SetStringTagSymbol(thread, env, mapIteratorPrototype, "TreeMap Iterator");
496     env->SetTreeMapIteratorPrototype(thread, mapIteratorPrototype);
497 }
498 
InitializeTreeSet(JSThread * thread)499 JSHandle<JSTaggedValue> ContainersPrivate::InitializeTreeSet(JSThread *thread)
500 {
501     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
502     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
503     // TreeSet.prototype
504     JSHandle<JSObject> setFuncPrototype = factory->NewEmptyJSObject();
505     JSHandle<JSTaggedValue> setFuncPrototypeValue(setFuncPrototype);
506     // TreeSet.prototype_or_hclass
507     JSHandle<JSHClass> setInstanceClass =
508         factory->NewEcmaHClass(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, setFuncPrototypeValue);
509     // TreeSet() = new Function()
510     JSHandle<JSTaggedValue> setFunction(NewContainerConstructor(
511         thread, setFuncPrototype, ContainersTreeSet::TreeSetConstructor, "TreeSet", FuncLength::ZERO));
512     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
513         JSHandle<JSFunction>::Cast(setFunction), setInstanceClass.GetTaggedValue());
514 
515     // "constructor" property on the prototype
516     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
517     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(setFuncPrototype), constructorKey, setFunction);
518     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
519 
520     // TreeSet.prototype methods (excluding constructor and '@@' internal properties)
521     for (const base::BuiltinFunctionEntry &entry: ContainersTreeSet::GetTreeSetPrototypeFunctions()) {
522         SetFrozenFunction(thread, setFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
523                           entry.GetLength(), entry.GetBuiltinStubId());
524     }
525 
526     // @@ToStringTag
527     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
528     SetStringTagSymbol(thread, env, setFuncPrototype, "TreeSet");
529     // %TreeSetPrototype% [ @@iterator ]
530     JSHandle<JSTaggedValue> iteratorSymbol = env->GetIteratorSymbol();
531     JSHandle<JSTaggedValue> values(thread, globalConst->GetValuesString());
532     JSHandle<JSTaggedValue> valuesFunc =
533         JSObject::GetMethod(thread, JSHandle<JSTaggedValue>::Cast(setFuncPrototype), values);
534     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
535     PropertyDescriptor descriptor(thread, valuesFunc, false, false, false);
536     JSObject::DefineOwnProperty(thread, setFuncPrototype, iteratorSymbol, descriptor);
537     // length
538     JSHandle<JSTaggedValue> lengthGetter =
539         CreateGetter(thread, ContainersTreeSet::GetLength, "length", FuncLength::ZERO);
540     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
541     SetGetter(thread, setFuncPrototype, lengthKey, lengthGetter);
542 
543     InitializeTreeSetIterator(thread);
544     return setFunction;
545 }
546 
InitializeTreeSetIterator(JSThread * thread)547 void ContainersPrivate::InitializeTreeSetIterator(JSThread *thread)
548 {
549     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
550     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
551     // Iterator.hclass
552     JSHandle<JSHClass> iteratorClass =
553         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
554 
555     // TreeSetIterator.prototype
556     JSHandle<JSObject> setIteratorPrototype(factory->NewJSObject(iteratorClass));
557     // TreeSetIterator.prototype.next()
558     SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPITreeSetIterator::Next, FuncLength::ZERO);
559     SetStringTagSymbol(thread, env, setIteratorPrototype, "TreeSet Iterator");
560     env->SetTreeSetIteratorPrototype(thread, setIteratorPrototype);
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     env->SetPlainArrayFunction(thread, plainArrayFunction);
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     JSHandle<JSHClass> iteratorClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
609     JSHandle<JSObject> plainarrayIteratorPrototype(factory->NewJSObject(iteratorClass));
610     SetFrozenFunction(thread, plainarrayIteratorPrototype, "next", JSAPIPlainArrayIterator::Next, FuncLength::ONE);
611     SetStringTagSymbol(thread, env, plainarrayIteratorPrototype, "PlainArray Iterator");
612     env->SetPlainArrayIteratorPrototype(thread, plainarrayIteratorPrototype);
613 }
614 
InitializeStack(JSThread * thread)615 JSHandle<JSTaggedValue> ContainersPrivate::InitializeStack(JSThread *thread)
616 {
617     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
618     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
619     // Stack.prototype
620     JSHandle<JSObject> stackFuncPrototype = factory->NewEmptyJSObject();
621     JSHandle<JSTaggedValue> stackFuncPrototypeValue(stackFuncPrototype);
622     // Stack.prototype_or_hclass
623     JSHandle<JSHClass> stackInstanceClass =
624         factory->NewEcmaHClass(JSAPIStack::SIZE, JSType::JS_API_STACK, stackFuncPrototypeValue);
625     // Stack() = new Function()
626     JSHandle<JSTaggedValue> stackFunction(NewContainerConstructor(
627         thread, stackFuncPrototype, ContainersStack::StackConstructor, "Stack", FuncLength::ZERO));
628     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
629         JSHandle<JSFunction>::Cast(stackFunction), stackInstanceClass.GetTaggedValue());
630 
631     // "constructor" property on the prototype
632     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
633     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(stackFuncPrototype), constructorKey, stackFunction);
634     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
635 
636     // Stack.prototype methods (excluding constructor and '@@' internal properties)
637     for (const base::BuiltinFunctionEntry &entry: ContainersStack::GetStackPrototypeFunctions()) {
638         SetFrozenFunction(thread, stackFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
639                           entry.GetLength(), entry.GetBuiltinStubId());
640     }
641 
642     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
643     SetStringTagSymbol(thread, env, stackFuncPrototype, "Stack");
644 
645     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersStack::GetLength, "length", FuncLength::ZERO);
646     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
647     SetGetter(thread, stackFuncPrototype, lengthKey, lengthGetter);
648 
649     SetFunctionAtSymbol(thread, env, stackFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
650                         ContainersStack::Iterator, FuncLength::ONE);
651 
652     ContainersPrivate::InitializeStackIterator(thread);
653     return stackFunction;
654 }
655 
InitializeStackIterator(JSThread * thread)656 void ContainersPrivate::InitializeStackIterator(JSThread *thread)
657 {
658     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
659     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
660     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
661     // StackIterator.prototype
662     JSHandle<JSObject> stackIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
663     // Iterator.prototype.next()
664     SetFrozenFunction(thread, stackIteratorPrototype, "next", JSAPIStackIterator::Next, FuncLength::ONE);
665     env->SetStackIteratorPrototype(thread, stackIteratorPrototype);
666 }
667 
InitializeVector(JSThread * thread)668 JSHandle<JSTaggedValue> ContainersPrivate::InitializeVector(JSThread *thread)
669 {
670     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
671     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
672     // Vector.prototype
673     JSHandle<JSObject> prototype = factory->NewEmptyJSObject();
674     JSHandle<JSTaggedValue> vectorFuncPrototypeValue(prototype);
675     // Vector.prototype_or_hclass
676     JSHandle<JSHClass> vectorInstanceClass =
677         factory->NewEcmaHClass(JSAPIVector::SIZE, JSType::JS_API_VECTOR, vectorFuncPrototypeValue);
678     // Vector() = new Function()
679     JSHandle<JSTaggedValue> vectorFunction(NewContainerConstructor(
680         thread, prototype, ContainersVector::VectorConstructor, "Vector", FuncLength::ZERO));
681     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
682         JSHandle<JSFunction>::Cast(vectorFunction), vectorInstanceClass.GetTaggedValue());
683 
684     // "constructor" property on the prototype
685     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
686     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(prototype), constructorKey, vectorFunction);
687     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
688     // Vector.prototype
689     SetFrozenFunction(thread, prototype, "add", ContainersVector::Add, FuncLength::ONE);
690     SetFrozenFunction(thread, prototype, "insert", ContainersVector::Insert, FuncLength::TWO);
691     SetFrozenFunction(thread, prototype, "setLength", ContainersVector::SetLength, FuncLength::ONE);
692     SetFrozenFunction(thread, prototype, "getCapacity", ContainersVector::GetCapacity, FuncLength::ZERO);
693     SetFrozenFunction(thread, prototype, "increaseCapacityTo", ContainersVector::IncreaseCapacityTo, FuncLength::ONE);
694     SetFrozenFunction(thread, prototype, "get", ContainersVector::Get, FuncLength::ONE);
695     SetFrozenFunction(thread, prototype, "getIndexOf", ContainersVector::GetIndexOf, FuncLength::ONE);
696     SetFrozenFunction(thread, prototype, "getIndexFrom", ContainersVector::GetIndexFrom, FuncLength::TWO);
697     SetFrozenFunction(thread, prototype, "isEmpty", ContainersVector::IsEmpty, FuncLength::ZERO);
698     SetFrozenFunction(thread, prototype, "getLastElement", ContainersVector::GetLastElement, FuncLength::ZERO);
699     SetFrozenFunction(thread, prototype, "getLastIndexOf", ContainersVector::GetLastIndexOf, FuncLength::ONE);
700     SetFrozenFunction(thread, prototype, "getLastIndexFrom", ContainersVector::GetLastIndexFrom, FuncLength::TWO);
701     SetFrozenFunction(thread, prototype, "remove", ContainersVector::Remove, FuncLength::ONE);
702     SetFrozenFunction(thread, prototype, "removeByIndex", ContainersVector::RemoveByIndex, FuncLength::ONE);
703     SetFrozenFunction(thread, prototype, "removeByRange", ContainersVector::RemoveByRange, FuncLength::TWO);
704     SetFrozenFunction(thread, prototype, "set", ContainersVector::Set, FuncLength::TWO);
705     SetFrozenFunction(thread, prototype, "subVector", ContainersVector::SubVector, FuncLength::TWO);
706     SetFrozenFunction(thread, prototype, "toString", ContainersVector::ToString, FuncLength::ZERO);
707     SetFrozenFunction(thread, prototype, "forEach", ContainersVector::ForEach, FuncLength::TWO,
708                       BUILTINS_STUB_ID(VectorForEach));
709     SetFrozenFunction(thread, prototype, "replaceAllElements", ContainersVector::ReplaceAllElements, FuncLength::TWO,
710                       BUILTINS_STUB_ID(VectorReplaceAllElements));
711     SetFrozenFunction(thread, prototype, "has", ContainersVector::Has, FuncLength::ONE);
712     SetFrozenFunction(thread, prototype, "sort", ContainersVector::Sort, FuncLength::ZERO);
713     SetFrozenFunction(thread, prototype, "clear", ContainersVector::Clear, FuncLength::ZERO);
714     SetFrozenFunction(thread, prototype, "clone", ContainersVector::Clone, FuncLength::ZERO);
715     SetFrozenFunction(thread, prototype, "copyToArray", ContainersVector::CopyToArray, FuncLength::ONE);
716     SetFrozenFunction(thread, prototype, "convertToArray", ContainersVector::ConvertToArray, FuncLength::ZERO);
717     SetFrozenFunction(thread, prototype, "getFirstElement", ContainersVector::GetFirstElement, FuncLength::ZERO);
718     SetFrozenFunction(thread, prototype, "trimToCurrentLength",
719                       ContainersVector::TrimToCurrentLength, FuncLength::ZERO);
720 
721     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
722     SetStringTagSymbol(thread, env, prototype, "Vector");
723 
724     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersVector::GetSize, "length", FuncLength::ZERO);
725     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
726     SetGetter(thread, prototype, lengthKey, lengthGetter);
727 
728     SetFunctionAtSymbol(thread, env, prototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
729                         ContainersVector::GetIteratorObj, FuncLength::ONE);
730 
731     ContainersPrivate::InitializeVectorIterator(thread, env);
732     env->SetVectorFunction(thread, vectorFunction);
733     return vectorFunction;
734 }
735 
InitializeVectorIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)736 void ContainersPrivate::InitializeVectorIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
737 {
738     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
739     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
740     // VectorIterator.prototype
741     JSHandle<JSObject> vectorIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
742     // Iterator.prototype.next()
743     SetFrozenFunction(thread, vectorIteratorPrototype, "next", JSAPIVectorIterator::Next, FuncLength::ONE);
744     SetStringTagSymbol(thread, env, vectorIteratorPrototype, "Vector Iterator");
745     env->SetVectorIteratorPrototype(thread, vectorIteratorPrototype);
746 }
747 
InitializeBitVector(JSThread * thread)748 JSHandle<JSTaggedValue> ContainersPrivate::InitializeBitVector(JSThread* thread)
749 {
750     auto vm = thread->GetEcmaVM();
751     ObjectFactory* factory = vm->GetFactory();
752     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
753     Builtins builtin(thread, factory, vm);
754     JSHandle<JSObject> sObjPrototype = JSHandle<JSObject>::Cast(env->GetSObjectFunctionPrototype());
755     JSHandle<JSFunction> sFuncPrototype = JSHandle<JSFunction>::Cast(env->GetSFunctionPrototype());
756     builtin.InitializeSharedBitVector(env, sObjPrototype, sFuncPrototype);
757     InitializeBitVectorIterator(thread, env);
758     JSHandle<JSTaggedValue> bitVectorFunction = env->GetBitVectorFunction();
759     return bitVectorFunction;
760 }
761 
InitializeBitVectorIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)762 void ContainersPrivate::InitializeBitVectorIterator(JSThread* thread, const JSHandle<GlobalEnv>& env)
763 {
764     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
765     JSHandle<JSHClass> iteratorFuncClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
766     JSHandle<JSObject> bitVectorIteratorPrototype(factory->NewJSObjectWithInit(iteratorFuncClass));
767     // Iterator.prototype.next()
768     SetFrozenFunction(thread, bitVectorIteratorPrototype, "next", JSAPIBitVectorIterator::Next, FuncLength::ONE);
769     SetStringTagSymbol(thread, env, bitVectorIteratorPrototype, "BitVector Iterator");
770     env->SetBitVectorIteratorPrototype(thread, bitVectorIteratorPrototype);
771 }
772 
InitializeQueue(JSThread * thread)773 JSHandle<JSTaggedValue> ContainersPrivate::InitializeQueue(JSThread *thread)
774 {
775     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
776     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
777     // Queue.prototype
778     JSHandle<JSObject> queueFuncPrototype = factory->NewEmptyJSObject();
779     JSHandle<JSTaggedValue> queueFuncPrototypeValue(queueFuncPrototype);
780     // Queue.prototype_or_hclass
781     JSHandle<JSHClass> queueInstanceClass =
782         factory->NewEcmaHClass(JSAPIQueue::SIZE, JSType::JS_API_QUEUE, queueFuncPrototypeValue);
783     // Queue() = new Function()
784     JSHandle<JSTaggedValue> queueFunction(NewContainerConstructor(
785         thread, queueFuncPrototype, ContainersQueue::QueueConstructor, "Queue", FuncLength::ZERO));
786     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
787         JSHandle<JSFunction>::Cast(queueFunction), queueInstanceClass.GetTaggedValue());
788 
789     // "constructor" property on the prototype
790     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
791     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(queueFuncPrototype), constructorKey, queueFunction);
792     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
793 
794     // Queue.prototype methods (excluding constructor and '@@' internal properties)
795     for (const base::BuiltinFunctionEntry &entry: ContainersQueue::GetQueuePrototypeFunctions()) {
796         SetFrozenFunction(thread, queueFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
797                           entry.GetLength(), entry.GetBuiltinStubId());
798     }
799 
800     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
801     SetStringTagSymbol(thread, env, queueFuncPrototype, "Queue");
802 
803     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersQueue::GetSize, "length", FuncLength::ZERO);
804     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
805     SetGetter(thread, queueFuncPrototype, lengthKey, lengthGetter);
806 
807     SetFunctionAtSymbol(thread, env, queueFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
808                         ContainersQueue::GetIteratorObj, FuncLength::ONE);
809 
810     ContainersPrivate::InitializeQueueIterator(thread, env);
811     return queueFunction;
812 }
813 
InitializeQueueIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)814 void ContainersPrivate::InitializeQueueIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
815 {
816     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
817     JSHandle<JSHClass> iteratorFuncHClass =
818         factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_ITERATOR, env->GetIteratorPrototype());
819     // QueueIterator.prototype
820     JSHandle<JSObject> queueIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
821     // Iterator.prototype.next()
822     SetFrozenFunction(thread, queueIteratorPrototype, "next", JSAPIQueueIterator::Next, FuncLength::ONE);
823     SetStringTagSymbol(thread, env, queueIteratorPrototype, "Queue Iterator");
824     env->SetQueueIteratorPrototype(thread, queueIteratorPrototype);
825 }
826 
InitializeDeque(JSThread * thread)827 JSHandle<JSTaggedValue> ContainersPrivate::InitializeDeque(JSThread *thread)
828 {
829     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
830     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
831     // Deque.prototype
832     JSHandle<JSObject> dequeFuncPrototype = factory->NewEmptyJSObject();
833     JSHandle<JSTaggedValue> dequeFuncPrototypeValue(dequeFuncPrototype);
834     // Deque.prototype_or_hclass
835     JSHandle<JSHClass> dequeInstanceClass =
836         factory->NewEcmaHClass(JSAPIDeque::SIZE, JSType::JS_API_DEQUE, dequeFuncPrototypeValue);
837     // Deque() = new Function()
838     JSHandle<JSTaggedValue> dequeFunction(NewContainerConstructor(
839         thread, dequeFuncPrototype, ContainersDeque::DequeConstructor, "Deque", FuncLength::ZERO));
840     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
841         JSHandle<JSFunction>::Cast(dequeFunction), dequeInstanceClass.GetTaggedValue());
842 
843     // "constructor" property on the prototype
844     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
845     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(dequeFuncPrototype), constructorKey, dequeFunction);
846     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
847 
848     // Deque.prototype methods (excluding constructor and '@@' internal properties)
849     for (const base::BuiltinFunctionEntry &entry: ContainersDeque::GetDequePrototypeFunctions()) {
850         SetFrozenFunction(thread, dequeFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
851                           entry.GetBuiltinStubId());
852     }
853 
854     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
855     SetStringTagSymbol(thread, env, dequeFuncPrototype, "Deque");
856 
857     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersDeque::GetSize, "length", FuncLength::ZERO);
858     JSHandle<JSTaggedValue> lengthKey = globalConst->GetHandledLengthString();
859     SetGetter(thread, dequeFuncPrototype, lengthKey, lengthGetter);
860 
861     SetFunctionAtSymbol(thread, env, dequeFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
862                         ContainersDeque::GetIteratorObj, FuncLength::ONE);
863 
864     ContainersPrivate::InitializeDequeIterator(thread, env);
865 
866     return dequeFunction;
867 }
868 
InitializeDequeIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)869 void ContainersPrivate::InitializeDequeIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
870 {
871     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
872     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
873     JSHandle<JSObject> dequeIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
874     SetFrozenFunction(thread, dequeIteratorPrototype, "next", JSAPIDequeIterator::Next, FuncLength::ONE);
875     SetStringTagSymbol(thread, env, dequeIteratorPrototype, "Deque Iterator");
876     env->SetDequeIteratorPrototype(thread, dequeIteratorPrototype);
877 }
878 
InitializeList(JSThread * thread)879 JSHandle<JSTaggedValue> ContainersPrivate::InitializeList(JSThread *thread)
880 {
881     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
882     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
883     JSHandle<JSObject> listFuncPrototype = factory->NewEmptyJSObject();
884     JSHandle<JSTaggedValue> listFuncPrototypeValue(listFuncPrototype);
885     JSHandle<JSHClass> listInstanceClass =
886         factory->NewEcmaHClass(JSAPIList::SIZE, JSType::JS_API_LIST, listFuncPrototypeValue);
887     JSHandle<JSTaggedValue> listFunction(NewContainerConstructor(
888         thread, listFuncPrototype, ContainersList::ListConstructor, "List", FuncLength::ZERO));
889     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
890         JSHandle<JSFunction>::Cast(listFunction), listInstanceClass.GetTaggedValue());
891 
892     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
893     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(listFuncPrototype), constructorKey, listFunction);
894     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
895 
896     // List.prototype methods (excluding constructor and '@@' internal properties)
897     for (const base::BuiltinFunctionEntry &entry: ContainersList::GetListPrototypeFunctions()) {
898         SetFrozenFunction(thread, listFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
899                           entry.GetBuiltinStubId());
900     }
901 
902     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersList::Length, "length", FuncLength::ZERO);
903     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
904     SetGetter(thread, listFuncPrototype, lengthKey, lengthGetter);
905 
906     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
907     SetFunctionAtSymbol(thread, env, listFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
908                         ContainersList::GetIteratorObj, FuncLength::ONE);
909 
910     InitializeListIterator(thread, env);
911     env->SetListFunction(thread, listFunction);
912     return listFunction;
913 }
914 
InitializeLinkedList(JSThread * thread)915 JSHandle<JSTaggedValue> ContainersPrivate::InitializeLinkedList(JSThread *thread)
916 {
917     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
918     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
919     JSHandle<JSObject> linkedListFuncPrototype = factory->NewEmptyJSObject();
920     JSHandle<JSTaggedValue> linkedListFuncPrototypeValue(linkedListFuncPrototype);
921     JSHandle<JSHClass> linkedListInstanceClass =
922         factory->NewEcmaHClass(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, linkedListFuncPrototypeValue);
923     JSHandle<JSTaggedValue> linkedListFunction(NewContainerConstructor(
924         thread, linkedListFuncPrototype, ContainersLinkedList::LinkedListConstructor, "LinkedList", FuncLength::ZERO));
925     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
926         JSHandle<JSFunction>::Cast(linkedListFunction), linkedListInstanceClass.GetTaggedValue());
927 
928     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
929     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(linkedListFuncPrototype), constructorKey, linkedListFunction);
930     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
931 
932     // LinkedList.prototype methods (excluding constructor and '@@' internal properties)
933     for (const base::BuiltinFunctionEntry &entry: ContainersLinkedList::GetLinkedListPrototypeFunctions()) {
934         SetFrozenFunction(thread, linkedListFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
935                           entry.GetBuiltinStubId());
936     }
937 
938     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersLinkedList::Length, "length",
939                                                         FuncLength::ZERO);
940     JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
941     SetGetter(thread, linkedListFuncPrototype, lengthKey, lengthGetter);
942 
943     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
944     SetFunctionAtSymbol(thread, env, linkedListFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
945                         ContainersLinkedList::GetIteratorObj, FuncLength::ONE);
946 
947     InitializeLinkedListIterator(thread, env);
948     env->SetLinkedListFunction(thread, linkedListFunction);
949     return linkedListFunction;
950 }
951 
InitializeLinkedListIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)952 void ContainersPrivate::InitializeLinkedListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
953 {
954     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
955     JSHandle<JSHClass> iteratorClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
956     JSHandle<JSObject> linkedListIteratorPrototype(factory->NewJSObject(iteratorClass));
957     SetFrozenFunction(thread, linkedListIteratorPrototype, "next", JSAPILinkedListIterator::Next, FuncLength::ONE);
958     SetStringTagSymbol(thread, env, linkedListIteratorPrototype, "linkedlist Iterator");
959     env->SetLinkedListIteratorPrototype(thread, linkedListIteratorPrototype);
960 }
961 
InitializeListIterator(JSThread * thread,const JSHandle<GlobalEnv> & env)962 void ContainersPrivate::InitializeListIterator(JSThread *thread, const JSHandle<GlobalEnv> &env)
963 {
964     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
965     JSHandle<JSHClass> iteratorClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
966     JSHandle<JSObject> listIteratorPrototype(factory->NewJSObject(iteratorClass));
967     SetFrozenFunction(thread, listIteratorPrototype, "next", JSAPIListIterator::Next, FuncLength::ONE);
968     SetStringTagSymbol(thread, env, listIteratorPrototype, "list Iterator");
969     env->SetListIteratorPrototype(thread, listIteratorPrototype);
970 }
971 
InitializeHashMap(JSThread * thread)972 JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashMap(JSThread *thread)
973 {
974     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
975     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
976     // HashMap.prototype
977     JSHandle<JSObject> hashMapFuncPrototype = factory->NewEmptyJSObject();
978     JSHandle<JSTaggedValue> hashMapFuncPrototypeValue(hashMapFuncPrototype);
979     // HashMap.prototype_or_hclass
980     JSHandle<JSHClass> hashMapInstanceClass =
981         factory->NewEcmaHClass(JSAPIHashMap::SIZE, JSType::JS_API_HASH_MAP, hashMapFuncPrototypeValue);
982 
983     JSHandle<JSTaggedValue> hashMapFunction(NewContainerConstructor(
984         thread, hashMapFuncPrototype, ContainersHashMap::HashMapConstructor, "HashMap", FuncLength::ZERO));
985     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
986         JSHandle<JSFunction>::Cast(hashMapFunction), hashMapInstanceClass.GetTaggedValue());
987 
988     // "constructor" property on the prototype
989     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
990     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(hashMapFuncPrototype), constructorKey, hashMapFunction);
991     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
992 
993     // HashMap.prototype methods (excluding constructor and '@@' internal properties)
994     for (const base::BuiltinFunctionEntry &entry: ContainersHashMap::GetHashMapPrototypeFunctions()) {
995         SetFrozenFunction(thread, hashMapFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
996                           entry.GetLength(), entry.GetBuiltinStubId());
997     }
998 
999     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1000     // @@ToStringTag
1001     SetStringTagSymbol(thread, env, hashMapFuncPrototype, "HashMap");
1002     // %HashMapPrototype% [ @@iterator ]
1003     SetFunctionAtSymbol(thread, env, hashMapFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1004                         ContainersHashMap::GetIteratorObj, FuncLength::ONE);
1005 
1006     JSHandle<JSTaggedValue> lengthGetter =
1007         CreateGetter(thread, ContainersHashMap::GetLength, "length", FuncLength::ZERO);
1008     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1009     SetGetter(thread, hashMapFuncPrototype, lengthKey, lengthGetter);
1010     InitializeHashMapIterator(thread);
1011     return hashMapFunction;
1012 }
1013 
InitializeHashMapIterator(JSThread * thread)1014 void ContainersPrivate::InitializeHashMapIterator(JSThread *thread)
1015 {
1016     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1017     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1018     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
1019     // HashMapIterator.prototype
1020     JSHandle<JSObject> hashMapIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1021     // HashMapIterator.prototype.next()
1022     SetFrozenFunction(thread, hashMapIteratorPrototype, "next", JSAPIHashMapIterator::Next, FuncLength::ZERO);
1023     SetStringTagSymbol(thread, env, hashMapIteratorPrototype, "HashMap Iterator");
1024     env->SetHashMapIteratorPrototype(thread, hashMapIteratorPrototype);
1025 }
1026 
InitializeHashSet(JSThread * thread)1027 JSHandle<JSTaggedValue> ContainersPrivate::InitializeHashSet(JSThread *thread)
1028 {
1029     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1030     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1031     // HashSet.prototype
1032     JSHandle<JSObject> hashSetFuncPrototype = factory->NewEmptyJSObject();
1033     JSHandle<JSTaggedValue> hashSetFuncPrototypeValue(hashSetFuncPrototype);
1034     // HashSet.prototype_or_hclass
1035     JSHandle<JSHClass> hashSetInstanceClass =
1036         factory->NewEcmaHClass(JSAPIHashSet::SIZE, JSType::JS_API_HASH_SET, hashSetFuncPrototypeValue);
1037 
1038     JSHandle<JSTaggedValue> hashSetFunction(NewContainerConstructor(
1039         thread, hashSetFuncPrototype, ContainersHashSet::HashSetConstructor, "HashSet", FuncLength::ZERO));
1040     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread,
1041         JSHandle<JSFunction>::Cast(hashSetFunction), hashSetInstanceClass.GetTaggedValue());
1042 
1043     // "constructor" property on the prototype
1044     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1045     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(hashSetFuncPrototype), constructorKey, hashSetFunction);
1046     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1047 
1048     // HashSet.prototype methods (excluding constructor and '@@' internal properties)
1049     for (const base::BuiltinFunctionEntry &entry: ContainersHashSet::GetHashSetPrototypeFunctions()) {
1050         SetFrozenFunction(thread, hashSetFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(),
1051                           entry.GetLength(), entry.GetBuiltinStubId());
1052     }
1053 
1054     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1055     // @@ToStringTag
1056     SetStringTagSymbol(thread, env, hashSetFuncPrototype, "HashSet");
1057     // %HashSetPrototype% [ @@iterator ]
1058     SetFunctionAtSymbol(thread, env, hashSetFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]",
1059                         ContainersHashSet::GetIteratorObj, FuncLength::ONE);
1060 
1061     JSHandle<JSTaggedValue> lengthGetter =
1062         CreateGetter(thread, ContainersHashSet::GetLength, "length", FuncLength::ZERO);
1063     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1064     SetGetter(thread, hashSetFuncPrototype, lengthKey, lengthGetter);
1065     InitializeHashSetIterator(thread);
1066     return hashSetFunction;
1067 }
1068 
InitializeHashSetIterator(JSThread * thread)1069 void ContainersPrivate::InitializeHashSetIterator(JSThread *thread)
1070 {
1071     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1072     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1073     JSHandle<JSHClass> iteratorFuncHClass = JSHandle<JSHClass>::Cast(env->GetIteratorFuncClass());
1074 
1075     // HashSetIterator.prototype
1076     JSHandle<JSObject> hashSetIteratorPrototype(factory->NewJSObject(iteratorFuncHClass));
1077     // HashSetIterator.prototype.next()
1078     SetFrozenFunction(thread, hashSetIteratorPrototype, "next", JSAPIHashSetIterator::Next, FuncLength::ZERO);
1079     SetStringTagSymbol(thread, env, hashSetIteratorPrototype, "HashSet Iterator");
1080     env->SetHashSetIteratorPrototype(thread, hashSetIteratorPrototype);
1081 }
1082 
InitializeBuffer(JSThread * thread)1083 JSHandle<JSTaggedValue> ContainersPrivate::InitializeBuffer(JSThread *thread)
1084 {
1085     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
1086     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1087     // Buffer.prototype
1088     JSHandle<JSObject> bufferFuncPrototype = factory->NewEmptyJSObject();
1089     JSHandle<JSTaggedValue> bufferFuncPrototypeValue(bufferFuncPrototype);
1090     // Buffer.prototype_or_hclass
1091     JSHandle<JSHClass> bufferInstanceClass =
1092         factory->NewEcmaHClass(JSAPIFastBuffer::SIZE, JSType::JS_API_FAST_BUFFER, bufferFuncPrototypeValue);
1093     // Buffer() = new Function()
1094     JSHandle<JSTaggedValue> bufferFunction(NewContainerConstructor(
1095         thread, bufferFuncPrototype, ContainersBuffer::BufferConstructor, "FastBuffer", FuncLength::ZERO));
1096     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread, JSHandle<JSFunction>::Cast(bufferFunction),
1097                                                      bufferInstanceClass.GetTaggedValue());
1098 
1099     // "constructor" property on the prototype
1100     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
1101     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(bufferFuncPrototype), constructorKey, bufferFunction);
1102     RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
1103 
1104     // FastBuffer.prototype methods (excluding constructor and '@@' internal properties)
1105     for (const base::BuiltinFunctionEntry &entry : ContainersBuffer::GetFastBufferPrototypeFunctions()) {
1106         SetFrozenFunction(thread, bufferFuncPrototype, entry.GetName().data(), entry.GetEntrypoint(), entry.GetLength(),
1107                           entry.GetBuiltinStubId());
1108     }
1109 
1110     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1111     SetStringTagSymbol(thread, env, bufferFuncPrototype, "FastBuffer");
1112 
1113     JSHandle<JSTaggedValue> lengthGetter = CreateGetter(thread, ContainersBuffer::GetSize, "length", FuncLength::ZERO);
1114     JSHandle<JSTaggedValue> lengthKey(thread, globalConst->GetLengthString());
1115     SetGetter(thread, bufferFuncPrototype, lengthKey, lengthGetter);
1116     JSHandle<JSTaggedValue> bufferGetter =
1117         CreateGetter(thread, ContainersBuffer::GetArrayBuffer, "buffer", FunctionLength::ZERO);
1118     JSHandle<JSTaggedValue> bufferKey(factory->NewFromASCII("buffer"));
1119     SetGetter(thread, bufferFuncPrototype, bufferKey, bufferGetter);
1120     JSHandle<JSTaggedValue> offsetGetter =
1121         CreateGetter(thread, ContainersBuffer::GetByteOffset, "byteOffset", FunctionLength::ZERO);
1122     JSHandle<JSTaggedValue> offsetKey(factory->NewFromASCII("byteOffset"));
1123     SetGetter(thread, bufferFuncPrototype, offsetKey, offsetGetter);
1124 
1125     env->SetBufferFunction(thread, bufferFunction);
1126     return bufferFunction;
1127 }
1128 }  // namespace panda::ecmascript::containers
1129