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
28namespace panda::test {
29
30using namespace panda;
31using namespace panda::ecmascript;
32using ecmascript::base::BuiltinsBase;
33
34constexpr uint32_t g_numberFive = 5;
35constexpr uint32_t g_numberNine = 9;
36constexpr uint32_t g_nintyNine = 99;
37constexpr uint32_t g_hundred = 100;
38constexpr uint32_t g_hundredAndOne = 101;
39static uint8_t g_arrayFrontU8[] = {"abcdef"};
40static uint32_t g_lenFrontU8 = sizeof(g_arrayFrontU8) - 1;
41
42class EcmaTestCommon {
43public:
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
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
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
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
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
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
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>
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>
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>
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>
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>
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
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
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
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
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
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
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