/* * 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" #include "utils/bit_utils.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); } PandaVM *instance {nullptr}; EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; }; JSTaggedValue CreateRegExpObjByPatternAndFlags(JSThread *thread, const JSHandle &pattern, const JSHandle &flags) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regexp(env->GetRegExpFunction()); JSHandle globalObject(thread, env->GetGlobalObject()); // make dyn_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.get()); // invoke RegExpConstructor method JSTaggedValue result = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo.get()); return result; } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor1) { // invoke RegExpConstructor method JSHandle pattern = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("\\w+"); JSHandle flags = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("i"); JSTaggedValue result = CreateRegExpObjByPatternAndFlags(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(static_cast(originalSource->GetTaggedObject())->Compare(*pattern), 0); ASSERT_EQ(static_cast(originalFlags->GetTaggedObject())->Compare(*flags), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor2) { // invoke RegExpConstructor method JSHandle pattern = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("\\w+"); JSHandle flags = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("i"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(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.get()); // invoke RegExpConstructor method JSTaggedValue result2 = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo.get()); // 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(static_cast(originalSource->GetTaggedObject())->Compare(*pattern), 0); ASSERT_EQ(static_cast(originalFlags->GetTaggedObject())->Compare(*flags), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpConstructor3) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("i"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(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()->NewFromCanBeCompressString("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.get()); // invoke RegExpConstructor method JSTaggedValue result2 = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo.get()); // 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(static_cast(originalSource->GetTaggedObject())->Compare(*pattern1), 0); ASSERT_EQ(static_cast(originalFlags->GetTaggedObject())->Compare(*flags2), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSource1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(""); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("i"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); // invoke GetSource method JSHandle source( thread, thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("source").GetTaggedValue()); JSHandle sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue()); JSHandle expect = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("(?:)"); ASSERT_EQ(static_cast(sourceResult->GetTaggedObject())->Compare(*expect), 0); } HWTEST_F_L0(BuiltinsRegExpTest, GetSource2) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("/w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("i"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); // invoke GetSource method JSHandle source(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("source")); JSHandle sourceResult(JSObject::GetProperty(thread, result1Handle, source).GetValue()); JSHandle expect = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("\\/w+"); ASSERT_EQ(static_cast(sourceResult->GetTaggedObject())->Compare(*expect), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Get) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("gimuy"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); JSHandle global(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("global")); JSTaggedValue taggedGlobalResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, global).GetValue().GetTaggedValue()); ASSERT_EQ(taggedGlobalResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle ignoreCase(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("ignoreCase")); JSTaggedValue taggedIgnoreCaseResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, ignoreCase).GetValue().GetTaggedValue()); ASSERT_EQ(taggedIgnoreCaseResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle multiline(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("multiline")); JSTaggedValue taggedMultilineResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, multiline).GetValue().GetTaggedValue()); ASSERT_EQ(taggedMultilineResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle sticky(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("sticky")); JSTaggedValue taggedStickyResult = JSTaggedValue(JSObject::GetProperty(thread, result1Handle, sticky).GetValue().GetTaggedValue()); ASSERT_EQ(taggedStickyResult.GetRawData(), JSTaggedValue::True().GetRawData()); JSHandle unicode(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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()->NewFromCanBeCompressString("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("imuyg"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle result1Handle(thread, result1); // invoke GetFlags method JSHandle flags(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("flags")); JSHandle flagsResult(JSObject::GetProperty(thread, result1Handle, flags).GetValue()); JSHandle expectResult = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("gimuy"); ASSERT_EQ(static_cast(flagsResult->GetTaggedObject())->Compare(*expectResult), 0); } HWTEST_F_L0(BuiltinsRegExpTest, toString) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("\\w+"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("imuyg"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(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.get()); // invoke ToString method JSTaggedValue toStringResult = BuiltinsRegExp::ToString(ecmaRuntimeCallInfo.get()); ASSERT_TRUE(toStringResult.IsString()); JSHandle toStringResultHandle(thread, toStringResult); JSHandle expectResult = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("/\\w+/gimuy"); ASSERT_EQ(static_cast(toStringResultHandle->GetTaggedObject())->Compare(*expectResult), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Exec1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("ig"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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.get()); // invoke Exec method JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo.get()); JSHandle execResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("Quick Brown Fox Jumps"); JSHandle resultOne = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("Brown"); JSHandle resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("Jumps"); JSHandle index(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("index")); JSHandle indexHandle(JSObject::GetProperty(thread, execResult, index).GetValue()); uint32_t resultIndex = JSTaggedValue::ToUint32(thread, indexHandle); ASSERT_TRUE(resultIndex == 4); JSHandle input(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("input")); JSHandle inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue()); JSHandle outputInput = JSTaggedValue::ToString(thread, inputHandle); ASSERT_EQ(outputInput->Compare(*inputString), 0); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(outputZero->Compare(*resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("1")); JSHandle oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); ASSERT_EQ(outputOne->Compare(*resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("2")); JSHandle twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); ASSERT_EQ(outputTwo->Compare(*resultTwo), 0); JSHandle regexp = JSHandle::Cast(value); JSHandle lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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()->NewFromCanBeCompressString("((1)|(12))((3)|(23))"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("ig"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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.get()); // invoke Exec method JSTaggedValue results = BuiltinsRegExp::Exec(ecmaRuntimeCallInfo.get()); JSHandle execResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("123"); JSHandle resultOne = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("1"); JSHandle resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("1"); JSHandle resultFour = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("23"); JSHandle resultSix = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("23"); JSHandle index(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("index")); JSHandle indexHandle(JSObject::GetProperty(thread, execResult, index).GetValue()); uint32_t resultIndex = JSTaggedValue::ToUint32(thread, indexHandle); ASSERT_TRUE(resultIndex == 0); JSHandle input(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("input")); JSHandle inputHandle(JSObject::GetProperty(thread, execResult, input).GetValue()); JSHandle outputInput = JSTaggedValue::ToString(thread, inputHandle); ASSERT_EQ(outputInput->Compare(*inputString), 0); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, execResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(outputZero->Compare(*resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("1")); JSHandle oneHandle(JSObject::GetProperty(thread, execResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); ASSERT_EQ(outputOne->Compare(*resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("2")); JSHandle twoHandle(JSObject::GetProperty(thread, execResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); ASSERT_EQ(outputTwo->Compare(*resultTwo), 0); JSHandle regexp = JSHandle::Cast(value); JSHandle lastIndexHandle(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("lastIndex")); JSHandle lastIndexObj(JSObject::GetProperty(thread, regexp, lastIndexHandle).GetValue()); int lastIndex = lastIndexObj->GetInt(); ASSERT_TRUE(lastIndex == 3); JSHandle third(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("3")); JSHandle thirdHandle(JSObject::GetProperty(thread, execResult, third).GetValue()); ASSERT_TRUE(thirdHandle->IsUndefined()); JSHandle four(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("4")); JSHandle fourHandle(JSObject::GetProperty(thread, execResult, four).GetValue()); JSHandle outputFour = JSTaggedValue::ToString(thread, fourHandle); ASSERT_EQ(outputFour->Compare(*resultFour), 0); JSHandle five(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("5")); JSHandle fiveHandle(JSObject::GetProperty(thread, execResult, five).GetValue()); ASSERT_TRUE(fiveHandle->IsUndefined()); JSHandle six(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("6")); JSHandle sixHandle(JSObject::GetProperty(thread, execResult, six).GetValue()); JSHandle outputSix = JSTaggedValue::ToString(thread, sixHandle); ASSERT_EQ(outputSix->Compare(*resultSix), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Match1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("iug"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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.get()); // invoke Match method JSTaggedValue matchResults = BuiltinsRegExp::Match(ecmaRuntimeCallInfo.get()); JSHandle matchResult(thread, matchResults); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("0")); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("Quick Brown Fox Jumps"); JSHandle zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(outputZero->Compare(*resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Test1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("iug"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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.get()); // invoke Test method JSTaggedValue testResult = BuiltinsRegExp::Test(ecmaRuntimeCallInfo.get()); ASSERT_EQ(testResult.GetRawData(), JSTaggedValue::True().GetRawData()); } HWTEST_F_L0(BuiltinsRegExpTest, Search1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("iug"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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.get()); // invoke Search method JSTaggedValue searchResult = BuiltinsRegExp::Search(ecmaRuntimeCallInfo.get()); ASSERT_EQ(searchResult.GetRawData(), JSTaggedValue(4).GetRawData()); } HWTEST_F_L0(BuiltinsRegExpTest, Split1) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("-"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("iug"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString(""); 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.get()); // invoke Split method JSTaggedValue splitResults = BuiltinsRegExp::Split(ecmaRuntimeCallInfo.get()); JSHandle splitResult(thread, splitResults); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(outputZero->Compare(*inputString), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Split2) { // invoke RegExpConstructor method JSHandle pattern1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("-"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("iug"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("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.get()); // invoke Split method JSTaggedValue splitResults = BuiltinsRegExp::Split(ecmaRuntimeCallInfo.get()); JSHandle splitResult(thread, splitResults); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("a"); JSHandle resultOne = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("b"); JSHandle resultTwo = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("c"); JSHandle zero(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("0")); JSHandle zeroHandle(JSObject::GetProperty(thread, splitResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); ASSERT_EQ(outputZero->Compare(*resultZero), 0); JSHandle first(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("1")); JSHandle oneHandle(JSObject::GetProperty(thread, splitResult, first).GetValue()); JSHandle outputOne = JSTaggedValue::ToString(thread, oneHandle); ASSERT_EQ(outputOne->Compare(*resultOne), 0); JSHandle second(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("2")); JSHandle twoHandle(JSObject::GetProperty(thread, splitResult, second).GetValue()); JSHandle outputTwo = JSTaggedValue::ToString(thread, twoHandle); ASSERT_EQ(outputTwo->Compare(*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()->NewFromCanBeCompressString("quick\\s(brown).+?(jumps)"); JSHandle flags1 = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("iug"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("The Quick Brown Fox Jumps Over The Lazy Dog"); JSHandle replaceString = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("$&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.get()); // invoke replace method JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo.get()); JSHandle replaceResult(thread, results); JSHandle resultZero = thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString( "The Quick Brown Fox Jumpsa The Over The Lazy Dog Jumps Brown $1 Jumps1 $32 a Over The Lazy Dog"); ASSERT_EQ(static_cast(replaceResult->GetTaggedObject())->Compare(*resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Replace2) { // invoke RegExpConstructor method ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle pattern1 = factory->NewFromCanBeCompressString("b(c)(z)?(.)"); JSHandle flags1 = factory->NewFromCanBeCompressString(""); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = factory->NewFromCanBeCompressString("abcde"); JSHandle replaceString = factory->NewFromCanBeCompressString("[$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.get()); // invoke replace method JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo.get()); JSHandle replaceResult(thread, results); JSHandle resultZero = factory->NewFromCanBeCompressString("a[cd$04$00]e"); ASSERT_EQ(static_cast(replaceResult->GetTaggedObject())->Compare(*resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, Replace3) { // invoke RegExpConstructor method ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle pattern1 = factory->NewFromCanBeCompressString("abc"); JSHandle flags1 = factory->NewFromCanBeCompressString("g"); JSTaggedValue result1 = CreateRegExpObjByPatternAndFlags(thread, pattern1, flags1); JSHandle value(thread, reinterpret_cast(result1.GetRawData())); JSHandle inputString = factory->NewFromCanBeCompressString("abcde"); JSHandle replaceString = factory->NewFromCanBeCompressString(""); 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.get()); // invoke replace method JSTaggedValue results = BuiltinsRegExp::Replace(ecmaRuntimeCallInfo.get()); JSHandle replaceResult(thread, results); JSHandle resultZero = factory->NewFromCanBeCompressString("de"); ASSERT_EQ(static_cast(replaceResult->GetTaggedObject())->Compare(*resultZero), 0); } HWTEST_F_L0(BuiltinsRegExpTest, RegExpParseCache) { RegExpParserCache *regExpParserCache = thread->GetEcmaVM()->GetRegExpParserCache(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle string1 = factory->NewFromCanBeCompressString("abc"); JSHandle string2 = factory->NewFromCanBeCompressString("abcd"); regExpParserCache->SetCache(*string1, 0, JSTaggedValue::True(), 2); ASSERT_TRUE(regExpParserCache->GetCache(*string1, 0).first == JSTaggedValue::True()); ASSERT_TRUE(regExpParserCache->GetCache(*string1, 0).second == 2); ASSERT_TRUE(regExpParserCache->GetCache(*string1, RegExpParserCache::CACHE_SIZE).first == JSTaggedValue::Hole()); ASSERT_TRUE(regExpParserCache->GetCache(*string2, 0).first == JSTaggedValue::Hole()); } } // namespace panda::test