diff --git a/packages/core-js/internals/regexp-exec.js b/packages/core-js/internals/regexp-exec.js index a9a0c57ff851..9eae2c437b4e 100644 --- a/packages/core-js/internals/regexp-exec.js +++ b/packages/core-js/internals/regexp-exec.js @@ -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) { @@ -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; } }); diff --git a/packages/core-js/modules/es.string.split.js b/packages/core-js/modules/es.string.split.js index 23d56a372bb3..878219225c08 100644 --- a/packages/core-js/modules/es.string.split.js +++ b/packages/core-js/modules/es.string.split.js @@ -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)); diff --git a/tests/tests/es.regexp.exec.js b/tests/tests/es.regexp.exec.js index fc3a9e8f17df..fd9222a01373 100644 --- a/tests/tests/es.regexp.exec.js +++ b/tests/tests/es.regexp.exec.js @@ -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 => {