Skip to content

Commit

Permalink
Fix String#split and another RegExp#lastIndex case in IE8
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Nov 13, 2018
1 parent 5bd11fc commit b8f73b1
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 13 deletions.
27 changes: 16 additions & 11 deletions packages/core-js/internals/regexp-exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ var nativeReplace = String.prototype.replace;
var patchedExec = nativeExec;

var LAST_INDEX = 'lastIndex';

var UPDATES_LAST_INDEX_NON_GLOBAL = (function () {
var re = /a/;
nativeExec.call(re, 'a');
return re[LAST_INDEX] !== 0;
var LENGTH = 'length';

var UPDATES_LAST_INDEX_WRONG = (function () {
var re1 = /a/,
re2 = /b*/g;
nativeExec.call(re1, 'a');
nativeExec.call(re2, 'a');
return re1[LAST_INDEX] !== 0 || re2[LAST_INDEX] !== 0;
})();

// nonparticipating capturing group, copied from es5-shim's String#split patch.
var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;

var patch = UPDATES_LAST_INDEX_NON_GLOBAL || NPCG_INCLUDED;
var patch = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED;

if (patch) {
patchedExec = function exec(str) {
Expand All @@ -31,17 +34,19 @@ if (patch) {
if (NPCG_INCLUDED) {
reCopy = new RegExp('^' + re.source + '$(?!\\s)', regexpFlags.call(re));
}
if (UPDATES_LAST_INDEX_NON_GLOBAL) lastIndex = this[LAST_INDEX];
if (UPDATES_LAST_INDEX_WRONG) lastIndex = re[LAST_INDEX];

match = nativeExec.call(this, str);
match = nativeExec.call(re, str);

if (UPDATES_LAST_INDEX_NON_GLOBAL && !this.global) this[LAST_INDEX] = lastIndex;
if (NPCG_INCLUDED && match && match.length > 1) {
if (UPDATES_LAST_INDEX_WRONG && match) {
re[LAST_INDEX] = re.global ? match.index + match[0][LENGTH] : lastIndex;
}
if (NPCG_INCLUDED && match && match[LENGTH] > 1) {
// Fix browsers whose `exec` methods don't consistently return `undefined`
// for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
// eslint-disable-next-line no-loop-func
nativeReplace.call(match[0], reCopy, function () {
for (i = 1; i < arguments.length - 2; i++) {
for (i = 1; i < arguments[LENGTH] - 2; i++) {
if (arguments[i] === undefined) match[i] = undefined;
}
});
Expand Down
3 changes: 1 addition & 2 deletions packages/core-js/modules/es.string.split.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ require('../internals/fix-regexp-well-known-symbol-logic')(
var separatorCopy = new RegExp(separator.source, flags + 'g');
var match, lastIndex, lastLength;
while (match = regexpExec.impl.call(separatorCopy, string)) {
// `separatorCopy.lastIndex` is not reliable cross-browser
lastIndex = match.index + match[0][LENGTH];
lastIndex = separatorCopy.lastIndex;
if (lastIndex > lastLastIndex) {
output.push(string.slice(lastLastIndex, match.index));
if (match[LENGTH] > 1 && match.index < string[LENGTH]) arrayPush.apply(output, match.slice(1));
Expand Down
8 changes: 8 additions & 0 deletions tests/tests/es.regexp.exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ QUnit.test('RegExp#exec lastIndex updating', assert => {
assert.strictEqual(re.lastIndex, 0, '.lastIndex starts at 0 for global regexps');
re.exec('abc');
assert.strictEqual(re.lastIndex, 2, '.lastIndex is updated for global regexps');

re = /b*/;
re.exec('a');
assert.strictEqual(re.lastIndex, 0, '.lastIndex isn\'t updated for non-global regexps if the match is empty');

re = /b*/g;
re.exec('a');
assert.strictEqual(re.lastIndex, 0, '.lastIndex isn\'t updated for global regexps if the match is empty');
});

QUnit.test('RegExp#exec capturing groups', assert => {
Expand Down

0 comments on commit b8f73b1

Please sign in to comment.