blob: 5c30da938bf21a5dc1c9074ede8a6501a3790b9a [file] [log] [blame] [edit]
function shouldBe(actual, expected, msg) {
if (actual !== expected)
throw new Error(`FAIL: ${msg}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
}
function shouldBeArray(actual, expected, msg) {
if (actual === null && expected !== null)
throw new Error(`FAIL: ${msg}: expected ${JSON.stringify(expected)}, got null`);
if (actual === null && expected === null)
return;
if (actual.length !== expected.length)
throw new Error(`FAIL: ${msg}: length mismatch: expected ${expected.length}, got ${actual.length}`);
for (let i = 0; i < expected.length; i++) {
if (actual[i] !== expected[i])
throw new Error(`FAIL: ${msg}: index ${i}: expected ${JSON.stringify(expected[i])}, got ${JSON.stringify(actual[i])}`);
}
}
for (let i = 0; i < testLoopCount; i++) {
shouldBeArray(/(abc)\1/.exec("abcabc"), ["abcabc", "abc"], "basic backref match");
shouldBe(/(abc)\1/.exec("abcdef"), null, "basic backref mismatch");
shouldBe(/(abcd)\1/.exec("abcdabce"), null, "partial backref mismatch");
shouldBeArray(/(\u00e9)\1/u.exec("\u00e9\u00e9"), ["\u00e9\u00e9", "\u00e9"], "unicode BMP backref");
shouldBeArray(/(.)\1/u.exec("\u{1F600}\u{1F600}"), ["\u{1F600}\u{1F600}", "\u{1F600}"], "non-BMP backref match");
shouldBe(/(.)\1/u.exec("\u{1F600}\u{1F601}"), null, "non-BMP backref mismatch");
shouldBeArray(/(.\u0041)\1/u.exec("\u{10000}A\u{10000}A"), ["\u{10000}A\u{10000}A", "\u{10000}A"], "astral+BMP backref");
shouldBeArray(/(a)\1{9}/.exec("aaaaaaaaaa"), ["aaaaaaaaaa", "a"], "quantified backref x10");
shouldBe(/(a)\1{9}/.exec("aaaaaaaab"), null, "quantified backref mismatch at end");
shouldBeArray(/(abc)\1/i.exec("abcABC"), ["abcABC", "abc"], "case-insensitive backref");
shouldBe(/(abc)\1/i.exec("abcDEF"), null, "case-insensitive backref mismatch");
shouldBeArray(/(?:(abc)|(def))\1/.exec("abcabc"), ["abcabc", "abc", undefined], "backref in alternation");
shouldBeArray(/()\1/.exec("abc"), ["", ""], "empty capture backref");
shouldBeArray(/(a)(b)\2\1/.exec("abba"), ["abba", "a", "b"], "multiple backrefs");
shouldBe(/(a)(b)\2\1/.exec("abab"), null, "multiple backrefs mismatch");
shouldBeArray(/(\u{1F600})\1/u.exec("\u{1F600}\u{1F600}"), ["\u{1F600}\u{1F600}", "\u{1F600}"], "unicode emoji backref");
shouldBe(/(abc)\1/.test("abcabc"), true, "test() backref match");
shouldBe(/(abc)\1/.test("abcdef"), false, "test() backref mismatch");
}
{
let highSurrogate = "\uD800";
let input = highSurrogate + "x" + highSurrogate + "x";
for (let i = 0; i < testLoopCount; i++)
shouldBeArray(/(..)\1/.exec(input), [input, highSurrogate + "x"], "lone high surrogate backref");
}
{
let lowSurrogate = "\uDC00";
let input = lowSurrogate + "y" + lowSurrogate + "y";
for (let i = 0; i < testLoopCount; i++)
shouldBeArray(/(..)\1/.exec(input), [input, lowSurrogate + "y"], "lone low surrogate backref");
}
{
let chunk = "abcdefghij";
let input = chunk + chunk;
for (let i = 0; i < testLoopCount; i++)
shouldBeArray(new RegExp("(" + chunk + ")\\1").exec(input), [input, chunk], "long repeated chunk backref");
}