archives

« Bugzilla Issues Index

#1467 — 15.10.6.11/15.10.6.12: RegExp.prototype.{match, replace} algorithm is wrong for empty matches


From ES3, 15.5.4.10 String.prototype.match:
> Set the regexp.lastIndex property to 0 and invoke RegExp.prototype.exec
> repeatedly until there is no match. If there is a match with an empty
> string (in other words, if the value of regexp.lastIndex is left unchanged),
> increment regexp.lastIndex by 1.

The part `(in other words, if the value of regexp.lastIndex is left unchanged)` is actually wrong. Nevertheless, this part was carried over to ES5/5.1 and eventually also into the current ES6 draft. See 15.10.6.11, step 10.g.iv.3.

These are the expected results from RegExp.prototype.match:
js> matchWithLength(/^|$/g, "aa")
["", ""]
js> matchWithLength(/\b/g, "aa aa")
["", "", "", ""]

These are results with the currently specified algorithm:
js> matchWithLastIndex(/^|$/g, "aa")
["", "", ""]
js> matchWithLastIndex(/\b/g, "aa aa")
["", "", "", "", "", ""]

RegExp.prototype.match as expected:
----
function matchWithLength(re,s) {
re.lastIndex = 0;
var a = [];
for (;;) {
var r = re.exec(s);
if (!r) break;
a.push(r[0]);
if (r[0].length === 0)
re.lastIndex = re.lastIndex + 1;
}
return a;
}
----

RegExp.prototype.match as currently specified:
----
function matchWithLastIndex(re, s) {
re.lastIndex = 0;
var a = [];
var prev = 0;
for(;;) {
var r = re.exec(s);
if (!r) break;
a.push(r[0]);
if (re.lastIndex === prev)
re.lastIndex = re.lastIndex + 1;
prev = re.lastIndex
}
return a;
}
----


need to confirm that "expected" results matches current browsers reality


Still present in new RegExp.prototype.replace implementation.

Test case:
---
"aa".replace(/^|$/g, "bb")
---

Expected: "bbaabb"
Actual: "bbaabbbb"

Tested in: V8, IE11, JSC, SpiderMonkey, Nashorn


fixed in rev30 editor's draft

also added an item to Annex D.


fixed in rev30