Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| --fast-warmup
function checkStatics(str, m, label) {
assertEq(RegExp.lastMatch, m[0], label + ": lastMatch");
assertEq(RegExp.leftContext, str.slice(0, m.index), label + ": leftContext");
assertEq(RegExp.rightContext, str.slice(m.index + m[0].length),
label + ": rightContext");
assertEq(RegExp.$1, m[1] ?? "", label + ": $1");
assertEq(RegExp.$2, m[2] ?? "", label + ": $2");
assertEq(RegExp.input, str, label + ": input");
}
function lastMatchOf(re, str) {
let last = null;
for (const m of str.matchAll(re)) {
last = m;
}
return last;
}
const outerStr = "a1-b2-c3-d4-e5-f6-g7-h8";
const innerStr = "x9y8z7";
const outerRe = /([a-h])(\d)/g;
const outerLast = lastMatchOf(outerRe, outerStr);
for (let i = 0; i < 200; i++) {
let lastRun = [outerStr, outerLast];
outerStr.replace(outerRe, (m, letter, digit, index) => {
const mine = Object.assign([m, letter, digit], { index });
switch (i % 4) {
case 0: {
const im = /([xyz])(\d)/.exec(innerStr);
checkStatics(innerStr, im, "different input");
lastRun = [innerStr, im];
break;
}
case 1: {
const im = /(\d)-([a-h])/.exec(outerStr);
checkStatics(outerStr, im, "same input, different regexp");
lastRun = [outerStr, im];
break;
}
case 2: {
const re = /([a-h])(\d)/g;
re.lastIndex = index;
const im = re.exec(outerStr);
checkStatics(outerStr, im, "same input and source");
lastRun = [outerStr, im];
break;
}
case 3:
checkStatics(outerStr, mine, "statics read in callback");
break;
}
return "";
});
checkStatics(lastRun[0], lastRun[1], "after replace " + (i % 4));
}
const reA = /([a-h])(\d)/g;
const reB = /(\d)-/g;
for (let i = 0; i < 200; i++) {
reA.lastIndex = 0;
reB.lastIndex = 0;
let ma, mb;
while ((ma = reA.exec(outerStr))) {
checkStatics(outerStr, ma, "interleaved A");
mb = reB.exec(outerStr);
if (mb) {
checkStatics(outerStr, mb, "interleaved B");
}
if (i % 2) {
RegExp.$1;
}
}
}