• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef ECMA_TEST_COMMON_H
16 #define ECMA_TEST_COMMON_H
17 #include <functional>
18 #include "ecmascript/containers/containers_private.h"
19 #include "ecmascript/ecma_string-inl.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_date_time_format.h"
22 #include "ecmascript/js_tagged_value.h"
23 #include "ecmascript/object_factory.h"
24 #include "ecmascript/tagged_tree.h"
25 #include "ecmascript/tests/ecma_container_common.h"
26 #include "ecmascript/tests/test_common.h"
27 
28 namespace panda::test {
29 
30 using namespace panda;
31 using namespace panda::ecmascript;
32 using ecmascript::base::BuiltinsBase;
33 
34 constexpr uint32_t g_numberFive = 5;
35 constexpr uint32_t g_numberNine = 9;
36 constexpr uint32_t g_nintyNine = 99;
37 constexpr uint32_t g_hundred = 100;
38 constexpr uint32_t g_hundredAndOne = 101;
39 static uint8_t g_arrayFrontU8[] = {"abcdef"};
40 static uint32_t g_lenFrontU8 = sizeof(g_arrayFrontU8) - 1;
41 
42 class EcmaTestCommon {
43 public:
44     using CreateStringFunc =
45         std::function<EcmaString *(const EcmaVM *vm, const uint8_t *utf8Data, size_t length, bool canBeCompress)>;
46     using CreateStringUtf16Func =
47         std::function<EcmaString *(const EcmaVM *vm, const uint16_t *utf8Data, size_t length, bool canBeCompress)>;
48     using StringAreEqualUtf16Func =
49         std::function<bool(const EcmaString *str1, const uint16_t *utf16Data, uint32_t utf16Len)>;
50     using StringIsEqualUint8Func =
51         std::function<bool(const EcmaString *str1, const uint8_t *dataAddr, uint32_t dataLen, bool canBeCompress)>;
52     using Compare =
53         std::function<int32_t(const EcmaVM *vm, const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right)>;
54 
55     static void ConcatCommonCase2(JSThread *thread, const EcmaVM *instance, bool constantString = true)
56     {
57         uint16_t arrayBackU16NotComp[] = {88, 768, 1, 270, 345, 333};
58         uint32_t lengthEcmaStrBackU16NotComp = sizeof(arrayBackU16NotComp) / sizeof(arrayBackU16NotComp[0]);
59 
60         EcmaString *ecmaFrontU8 = nullptr;
61         if (constantString) {
62             ecmaFrontU8 = EcmaStringAccessor::CreateConstantString(instance, &g_arrayFrontU8[0], g_lenFrontU8, true);
63         } else {
64             ecmaFrontU8 = EcmaStringAccessor::CreateFromUtf8(instance, &g_arrayFrontU8[0], g_lenFrontU8, true);
65         }
66         JSHandle<EcmaString> handleEcmaStrFrontU8(thread, ecmaFrontU8);
67         JSHandle<EcmaString> handleEcmaStrBackU16NotComp(
68             thread,
69             EcmaStringAccessor::CreateFromUtf16(instance, &arrayBackU16NotComp[0], lengthEcmaStrBackU16NotComp, false));
70         JSHandle<EcmaString> handleEcmaStrConcatU8U16NotComp(
71             thread, EcmaStringAccessor::Concat(instance, handleEcmaStrFrontU8, handleEcmaStrBackU16NotComp));
72         EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).IsUtf16());
73         for (uint32_t i = 0; i < g_lenFrontU8; i++) {
74             EXPECT_EQ(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).Get(i), g_arrayFrontU8[i]);
75         }
76         for (uint32_t i = 0; i < lengthEcmaStrBackU16NotComp; i++) {
77             EXPECT_EQ(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).Get(i + g_lenFrontU8),
78                       arrayBackU16NotComp[i]);
79         }
80         EXPECT_EQ(EcmaStringAccessor(handleEcmaStrConcatU8U16NotComp).GetLength(),
81                   g_lenFrontU8 + lengthEcmaStrBackU16NotComp);
82     }
83 
FastSubStringCommonCase(JSThread * thread,const EcmaVM * instance,std::vector<uint8_t> & data,CreateStringFunc createStringFunc)84     static void FastSubStringCommonCase(JSThread *thread, const EcmaVM *instance, std::vector<uint8_t> &data,
85                                         CreateStringFunc createStringFunc)
86     {
87         EcmaString *frontEcmaStr = createStringFunc(instance, data.data(), data.size(), true);
88         JSHandle<EcmaString> handleEcmaStrU8(thread, frontEcmaStr);
89         uint32_t indexStartSubU8 = 2;  // 2: sub index
90         uint32_t lengthSubU8 = 2;      // 2: length
91         JSHandle<EcmaString> handleEcmaStrSubU8(
92             thread, EcmaStringAccessor::FastSubString(instance, handleEcmaStrU8, indexStartSubU8, lengthSubU8));
93         for (uint32_t i = 0; i < lengthSubU8; i++) {
94             EXPECT_EQ(EcmaStringAccessor(handleEcmaStrSubU8).Get(i),
95                       EcmaStringAccessor(handleEcmaStrU8).Get(i + indexStartSubU8));
96         }
97         EXPECT_EQ(EcmaStringAccessor(handleEcmaStrSubU8).GetLength(), lengthSubU8);
98     }
99 
IndexOfCommonCase(JSThread * thread,const EcmaVM * instance,std::vector<uint16_t> & dataU16,std::vector<uint8_t> & dataU8,CreateStringFunc createStringFunc)100     static void IndexOfCommonCase(JSThread *thread, const EcmaVM *instance, std::vector<uint16_t> &dataU16,
101                                   std::vector<uint8_t> &dataU8, CreateStringFunc createStringFunc)
102     {
103         JSHandle<EcmaString> ecmaU16(
104             thread, EcmaStringAccessor::CreateFromUtf16(instance, dataU16.data(), dataU16.size(), true));
105 
106         EcmaString *ecmaStr = createStringFunc(instance, dataU8.data(), dataU8.size(), true);
107         JSHandle<EcmaString> ecmaU8(thread, ecmaStr);
108 
109         int32_t posStart = 0;
110         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
111         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU16, ecmaU8, posStart), -1);
112         posStart = -1;
113         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
114         posStart = 1;
115         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
116         posStart = 3;                                                                    // 3: pos start
117         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), 3);  // 3: value
118         posStart = 4;                                                                    // 4: pos start
119         EXPECT_EQ(EcmaStringAccessor::IndexOf(instance, ecmaU8, ecmaU16, posStart), -1);
120     }
121 
StringIsEqualCommonCase(JSThread * thread,const EcmaVM * instance,StringIsEqualUint8Func stringIsEqualFunc)122     static void StringIsEqualCommonCase(JSThread *thread, const EcmaVM *instance,
123                                         StringIsEqualUint8Func stringIsEqualFunc)
124     {
125         uint8_t arrayU8No1[4] = {45, 92, 78};
126         uint16_t arrayU16NotCompNo1[] = {45, 92, 78};
127         uint16_t arrayU16NotCompNo2[] = {45, 92, 78, 24};
128         uint16_t arrayU16NotCompNo3[] = {45, 92};
129         uint16_t arrayU16NotCompNo4[] = {25645, 25692, 25678};
130         uint32_t lengthEcmaStrU8No1 = sizeof(arrayU8No1) - 1;
131         uint32_t lengthEcmaStrU16NotCompNo1 = sizeof(arrayU16NotCompNo1) / sizeof(arrayU16NotCompNo1[0]);
132         uint32_t lengthEcmaStrU16NotCompNo2 = sizeof(arrayU16NotCompNo2) / sizeof(arrayU16NotCompNo2[0]);
133         uint32_t lengthEcmaStrU16NotCompNo3 = sizeof(arrayU16NotCompNo3) / sizeof(arrayU16NotCompNo3[0]);
134         uint32_t lengthEcmaStrU16NotCompNo4 = sizeof(arrayU16NotCompNo4) / sizeof(arrayU16NotCompNo4[0]);
135         JSHandle<EcmaString> handleEcmaStrU16NotCompNo1(
136             thread,
137             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo1[0], lengthEcmaStrU16NotCompNo1, true));
138         JSHandle<EcmaString> handleEcmaStrU16NotCompNo2(
139             thread,
140             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo2[0], lengthEcmaStrU16NotCompNo2, true));
141         JSHandle<EcmaString> handleEcmaStrU16NotCompNo3(
142             thread,
143             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo3[0], lengthEcmaStrU16NotCompNo3, true));
144         JSHandle<EcmaString> handleEcmaStrU16NotCompNo4(
145             thread,
146             EcmaStringAccessor::CreateFromUtf16(instance, &arrayU16NotCompNo4[0], lengthEcmaStrU16NotCompNo4, false));
147         EXPECT_FALSE(stringIsEqualFunc(*handleEcmaStrU16NotCompNo1, &arrayU8No1[0], lengthEcmaStrU8No1, false));
148         EXPECT_TRUE(stringIsEqualFunc(*handleEcmaStrU16NotCompNo1, &arrayU8No1[0], lengthEcmaStrU8No1, true));
149         EXPECT_FALSE(stringIsEqualFunc(*handleEcmaStrU16NotCompNo2, &arrayU8No1[0], lengthEcmaStrU8No1, false));
150         EXPECT_FALSE(stringIsEqualFunc(*handleEcmaStrU16NotCompNo3, &arrayU8No1[0], lengthEcmaStrU8No1, false));
151         EXPECT_FALSE(stringIsEqualFunc(*handleEcmaStrU16NotCompNo4, &arrayU8No1[0], lengthEcmaStrU8No1, false));
152     }
153 
TryLowerCommonCase(JSThread * thread,const EcmaVM * instance,JSHandle<EcmaString> & lowerStr,std::vector<JSHandle<EcmaString>> caseStrings)154     static void TryLowerCommonCase(JSThread *thread, const EcmaVM *instance, JSHandle<EcmaString> &lowerStr,
155                                    std::vector<JSHandle<EcmaString>> caseStrings)
156     {
157         {
158             JSHandle<EcmaString> lowerEcmaString(thread, EcmaStringAccessor::TryToLower(instance, lowerStr));
159             EXPECT_TRUE(JSTaggedValue::SameValue(lowerStr.GetTaggedValue(), lowerEcmaString.GetTaggedValue()));
160             EXPECT_EQ(EcmaStringAccessor(lowerStr).GetLength(), EcmaStringAccessor(lowerEcmaString).GetLength());
161             EXPECT_TRUE(EcmaStringAccessor(lowerEcmaString).IsUtf8());
162             EXPECT_FALSE(EcmaStringAccessor(lowerEcmaString).IsUtf16());
163         }
164 
165         for (size_t i = 0; i < caseStrings.size(); i++) {
166             JSHandle<EcmaString> lowerEcmaString(thread, EcmaStringAccessor::TryToLower(instance, caseStrings[i]));
167             EXPECT_TRUE(JSTaggedValue::SameValue(lowerStr.GetTaggedValue(), lowerEcmaString.GetTaggedValue()));
168             EXPECT_EQ(EcmaStringAccessor(lowerStr).GetLength(), EcmaStringAccessor(lowerEcmaString).GetLength());
169             EXPECT_TRUE(EcmaStringAccessor(lowerEcmaString).IsUtf8());
170             EXPECT_FALSE(EcmaStringAccessor(lowerEcmaString).IsUtf16());
171         }
172     }
173 
CompareCommonCase(JSThread * thread,const EcmaVM * instance,CreateStringFunc createUtf8,CreateStringUtf16Func createUtf16,Compare compare)174     static void CompareCommonCase(JSThread *thread, const EcmaVM *instance, CreateStringFunc createUtf8,
175                                   CreateStringUtf16Func createUtf16, Compare compare)
176     {
177         // Compare(). EcmaString made by CreateFromUtf8() and EcmaString made by CreateFromUtf16( , , , true).
178         uint8_t arrayU8No1[3] = {1, 23};
179         uint8_t arrayU8No2[4] = {1, 23, 49};
180         uint16_t arrayU16CompNo1[] = {1, 23};
181         uint16_t arrayU16CompNo2[] = {1, 23, 49};
182         uint16_t arrayU16CompNo3[] = {1, 23, 45, 97, 127};
183         uint32_t lengthEcmaStrU8No1 = sizeof(arrayU8No1) - 1;
184         uint32_t lengthEcmaStrU8No2 = sizeof(arrayU8No2) - 1;
185         uint32_t lengthEcmaStrU16CompNo1 = sizeof(arrayU16CompNo1) / sizeof(arrayU16CompNo1[0]);
186         uint32_t lengthEcmaStrU16CompNo2 = sizeof(arrayU16CompNo2) / sizeof(arrayU16CompNo2[0]);
187         uint32_t lengthEcmaStrU16CompNo3 = sizeof(arrayU16CompNo3) / sizeof(arrayU16CompNo3[0]);
188         JSHandle<EcmaString> handleEcmaStrU8No1(thread, createUtf8(instance, &arrayU8No1[0], lengthEcmaStrU8No1, true));
189         JSHandle<EcmaString> handleEcmaStrU8No2(thread, createUtf8(instance, &arrayU8No2[0], lengthEcmaStrU8No2, true));
190         JSHandle<EcmaString> handleEcmaStrU16CompNo1(
191             thread, createUtf16(instance, &arrayU16CompNo1[0], lengthEcmaStrU16CompNo1, true));
192         JSHandle<EcmaString> handleEcmaStrU16CompNo2(
193             thread, createUtf16(instance, &arrayU16CompNo2[0], lengthEcmaStrU16CompNo2, true));
194         JSHandle<EcmaString> handleEcmaStrU16CompNo3(
195             thread, createUtf16(instance, &arrayU16CompNo3[0], lengthEcmaStrU16CompNo3, true));
196         EXPECT_EQ(compare(instance, handleEcmaStrU8No1, handleEcmaStrU16CompNo1), 0);
197         EXPECT_EQ(compare(instance, handleEcmaStrU16CompNo1, handleEcmaStrU8No1), 0);
198         EXPECT_EQ(compare(instance, handleEcmaStrU8No1, handleEcmaStrU16CompNo2), -1);
199         EXPECT_EQ(compare(instance, handleEcmaStrU16CompNo2, handleEcmaStrU8No1), 1);
200         EXPECT_EQ(compare(instance, handleEcmaStrU8No2, handleEcmaStrU16CompNo3), 49 - 45);  // 49: value, 45: value
201         EXPECT_EQ(compare(instance, handleEcmaStrU16CompNo3, handleEcmaStrU8No2), 45 - 49);  // 49: value, 45: value
202     }
203 
204     static void GcCommonCase(JSThread *thread, Heap *heap, bool nonMovable = true)
205     {
206         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
207         size_t oldNativeSize = heap->GetNativeBindingSize();
208         size_t newNativeSize = heap->GetNativeBindingSize();
209         constexpr int32_t nums = 1024;
210         {
211             [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
212             auto newData = thread->GetEcmaVM()->GetNativeAreaAllocator()->AllocateBuffer(1 * nums * nums);
213             [[maybe_unused]] JSHandle<JSNativePointer> obj = factory->NewJSNativePointer(
214                 newData, NativeAreaAllocator::FreeBufferFunc, nullptr, nonMovable, 1 * nums * nums);
215             newNativeSize = heap->GetNativeBindingSize();
216             EXPECT_EQ(newNativeSize - oldNativeSize, 1UL * nums * nums);
217             auto newData1 = thread->GetEcmaVM()->GetNativeAreaAllocator()->AllocateBuffer(1 * nums * nums);
218             [[maybe_unused]] JSHandle<JSNativePointer> obj2 = factory->NewJSNativePointer(
219                 newData1, NativeAreaAllocator::FreeBufferFunc, nullptr, false, 1 * nums * nums);
220 
221             EXPECT_TRUE(newNativeSize - oldNativeSize > 0);
222             EXPECT_TRUE(newNativeSize - oldNativeSize <= 2 * nums * nums);  // 2: value
223             for (int i = 0; i < 2048; i++) {                                // 2048: loop count
224                 [[maybe_unused]] ecmascript::EcmaHandleScope baseScopeForeach(thread);
225                 auto newData2 = thread->GetEcmaVM()->GetNativeAreaAllocator()->AllocateBuffer(1 * nums);
226                 // malloc size is smaller to avoid test fail in the small devices.
227                 [[maybe_unused]] JSHandle<JSNativePointer> obj3 = factory->NewJSNativePointer(
228                     newData2, NativeAreaAllocator::FreeBufferFunc, nullptr, true, 1 * nums * nums);
229             }
230             newNativeSize = heap->GetNativeBindingSize();
231             // Old GC should be trigger here, so the size should be reduced.
232             EXPECT_TRUE(newNativeSize - oldNativeSize < 2048 * nums * nums);  // 2048: value
233         }
234     }
235 
GcCommonCase(JSThread * thread)236     static size_t GcCommonCase(JSThread *thread)
237     {
238         {
239             [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
240             for (int i = 0; i < g_hundred; i++) {  // g_hundred: run count
241                 [[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
242                     10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);  // 10: value, 1024: value
243             }
244         }
245         return thread->GetEcmaVM()->GetHeap()->GetCommittedSize();
246     }
247 
248     template <class T>
ListAddHasCommon(JSThread * thread,JSHandle<T> & toor,JSMutableHandle<JSTaggedValue> & value,std::string myValue,int32_t numbers)249     static void ListAddHasCommon(JSThread *thread, JSHandle<T> &toor, JSMutableHandle<JSTaggedValue> &value,
250                                  std::string myValue, int32_t numbers)
251     {
252         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
253         for (int32_t i = 0; i < numbers; i++) {
254             std::string ivalue = myValue + std::to_string(i);
255             value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
256 
257             JSTaggedValue gValue = toor->Get(i);
258             EXPECT_EQ(gValue, value.GetTaggedValue());
259         }
260         JSTaggedValue gValue = toor->Get(10);  // 10: index
261         EXPECT_EQ(gValue, JSTaggedValue::Undefined());
262 
263         std::string ivalue = myValue + std::to_string(1);
264         value.Update(factory->NewFromStdString(ivalue).GetTaggedValue());
265         EXPECT_TRUE(toor->Has(value.GetTaggedValue()));
266     }
267 
268     template <class T>
ListGetLastCommon(JSThread * thread,JSHandle<T> & toor)269     static JSMutableHandle<JSTaggedValue> ListGetLastCommon(JSThread *thread, JSHandle<T> &toor)
270     {
271         constexpr uint32_t NODE_NUMBERS = 9;
272         JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
273         EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
274         EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
275         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
276             value.Update(JSTaggedValue(i + 1));
277             T::Add(thread, toor, value);
278         }
279         EXPECT_EQ(toor->GetLast().GetInt(), g_numberNine);
280         EXPECT_EQ(toor->GetFirst().GetInt(), 1);
281 
282         value.Update(JSTaggedValue(g_nintyNine));
283         int len = toor->Length();
284         toor->Insert(thread, toor, value, len);
285         return value;
286     }
287 
288     template <class T>
GetIndexOfAndGetLastIndexOfCommon(JSThread * thread,JSHandle<T> & toor)289     static void GetIndexOfAndGetLastIndexOfCommon(JSThread *thread, JSHandle<T> &toor)
290     {
291         auto value = ListGetLastCommon<T>(thread, toor);
292         EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), g_numberNine);
293         EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), g_numberNine);
294         EXPECT_EQ(toor->Length(), 10);  // 10: len
295 
296         value.Update(JSTaggedValue(g_hundred));
297         toor->Insert(thread, toor, value, 0);
298         EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 0);
299         EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 0);
300         EXPECT_EQ(toor->Length(), 11);  // 11: len
301 
302         value.Update(JSTaggedValue(g_hundredAndOne));
303         toor->Insert(thread, toor, value, g_numberFive);
304         EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), g_numberFive);
305         EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), g_numberFive);
306         EXPECT_EQ(toor->Length(), 12);  // 12: len
307 
308         toor->Dump();
309     }
310 
311     template <class T>
InsertAndGetLastCommon(JSThread * thread,JSHandle<T> & toor)312     static void InsertAndGetLastCommon(JSThread *thread, JSHandle<T> &toor)
313     {
314         auto value = ListGetLastCommon<T>(thread, toor);
315         EXPECT_EQ(toor->GetLast().GetInt(), g_nintyNine);
316         EXPECT_EQ(toor->Length(), 10);  // 10: len
317 
318         value.Update(JSTaggedValue(g_hundred));
319         toor->Insert(thread, toor, value, 0);
320         EXPECT_EQ(toor->GetFirst().GetInt(), g_hundred);
321         EXPECT_EQ(toor->Length(), 11);  // 11: len
322 
323         toor->Dump();
324 
325         value.Update(JSTaggedValue(g_hundredAndOne));
326         toor->Insert(thread, toor, value, g_numberFive);
327         EXPECT_EQ(toor->Length(), 12);  // 12: len
328         toor->Dump();
329         EXPECT_EQ(toor->Get(g_numberFive).GetInt(), g_hundredAndOne);
330     }
331 
332     template <class T>
ListRemoveCommon(JSThread * thread,JSHandle<T> & toor,JSMutableHandle<JSTaggedValue> & value)333     static void ListRemoveCommon(JSThread *thread, JSHandle<T> &toor, JSMutableHandle<JSTaggedValue> &value)
334     {
335         constexpr uint32_t NODE_NUMBERS = 20;
336         EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined());
337         EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined());
338         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
339             value.Update(JSTaggedValue(i));
340             T::Add(thread, toor, value);
341         }
342         EXPECT_EQ(toor->Length(), NODE_NUMBERS);
343         for (uint32_t i = 0; i < NODE_NUMBERS; i++) {
344             value.Update(JSTaggedValue(i));
345             JSTaggedValue gValue = toor->Get(i);
346             EXPECT_EQ(gValue, value.GetTaggedValue());
347         }
348     }
349 
SetDateOptionsTest(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & dateOptions)350     static void SetDateOptionsTest(JSThread *thread, JSHandle<JSObject> &optionsObj,
351                                    std::map<std::string, std::string> &dateOptions)
352     {
353         auto factory = thread->GetEcmaVM()->GetFactory();
354         auto globalConst = thread->GlobalConstants();
355         // Date options keys.
356         JSHandle<JSTaggedValue> weekdayKey = globalConst->GetHandledWeekdayString();
357         JSHandle<JSTaggedValue> yearKey = globalConst->GetHandledYearString();
358         JSHandle<JSTaggedValue> monthKey = globalConst->GetHandledMonthString();
359         JSHandle<JSTaggedValue> dayKey = globalConst->GetHandledDayString();
360         // Date options values.
361         JSHandle<JSTaggedValue> weekdayValue(factory->NewFromASCII(dateOptions["weekday"].c_str()));
362         JSHandle<JSTaggedValue> yearValue(factory->NewFromASCII(dateOptions["year"].c_str()));
363         JSHandle<JSTaggedValue> monthValue(factory->NewFromASCII(dateOptions["month"].c_str()));
364         JSHandle<JSTaggedValue> dayValue(factory->NewFromASCII(dateOptions["day"].c_str()));
365         // Set date options.
366         JSObject::SetProperty(thread, optionsObj, weekdayKey, weekdayValue);
367         JSObject::SetProperty(thread, optionsObj, yearKey, yearValue);
368         JSObject::SetProperty(thread, optionsObj, monthKey, monthValue);
369         JSObject::SetProperty(thread, optionsObj, dayKey, dayValue);
370     }
371 
SetTimeOptionsTest(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & timeOptionsMap)372     static void SetTimeOptionsTest(JSThread *thread, JSHandle<JSObject> &optionsObj,
373                                    std::map<std::string, std::string> &timeOptionsMap)
374     {
375         auto factory = thread->GetEcmaVM()->GetFactory();
376         auto globalConst = thread->GlobalConstants();
377         // Time options keys.
378         JSHandle<JSTaggedValue> dayPeriodKey = globalConst->GetHandledDayPeriodString();
379         JSHandle<JSTaggedValue> hourKey = globalConst->GetHandledHourString();
380         JSHandle<JSTaggedValue> minuteKey = globalConst->GetHandledMinuteString();
381         JSHandle<JSTaggedValue> secondKey = globalConst->GetHandledSecondString();
382         JSHandle<JSTaggedValue> fractionalSecondDigitsKey = globalConst->GetHandledFractionalSecondDigitsString();
383         // Time options values.
384         JSHandle<JSTaggedValue> dayPeriodValue(factory->NewFromASCII(timeOptionsMap["dayPeriod"].c_str()));
385         JSHandle<JSTaggedValue> hourValue(factory->NewFromASCII(timeOptionsMap["hour"].c_str()));
386         JSHandle<JSTaggedValue> minuteValue(factory->NewFromASCII(timeOptionsMap["minute"].c_str()));
387         JSHandle<JSTaggedValue> secondValue(factory->NewFromASCII(timeOptionsMap["second"].c_str()));
388         JSHandle<JSTaggedValue> fractionalSecondDigitsValue(
389             factory->NewFromASCII(timeOptionsMap["fractionalSecond"].c_str()));
390         // Set time options.
391         JSObject::SetProperty(thread, optionsObj, dayPeriodKey, dayPeriodValue);
392         JSObject::SetProperty(thread, optionsObj, hourKey, hourValue);
393         JSObject::SetProperty(thread, optionsObj, minuteKey, minuteValue);
394         JSObject::SetProperty(thread, optionsObj, secondKey, secondValue);
395         JSObject::SetProperty(thread, optionsObj, fractionalSecondDigitsKey, fractionalSecondDigitsValue);
396     }
397 
CreateDateTimeFormatTest(JSThread * thread,icu::Locale icuLocale,JSHandle<JSObject> options)398     static JSHandle<JSDateTimeFormat> CreateDateTimeFormatTest(JSThread *thread, icu::Locale icuLocale,
399                                                                JSHandle<JSObject> options)
400     {
401         auto factory = thread->GetEcmaVM()->GetFactory();
402 
403         JSHandle<JSTaggedValue> localeCtor = thread->GetEcmaVM()->GetGlobalEnv()->GetLocaleFunction();
404         JSHandle<JSTaggedValue> dtfCtor = thread->GetEcmaVM()->GetGlobalEnv()->GetDateTimeFormatFunction();
405         JSHandle<JSLocale> locales =
406             JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(localeCtor), localeCtor));
407         JSHandle<JSDateTimeFormat> dtf =
408             JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dtfCtor), dtfCtor));
409 
410         JSHandle<JSTaggedValue> optionsVal = JSHandle<JSTaggedValue>::Cast(options);
411         factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale);
412         dtf =
413             JSDateTimeFormat::InitializeDateTimeFormat(thread, dtf, JSHandle<JSTaggedValue>::Cast(locales), optionsVal);
414         return dtf;
415     }
416 
SetHourCycleKeyValue(JSThread * thread,std::string & cycle,std::string & zone)417     static JSHandle<JSObject> SetHourCycleKeyValue(JSThread *thread, std::string &cycle, std::string &zone)
418     {
419         auto factory = thread->GetEcmaVM()->GetFactory();
420         JSHandle<JSTaggedValue> objFun = thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction();
421         JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
422         JSHandle<JSTaggedValue> hourCycleKey = thread->GlobalConstants()->GetHandledHourCycleString();
423         JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII(cycle));
424         JSHandle<JSTaggedValue> timeZoneKey = thread->GlobalConstants()->GetHandledTimeZoneString();
425         JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII(zone));
426         JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
427         JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
428         return options;
429     }
430 
ArrayUndefinedGcCommon(JSThread * thread,TriggerGCType type)431     static void ArrayUndefinedGcCommon(JSThread *thread, TriggerGCType type)
432     {
433         EcmaVM *ecmaVM = thread->GetEcmaVM();
434         JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);  // 2: len
435         EXPECT_TRUE(*array != nullptr);
436         JSHandle<JSObject> newObj1(thread, EcmaContainerCommon::JSObjectTestCreate(thread));
437         array->Set(thread, 0, newObj1.GetTaggedValue());
438 
439         JSObject *newObj2 = EcmaContainerCommon::JSObjectTestCreate(thread);
440         JSTaggedValue value(newObj2);
441         value.CreateWeakRef();
442         array->Set(thread, 1, value);
443         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
444         EXPECT_EQ(value, array->Get(1));
445         ecmaVM->CollectGarbage(type);
446         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
447         EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));  // 1 : index
448     }
449 
ArrayKeepGcCommon(JSThread * thread,TriggerGCType type)450     static void ArrayKeepGcCommon(JSThread *thread, TriggerGCType type)
451     {
452         EcmaVM *ecmaVM = thread->GetEcmaVM();
453         JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);  // 2: len
454         EXPECT_TRUE(*array != nullptr);
455         JSHandle<JSObject> newObj1(thread, EcmaContainerCommon::JSObjectTestCreate(thread));
456         array->Set(thread, 0, newObj1.GetTaggedValue());
457 
458         JSHandle<JSObject> newObj2(thread, EcmaContainerCommon::JSObjectTestCreate(thread));
459         JSTaggedValue value(newObj2.GetTaggedValue());
460         value.CreateWeakRef();
461         array->Set(thread, 1, value);
462         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
463         EXPECT_EQ(value, array->Get(1));
464         ecmaVM->CollectGarbage(type);
465         EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
466         EXPECT_EQ(true, array->Get(1).IsWeak());
467         value = newObj2.GetTaggedValue();
468         value.CreateWeakRef();
469         EXPECT_EQ(value, array->Get(1));
470     }
471 };
472 };  // namespace panda::test
473 
474 #endif
475