Skip to content

Commit

Permalink
es5-shim: fix groups with quantifiers preventing its exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
elitvyakov authored and ljharb committed Nov 24, 2016
1 parent d855953 commit e44022d
Showing 1 changed file with 80 additions and 7 deletions.
87 changes: 80 additions & 7 deletions es5-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -1921,20 +1921,93 @@
}());

if (!replaceReportsGroupsCorrectly) {
/**
* @param regexp {RegExp}
* @returns {Object[]} groups
* @return {number} groups[].number - The number of group.
* @return {boolean} groups[].mayBeMissing - The group with quantifiers preventing its exercise, the matched text
* for a capturing group is now undefined instead of an empty string.
* The group without quantifiers, may be empty string.
* @return {boolean} groups[].isResulting - The groups with ?:, ?=, ?! are non-capturing groups.
*/
var getExtendedGroups = function getExtendedGroups(regexp) {
var source = regexp.source;
var result = [];
var groupNumberCounter = 0;

for (var charIndex in source) {
var char = source[+charIndex];
var prevFirst = source[+charIndex - 1] || null;
var nextFirst = source[+charIndex + 1] || null;
var nextSecond = source[+charIndex + 2] || null;

if (char === '(') {
if (prevFirst && prevFirst === '\\') {
continue;
}

if (
nextFirst && nextFirst === '?' && nextSecond && nextSecond === ':'
|| nextFirst && nextFirst === '?' && nextSecond && nextSecond === '='
|| nextFirst && nextFirst === '?' && nextSecond && nextSecond === '!'
) {
groupNumberCounter += 1;
result.push({
number: groupNumberCounter,
mayBeMissing: true,
isResulting: false
});
continue;
}

result.push({
number: ++groupNumberCounter,
mayBeMissing: false,
isResulting: true
});
}

if (char === ')') {
var groupIndex = groupNumberCounter - 1;

if (prevFirst && prevFirst === '\\') {
continue;
}

if (result[groupIndex] && !result[groupIndex].isResulting) {
result.splice(groupIndex, 1);
groupNumberCounter = --groupNumberCounter;
continue;
}

if (nextFirst && (nextFirst === '?' || nextFirst === '*')) {
result[groupIndex].mayBeMissing = true;
}
}
}

return result;
};

StringPrototype.replace = function replace(searchValue, replaceValue) {
var isFn = isCallable(replaceValue);
var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
var extendedGroups = getExtendedGroups(searchValue);

if (!isFn || !hasCapturingGroups) {
return str_replace.call(this, searchValue, replaceValue);
} else {
var wrappedReplaceValue = function (match) {
var length = arguments.length;
var originalLastIndex = searchValue.lastIndex;
searchValue.lastIndex = 0; // eslint-disable-line no-param-reassign
var args = searchValue.exec(match) || [];
searchValue.lastIndex = originalLastIndex; // eslint-disable-line no-param-reassign
pushCall(args, arguments[length - 2], arguments[length - 1]);
return replaceValue.apply(this, args);
var groups = ArrayPrototype.slice.call(arguments, 1, -2);

for (var i = 0; i < groups.length; i++) {
var argumentIndex = i + 1;
if (groups[i] === '' && extendedGroups[i].mayBeMissing) {
arguments[argumentIndex] = undefined;
}
}

return replaceValue.apply(this, arguments);
};
return str_replace.call(this, searchValue, wrappedReplaceValue);
}
Expand Down

0 comments on commit e44022d

Please sign in to comment.