diff --git a/Tests/LibRegex/Regex.cpp b/Tests/LibRegex/Regex.cpp index 2e498811b5..c7e699c194 100644 --- a/Tests/LibRegex/Regex.cpp +++ b/Tests/LibRegex/Regex.cpp @@ -984,7 +984,9 @@ TEST_CASE(negative_lookahead) { { // Negative lookahead with more than 2 forks difference between lookahead init and finish. - Regex re(":(?!\\^\\)|1)", ECMAScriptFlags::Global); + auto options = ECMAScriptOptions { ECMAScriptFlags::Global }; + options.reset_flag((ECMAScriptFlags)regex::AllFlags::Internal_Stateful); + Regex re(":(?!\\^\\)|1)", options); EXPECT_EQ(re.match(":^)").success, false); EXPECT_EQ(re.match(":1").success, false); EXPECT_EQ(re.match(":foobar").success, true); diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp index ab09999815..5a58afbd02 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp @@ -208,46 +208,36 @@ static ThrowCompletionOr regexp_builtin_exec(GlobalObject& global_object, RegexResult result; + // NOTE: For optimisation purposes, this whole loop is implemented in LibRegex. // 12. Let matchSucceeded be false. // 13. Let Input be a List consisting of all of the characters, in order, of S. If fullUnicode is true, each character is a code unit, otherwise each character is a code point. - // 14. Repeat, while matchSucceeded is false, - while (true) { - // a. If lastIndex > length, then - if (last_index > string.length_in_code_units()) { - // i. If global is true or sticky is true, then - if (global || sticky) { - // 1. Perform ? Set(R, "lastIndex", +0𝔽, true). - TRY(regexp_object.set(vm.names.lastIndex, Value(0), Object::ShouldThrowExceptions::Yes)); - } + // 14. Repeat, while matchSucceeded is false + // a. If lastIndex > length, then + // i. If global is true or sticky is true, then + // 1. Perform ? Set(R, "lastIndex", 0, true). + // ii. Return null. + // b. Let r be matcher(Input, lastIndex). + // c. If r is failure, then + // i. If sticky is true, then + // 1. Perform ? Set(R, "lastIndex", 0, true). + // 2. Return null. + // ii. Set lastIndex to AdvanceStringIndex(S, lastIndex, fullUnicode). + // d. Else, + // i. Assert: r is a State. + // ii. Set matchSucceeded to true. - // ii. Return null. - return js_null(); - } + // 14.b + regex.start_offset = full_unicode ? string.view().code_point_offset_of(last_index) : last_index; + result = regex.match(string.view()); - // b. Let r be matcher(Input, lastIndex). - regex.start_offset = full_unicode ? string.view().code_point_offset_of(last_index) : last_index; - result = regex.match(string.view()); + // 14.c and 14.a + if (!result.success) { + // 14.c.i, 14.a.i + if (sticky || global) + TRY(regexp_object.set(vm.names.lastIndex, Value(0), Object::ShouldThrowExceptions::Yes)); - // c. If r is failure, then - if (!result.success) { - // i. If sticky is true, then - if (sticky) { - // 1. Perform ? Set(R, "lastIndex", +0𝔽, true). - TRY(regexp_object.set(vm.names.lastIndex, Value(0), Object::ShouldThrowExceptions::Yes)); - - // 2. Return null. - return js_null(); - } - - // ii. Set lastIndex to AdvanceStringIndex(S, lastIndex, fullUnicode). - last_index = advance_string_index(string.view(), last_index, full_unicode); - } - // d. Else, - else { - // i. Assert: r is a State. - // ii. Set matchSucceeded to true. - break; - } + // 14.a.ii, 14.c.i.2 + return js_null(); } auto& match = result.matches[0]; diff --git a/Userland/Libraries/LibRegex/RegexMatcher.cpp b/Userland/Libraries/LibRegex/RegexMatcher.cpp index baa3c6490a..bcb89b8470 100644 --- a/Userland/Libraries/LibRegex/RegexMatcher.cpp +++ b/Userland/Libraries/LibRegex/RegexMatcher.cpp @@ -180,8 +180,6 @@ RegexResult Matcher::match(Vector const& views, Optiona #endif bool continue_search = input.regex_options.has_flag_set(AllFlags::Global) || input.regex_options.has_flag_set(AllFlags::Multiline); - if (input.regex_options.has_flag_set(AllFlags::Internal_Stateful)) - continue_search = false; auto single_match_only = input.regex_options.has_flag_set(AllFlags::SingleMatch); @@ -282,11 +280,7 @@ RegexResult Matcher::match(Vector const& views, Optiona break; continue; } - if (input.regex_options.has_flag_set(AllFlags::Internal_Stateful)) { - append_match(input, state, view_index); - break; - } - if (state.string_position < view_length) { + if (state.string_position < view_length && !input.regex_options.has_flag_set(AllFlags::Internal_Stateful)) { return { false, 0, {}, {}, {}, operations }; } @@ -503,8 +497,6 @@ Optional Matcher::execute(MatchInput const& input, MatchState& sta return false; case ExecutionResult::Failed_ExecuteLowPrioForks: { if (states_to_try_next.is_empty()) { - if (input.regex_options.has_flag_set(AllFlags::Internal_Stateful)) - return {}; return false; } state = states_to_try_next.take_last();