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 f0dd919 commit 523fc8b
Show file tree
Hide file tree
Showing 2 changed files with 109 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 @@ -1925,20 +1925,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) {
array_splice.apply(result,[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 = arraySlice(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 apply.call(replaceValue, this, arguments);
};
return str_replace.call(this, searchValue, wrappedReplaceValue);
}
Expand Down
29 changes: 29 additions & 0 deletions tests/spec/s-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ describe('String', function () {
);
}).not.toThrow();
});

it('should be 10 arguments in Firefox prior 34 version', function () {
var size = null;

'* alef\n* beth \n* gimel~0\n'.replace(
/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
function (match, m1, m2, m3, m4) {
size = arguments.length;
}
);

expect(size).toBe(10);
});

it('first group have to be undefined and second have to be empty string', function () {
var firstGroup,
secondGroup;

'x'.replace(
/x(.)?(.*)/gm,
function (match, m1, m2) {
firstGroup = m1;
secondGroup = m2;
}
);

expect(firstGroup).toBe(undefined);
expect(secondGroup).toBe('');
});
});

describe('#split()', function () {
Expand Down

0 comments on commit 523fc8b

Please sign in to comment.