Commit 3f8b2aeb authored by jgruber's avatar jgruber Committed by Commit bot

[regexp] Fix numbered reference before named capture

Numbered back-references that occur before the referenced capture
trigger an internal mini-parser that looks ahead in the pattern and
counts capturing groups.

This updates the mini-parser to correctly handle named captures.

BUG=v8:5437

Review-Url: https://codereview.chromium.org/2792523002
Cr-Commit-Position: refs/heads/master@{#44303}
parent d6bd3eba
......@@ -680,7 +680,25 @@ void RegExpParser::ScanForCaptures() {
break;
}
case '(':
if (current() != '?') capture_count++;
if (current() == '?') {
// At this point we could be in
// * a non-capturing group '(:',
// * a lookbehind assertion '(?<=' '(?<!'
// * or a named capture '(?<'.
//
// Of these, only named captures are capturing groups.
if (!FLAG_harmony_regexp_named_captures) break;
Advance();
if (current() != '<') break;
// TODO(jgruber): To be more future-proof we could test for
// IdentifierStart here once it becomes clear whether group names
// allow unicode escapes.
Advance();
if (current() == '=' || current() == '!') break;
}
capture_count++;
break;
}
}
......
......@@ -124,6 +124,12 @@ assertEquals(["fst", "snd"],
assertEquals(undefined, /(?<a>.)/u.exec("a").groups.__proto__);
assertEquals("a", /(?<__proto__>a)/u.exec("a").groups.__proto__);
// Backreference before the group (exercises the capture mini-parser).
assertThrows("/\\1(?:.)/u", SyntaxError);
assertThrows("/\\1(?<=a)./u", SyntaxError);
assertThrows("/\\1(?<!a)./u", SyntaxError);
assertEquals(["a", "a"], /\1(?<a>.)/u.exec("abcd"));
// @@replace with a callable replacement argument (no named captures).
{
let result = "abcd".replace(/(.)(.)/u, (match, fst, snd, offset, str) => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment