Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
REGRESSION(257823@main): named-groups/lookbehind.js Test262-test is f…
…ailing https://bugs.webkit.org/show_bug.cgi?id=249330 rdar://103367993 Reviewed by Yusuke Suzuki. Fixed the case where a nested capturing group within a lookahead / lookbehind doesn't get its capture cleared if the lookaround fails. This has been a long standing issue for lookaheads. The fix is slightly different in the Yarr interpreter than in the Yarr JIT. For the interpreter, the Parenthetical Assertion processing will clear the nested captures within the assertion for the case where an inverted assertion succeeds or a normal assertion fails. For the JIT, the clearing is done at the end of a failed top level alternative for all the contained captures for that alternative. * JSTests/stress/regexp-lookaround-captures.js: Added. (arrayToString): (dumpValue): (compareArray): (testRegExp): (testRegExp.c): * Source/JavaScriptCore/yarr/YarrInterpreter.cpp: (JSC::Yarr::Interpreter::ParenthesesDisjunctionContext::ParenthesesDisjunctionContext): (JSC::Yarr::Interpreter::matchBackReference): (JSC::Yarr::Interpreter::backtrackBackReference): (JSC::Yarr::Interpreter::recordParenthesesMatch): (JSC::Yarr::Interpreter::resetMatches): (JSC::Yarr::Interpreter::matchParenthesesOnceBegin): (JSC::Yarr::Interpreter::matchParenthesesOnceEnd): (JSC::Yarr::Interpreter::backtrackParenthesesOnceBegin): (JSC::Yarr::Interpreter::backtrackParenthesesOnceEnd): (JSC::Yarr::Interpreter::matchParentheticalAssertionEnd): (JSC::Yarr::Interpreter::backtrackParentheticalAssertionEnd): (JSC::Yarr::Interpreter::matchDisjunction): (JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd): (JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd): (JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd): (JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd): (JSC::Yarr::ByteCompiler::emitDisjunction): (JSC::Yarr::ByteTermDumper::dumpTerm): * Source/JavaScriptCore/yarr/YarrInterpreter.h: (JSC::Yarr::ByteTerm::ByteTerm): (JSC::Yarr::ByteTerm::containsAnyCaptures): (JSC::Yarr::ByteTerm::subpatternId): (JSC::Yarr::ByteTerm::lastSubpatternId): * Source/JavaScriptCore/yarr/YarrJIT.cpp: * Source/JavaScriptCore/yarr/YarrParser.h: (JSC::Yarr::Parser::parseTokens): * Source/JavaScriptCore/yarr/YarrPattern.cpp: (JSC::Yarr::YarrPatternConstructor::atomParenthesesSubpatternBegin): (JSC::Yarr::YarrPatternConstructor::atomParentheticalAssertionBegin): (JSC::Yarr::YarrPatternConstructor::copyDisjunction): (JSC::Yarr::YarrPatternConstructor::disjunction): * Source/JavaScriptCore/yarr/YarrPattern.h: (JSC::Yarr::PatternTerm::containsAnyCaptures): (JSC::Yarr::PatternAlternative::PatternAlternative): (JSC::Yarr::PatternAlternative::cleanupCaptures const): (JSC::Yarr::PatternDisjunction::addNewAlternative): * Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp: (JSC::Yarr::SyntaxChecker::disjunction): * Source/WebCore/contentextensions/URLFilterParser.cpp: (WebCore::ContentExtensions::PatternParser::disjunction): Canonical link: https://commits.webkit.org/258195@main
- Loading branch information
Showing
9 changed files
with
206 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// With verbose set to false, this test is successful if there is no output. Set verbose to true to see expected matches. | ||
let verbose = false; | ||
|
||
function arrayToString(arr) | ||
{ | ||
let str = ''; | ||
arr.forEach(function(v, index) { | ||
if (typeof v == "string") | ||
str += "\"" + v + "\""; | ||
else | ||
str += v; | ||
|
||
if (index != (arr.length - 1)) { | ||
str += ','; | ||
}; | ||
}); | ||
return "[" + str + "]"; | ||
} | ||
|
||
function dumpValue(v) | ||
{ | ||
if (v === null) | ||
return "<null>"; | ||
|
||
if (v === undefined) | ||
return "<undefined>"; | ||
|
||
if (typeof v == "string") | ||
return "\"" + v + "\""; | ||
|
||
if (v.length) | ||
return arrayToString(v); | ||
|
||
return v; | ||
} | ||
|
||
function compareArray(a, b) | ||
{ | ||
if (a === null && b === null) | ||
return true; | ||
|
||
if (a === null) { | ||
print("### a is null, b is not null"); | ||
return false; | ||
} | ||
|
||
if (b === null) { | ||
print("### a is not null, b is null"); | ||
return false; | ||
} | ||
|
||
if (a.length !== b.length) { | ||
print("### a.length: " + a.length + ", b.length: " + b.length); | ||
return false; | ||
} | ||
|
||
for (var i = 0; i < a.length; i++) { | ||
if (a[i] !== b[i]) { | ||
print("### a[" + i + "]: \"" + a[i] + "\" !== b[" + i + "]: \"" + b[i] + "\""); | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
let testNumber = 0; | ||
|
||
function testRegExp(re, str, exp) | ||
{ | ||
testNumber++; | ||
|
||
let actual = str.match(re); | ||
|
||
if (compareArray(exp, actual)) { | ||
if (verbose) | ||
print(dumpValue(str) +".match(" + re.toString() + "), passed ", dumpValue(exp)); | ||
} else | ||
print(dumpValue(str) +".match(" + re.toString() + "), FAILED test #" + testNumber + ", Expected ", dumpValue(exp), " got ", dumpValue(actual)); | ||
} | ||
|
||
// Test 1 | ||
testRegExp(/c(?!(\D))|c/u, "abcdef", ["c", undefined]); | ||
testRegExp(/c(?!(\D){3})|c/u, "abcdef", ["c", undefined]); | ||
testRegExp(/c(?=(de)x)|c/u, "abcdef", ["c", undefined]); | ||
testRegExp(/c(?=(def))x|c/u, "abcdef", ["c", undefined]); | ||
testRegExp(/c(?=(def))x|c(?!(def))|c/, "abcdef", ["c", undefined, undefined]); | ||
|
||
// Test 6 | ||
testRegExp(/(?<!(\D{3}))f|f/u, "abcdef", ["f", undefined]); | ||
testRegExp(/(?<!(\D{3}))f/, "abcdef", null); | ||
testRegExp(/(?<!(\D))f/u, "abcdef", null); | ||
testRegExp(/(?<!(\D){3})f/u, "abcdef", null); | ||
testRegExp(/(?<!(\D){3})f|f/u, "abcdef", ["f", undefined]); | ||
|
||
// Test 11 | ||
testRegExp(/(?<=(\w){6})f/, "abcdef", null); | ||
testRegExp(/f(?=(\w{6})})/, "abcdef", null); | ||
testRegExp(/((?<!\D{3}))f|f/u, "abcdef", ["f", undefined]); | ||
testRegExp(/(?<!(\D){3})f/, "abcdef", null); | ||
testRegExp(/(?<!(\d){3})f/, "abcdef", ["f", undefined]); | ||
|
||
// Test 16 | ||
testRegExp(/(?<!(\D){3})f/, "abcdef", null); | ||
testRegExp(/(?<!(\D){3})f|f/, "abcdef", ["f", undefined]); | ||
testRegExp(/((?<!\D{3}))f|f/, "abcdef", ["f", undefined]); | ||
testRegExp(/(?<!(\w{3}))f(?=(\w{3}))|(?<=(\w+?))c(?=(\w{2}))|(?<=(\w{4}))c(?=(\w{3})$)/, "abcdef", ["c",undefined,undefined,"b","de",undefined,undefined]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.