Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

regex lastIndex #403

Open
espretto opened this issue Jun 13, 2016 · 5 comments
Open

regex lastIndex #403

espretto opened this issue Jun 13, 2016 · 5 comments

Comments

@espretto
Copy link

the regex lastIndex bug seems to persist although es5shim is included.

var empty = ''
var re = /.*/g
re.exec(empty)
re.lastIndex === 0 // false in IE6

I've seen this is being worked around to patch String#replace but RegExp#exec is none the wiser.

@ljharb
Copy link
Member

ljharb commented Jun 13, 2016

Indeed, I see that in IE 6, 7, and 8, var re = /.*/g; alert(re.lastIndex); re.exec(''); alert(re.lastIndex); alerts 0/1, whereas in IE 9 and everything else, it alerts 0/0.

I'll look into this; thanks for the report!

@ljharb
Copy link
Member

ljharb commented Jun 15, 2016

@espretto where do you see this being worked around with String#replace? We're only patching it if the function form reports capture groups incorrectly.

@espretto
Copy link
Author

espretto commented Jun 15, 2016

my mistake, it wasn't String#replace but String#split when using regular expressions. here you can find the exact line: lastIndex = match.index + match[0].length. I cannot attest whether it's the same bug being worked around though.

@ljharb
Copy link
Member

ljharb commented Jun 15, 2016

Thanks, I'll see what I can do.

This seems like it's only a bug when exec is given an empty string, no?

@espretto
Copy link
Author

espretto commented Jun 16, 2016

unfortunately, i've seen this bug occur on non-empty strings, too. i think the question is whether or not the regex matches zero or more of something. for example this yields different results, too:

var re = /[a-z]*/g
re.lastIndex = 1
re.exec('s')
re.lastIndex === 2 // in IE6, expected empty string match at pos 1 instead
re.lastIndex = 1
re.exec('s1')
re.lastIndex === 2 // in IE6, expected empty string match at pos 1 instead

for a patch i'm thinking (not tested):

var hasLastIndexBug = (function () {
  var re = /.*/g
  re.exec('')
  return re.lastIndex !== 0
}())

if (hasLastIndexBug) {
  var nativeExec = RegExp.prototype.exec
  RegExp.prototype.exec = function exec (string) {
    var match = nativeExec.call(this, string)
    if (match && !match[0].length) this.lastIndex--
    /* or alternatively
    if (match && !match[0].length) this.lastIndex = match.index
     * or most explicit
    if (match && !match[0].length) this.lastIndex = match.index + match[0].length
     */
    return match
  }
}

it seems the state-machine forgets to reset its look-ahead pointer before it bails out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants