/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/js_regexp.h" #include "ecmascript/builtins/builtins_regexp.h" #include "ecmascript/ecma_runtime_call_info.h" #include "ecmascript/ecma_string.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/js_thread.h" #include "ecmascript/regexp/regexp_parser_cache.h" #include "ecmascript/object_factory.h" #include "ecmascript/tests/test_helper.h" using namespace panda::ecmascript; using namespace panda::ecmascript::builtins; namespace panda::test { class BuiltinsRegExpTest : public testing::Test { public: static void SetUpTestCase() { GTEST_LOG_(INFO) << "SetUpTestCase"; } static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } void SetUp() override { TestHelper::CreateEcmaVMWithScope(instance, thread, scope); } void TearDown() override { TestHelper::DestroyEcmaVMWithScope(instance, scope); } EcmaVM *instance {nullptr}; EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; }; JSTaggedValue CreateBuiltinsRegExpObjByPatternAndFlags(JSThread *thread, const JSHandle &pattern, const JSHandle &flags) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regexp(env->GetRegExpFunction()); JSHandle globalObject(thread, env->GetGlobalObject()); // make ecma_runtime_call_info // 8 : test case auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*regexp), 8); ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue()); ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, pattern.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, flags.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke RegExpConstructor method JSTaggedValue result = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo); TestHelper::TearDownFrame(thread, prev); return result; } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor1) { // invoke RegExpConstructor method JSHandle pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+"); JSHandle flags = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); JSTaggedValue result = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern, flags); // ASSERT IsRegExp() JSHandle regexpObject(thread, result); ASSERT_TRUE(JSObject::IsRegExp(thread, regexpObject)); JSHandle jsRegexp(thread, JSRegExp::Cast(regexpObject->GetTaggedObject())); JSHandle originalSource(thread, jsRegexp->GetOriginalSource()); uint8_t flagsBits = static_cast(jsRegexp->GetOriginalFlags().GetInt()); JSHandle originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits)); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalSource), pattern), 0); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalFlags), flags), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2) { // invoke RegExpConstructor method JSHandle pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+"); JSHandle flags = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern, flags); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regexp(env->GetRegExpFunction()); JSHandle globalObject(thread, env->GetGlobalObject()); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*regexp), 8); ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue()); ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke RegExpConstructor method JSTaggedValue result2 = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo); TestHelper::TearDownFrame(thread, prev); // ASSERT IsRegExp() JSHandle regexpObject(thread, result2); ASSERT_TRUE(JSObject::IsRegExp(thread, regexpObject)); JSHandle jsRegexp(thread, JSRegExp::Cast(regexpObject->GetTaggedObject())); JSHandle originalSource(thread, jsRegexp->GetOriginalSource()); uint8_t flagsBits = static_cast(jsRegexp->GetOriginalFlags().GetInt()); JSHandle originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits)); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalSource), pattern), 0); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalFlags), flags), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regexp(env->GetRegExpFunction()); JSHandle globalObject(thread, env->GetGlobalObject()); JSHandle flags2 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gi"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*regexp), 8); ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue()); ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, flags2.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke RegExpConstructor method JSTaggedValue result2 = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo); // ASSERT IsRegExp() JSHandle regexpObject(thread, result2); ASSERT_TRUE(JSObject::IsRegExp(thread, regexpObject)); JSHandle jsRegexp(thread, JSRegExp::Cast(regexpObject->GetTaggedObject())); JSHandle originalSource(thread, jsRegexp->GetOriginalSource()); uint8_t flagsBits = static_cast(jsRegexp->GetOriginalFlags().GetInt()); JSHandle originalFlags(thread, BuiltinsRegExp::FlagsBitsToString(thread, flagsBits)); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalSource), pattern1), 0); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(originalFlags), flags2), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSource1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII(""); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); // invoke GetSource method JSHandle source( thread, thread->GetEcmaVM()->GetFactory()->NewFromASCII("source").GetTaggedValue()); JSHandle sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue()); JSHandle expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("(?:)"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(sourceResult), expect), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSource2) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("/w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); // invoke GetSource method JSHandle source(thread->GetEcmaVM()->GetFactory()->NewFromASCII("source")); JSHandle sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue()); JSHandle expect = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\/w+"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(sourceResult), expect), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Get) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gimuy"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); JSHandle global(thread->GetEcmaVM()->GetFactory()->NewFromASCII("global")); JSTaggedValue taggedGlobalResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, global).GetValue().GetTaggedValue()); ASSERT_EQ(taggedGlobalResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle ignoreCase(thread->GetEcmaVM()->GetFactory()->NewFromASCII("ignoreCase")); JSTaggedValue taggedIgnoreCaseResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, ignoreCase).GetValue().GetTaggedValue()); ASSERT_EQ(taggedIgnoreCaseResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle multiline(thread->GetEcmaVM()->GetFactory()->NewFromASCII("multiline")); JSTaggedValue taggedMultilineResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, multiline).GetValue().GetTaggedValue()); ASSERT_EQ(taggedMultilineResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle sticky(thread->GetEcmaVM()->GetFactory()->NewFromASCII("sticky")); JSTaggedValue taggedStickyResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, sticky).GetValue().GetTaggedValue()); ASSERT_EQ(taggedStickyResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle unicode(thread->GetEcmaVM()->GetFactory()->NewFromASCII("unicode")); JSTaggedValue taggedUnicodeResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, unicode).GetValue().GetTaggedValue()); ASSERT_EQ(taggedUnicodeResult.GetRawData(), JSTaggedValue::True().GetRawData()); } HWTEST_F_L0(BuiltinsRegExpTest, GetFlags) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("imuyg"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); // invoke GetFlags method JSHandle flags(thread->GetEcmaVM()->GetFactory()->NewFromASCII("flags")); JSHandle flagsResult(JSObject::GetProperty(thread, result1Handle, flags).GetValue()); JSHandle expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("gimuy"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(flagsResult), expectResult), 0); } HWTEST_F_L0(BuiltinsRegExpTest, toString) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("imuyg"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke ToString method JSTaggedValue toStringResult = BuiltinsRegExp::ToString(ecmaRuntimeCallInfo); ASSERT_TRUE(toStringResult.IsString()); JSHandle toStringResultHandle(thread, toStringResult); JSHandle expectResult = thread->GetEcmaVM()->GetFactory()->NewFromASCII("/\\w+/gimuy"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(toStringResultHandle), expectResult), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Exec1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("ig"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Exec method JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo); JSHandle execResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII("Quick Brown Fox Jumps"); JSHandle resultOne = thread->GetEcmaVM()->GetFactory()->NewFromASCII("Brown"); JSHandle resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromASCII("Jumps"); JSHandle index(thread->GetEcmaVM()->GetFactory()->NewFromASCII("index")); JSHandle indexHandle(JSObject::GetProperty(thread, execResult, index).GetValue()); uint32_t resultIndex = JSTaggedValue::ToUint32(thread, indexHandle); ASSERT_TRUE(resultIndex == 4U); JSHandle input(thread->GetEcmaVM()->GetFactory()->NewFromASCII("input")); JSHandle inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue()); JSHandle outputInput = JSTaggedValue::ToString(thread, inputHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1")); JSHandle oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2")); JSHandle twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0); JSHandle regexp = JSHandle::Cast(value); JSHandle lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex")); JSHandle lastIndexObj(JSObject::GetProperty(thread, regexp, lastIndexHandle).GetValue()); int lastIndex = lastIndexObj->GetInt(); ASSERT_TRUE(lastIndex == 25); } HWTEST_F_L0(BuiltinsRegExpTest, Exec2) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("((1)|(12))((3)|(23))"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("ig"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("123"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Exec method JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo); JSHandle execResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII("123"); JSHandle resultOne = thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"); JSHandle resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromASCII("1"); JSHandle resultFour = thread->GetEcmaVM()->GetFactory()->NewFromASCII("23"); JSHandle resultSix = thread->GetEcmaVM()->GetFactory()->NewFromASCII("23"); JSHandle index(thread->GetEcmaVM()->GetFactory()->NewFromASCII("index")); JSHandle indexHandle(JSObject::GetProperty(thread, execResult, index).GetValue()); uint32_t resultIndex = JSTaggedValue::ToUint32(thread, indexHandle); ASSERT_TRUE(resultIndex == 0U); JSHandle input(thread->GetEcmaVM()->GetFactory()->NewFromASCII("input")); JSHandle inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue()); JSHandle outputInput = JSTaggedValue::ToString(thread, inputHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputInput, inputString), 0); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1")); JSHandle oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2")); JSHandle twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0); JSHandle regexp = JSHandle::Cast(value); JSHandle lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromASCII("lastIndex")); JSHandle lastIndexObj(JSObject::GetProperty(thread, regexp, lastIndexHandle).GetValue()); int lastIndex = lastIndexObj->GetInt(); ASSERT_TRUE(lastIndex == 3); JSHandle third(thread->GetEcmaVM()->GetFactory()->NewFromASCII("3")); JSHandle thirdHandle(JSObject::GetProperty(thread, execResult, third).GetValue()); ASSERT_TRUE(thirdHandle->IsUndefined()); JSHandle four(thread->GetEcmaVM()->GetFactory()->NewFromASCII("4")); JSHandle fourHandle(JSObject::GetProperty(thread, execResult, four).GetValue()); JSHandle outputFour = JSTaggedValue::ToString(thread, fourHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputFour, resultFour), 0); JSHandle five(thread->GetEcmaVM()->GetFactory()->NewFromASCII("5")); JSHandle fiveHandle(JSObject::GetProperty(thread, execResult, five).GetValue()); ASSERT_TRUE(fiveHandle->IsUndefined()); JSHandle six(thread->GetEcmaVM()->GetFactory()->NewFromASCII("6")); JSHandle sixHandle(JSObject::GetProperty(thread, execResult, six).GetValue()); JSHandle outputSix = JSTaggedValue::ToString(thread, sixHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputSix, resultSix), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Match1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Match method JSTaggedValue matchResults = BuiltinsRegExp::Match(ecmaRuntimeCallInfo); JSHandle matchResult(thread, matchResults); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII("Quick Brown Fox Jumps"); JSHandle zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Test1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Test method JSTaggedValue testResult = BuiltinsRegExp::Test(ecmaRuntimeCallInfo); ASSERT_EQ(testResult.GetRawData(), JSTaggedValue::True().GetRawData()); } HWTEST_F_L0(BuiltinsRegExpTest, Search1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Search method JSTaggedValue searchResult = BuiltinsRegExp::Search(ecmaRuntimeCallInfo); ASSERT_EQ(searchResult.GetRawData(), JSTaggedValue(4).GetRawData()); } HWTEST_F_L0(BuiltinsRegExpTest, Split1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("-"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(""); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Split method JSTaggedValue splitResults = BuiltinsRegExp::Split(ecmaRuntimeCallInfo); JSHandle splitResult(thread, splitResults); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, inputString), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Split2) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("-"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("a-b-c"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke Split method JSTaggedValue splitResults = BuiltinsRegExp::Split(ecmaRuntimeCallInfo); JSHandle splitResult(thread, splitResults); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII("a"); JSHandle resultOne = thread->GetEcmaVM()->GetFactory()->NewFromASCII("b"); JSHandle resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromASCII("c"); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromASCII("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputZero, resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromASCII("1")); JSHandle oneHandle(JSObject::GetProperty(thread, splitResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputOne, resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromASCII("2")); JSHandle twoHandle(JSObject::GetProperty(thread, splitResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); ASSERT_EQ(EcmaStringAccessor::Compare(instance, outputTwo, resultTwo), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSpecies) { // invoke RegExpConstructor method JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle speciesSymbol = env->GetSpeciesSymbol(); EXPECT_TRUE(!speciesSymbol.GetTaggedValue().IsUndefined()); JSHandle newTarget(env->GetRegExpFunction()); JSTaggedValue value = JSObject::GetProperty(thread, JSHandle(newTarget), speciesSymbol).GetValue().GetTaggedValue(); EXPECT_EQ(value, newTarget.GetTaggedValue()); } HWTEST_F_L0(BuiltinsRegExpTest, Replace1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromASCII("iug"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("The Quick Brown Fox Jumps Over The Lazy Dog"); JSHandle replaceString = thread->GetEcmaVM()->GetFactory()->NewFromASCII("$&a $` $\' $2 $01 $$1 $21 $32 a"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, replaceString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke replace method JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo); JSHandle replaceResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromASCII( "The Quick Brown Fox Jumpsa The Over The Lazy Dog Jumps Brown $1 Jumps1 $32 a Over The Lazy Dog"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(replaceResult), resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Replace2) { // invoke RegExpConstructor method ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle pattern1 = factory->NewFromASCII("b(c)(z)?(.)"); JSHandle flags1 = factory->NewFromASCII(""); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = factory->NewFromASCII("abcde"); JSHandle replaceString = factory->NewFromASCII("[$01$02$03$04$00]"); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, replaceString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke replace method JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo); JSHandle replaceResult(thread, results); JSHandle resultZero = factory->NewFromASCII("a[cd$04$00]e"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(replaceResult), resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Replace3) { // invoke RegExpConstructor method ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle pattern1 = factory->NewFromASCII("abc"); JSHandle flags1 = factory->NewFromASCII("g"); JSTaggedValue result1 = CreateBuiltinsRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = factory->NewFromASCII("abcde"); JSHandle replaceString = factory->NewFromASCII(""); auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo->SetThis(value.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, inputString.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, replaceString.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // invoke replace method JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo); JSHandle replaceResult(thread, results); JSHandle resultZero = factory->NewFromASCII("de"); ASSERT_EQ(EcmaStringAccessor::Compare(instance, JSHandle(replaceResult), resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpParseCache) { RegExpParserCache *regExpParserCache = thread->GetCurrentEcmaContext()->GetRegExpParserCache(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle string1 = factory->NewFromASCII("abc"); JSHandle string2 = factory->NewFromASCII("abcd"); CVector vec; regExpParserCache->SetCache(*string1, 0, JSTaggedValue::True(), 2, vec); ASSERT_TRUE(regExpParserCache->GetCache(*string1, 0, vec).first.IsTrue()); ASSERT_TRUE(regExpParserCache->GetCache(*string1, 0, vec).second == 2U); ASSERT_TRUE(regExpParserCache->GetCache(*string1, RegExpParserCache::CACHE_SIZE, vec).first.IsHole()); ASSERT_TRUE(regExpParserCache->GetCache(*string2, 0, vec).first.IsHole()); } } // namespace panda::test