1 /*
2 * Copyright (c) 2021 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/js_regexp.h"
17
18 #include "ecmascript/builtins/builtins_regexp.h"
19 #include "ecmascript/ecma_runtime_call_info.h"
20 #include "ecmascript/ecma_string.h"
21 #include "ecmascript/ecma_vm.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/js_handle.h"
24 #include "ecmascript/js_hclass.h"
25 #include "ecmascript/js_object-inl.h"
26 #include "ecmascript/js_tagged_value.h"
27 #include "ecmascript/js_thread.h"
28 #include "ecmascript/regexp/regexp_parser_cache.h"
29 #include "ecmascript/object_factory.h"
30 #include "ecmascript/tests/ecma_test_common.h"
31
32 using namespace panda::ecmascript;
33 using namespace panda::ecmascript::builtins;
34
35 namespace panda::test {
36 class BuiltinsRegExpTest : public BaseTestWithScope<false> {
37 };
38
HWTEST_F_L0(BuiltinsRegExpTest,RegExpConstructor1)39 HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor1)
40 {
41 // invoke RegExpConstructor method
42 JSHandle<EcmaString> pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+");
43 JSHandle<EcmaString> flags = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i");
44 JSTaggedValue result = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern, flags);
45
46 // ASSERT IsRegExp()
47 JSHandle<JSTaggedValue> regexpObject(thread, result);
48 ASSERT_TRUE(JSObject::IsRegExp(thread, regexpObject));
49
50 JSHandle<JSRegExp> jsRegexp(thread, JSRegExp::Cast(regexpObject->GetTaggedObject()));
51 JSHandle<JSTaggedValue> originalSource(thread, jsRegexp->GetOriginalSource());
52 uint8_t flagsBits = static_cast<uint8_t>(jsRegexp->GetOriginalFlags().GetInt());
53 JSHandle<JSTaggedValue> originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits));
54 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalSource), pattern), 0);
55 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalFlags), flags), 0);
56 }
57
HWTEST_F_L0(BuiltinsRegExpTest,RegExpConstructor2)58 HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2)
59 {
60 // invoke RegExpConstructor method
61 JSHandle<EcmaString> pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+");
62 JSHandle<EcmaString> flags = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i");
63 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern, flags);
64 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
65
66 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
67 JSHandle<JSFunction> regexp(env->GetRegExpFunction());
68 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
69
70 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*regexp), 8);
71 ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue());
72 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
73 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
74 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
75
76 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
77 // invoke RegExpConstructor method
78 JSTaggedValue result2 = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo);
79 TestHelper::TearDownFrame(thread, prev);
80
81 // ASSERT IsRegExp()
82 JSHandle<JSTaggedValue> regexpObject(thread, result2);
83 ASSERT_TRUE(JSObject::IsRegExp(thread, regexpObject));
84
85 JSHandle<JSRegExp> jsRegexp(thread, JSRegExp::Cast(regexpObject->GetTaggedObject()));
86 JSHandle<JSTaggedValue> originalSource(thread, jsRegexp->GetOriginalSource());
87 uint8_t flagsBits = static_cast<uint8_t>(jsRegexp->GetOriginalFlags().GetInt());
88 JSHandle<JSTaggedValue> originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits));
89 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalSource), pattern), 0);
90 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalFlags), flags), 0);
91 }
92
HWTEST_F_L0(BuiltinsRegExpTest,RegExpConstructor3)93 HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3)
94 {
95 // invoke RegExpConstructor method
96 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+");
97 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i");
98 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
99 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
100
101 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
102 JSHandle<JSFunction> regexp(env->GetRegExpFunction());
103 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
104 JSHandle<EcmaString> flags2 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gi");
105
106 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*regexp), 8);
107 ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue());
108 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
109 ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue());
110 ecmaRuntimeCallInfo->SetCallArg(1, flags2.GetTaggedValue());
111
112 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
113 // invoke RegExpConstructor method
114 JSTaggedValue result2 = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo);
115
116 // ASSERT IsRegExp()
117 JSHandle<JSTaggedValue> regexpObject(thread, result2);
118 ASSERT_TRUE(JSObject::IsRegExp(thread, regexpObject));
119
120 JSHandle<JSRegExp> jsRegexp(thread, JSRegExp::Cast(regexpObject->GetTaggedObject()));
121 JSHandle<JSTaggedValue> originalSource(thread, jsRegexp->GetOriginalSource());
122 uint8_t flagsBits = static_cast<uint8_t>(jsRegexp->GetOriginalFlags().GetInt());
123 JSHandle<JSTaggedValue> originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits));
124 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalSource), pattern1), 0);
125 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(originalFlags), flags2), 0);
126 }
127
HWTEST_F_L0(BuiltinsRegExpTest,GetSource1)128 HWTEST_F_L0(BuiltinsRegExpTest, GetSource1)
129 {
130 // invoke RegExpConstructor method
131 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("");
132 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i");
133 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
134 JSHandle<JSTaggedValue> result1Handle(thread, result1);
135
136 // invoke GetSource method
137 JSHandle<JSTaggedValue> source(
138 thread, thread->GetEcmaVM()->GetFactory()->NewFromASCII("source").GetTaggedValue());
139 JSHandle<JSTaggedValue> sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue());
140
141 JSHandle<EcmaString> expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("(?:)");
142 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(sourceResult), expect), 0);
143 }
144
HWTEST_F_L0(BuiltinsRegExpTest,GetSource2)145 HWTEST_F_L0(BuiltinsRegExpTest, GetSource2)
146 {
147 // invoke RegExpConstructor method
148 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("/w+");
149 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i");
150 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
151 JSHandle<JSTaggedValue> result1Handle(thread, result1);
152
153 // invoke GetSource method
154 JSHandle<JSTaggedValue> source(thread->GetEcmaVM()->GetFactory()->NewFromASCII("source"));
155 JSHandle<JSTaggedValue> sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue());
156
157 JSHandle<EcmaString> expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\/w+");
158 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(sourceResult), expect), 0);
159 }
160
HWTEST_F_L0(BuiltinsRegExpTest,Get)161 HWTEST_F_L0(BuiltinsRegExpTest, Get)
162 {
163 // invoke RegExpConstructor method
164 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+");
165 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gimuy");
166 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
167 JSHandle<JSTaggedValue> result1Handle(thread, result1);
168
169 JSHandle<JSTaggedValue> global(thread->GetEcmaVM()->GetFactory()->NewFromASCII("global"));
170 JSTaggedValue taggedGlobalResult =
171 JSTaggedValue(JSObject::GetProperty(thread, result1Handle, global).GetValue().GetTaggedValue());
172 ASSERT_EQ(taggedGlobalResult.GetRawData(), JSTaggedValue::True().GetRawData());
173
174 JSHandle<JSTaggedValue> ignoreCase(thread->GetEcmaVM()->GetFactory()->NewFromASCII("ignoreCase"));
175 JSTaggedValue taggedIgnoreCaseResult =
176 JSTaggedValue(JSObject::GetProperty(thread, result1Handle, ignoreCase).GetValue().GetTaggedValue());
177 ASSERT_EQ(taggedIgnoreCaseResult.GetRawData(), JSTaggedValue::True().GetRawData());
178
179 JSHandle<JSTaggedValue> multiline(thread->GetEcmaVM()->GetFactory()->NewFromASCII("multiline"));
180 JSTaggedValue taggedMultilineResult =
181 JSTaggedValue(JSObject::GetProperty(thread, result1Handle, multiline).GetValue().GetTaggedValue());
182 ASSERT_EQ(taggedMultilineResult.GetRawData(), JSTaggedValue::True().GetRawData());
183
184 JSHandle<JSTaggedValue> sticky(thread->GetEcmaVM()->GetFactory()->NewFromASCII("sticky"));
185 JSTaggedValue taggedStickyResult =
186 JSTaggedValue(JSObject::GetProperty(thread, result1Handle, sticky).GetValue().GetTaggedValue());
187 ASSERT_EQ(taggedStickyResult.GetRawData(), JSTaggedValue::True().GetRawData());
188
189 JSHandle<JSTaggedValue> unicode(thread->GetEcmaVM()->GetFactory()->NewFromASCII("unicode"));
190 JSTaggedValue taggedUnicodeResult =
191 JSTaggedValue(JSObject::GetProperty(thread, result1Handle, unicode).GetValue().GetTaggedValue());
192 ASSERT_EQ(taggedUnicodeResult.GetRawData(), JSTaggedValue::True().GetRawData());
193 }
194
HWTEST_F_L0(BuiltinsRegExpTest,GetFlags)195 HWTEST_F_L0(BuiltinsRegExpTest, GetFlags)
196 {
197 // invoke RegExpConstructor method
198 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+");
199 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("imuyg");
200 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
201 JSHandle<JSTaggedValue> result1Handle(thread, result1);
202
203 // invoke GetFlags method
204 JSHandle<JSTaggedValue> flags(thread->GetEcmaVM()->GetFactory()->NewFromASCII("flags"));
205 JSHandle<JSTaggedValue> flagsResult(JSObject::GetProperty(thread, result1Handle, flags).GetValue());
206
207 JSHandle<EcmaString> expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gimuy");
208 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(flagsResult), expectResult), 0);
209 }
210
HWTEST_F_L0(BuiltinsRegExpTest,toString)211 HWTEST_F_L0(BuiltinsRegExpTest, toString)
212 {
213 // invoke RegExpConstructor method
214 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+");
215 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("imuyg");
216 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
217 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
218
219 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
220 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
221 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
222
223 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
224 // invoke ToString method
225 JSTaggedValue toStringResult = BuiltinsRegExp::ToString(ecmaRuntimeCallInfo);
226 ASSERT_TRUE(toStringResult.IsString());
227 JSHandle<JSTaggedValue> toStringResultHandle(thread, toStringResult);
228 JSHandle<EcmaString> expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("/\\w+/gimuy");
229 ASSERT_EQ(EcmaStringAccessor::Compare(instance,
230 JSHandle<EcmaString>(toStringResultHandle), expectResult), 0);
231 }
232
ExecCommon(JSThread * thread,EcmaVM * instance,JSHandle<JSTaggedValue> & execResult,JSHandle<EcmaString> & inputString,std::vector<JSHandle<EcmaString>> & result)233 void ExecCommon(JSThread* thread, EcmaVM* instance, JSHandle<JSTaggedValue>& execResult,
234 JSHandle<EcmaString>& inputString, std::vector<JSHandle<EcmaString>>& result)
235 {
236 JSHandle<JSTaggedValue> input(thread->GetEcmaVM()->GetFactory()->NewFromASCII("input"));
237 JSHandle<JSTaggedValue> inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue());
238 JSHandle<EcmaString> outputInput = JSTaggedValue::ToString(thread, inputHandle);
239 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0);
240
241 JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
242 JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue());
243 JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
244 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, result[0]), 0);
245
246 JSHandle<JSTaggedValue> first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"));
247 JSHandle<JSTaggedValue> oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue());
248 JSHandle<EcmaString> outputOne = JSTaggedValue::ToString(thread, oneHandle);
249 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, result[1]), 0); // 1: second value
250
251 JSHandle<JSTaggedValue> second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2"));
252 JSHandle<JSTaggedValue> twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue());
253 JSHandle<EcmaString> outputTwo = JSTaggedValue::ToString(thread, twoHandle);
254 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, result[2]), 0); // 2: third value
255 }
256
HWTEST_F_L0(BuiltinsRegExpTest,Exec1)257 HWTEST_F_L0(BuiltinsRegExpTest, Exec1)
258 {
259 // invoke RegExpConstructor method
260 JSHandle<EcmaString> pattern1 =
261 thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)");
262 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("ig");
263 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
264 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
265
266 JSHandle<EcmaString> inputString =
267 thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog");
268 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
269 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
270 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
271 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
272
273 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
274 // invoke Exec method
275 JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo);
276
277 JSHandle<JSTaggedValue> execResult(thread, results);
278 JSHandle<EcmaString> resultZero =
279 thread->GetEcmaVM()->GetFactory()->NewFromASCII("Quick Brown Fox Jumps");
280 JSHandle<EcmaString> resultOne = thread->GetEcmaVM()->GetFactory()->NewFromASCII("Brown");
281 JSHandle<EcmaString> resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromASCII("Jumps");
282
283 JSHandle<JSTaggedValue> index(thread->GetEcmaVM()->GetFactory()->NewFromASCII("index"));
284 JSHandle<JSTaggedValue> indexHandle(JSObject::GetProperty(thread, execResult, index).GetValue());
285 uint32_t resultIndex = JSTaggedValue::ToUint32(thread, indexHandle);
286 ASSERT_TRUE(resultIndex == 4U);
287
288 std::vector<JSHandle<EcmaString>> result{resultZero, resultOne, resultTwo};
289 ExecCommon(thread, instance, execResult, inputString, result);
290 JSHandle<JSTaggedValue> regexp = JSHandle<JSTaggedValue>::Cast(value);
291 JSHandle<JSTaggedValue> lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex"));
292 JSHandle<JSTaggedValue> lastIndexObj(JSObject::GetProperty(thread, regexp, lastIndexHandle).GetValue());
293 int lastIndex = lastIndexObj->GetInt();
294 ASSERT_TRUE(lastIndex == 25);
295 }
296
HWTEST_F_L0(BuiltinsRegExpTest,Exec2)297 HWTEST_F_L0(BuiltinsRegExpTest, Exec2)
298 {
299 // invoke RegExpConstructor method
300 JSHandle<EcmaString> pattern1 =
301 thread->GetEcmaVM()->GetFactory()->NewFromASCII("((1)|(12))((3)|(23))");
302 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("ig");
303 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
304 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
305
306 JSHandle<EcmaString> inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("123");
307 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
308 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
309 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
310 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
311
312 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
313 // invoke Exec method
314 JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo);
315
316 JSHandle<JSTaggedValue> execResult(thread, results);
317 JSHandle<EcmaString> resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII("123");
318 JSHandle<EcmaString> resultOne = thread->GetEcmaVM()->GetFactory()->NewFromASCII("1");
319 JSHandle<EcmaString> resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromASCII("1");
320 JSHandle<EcmaString> resultFour = thread->GetEcmaVM()->GetFactory()->NewFromASCII("23");
321 JSHandle<EcmaString> resultSix = thread->GetEcmaVM()->GetFactory()->NewFromASCII("23");
322
323 JSHandle<JSTaggedValue> index(thread->GetEcmaVM()->GetFactory()->NewFromASCII("index"));
324 JSHandle<JSTaggedValue> indexHandle(JSObject::GetProperty(thread, execResult, index).GetValue());
325 uint32_t resultIndex = JSTaggedValue::ToUint32(thread, indexHandle);
326 ASSERT_TRUE(resultIndex == 0U);
327
328 std::vector<JSHandle<EcmaString>> result{resultZero, resultOne, resultTwo};
329 ExecCommon(thread, instance, execResult, inputString, result);
330 JSHandle<JSTaggedValue> regexp = JSHandle<JSTaggedValue>::Cast(value);
331 JSHandle<JSTaggedValue> lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex"));
332 JSHandle<JSTaggedValue> lastIndexObj(JSObject::GetProperty(thread, regexp, lastIndexHandle).GetValue());
333 int lastIndex = lastIndexObj->GetInt();
334 ASSERT_TRUE(lastIndex == 3);
335
336 JSHandle<JSTaggedValue> third(thread->GetEcmaVM()->GetFactory()->NewFromASCII("3"));
337 JSHandle<JSTaggedValue> thirdHandle(JSObject::GetProperty(thread, execResult, third).GetValue());
338 ASSERT_TRUE(thirdHandle->IsUndefined());
339
340 JSHandle<JSTaggedValue> four(thread->GetEcmaVM()->GetFactory()->NewFromASCII("4"));
341 JSHandle<JSTaggedValue> fourHandle(JSObject::GetProperty(thread, execResult, four).GetValue());
342 JSHandle<EcmaString> outputFour = JSTaggedValue::ToString(thread, fourHandle);
343 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputFour, resultFour), 0);
344
345 JSHandle<JSTaggedValue> five(thread->GetEcmaVM()->GetFactory()->NewFromASCII("5"));
346 JSHandle<JSTaggedValue> fiveHandle(JSObject::GetProperty(thread, execResult, five).GetValue());
347 ASSERT_TRUE(fiveHandle->IsUndefined());
348
349 JSHandle<JSTaggedValue> six(thread->GetEcmaVM()->GetFactory()->NewFromASCII("6"));
350 JSHandle<JSTaggedValue> sixHandle(JSObject::GetProperty(thread, execResult, six).GetValue());
351 JSHandle<EcmaString> outputSix = JSTaggedValue::ToString(thread, sixHandle);
352 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputSix, resultSix), 0);
353 }
354
HWTEST_F_L0(BuiltinsRegExpTest,Match1)355 HWTEST_F_L0(BuiltinsRegExpTest, Match1)
356 {
357 // invoke RegExpConstructor method
358 JSHandle<EcmaString> pattern1 =
359 thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)");
360 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
361 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
362 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
363
364 JSHandle<EcmaString> inputString =
365 thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog");
366 std::vector<JSTaggedValue> args{inputString.GetTaggedValue()};
367 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6, value.GetTaggedValue());
368
369 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
370 // invoke Match method
371 JSTaggedValue matchResults = BuiltinsRegExp::Match(ecmaRuntimeCallInfo);
372
373 JSHandle<JSTaggedValue> matchResult(thread, matchResults);
374 JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
375 JSHandle<EcmaString> resultZero =
376 thread->GetEcmaVM()->GetFactory()->NewFromASCII("Quick Brown Fox Jumps");
377 JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue());
378 JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
379 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0);
380 }
381
HWTEST_F_L0(BuiltinsRegExpTest,Test1)382 HWTEST_F_L0(BuiltinsRegExpTest, Test1)
383 {
384 // invoke RegExpConstructor method
385 JSHandle<EcmaString> pattern1 =
386 thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)");
387 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
388 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
389 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
390
391 JSHandle<EcmaString> inputString =
392 thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog");
393 std::vector<JSTaggedValue> args{inputString.GetTaggedValue()};
394 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6, value.GetTaggedValue());
395
396 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
397 // invoke Test method
398 JSTaggedValue testResult = BuiltinsRegExp::Test(ecmaRuntimeCallInfo);
399 ASSERT_EQ(testResult.GetRawData(), JSTaggedValue::True().GetRawData());
400 }
401
HWTEST_F_L0(BuiltinsRegExpTest,Search1)402 HWTEST_F_L0(BuiltinsRegExpTest, Search1)
403 {
404 // invoke RegExpConstructor method
405 JSHandle<EcmaString> pattern1 =
406 thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)");
407 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
408 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
409 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
410
411 JSHandle<EcmaString> inputString =
412 thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog");
413 std::vector<JSTaggedValue> args{inputString.GetTaggedValue()};
414 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6, value.GetTaggedValue());
415
416 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
417 // invoke Search method
418 JSTaggedValue searchResult = BuiltinsRegExp::Search(ecmaRuntimeCallInfo);
419 ASSERT_EQ(searchResult.GetRawData(), JSTaggedValue(4).GetRawData());
420 }
421
HWTEST_F_L0(BuiltinsRegExpTest,Split1)422 HWTEST_F_L0(BuiltinsRegExpTest, Split1)
423 {
424 // invoke RegExpConstructor method
425 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("-");
426 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
427 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
428 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
429
430 JSHandle<EcmaString> inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("");
431
432 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
433 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
434 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
435 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
436 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
437
438 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
439 // invoke Split method
440 JSTaggedValue splitResults = BuiltinsRegExp::Split(ecmaRuntimeCallInfo);
441 JSHandle<JSTaggedValue> splitResult(thread, splitResults);
442
443 JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
444 JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue());
445 JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
446
447 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, inputString), 0);
448 }
449
HWTEST_F_L0(BuiltinsRegExpTest,Split2)450 HWTEST_F_L0(BuiltinsRegExpTest, Split2)
451 {
452 // invoke RegExpConstructor method
453 JSHandle<EcmaString> pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("-");
454 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
455 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
456 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
457
458 JSHandle<EcmaString> inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("a-b-c");
459
460 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
461 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
462 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
463 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
464 ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
465
466 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
467 // invoke Split method
468 JSTaggedValue splitResults = BuiltinsRegExp::Split(ecmaRuntimeCallInfo);
469 JSHandle<JSTaggedValue> splitResult(thread, splitResults);
470 JSHandle<EcmaString> resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII("a");
471 JSHandle<EcmaString> resultOne = thread->GetEcmaVM()->GetFactory()->NewFromASCII("b");
472 JSHandle<EcmaString> resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromASCII("c");
473
474 JSHandle<JSTaggedValue> zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0"));
475 JSHandle<JSTaggedValue> zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue());
476 JSHandle<EcmaString> outputZero = JSTaggedValue::ToString(thread, zeroHandle);
477 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0);
478
479 JSHandle<JSTaggedValue> first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"));
480 JSHandle<JSTaggedValue> oneHandle(JSObject::GetProperty(thread, splitResult, first).GetValue());
481 JSHandle<EcmaString> outputOne = JSTaggedValue::ToString(thread, oneHandle);
482 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0);
483
484 JSHandle<JSTaggedValue> second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2"));
485 JSHandle<JSTaggedValue> twoHandle(JSObject::GetProperty(thread, splitResult, second).GetValue());
486 JSHandle<EcmaString> outputTwo = JSTaggedValue::ToString(thread, twoHandle);
487 ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0);
488 }
489
HWTEST_F_L0(BuiltinsRegExpTest,GetSpecies)490 HWTEST_F_L0(BuiltinsRegExpTest, GetSpecies)
491 {
492 // invoke RegExpConstructor method
493 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
494 JSHandle<JSTaggedValue> speciesSymbol = env->GetSpeciesSymbol();
495 EXPECT_TRUE(!speciesSymbol.GetTaggedValue().IsUndefined());
496
497 JSHandle<JSFunction> newTarget(env->GetRegExpFunction());
498
499 JSTaggedValue value =
500 JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(newTarget), speciesSymbol).GetValue().GetTaggedValue();
501 EXPECT_EQ(value, newTarget.GetTaggedValue());
502 }
503
HWTEST_F_L0(BuiltinsRegExpTest,Replace1)504 HWTEST_F_L0(BuiltinsRegExpTest, Replace1)
505 {
506 // invoke RegExpConstructor method
507 JSHandle<EcmaString> pattern1 =
508 thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)");
509 JSHandle<EcmaString> flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug");
510 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
511 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
512
513 JSHandle<EcmaString> inputString =
514 thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog");
515 JSHandle<EcmaString> replaceString =
516 thread->GetEcmaVM()->GetFactory()->NewFromASCII("$&a $` $\' $2 $01 $$1 $21 $32 a");
517 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
518 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
519 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
520 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
521 ecmaRuntimeCallInfo->SetCallArg(1, replaceString.GetTaggedValue());
522
523 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
524 // invoke replace method
525 JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo);
526 JSHandle<JSTaggedValue> replaceResult(thread, results);
527 JSHandle<EcmaString> resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII(
528 "The Quick Brown Fox Jumpsa The Over The Lazy Dog Jumps Brown $1 Jumps1 $32 a Over The Lazy Dog");
529 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(replaceResult), resultZero), 0);
530 }
531
HWTEST_F_L0(BuiltinsRegExpTest,Replace2)532 HWTEST_F_L0(BuiltinsRegExpTest, Replace2)
533 {
534 // invoke RegExpConstructor method
535 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
536 JSHandle<EcmaString> pattern1 = factory->NewFromASCII("b(c)(z)?(.)");
537 JSHandle<EcmaString> flags1 = factory->NewFromASCII("");
538 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
539 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
540
541 JSHandle<EcmaString> inputString = factory->NewFromASCII("abcde");
542 JSHandle<EcmaString> replaceString = factory->NewFromASCII("[$01$02$03$04$00]");
543 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
544 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
545 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
546 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
547 ecmaRuntimeCallInfo->SetCallArg(1, replaceString.GetTaggedValue());
548
549 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
550 // invoke replace method
551 JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo);
552 JSHandle<JSTaggedValue> replaceResult(thread, results);
553 JSHandle<EcmaString> resultZero = factory->NewFromASCII("a[cd$04$00]e");
554 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(replaceResult), resultZero), 0);
555 }
556
HWTEST_F_L0(BuiltinsRegExpTest,Replace3)557 HWTEST_F_L0(BuiltinsRegExpTest, Replace3)
558 {
559 // invoke RegExpConstructor method
560 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
561 JSHandle<EcmaString> pattern1 = factory->NewFromASCII("abc");
562 JSHandle<EcmaString> flags1 = factory->NewFromASCII("g");
563 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
564 JSHandle<JSRegExp> value(thread, reinterpret_cast<JSRegExp *>(result1.GetRawData()));
565
566 JSHandle<EcmaString> inputString = factory->NewFromASCII("abcde");
567 JSHandle<EcmaString> replaceString = factory->NewFromASCII("");
568 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
569 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
570 ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue());
571 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
572 ecmaRuntimeCallInfo->SetCallArg(1, replaceString.GetTaggedValue());
573
574 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
575 // invoke replace method
576 JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo);
577 JSHandle<JSTaggedValue> replaceResult(thread, results);
578 JSHandle<EcmaString> resultZero = factory->NewFromASCII("de");
579 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(replaceResult), resultZero), 0);
580 }
581
HWTEST_F_L0(BuiltinsRegExpTest,RegExpParseCache)582 HWTEST_F_L0(BuiltinsRegExpTest, RegExpParseCache)
583 {
584 RegExpParserCache *regExpParserCache = thread->GetCurrentEcmaContext()->GetRegExpParserCache();
585 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
586 JSHandle<EcmaString> string1 = factory->NewFromASCII("abc");
587 JSHandle<EcmaString> string2 = factory->NewFromASCII("abcd");
588 CVector<CString> vec;
589 regExpParserCache->SetCache(*string1, 0, JSTaggedValue::True(), 2, vec);
590 ASSERT_TRUE(regExpParserCache->GetCache(*string1, 0, vec).first.IsTrue());
591 ASSERT_TRUE(regExpParserCache->GetCache(*string1, 0, vec).second == 2U);
592 ASSERT_TRUE(regExpParserCache->GetCache(*string1,
593 RegExpParserCache::CACHE_SIZE, vec).first.IsHole());
594 ASSERT_TRUE(regExpParserCache->GetCache(*string2, 0, vec).first.IsHole());
595 ASSERT_TRUE(regExpParserCache->GetCache(*string2, UINT32_MAX, vec).first.IsHole());
596 }
597
HWTEST_F_L0(BuiltinsRegExpTest,FlagD)598 HWTEST_F_L0(BuiltinsRegExpTest, FlagD)
599 {
600 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
601 // invoke RegExpConstructor method
602 JSHandle<EcmaString> pattern1 = factory->NewFromASCII("(?<groupname>a)");
603 JSHandle<EcmaString> flags1 = factory->NewFromASCII("gd");
604 JSTaggedValue result1 = TestCommon::CreateJSRegexpByPatternAndFlags(thread, pattern1, flags1);
605 JSHandle<JSTaggedValue> result1Handle(thread, result1);
606
607 // invoke GetFlags method
608 JSHandle<JSTaggedValue> flags(factory->NewFromASCII("flags"));
609 JSHandle<JSTaggedValue> flagsResult(JSObject::GetProperty(thread, result1Handle, flags).GetValue());
610 JSHandle<EcmaString> expectResult = factory->NewFromASCII("dg");
611 ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle<EcmaString>(flagsResult), expectResult), 0);
612
613 // invoke GetHasIndices method
614 JSHandle<JSTaggedValue> hasIndices(factory->NewFromASCII("hasIndices"));
615 JSTaggedValue taggedHasIndicesResult =
616 JSObject::GetProperty(thread, result1Handle, hasIndices).GetValue().GetTaggedValue();
617 ASSERT_EQ(taggedHasIndicesResult.GetRawData(), JSTaggedValue::True().GetRawData());
618
619 JSHandle<EcmaString> inputString = factory->NewFromASCII("babcae");
620 auto ecmaRuntimeCallInfo =
621 TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); // 6 means 1 call arg
622 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
623 ecmaRuntimeCallInfo->SetThis(result1Handle.GetTaggedValue());
624 ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue());
625
626 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
627 // invoke Exec method
628 JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo);
629 TestHelper::TearDownFrame(thread, prev);
630
631 JSHandle<JSTaggedValue> execResult(thread, results);
632 JSHandle<JSTaggedValue> indices(factory->NewFromASCII("indices"));
633 JSHandle<JSTaggedValue> indicesArr = JSObject::GetProperty(thread, execResult, indices).GetValue();
634 EXPECT_TRUE(indicesArr->IsJSArray());
635
636 JSHandle<JSTaggedValue> indices0 = JSObject::GetProperty(thread, indicesArr, 0).GetValue();
637 EXPECT_TRUE(indices0->IsJSArray());
638 // indices[0] [1, 2]
639 EXPECT_EQ(JSObject::GetProperty(thread, indices0, 0).GetValue()->GetInt(), 1);
640 EXPECT_EQ(JSObject::GetProperty(thread, indices0, 1).GetValue()->GetInt(), 2);
641 JSHandle<JSTaggedValue> indices1 = JSObject::GetProperty(thread, indicesArr, 1).GetValue();
642 EXPECT_TRUE(indices1->IsJSArray());
643 // indices[1] [1, 2]
644 EXPECT_EQ(JSObject::GetProperty(thread, indices1, 0).GetValue()->GetInt(), 1);
645 EXPECT_EQ(JSObject::GetProperty(thread, indices1, 1).GetValue()->GetInt(), 2);
646
647 JSHandle<JSTaggedValue> groups(factory->NewFromASCII("groups"));
648 JSHandle<JSTaggedValue> groupsObj = JSObject::GetProperty(thread, indicesArr, groups).GetValue();
649 EXPECT_TRUE(groupsObj->IsJSObject());
650 JSHandle<JSTaggedValue> groupName(factory->NewFromASCII("groupname"));
651 JSHandle<JSTaggedValue> groupNameArr = JSObject::GetProperty(thread, groupsObj, groupName).GetValue();
652 EXPECT_TRUE(groupNameArr->IsJSArray());
653 // {groupname: [1,2]]}
654 EXPECT_EQ(JSObject::GetProperty(thread, groupNameArr, 0).GetValue()->GetInt(), 1);
655 EXPECT_EQ(JSObject::GetProperty(thread, groupNameArr, 1).GetValue()->GetInt(), 2);
656 }
657 } // namespace panda::test
658