From 27d3de1f17058da3cfef56d241797a22e337e975 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 5 Feb 2022 09:12:43 -0500 Subject: [PATCH] LibRegex: Do not continue searching input when the sticky bit is set This partially reverts commit a962ee020a6310b2d7c7479aa058c15484127418. When the sticky bit is set, the global bit should basically be ignored except by external callers who want their own special behavior. For example, RegExp.prototype [ @@match ] will use the global flag to accumulate consecutive matches. But on the first failure, the regex loop should break. --- .../LibJS/Tests/builtins/String/String.prototype.match.js | 8 ++++++++ Userland/Libraries/LibRegex/RegexMatcher.cpp | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.match.js b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.match.js index 859fd94b1e..137d28f9ec 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.match.js +++ b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.match.js @@ -70,3 +70,11 @@ test("escaped code points", () => { expect(string.match(re).groups.𝓑𝓻𝓸𝔀𝓷).toBe("brown"); expect(string.match(re).groups.𝓑𝓻𝓸𝔀𝓷).toBe("brown"); }); + +test("sticky and global flag set", () => { + const string = "aaba"; + expect(string.match(/a/)).toEqual(["a"]); + expect(string.match(/a/y)).toEqual(["a"]); + expect(string.match(/a/g)).toEqual(["a", "a", "a"]); + expect(string.match(/a/gy)).toEqual(["a", "a"]); +}); diff --git a/Userland/Libraries/LibRegex/RegexMatcher.cpp b/Userland/Libraries/LibRegex/RegexMatcher.cpp index bcb89b8470..a1f3dfe4d5 100644 --- a/Userland/Libraries/LibRegex/RegexMatcher.cpp +++ b/Userland/Libraries/LibRegex/RegexMatcher.cpp @@ -180,6 +180,8 @@ 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::Sticky)) + continue_search = false; auto single_match_only = input.regex_options.has_flag_set(AllFlags::SingleMatch); @@ -280,7 +282,11 @@ RegexResult Matcher::match(Vector const& views, Optiona break; continue; } - if (state.string_position < view_length && !input.regex_options.has_flag_set(AllFlags::Internal_Stateful)) { + if (input.regex_options.has_flag_set(AllFlags::Internal_Stateful)) { + append_match(input, state, view_index); + break; + } + if (state.string_position < view_length) { return { false, 0, {}, {}, {}, operations }; }