1/*
2 * Copyright (c) 2021-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
16#include "ecmascript/builtins/builtins_string.h"
17
18#include "ecmascript/base/builtins_base.h"
19#include "ecmascript/builtins/builtins_regexp.h"
20#include "ecmascript/ecma_runtime_call_info.h"
21#include "ecmascript/ecma_string.h"
22#include "ecmascript/ecma_vm.h"
23#include "ecmascript/global_env.h"
24#include "ecmascript/js_array.h"
25#include "ecmascript/js_object-inl.h"
26#include "ecmascript/js_primitive_ref.h"
27#include "ecmascript/js_regexp.h"
28#include "ecmascript/js_tagged_value.h"
29#include "ecmascript/object_factory.h"
30#include "ecmascript/tests/test_helper.h"
31
32using namespace panda::ecmascript;
33using namespace panda::ecmascript::builtins;
34
35namespace panda::test {
36class BuiltinsStringTest : public BaseTestWithScope<true> {
37};
38
39JSTaggedValue CreateBuiltinsStringRegExpObjByPatternAndFlags(JSThread *thread, const JSHandle<EcmaString> &pattern,
40                                                             const JSHandle<EcmaString> &flags)
41{
42    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
43    JSHandle<JSFunction> regexp(env->GetRegExpFunction());
44    JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
45
46    // 8 : test case
47    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, regexp.GetTaggedValue(), 8);
48    ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue());
49    ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
50    ecmaRuntimeCallInfo->SetCallArg(0, pattern.GetTaggedValue());
51    ecmaRuntimeCallInfo->SetCallArg(1, flags.GetTaggedValue());
52
53    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
54    JSTaggedValue result = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo);
55    TestHelper::TearDownFrame(thread, prev);
56    return result;
57}
58
59enum class AlgorithmType {
60    FROM_CHAR_CODE,
61    FROM_CODE_POINT,
62    CHAR_AT,
63    CHAR_CODE_AT,
64    CODE_POINT_AT,
65    CONCAT,
66    INDEX_OF,
67    LAST_INDEX_OF,
68    INCLUDES,
69    START_WITH,
70    ENDS_WITH,
71    TO_STRING,
72    VALUE_OF,
73    REPLACE,
74    SPLIT,
75};
76
77JSTaggedValue StringAlgorithmOther(EcmaRuntimeCallInfo*ecmaRuntimeCallInfos, AlgorithmType type)
78{
79    switch (type) {
80        case AlgorithmType::START_WITH:
81            return BuiltinsString::StartsWith(ecmaRuntimeCallInfos);
82        case AlgorithmType::ENDS_WITH:
83            return BuiltinsString::EndsWith(ecmaRuntimeCallInfos);
84        case AlgorithmType::TO_STRING:
85            return BuiltinsString::ToString(ecmaRuntimeCallInfos);
86        case AlgorithmType::VALUE_OF:
87            return BuiltinsString::ValueOf(ecmaRuntimeCallInfos);
88        case AlgorithmType::REPLACE:
89            return BuiltinsString::Replace(ecmaRuntimeCallInfos);
90        case AlgorithmType::SPLIT:
91            return BuiltinsString::Split(ecmaRuntimeCallInfos);
92        default:
93            return JSTaggedValue::Undefined();
94    }
95}
96
97JSTaggedValue StringAlgorithm(JSThread *thread, JSTaggedValue thisArg, std::vector<JSTaggedValue>& args,
98    uint32_t argLen = 8, AlgorithmType type = AlgorithmType::FROM_CHAR_CODE)
99{
100    auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), argLen);
101    ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined());
102    ecmaRuntimeCallInfos->SetThis(thisArg);
103    for (size_t i = 0; i < args.size(); i++) {
104        ecmaRuntimeCallInfos->SetCallArg(i, args[i]);
105    }
106    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos);
107    JSTaggedValue result;
108    switch (type) {
109        case AlgorithmType::FROM_CHAR_CODE:
110            result = BuiltinsString::FromCharCode(ecmaRuntimeCallInfos);
111            break;
112        case AlgorithmType::FROM_CODE_POINT:
113            result = BuiltinsString::FromCodePoint(ecmaRuntimeCallInfos);
114            break;
115        case AlgorithmType::CHAR_AT:
116            result = BuiltinsString::CharAt(ecmaRuntimeCallInfos);
117            break;
118        case AlgorithmType::CHAR_CODE_AT:
119            result = BuiltinsString::CharCodeAt(ecmaRuntimeCallInfos);
120            break;
121        case AlgorithmType::CODE_POINT_AT:
122            result = BuiltinsString::CodePointAt(ecmaRuntimeCallInfos);
123            break;
124        case AlgorithmType::CONCAT:
125            result = BuiltinsString::Concat(ecmaRuntimeCallInfos);
126            break;
127        case AlgorithmType::INDEX_OF:
128            result = BuiltinsString::IndexOf(ecmaRuntimeCallInfos);
129            break;
130        case AlgorithmType::LAST_INDEX_OF:
131            result = BuiltinsString::LastIndexOf(ecmaRuntimeCallInfos);
132            break;
133        case AlgorithmType::INCLUDES:
134            result = BuiltinsString::Includes(ecmaRuntimeCallInfos);
135            break;
136        default:
137            result = StringAlgorithmOther(ecmaRuntimeCallInfos, type);
138            break;
139    }
140    TestHelper::TearDownFrame(thread, prev);
141    return result;
142}
143
144HWTEST_F_L0(BuiltinsStringTest, StringConstructor1)
145{
146    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
147
148    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
149    JSHandle<JSFunction> string(env->GetStringFunction());
150    JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
151    JSHandle<EcmaString> string2 = factory->NewFromASCII("ABC");
152
153    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, string.GetTaggedValue(), 6);
154    ecmaRuntimeCallInfo->SetFunction(string.GetTaggedValue());
155    ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
156    ecmaRuntimeCallInfo->SetCallArg(0, string2.GetTaggedValue());
157
158    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
159    JSTaggedValue result = BuiltinsString::StringConstructor(ecmaRuntimeCallInfo);
160    JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
161    ASSERT_TRUE(value.IsECMAObject());
162    JSHandle<JSPrimitiveRef> ref(thread, JSPrimitiveRef::Cast(value.GetTaggedObject()));
163    JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
164    ASSERT_EQ(EcmaStringAccessor::Compare(instance,
165        JSHandle<EcmaString>(thread, EcmaString::Cast(ref->GetValue())), test), 0);
166}
167
168// String.fromCharCode(65, 66, 67)
169HWTEST_F_L0(BuiltinsStringTest, fromCharCode1)
170{
171    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
172    const double arg1 = 65;
173    const double arg2 = 66;
174    const double arg3 = 67;
175
176    std::vector<JSTaggedValue> args{JSTaggedValue(arg1), JSTaggedValue(arg2), JSTaggedValue(arg3)};
177    auto result = StringAlgorithm(thread, JSTaggedValue::Undefined(), args, 10, AlgorithmType::FROM_CHAR_CODE);
178
179    ASSERT_TRUE(result.IsString());
180    JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
181    JSHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue(value.GetTaggedObject()));
182    JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
183    ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>::Cast(valueHandle), test), 0);
184}
185
186// String.fromCodePoint(65, 66, 67)
187HWTEST_F_L0(BuiltinsStringTest, fromCodePoint1)
188{
189    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
190    const double arg1 = 65;
191    const double arg2 = 66;
192    const double arg3 = 67;
193
194    std::vector<JSTaggedValue> args{JSTaggedValue(arg1), JSTaggedValue(arg2), JSTaggedValue(arg3)};
195    auto result = StringAlgorithm(thread, JSTaggedValue::Undefined(), args, 10, AlgorithmType::FROM_CODE_POINT);
196
197    ASSERT_TRUE(result.IsString());
198    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
199    JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
200    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
201}
202
203// "abcabcabc".charAt(5)
204HWTEST_F_L0(BuiltinsStringTest, charAt1)
205{
206    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
207    JSHandle<EcmaString> thisVal = factory->NewFromASCII("abcabcabc");
208
209    std::vector<JSTaggedValue> args{JSTaggedValue(static_cast<double>(5))};
210    auto result = StringAlgorithm(thread, thisVal.GetTaggedValue(), args, 6, AlgorithmType::CHAR_AT);
211
212    ASSERT_TRUE(result.IsString());
213    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
214    JSHandle<EcmaString> test = factory->NewFromASCII("c");
215    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
216}
217
218// "一二三四".charAt(2)
219HWTEST_F_L0(BuiltinsStringTest, charAt2)
220{
221    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
222    JSHandle<EcmaString> thisVal = factory->NewFromUtf8("一二三四");
223
224    std::vector<JSTaggedValue> args{JSTaggedValue(static_cast<double>(2))};
225    auto result = StringAlgorithm(thread, thisVal.GetTaggedValue(), args, 6, AlgorithmType::CHAR_AT);
226
227    ASSERT_TRUE(result.IsString());
228    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
229    JSHandle<EcmaString> test = factory->NewFromUtf8("三");
230    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
231}
232
233// "abcabcabc".charAt(-1)
234HWTEST_F_L0(BuiltinsStringTest, charAt3)
235{
236    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
237    JSHandle<EcmaString> thisVal = factory->NewFromASCII("abcabcabc");
238
239    std::vector<JSTaggedValue> args{JSTaggedValue(static_cast<double>(-1))};
240    auto result = StringAlgorithm(thread, thisVal.GetTaggedValue(), args, 6, AlgorithmType::CHAR_AT);
241
242    ASSERT_TRUE(result.IsString());
243    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
244    JSHandle<EcmaString> test = factory->GetEmptyString();
245    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
246}
247
248// "ABC".charCodeAt(0)
249HWTEST_F_L0(BuiltinsStringTest, charCodeAt1)
250{
251    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
252    JSHandle<EcmaString> thisVal = factory->NewFromASCII("ABC");
253
254    std::vector<JSTaggedValue> args{JSTaggedValue(static_cast<double>(0))};
255    auto result = StringAlgorithm(thread, thisVal.GetTaggedValue(), args, 6, AlgorithmType::CHAR_CODE_AT);
256
257    ASSERT_EQ(result.GetRawData(), JSTaggedValue(65).GetRawData());
258}
259
260// "ABC".charCodeAt(-1)
261HWTEST_F_L0(BuiltinsStringTest, charCodeAt2)
262{
263    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
264    JSHandle<EcmaString> thisVal = factory->NewFromASCII("ABC");
265
266    std::vector<JSTaggedValue> args{JSTaggedValue(static_cast<double>(-1))};
267    auto result = StringAlgorithm(thread, thisVal.GetTaggedValue(), args, 6, AlgorithmType::CHAR_CODE_AT);
268
269    JSTaggedValue test = BuiltinsString::GetTaggedDouble(base::NAN_VALUE);
270    ASSERT_EQ(result.GetRawData(), test.GetRawData());
271}
272
273// "ABC".codePointAt(1)
274HWTEST_F_L0(BuiltinsStringTest, codePointAt1)
275{
276    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
277    JSHandle<EcmaString> thisVal = factory->NewFromASCII("ABC");
278
279    std::vector<JSTaggedValue> args{JSTaggedValue(static_cast<double>(1))};
280    auto result = StringAlgorithm(thread, thisVal.GetTaggedValue(), args, 6, AlgorithmType::CODE_POINT_AT);
281
282    ASSERT_EQ(result.GetRawData(), JSTaggedValue(66).GetRawData());
283}
284
285// 'a'.concat('b', 'c', 'd')
286HWTEST_F_L0(BuiltinsStringTest, concat1)
287{
288    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
289    JSHandle<EcmaString> thisStr = factory->NewFromASCII("a");
290    JSHandle<EcmaString> val1 = factory->NewFromASCII("b");
291    JSHandle<EcmaString> val2 = factory->NewFromASCII("c");
292    JSHandle<EcmaString> val3 = factory->NewFromASCII("d");
293
294    std::vector<JSTaggedValue> args{val1.GetTaggedValue(), val2.GetTaggedValue(), val3.GetTaggedValue()};
295    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 10, AlgorithmType::CONCAT);
296
297    ASSERT_TRUE(result.IsString());
298    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
299    JSHandle<EcmaString> test = factory->NewFromASCII("abcd");
300    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
301}
302
303// "abcabcabc".indexof('b')
304HWTEST_F_L0(BuiltinsStringTest, indexof1)
305{
306    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
307    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
308    JSHandle<EcmaString> val = factory->NewFromASCII("b");
309
310    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
311    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::INDEX_OF);
312
313    ASSERT_EQ(result.GetRawData(), JSTaggedValue(1).GetRawData());
314}
315
316// "abcabcabc".indexof('b', 2)
317HWTEST_F_L0(BuiltinsStringTest, indexof2)
318{
319    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
320    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
321    JSHandle<EcmaString> val = factory->NewFromASCII("b");
322
323    std::vector<JSTaggedValue> args{val.GetTaggedValue(), JSTaggedValue(static_cast<double>(2))};
324    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::INDEX_OF);
325
326    ASSERT_EQ(result.GetRawData(), JSTaggedValue(4).GetRawData());
327}
328
329// "abcabcabc".indexof('d')
330HWTEST_F_L0(BuiltinsStringTest, indexof3)
331{
332    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
333    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
334    JSHandle<EcmaString> val = factory->NewFromASCII("d");
335
336    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
337    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::INDEX_OF);
338
339    ASSERT_EQ(result.GetRawData(), JSTaggedValue(-1).GetRawData());
340}
341
342// "abcabcabc".lastIndexOf('b')
343HWTEST_F_L0(BuiltinsStringTest, lastIndexOf1)
344{
345    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
346    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
347    JSHandle<EcmaString> val = factory->NewFromASCII("b");
348
349    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
350    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::LAST_INDEX_OF);
351
352    ASSERT_EQ(result.GetRawData(), JSTaggedValue(7).GetRawData());
353}
354// "abcabcabc".lastIndexOf('b', 2)
355HWTEST_F_L0(BuiltinsStringTest, lastIndexOf2)
356{
357    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
358    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
359    JSHandle<EcmaString> val = factory->NewFromASCII("b");
360
361    std::vector<JSTaggedValue> args{val.GetTaggedValue(), JSTaggedValue(static_cast<double>(2))};
362    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::LAST_INDEX_OF);
363
364    ASSERT_EQ(result.GetRawData(), JSTaggedValue(1).GetRawData());
365}
366
367// "abcabcabc".lastIndexOf('d')
368HWTEST_F_L0(BuiltinsStringTest, lastIndexOf3)
369{
370    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
371    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
372    JSHandle<EcmaString> val = factory->NewFromASCII("d");
373
374    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
375    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::LAST_INDEX_OF);
376
377    ASSERT_EQ(result.GetRawData(), JSTaggedValue(-1).GetRawData());
378}
379
380// "abcabcabc".includes('b')
381HWTEST_F_L0(BuiltinsStringTest, Includes2)
382{
383    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
384    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
385    JSHandle<EcmaString> val = factory->NewFromASCII("b");
386
387    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
388    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::INCLUDES);
389
390    ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
391}
392
393// "abccccccc".includes('b',2)
394HWTEST_F_L0(BuiltinsStringTest, Includes3)
395{
396    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
397    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abccccccc");
398    JSHandle<EcmaString> val = factory->NewFromASCII("b");
399
400    std::vector<JSTaggedValue> args{val.GetTaggedValue(), JSTaggedValue(static_cast<double>(2))};
401    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::INCLUDES);
402
403    ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
404}
405
406// "一二三四".includes('二')
407HWTEST_F_L0(BuiltinsStringTest, Includes4)
408{
409    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
410    JSHandle<EcmaString> thisStr = factory->NewFromUtf8("一二三四");
411    JSHandle<EcmaString> val = factory->NewFromUtf8("二");
412
413    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
414    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::INCLUDES);
415
416    ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
417}
418
419// "To be, or not to be, that is the question.".startsWith('To be')
420HWTEST_F_L0(BuiltinsStringTest, startsWith1)
421{
422    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
423    JSHandle<EcmaString> thisStr = factory->NewFromASCII("To be, or not to be, that is the question.");
424    JSHandle<EcmaString> val = factory->NewFromASCII("To be");
425
426    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
427    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::START_WITH);
428
429    ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
430}
431
432// "To be, or not to be, that is the question.".startsWith('not to be')
433HWTEST_F_L0(BuiltinsStringTest, startsWith2)
434{
435    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
436    JSHandle<EcmaString> thisStr = factory->NewFromASCII("To be, or not to be, that is the question.");
437    JSHandle<EcmaString> val = factory->NewFromASCII("not to be");
438
439    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
440    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::START_WITH);
441
442    ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
443}
444
445// "To be, or not to be, that is the question.".startsWith('not to be', 10)
446HWTEST_F_L0(BuiltinsStringTest, startsWith3)
447{
448    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
449    JSHandle<EcmaString> thisStr = factory->NewFromASCII("To be, or not to be, that is the question.");
450    JSHandle<EcmaString> val = factory->NewFromASCII("not to be");
451
452    std::vector<JSTaggedValue> args{val.GetTaggedValue(), JSTaggedValue(static_cast<double>(10))};
453    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::START_WITH);
454
455    ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
456}
457
458// "To be, or not to be, that is the question.".endsWith('question.')
459HWTEST_F_L0(BuiltinsStringTest, endsWith1)
460{
461    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
462    JSHandle<EcmaString> thisStr = factory->NewFromASCII("To be, or not to be, that is the question.");
463    JSHandle<EcmaString> val = factory->NewFromASCII("question.");
464
465    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
466    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::ENDS_WITH);
467
468    ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
469}
470
471// "To be, or not to be, that is the question.".endsWith('to be')
472HWTEST_F_L0(BuiltinsStringTest, endsWith2)
473{
474    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
475    JSHandle<EcmaString> thisStr = factory->NewFromASCII("To be, or not to be, that is the question.");
476    JSHandle<EcmaString> val = factory->NewFromASCII("to be");
477
478    std::vector<JSTaggedValue> args{val.GetTaggedValue()};
479    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 6, AlgorithmType::ENDS_WITH);
480
481    ASSERT_EQ(result.GetRawData(), JSTaggedValue::False().GetRawData());
482}
483
484// "To be, or not to be, that is the question.".endsWith('to be', 19)
485HWTEST_F_L0(BuiltinsStringTest, endsWith3)
486{
487    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
488    JSHandle<EcmaString> thisStr = factory->NewFromASCII("To be, or not to be, that is the question.");
489    JSHandle<EcmaString> val = factory->NewFromASCII("to be");
490
491    std::vector<JSTaggedValue> args{val.GetTaggedValue(), JSTaggedValue(static_cast<double>(19))};
492    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::ENDS_WITH);
493
494    ASSERT_EQ(result.GetRawData(), JSTaggedValue::True().GetRawData());
495}
496
497// "有ABC".toLocaleLowerCase()
498HWTEST_F_L0(BuiltinsStringTest, toLocaleLowerCase2)
499{
500    ASSERT_NE(thread, nullptr);
501    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
502    JSHandle<EcmaString> thisStr = factory->NewFromUtf8("有ABC");
503
504    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
505    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
506    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
507
508    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
509    JSTaggedValue result = BuiltinsString::ToLocaleLowerCase(ecmaRuntimeCallInfo);
510    ASSERT_TRUE(result.IsString());
511    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
512    JSHandle<EcmaString> test = factory->NewFromUtf8("有abc");
513    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
514}
515
516// "ABC".toLowerCase()
517HWTEST_F_L0(BuiltinsStringTest, toLowerCase1)
518{
519    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
520    JSHandle<EcmaString> thisStr = factory->NewFromASCII("ABC");
521
522    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
523    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
524    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
525
526    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
527    JSTaggedValue result = BuiltinsString::ToLowerCase(ecmaRuntimeCallInfo);
528    ASSERT_TRUE(result.IsString());
529    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
530    JSHandle<EcmaString> test = factory->NewFromASCII("abc");
531    ASSERT_TRUE(JSTaggedValue::SameValue(resultHandle.GetTaggedValue(), test.GetTaggedValue()));
532}
533
534// "abc".toUpperCase()
535HWTEST_F_L0(BuiltinsStringTest, toUpperCase1)
536{
537    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
538    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abc");
539
540    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
541    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
542    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
543
544    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
545    JSTaggedValue result = BuiltinsString::ToUpperCase(ecmaRuntimeCallInfo);
546    ASSERT_TRUE(result.IsString());
547    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
548    JSHandle<EcmaString> test = factory->NewFromASCII("ABC");
549    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
550}
551
552// "abc".localecompare('b')
553HWTEST_F_L0(BuiltinsStringTest, localecompare1)
554{
555    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
556    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abc");
557    JSHandle<EcmaString> val = factory->NewFromASCII("b");
558
559    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
560    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
561    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
562    ecmaRuntimeCallInfo->SetCallArg(0, val.GetTaggedValue());
563
564    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
565    JSTaggedValue result = BuiltinsString::LocaleCompare(ecmaRuntimeCallInfo);
566
567    ASSERT_EQ(result.GetRawData(), JSTaggedValue(-1).GetRawData());
568}
569
570// "abc".localecompare('abc')
571HWTEST_F_L0(BuiltinsStringTest, localecompare2)
572{
573    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
574    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abc");
575    JSHandle<EcmaString> val = factory->NewFromASCII("abc");
576
577    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
578    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
579    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
580    ecmaRuntimeCallInfo->SetCallArg(0, val.GetTaggedValue());
581
582    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
583    JSTaggedValue result = BuiltinsString::LocaleCompare(ecmaRuntimeCallInfo);
584
585    ASSERT_EQ(result.GetRawData(), JSTaggedValue(0).GetRawData());
586}
587
588// "abc".localecompare('aa')
589HWTEST_F_L0(BuiltinsStringTest, localecompare3)
590{
591    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
592    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abc");
593    JSHandle<EcmaString> val = factory->NewFromASCII("aa");
594
595    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
596    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
597    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
598    ecmaRuntimeCallInfo->SetCallArg(0, val.GetTaggedValue());
599
600    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
601    JSTaggedValue result = BuiltinsString::LocaleCompare(ecmaRuntimeCallInfo);
602
603    ASSERT_EQ(result.GetRawData(), JSTaggedValue(1).GetRawData());
604}
605
606// "你好".localecompare('辅助')
607HWTEST_F_L0(BuiltinsStringTest, localecompare4)
608{
609    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
610    std::string referenceStr = "你好";
611    std::string compareStr = "辅助";
612    JSHandle<EcmaString> thisStr = factory->NewFromStdString(referenceStr);
613    JSHandle<EcmaString> val = factory->NewFromStdString(compareStr);
614    JSHandle<EcmaString> locale = factory->NewFromASCII("zh-Hans");
615
616    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
617    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
618    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
619    ecmaRuntimeCallInfo->SetCallArg(0, val.GetTaggedValue());
620    ecmaRuntimeCallInfo->SetCallArg(1, locale.GetTaggedValue());
621
622    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
623    JSTaggedValue result = BuiltinsString::LocaleCompare(ecmaRuntimeCallInfo);
624    TestHelper::TearDownFrame(thread, prev);
625
626    ASSERT_GT(result.GetRawData(), JSTaggedValue(0).GetRawData());
627}
628
629// Test localeCompare when locales changed
630HWTEST_F_L0(BuiltinsStringTest, localecompare5)
631{
632    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
633    std::string referenceStr = "ä";
634    std::string compareStr = "z";
635    JSHandle<EcmaString> thisStr = factory->NewFromStdString(referenceStr);
636    JSHandle<EcmaString> val = factory->NewFromStdString(compareStr);
637    JSHandle<EcmaString> locale = factory->NewFromASCII("de");
638
639    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
640    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
641    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
642    ecmaRuntimeCallInfo->SetCallArg(0, val.GetTaggedValue());
643    ecmaRuntimeCallInfo->SetCallArg(1, locale.GetTaggedValue());
644
645    [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
646    JSTaggedValue result = BuiltinsString::LocaleCompare(ecmaRuntimeCallInfo);
647    TestHelper::TearDownFrame(thread, prev1);
648    ASSERT_EQ(result.GetRawData(), JSTaggedValue(-1).GetRawData());
649
650    auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
651    ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
652    ecmaRuntimeCallInfo1->SetThis(thisStr.GetTaggedValue());
653    ecmaRuntimeCallInfo1->SetCallArg(0, val.GetTaggedValue());
654    // change locale
655    ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue::Undefined());
656    [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
657    JSTaggedValue result1 = BuiltinsString::LocaleCompare(ecmaRuntimeCallInfo1);
658    TestHelper::TearDownFrame(thread, prev2);
659    ASSERT_EQ(result1.GetRawData(), JSTaggedValue(-1).GetRawData());
660}
661
662// "abc".normalize('NFC')
663HWTEST_F_L0(BuiltinsStringTest, normalize1)
664{
665    ASSERT_NE(thread, nullptr);
666    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
667    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abc");
668    JSHandle<EcmaString> val = factory->NewFromASCII("NFC");
669
670    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
671    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
672    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
673    ecmaRuntimeCallInfo->SetCallArg(0, val.GetTaggedValue());
674
675    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
676    JSTaggedValue result = BuiltinsString::Normalize(ecmaRuntimeCallInfo);
677    ASSERT_TRUE(result.IsString());
678    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
679    JSHandle<EcmaString> test = factory->NewFromASCII("abc");
680    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
681}
682
683// "abc".repeat(5)
684HWTEST_F_L0(BuiltinsStringTest, repeat1)
685{
686    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
687    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abc");
688
689    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
690    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
691    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
692    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(5)));
693
694    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
695    JSTaggedValue result = BuiltinsString::Repeat(ecmaRuntimeCallInfo);
696    ASSERT_TRUE(result.IsString());
697    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
698    JSHandle<EcmaString> test = factory->NewFromASCII("abcabcabcabcabc");
699    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
700}
701
702// 'The morning is upon us.'.slice(4, -2)
703HWTEST_F_L0(BuiltinsStringTest, slice1)
704{
705    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
706    JSHandle<EcmaString> thisStr = factory->NewFromASCII("The morning is upon us.");
707
708    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
709    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
710    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
711    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(4)));
712    ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<double>(-2)));
713
714    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
715    JSTaggedValue result = BuiltinsString::Slice(ecmaRuntimeCallInfo);
716    ASSERT_TRUE(result.IsString());
717    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
718    JSHandle<EcmaString> test = factory->NewFromASCII("morning is upon u");
719    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
720}
721
722// 'The morning is upon us.'.slice(12)
723HWTEST_F_L0(BuiltinsStringTest, slice2)
724{
725    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
726    JSHandle<EcmaString> thisStr = factory->NewFromASCII("The morning is upon us.");
727
728    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
729    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
730    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
731    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(12)));
732
733    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
734    JSTaggedValue result = BuiltinsString::Slice(ecmaRuntimeCallInfo);
735    ASSERT_TRUE(result.IsString());
736    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
737    JSHandle<EcmaString> test = factory->NewFromASCII("is upon us.");
738    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
739}
740
741// 'Mozilla'.substring(3, -3)
742HWTEST_F_L0(BuiltinsStringTest, substring1)
743{
744    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
745    JSHandle<EcmaString> thisStr = factory->NewFromASCII("Mozilla");
746
747    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
748    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
749    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
750    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(3)));
751    ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<double>(-3)));
752
753    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
754    JSTaggedValue result = BuiltinsString::Substring(ecmaRuntimeCallInfo);
755    ASSERT_TRUE(result.IsString());
756    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
757    JSHandle<EcmaString> test = factory->NewFromASCII("Moz");
758    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
759}
760
761// 'Mozilla'.substring(7, 4)
762HWTEST_F_L0(BuiltinsStringTest, substring2)
763{
764    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
765    JSHandle<EcmaString> thisStr = factory->NewFromASCII("Mozilla");
766
767    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
768    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
769    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
770    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(7)));
771    ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<double>(4)));
772
773    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
774    JSTaggedValue result = BuiltinsString::Substring(ecmaRuntimeCallInfo);
775    ASSERT_TRUE(result.IsString());
776    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
777    JSHandle<EcmaString> test = factory->NewFromASCII("lla");
778    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
779}
780
781// "   Hello world!   ".trim()
782HWTEST_F_L0(BuiltinsStringTest, trim1)
783{
784    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
785    JSHandle<EcmaString> thisStr = factory->NewFromASCII("   Hello world!   ");
786
787    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
788    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
789    ecmaRuntimeCallInfo->SetThis(thisStr.GetTaggedValue());
790
791    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
792    JSTaggedValue result = BuiltinsString::Trim(ecmaRuntimeCallInfo);
793    ASSERT_TRUE(result.IsString());
794    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
795    JSHandle<EcmaString> test = factory->NewFromASCII("Hello world!");
796    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
797}
798
799HWTEST_F_L0(BuiltinsStringTest, trim2)
800{
801    auto ecmaVM = thread->GetEcmaVM();
802    JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
803
804    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
805    JSHandle<EcmaString> thisStr = factory->NewFromASCII("   Hello world!   ");
806    JSHandle<JSFunction> stringObject(env->GetStringFunction());
807    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(thisStr.GetTaggedValue().GetTaggedObject()));
808    JSHandle<JSPrimitiveRef> str = factory->NewJSPrimitiveRef(stringObject, value);
809
810    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
811    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
812    ecmaRuntimeCallInfo->SetThis(str.GetTaggedValue());
813
814    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
815    JSTaggedValue result = BuiltinsString::Trim(ecmaRuntimeCallInfo);
816    ASSERT_TRUE(result.IsString());
817    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
818    JSHandle<EcmaString> test = factory->NewFromASCII("Hello world!");
819    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
820}
821
822HWTEST_F_L0(BuiltinsStringTest, trimRight)
823{
824    auto ecmaVM = thread->GetEcmaVM();
825    JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
826
827    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
828    JSHandle<EcmaString> thisStr = factory->NewFromASCII("      ");
829    JSHandle<JSFunction> stringObject(env->GetStringFunction());
830    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(thisStr.GetTaggedValue().GetTaggedObject()));
831    JSHandle<JSPrimitiveRef> str = factory->NewJSPrimitiveRef(stringObject, value);
832
833    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
834    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
835    ecmaRuntimeCallInfo->SetThis(str.GetTaggedValue());
836
837    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
838    JSTaggedValue result = BuiltinsString::TrimRight(ecmaRuntimeCallInfo);
839    ASSERT_TRUE(result.IsString());
840    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
841    JSHandle<EcmaString> test = factory->NewFromASCII("");
842    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
843}
844
845HWTEST_F_L0(BuiltinsStringTest, ToString)
846{
847    auto ecmaVM = thread->GetEcmaVM();
848    JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
849
850    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
851    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
852    JSHandle<JSFunction> stringObject(env->GetStringFunction());
853    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(thisStr.GetTaggedValue().GetTaggedObject()));
854    JSHandle<JSPrimitiveRef> str = factory->NewJSPrimitiveRef(stringObject, value);
855
856    std::vector<JSTaggedValue> args{};
857    auto result = StringAlgorithm(thread, str.GetTaggedValue(), args, 4, AlgorithmType::TO_STRING);
858
859    ASSERT_TRUE(result.IsString());
860    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
861    JSTaggedValue test = JSTaggedValue(*thisStr);
862    ASSERT_EQ(result.GetRawData(), test.GetRawData());
863}
864
865HWTEST_F_L0(BuiltinsStringTest, ValueOf)
866{
867    auto ecmaVM = thread->GetEcmaVM();
868    JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
869
870    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
871    JSHandle<EcmaString> thisStr = factory->NewFromASCII("abcabcabc");
872    JSHandle<JSFunction> stringObject(env->GetStringFunction());
873    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(thisStr.GetTaggedValue().GetTaggedObject()));
874    JSHandle<JSPrimitiveRef> str = factory->NewJSPrimitiveRef(stringObject, value);
875
876    std::vector<JSTaggedValue> args{};
877    auto result = StringAlgorithm(thread, str.GetTaggedValue(), args, 4, AlgorithmType::VALUE_OF);
878
879    ASSERT_TRUE(result.IsString());
880    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
881    JSTaggedValue test = JSTaggedValue(*thisStr);
882    ASSERT_EQ(result.GetRawData(), test.GetRawData());
883}
884
885static inline JSFunction *BuiltinsStringTestCreate(JSThread *thread)
886{
887    EcmaVM *ecmaVM = thread->GetEcmaVM();
888    JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
889    return globalEnv->GetObjectFunction().GetObject<JSFunction>();
890}
891
892HWTEST_F_L0(BuiltinsStringTest, Raw)
893{
894    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
895    JSHandle<JSTaggedValue> foo(factory->NewFromASCII("foo"));
896    JSHandle<JSTaggedValue> bar(factory->NewFromASCII("bar"));
897    JSHandle<JSTaggedValue> baz(factory->NewFromASCII("baz"));
898    JSHandle<JSTaggedValue> rawArray = JSHandle<JSTaggedValue>::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)));
899    JSHandle<JSObject> obj(rawArray);
900    JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
901    PropertyDescriptor desc0(thread, foo);
902    JSArray::DefineOwnProperty(thread, obj, key0, desc0);
903    JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
904    PropertyDescriptor desc1(thread, bar);
905    JSArray::DefineOwnProperty(thread, obj, key1, desc1);
906    JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
907    PropertyDescriptor desc2(thread, baz);
908    JSArray::DefineOwnProperty(thread, obj, key2, desc2);
909
910    JSHandle<JSTaggedValue> constructor(thread, BuiltinsStringTestCreate(thread));
911    JSHandle<JSTaggedValue> templateString(
912        factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
913    JSHandle<JSTaggedValue> rawKey(factory->NewFromASCII("raw"));
914    JSObject::SetProperty(thread, templateString, rawKey, rawArray);
915    JSHandle<EcmaString> test = factory->NewFromASCII("foo5barJavaScriptbaz");
916
917    JSHandle<EcmaString> javascript = factory->NewFromASCII("JavaScript");
918
919    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
920    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
921    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
922    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(templateString.GetObject<EcmaString>()));
923    ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast<int32_t>(5)));
924    ecmaRuntimeCallInfo->SetCallArg(2, javascript.GetTaggedValue());
925
926    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
927    JSTaggedValue result = BuiltinsString::Raw(ecmaRuntimeCallInfo);
928    ASSERT_TRUE(result.IsString());
929    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(reinterpret_cast<EcmaString *>(result.GetRawData()), *test));
930}
931
932HWTEST_F_L0(BuiltinsStringTest, Replace)
933{
934    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
935    JSHandle<EcmaString> thisStr = factory->NewFromASCII("Twas the night before Xmas...");
936    JSHandle<EcmaString> searchStr = factory->NewFromASCII("Xmas");
937    JSHandle<EcmaString> replaceStr = factory->NewFromASCII("Christmas");
938    JSHandle<EcmaString> expected = factory->NewFromASCII("Twas the night before Christmas...");
939
940    std::vector<JSTaggedValue> args{searchStr.GetTaggedValue(), replaceStr.GetTaggedValue()};
941    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
942
943    ASSERT_TRUE(result.IsString());
944    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(reinterpret_cast<EcmaString *>(result.GetRawData()), *expected));
945
946    JSHandle<EcmaString> replaceStr1 = factory->NewFromASCII("abc$$");
947    JSHandle<EcmaString> expected1 = factory->NewFromASCII("Twas the night before abc$...");
948    args[0] = searchStr.GetTaggedValue();
949    args[1] = replaceStr1.GetTaggedValue();
950    auto result1 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
951
952    JSHandle<EcmaString> resultString1(thread, result1);
953    ASSERT_TRUE(result1.IsString());
954    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString1, *expected1));
955
956    JSHandle<EcmaString> replaceStr2 = factory->NewFromASCII("abc$$dd");
957    JSHandle<EcmaString> expected2 = factory->NewFromASCII("Twas the night before abc$dd...");
958    args[0] = searchStr.GetTaggedValue();
959    args[1] = replaceStr2.GetTaggedValue();
960    auto result2 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
961
962    JSHandle<EcmaString> resultString2(thread, result2);
963    ASSERT_TRUE(result2.IsString());
964    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString2, *expected2));
965
966    JSHandle<EcmaString> replaceStr3 = factory->NewFromASCII("abc$&dd");
967    JSHandle<EcmaString> expected3 = factory->NewFromASCII("Twas the night before abcXmasdd...");
968    args[0] = searchStr.GetTaggedValue();
969    args[1] = replaceStr3.GetTaggedValue();
970    auto result3 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
971
972    JSHandle<EcmaString> resultString3(thread, result3);
973    ASSERT_TRUE(result3.IsString());
974    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString3, *expected3));
975
976    JSHandle<EcmaString> replaceStr4 = factory->NewFromASCII("abc$`dd");
977    JSHandle<EcmaString> expected4 =
978        factory->NewFromASCII("Twas the night before abcTwas the night before dd...");
979    args[0] = searchStr.GetTaggedValue();
980    args[1] = replaceStr4.GetTaggedValue();
981    auto result4 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
982
983    JSHandle<EcmaString> resultString4(thread, result4);
984    ASSERT_TRUE(result4.IsString());
985    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString4, *expected4));
986}
987
988HWTEST_F_L0(BuiltinsStringTest, Replace2)
989{
990    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
991    JSHandle<EcmaString> thisStr = factory->NewFromASCII("Twas the night before Xmas...");
992    JSHandle<EcmaString> searchStr = factory->NewFromASCII("Xmas");
993    JSHandle<EcmaString> replaceStr = factory->NewFromASCII("abc$\'dd");
994    JSHandle<EcmaString> expected = factory->NewFromASCII("Twas the night before abc...dd...");
995
996    std::vector<JSTaggedValue> args{searchStr.GetTaggedValue(), replaceStr.GetTaggedValue()};
997    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
998
999    ASSERT_TRUE(result.IsString());
1000    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(reinterpret_cast<EcmaString *>(result.GetRawData()), *expected));
1001
1002    JSHandle<EcmaString> replaceStr2 = factory->NewFromASCII("abc$`dd$\'$ff");
1003    JSHandle<EcmaString> expected2 =
1004        factory->NewFromASCII("Twas the night before abcTwas the night before dd...$ff...");
1005    args[0] = searchStr.GetTaggedValue();
1006    args[1] = replaceStr2.GetTaggedValue();
1007    auto result2 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
1008
1009
1010    JSHandle<EcmaString> resultString2(thread, result2);
1011    ASSERT_TRUE(result2.IsString());
1012    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString2, *expected2));
1013
1014    JSHandle<EcmaString> replaceStr3 = factory->NewFromASCII("abc$`dd$\'$");
1015    JSHandle<EcmaString> expected3 =
1016        factory->NewFromASCII("Twas the night before abcTwas the night before dd...$...");
1017    args[0] = searchStr.GetTaggedValue();
1018    args[1] = replaceStr3.GetTaggedValue();
1019    auto result3 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
1020
1021    JSHandle<EcmaString> resultString3(thread, result3);
1022    ASSERT_TRUE(result3.IsString());
1023    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString3, *expected3));
1024
1025    JSHandle<EcmaString> replaceStr4 = factory->NewFromASCII("abc$`dd$$");
1026    JSHandle<EcmaString> expected4 =
1027        factory->NewFromASCII("Twas the night before abcTwas the night before dd$...");
1028    args[0] = searchStr.GetTaggedValue();
1029    args[1] = replaceStr4.GetTaggedValue();
1030    auto result4 = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
1031
1032    ASSERT_TRUE(result4.IsString());
1033    JSHandle<EcmaString> resultString4(thread, result4);
1034    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*resultString4, *expected4));
1035}
1036
1037HWTEST_F_L0(BuiltinsStringTest, Replace3)
1038{
1039    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1040    JSHandle<EcmaString> thisStr = factory->NewFromASCII("Twas the night before Xmas...");
1041    JSHandle<EcmaString> searchStr = factory->NewFromASCII("Xmas");
1042    JSHandle<EcmaString> replaceStr = factory->NewFromASCII("$&a $` $\' $2 $01 $$1 $21 $32 a");
1043    JSHandle<EcmaString> expected = factory->NewFromASCII(
1044        "Twas the night before Xmasa Twas the night before  ... $2 $01 $1 $21 $32 a...");
1045
1046    std::vector<JSTaggedValue> args{searchStr.GetTaggedValue(), replaceStr.GetTaggedValue()};
1047    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
1048
1049    ASSERT_TRUE(result.IsString());
1050    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(reinterpret_cast<EcmaString *>(result.GetRawData()), *expected));
1051}
1052
1053HWTEST_F_L0(BuiltinsStringTest, Replace4)
1054{
1055    // invoke RegExpConstructor method
1056    JSHandle<EcmaString> pattern1 =
1057        thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)");
1058    JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
1059    JSTaggedValue result1 = CreateBuiltinsStringRegExpObjByPatternAndFlags(thread, pattern1, flags1);
1060    JSHandle<JSRegExp> searchStr(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
1061    JSHandle<EcmaString> expected = thread->GetEcmaVM()->GetFactory()->NewFromASCII(
1062        "The Quick Brown Fox Jumpsa The   Over The Lazy Dog Jumps Brown $1 Jumps1 $32 a Over The Lazy Dog");
1063
1064    // make ecma_runtime_call_info2
1065    JSHandle<EcmaString> thisStr =
1066        thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog");
1067    JSHandle<EcmaString> replaceStr =
1068        thread->GetEcmaVM()->GetFactory()->NewFromASCII("$&a $` $\' $2 $01 $$1 $21 $32 a");
1069
1070    std::vector<JSTaggedValue> args{searchStr.GetTaggedValue(), replaceStr.GetTaggedValue()};
1071    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::REPLACE);
1072
1073    ASSERT_TRUE(result.IsString());
1074    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(reinterpret_cast<EcmaString *>(result.GetRawData()), *expected));
1075}
1076
1077void SplitCommon(JSThread *thread, std::vector<JSHandle<EcmaString>> expecteds, JSHandle<JSArray> &resultArray)
1078{
1079    JSHandle<JSTaggedValue> resultObj(resultArray);
1080    for (size_t i = 0; i < expecteds.size(); i++) {
1081        JSHandle<EcmaString> str(
1082            JSObject::GetProperty(thread, resultObj,
1083                                  JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<int>(i))))
1084                .GetValue());
1085        ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(*str, *expecteds[i]));
1086    }
1087}
1088
1089HWTEST_F_L0(BuiltinsStringTest, Split)
1090{
1091    // invoke RegExpConstructor method
1092    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1093    JSHandle<EcmaString> thisStr = factory->NewFromASCII("Hello World. How are you doing?");
1094    JSHandle<EcmaString> separatorStr = factory->NewFromASCII(" ");
1095    JSHandle<JSTaggedValue> limit(thread, JSTaggedValue(3));
1096    JSHandle<EcmaString> expected1 = factory->NewFromASCII("Hello");
1097    JSHandle<EcmaString> expected2 = factory->NewFromASCII("World.");
1098    JSHandle<EcmaString> expected3 = factory->NewFromASCII("How");
1099
1100    std::vector<JSTaggedValue> args{separatorStr.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(3))};
1101    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::SPLIT);
1102
1103    ASSERT_TRUE(result.IsECMAObject());
1104    JSHandle<JSArray> resultArray(thread, reinterpret_cast<JSArray *>(result.GetRawData()));
1105    ASSERT_TRUE(resultArray->IsJSArray());
1106    std::vector<JSHandle<EcmaString>> expecteds{expected1, expected2, expected3};
1107    SplitCommon(thread, expecteds, resultArray);
1108}
1109
1110HWTEST_F_L0(BuiltinsStringTest, Split2)
1111{
1112    // invoke RegExpConstructor method
1113    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1114    JSHandle<EcmaString> thisStr = factory->NewFromASCII("a-b-c");
1115    JSHandle<EcmaString> pattern1 = factory->NewFromASCII("-");
1116    JSHandle<EcmaString> flags1 = factory->NewFromASCII("iug");
1117    JSTaggedValue result1 = CreateBuiltinsStringRegExpObjByPatternAndFlags(thread, pattern1, flags1);
1118    JSHandle<JSRegExp> separatorObj(thread, result1);
1119
1120    JSHandle<JSTaggedValue> limit(thread, JSTaggedValue(3));
1121    JSHandle<EcmaString> expected1 = factory->NewFromASCII("a");
1122    JSHandle<EcmaString> expected2 = factory->NewFromASCII("b");
1123    JSHandle<EcmaString> expected3 = factory->NewFromASCII("c");
1124
1125    std::vector<JSTaggedValue> args{separatorObj.GetTaggedValue(), JSTaggedValue(static_cast<int32_t>(3))};
1126    auto result = StringAlgorithm(thread, thisStr.GetTaggedValue(), args, 8, AlgorithmType::SPLIT);
1127
1128    ASSERT_TRUE(result.IsECMAObject());
1129    JSHandle<JSArray> resultArray(thread, result);
1130    ASSERT_TRUE(resultArray->IsJSArray());
1131    std::vector<JSHandle<EcmaString>> expecteds{expected1, expected2, expected3};
1132    SplitCommon(thread, expecteds, resultArray);
1133}
1134
1135// "一二三四".at(3)
1136HWTEST_F_L0(BuiltinsStringTest, at1)
1137{
1138    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1139    JSHandle<EcmaString> thisVal = factory->NewFromUtf8("一二三四");
1140
1141    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1142    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
1143    ecmaRuntimeCallInfo->SetThis(thisVal.GetTaggedValue());
1144    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(3)));
1145
1146    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1147    JSTaggedValue result = BuiltinsString::At(ecmaRuntimeCallInfo);
1148    ASSERT_TRUE(result.IsString());
1149    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
1150    JSHandle<EcmaString> test = factory->NewFromUtf8("四");
1151    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
1152}
1153
1154// "一二三四".at(-2)
1155HWTEST_F_L0(BuiltinsStringTest, at2)
1156{
1157    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1158    JSHandle<EcmaString> thisVal = factory->NewFromUtf8("一二三四");
1159
1160    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1161    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
1162    ecmaRuntimeCallInfo->SetThis(thisVal.GetTaggedValue());
1163    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(-2)));
1164
1165    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1166    JSTaggedValue result = BuiltinsString::At(ecmaRuntimeCallInfo);
1167    ASSERT_TRUE(result.IsString());
1168    JSHandle<EcmaString> resultHandle(thread, reinterpret_cast<EcmaString *>(result.GetRawData()));
1169    JSHandle<EcmaString> test = factory->NewFromUtf8("三");
1170    ASSERT_EQ(EcmaStringAccessor::Compare(instance, resultHandle, test), 0);
1171}
1172
1173// "一二三四".at(-5)
1174HWTEST_F_L0(BuiltinsStringTest, at3)
1175{
1176    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1177    JSHandle<EcmaString> thisVal = factory->NewFromUtf8("一二三四");
1178
1179    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1180    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
1181    ecmaRuntimeCallInfo->SetThis(thisVal.GetTaggedValue());
1182    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(-5)));
1183
1184    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1185    JSTaggedValue result = BuiltinsString::At(ecmaRuntimeCallInfo);
1186    ASSERT_TRUE(result.IsUndefined());
1187}
1188
1189// "abcabcabc".at(9)
1190HWTEST_F_L0(BuiltinsStringTest, at4)
1191{
1192    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1193    JSHandle<EcmaString> thisVal = factory->NewFromASCII("abcabcabc");
1194
1195    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
1196    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
1197    ecmaRuntimeCallInfo->SetThis(thisVal.GetTaggedValue());
1198    ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast<double>(9)));
1199
1200    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1201    JSTaggedValue result = BuiltinsString::At(ecmaRuntimeCallInfo);
1202    ASSERT_TRUE(result.IsUndefined());
1203}
1204}  // namespace panda::test
1205