Skip to content

Commit e44022d

Browse files
elitvyakovljharb
authored andcommitted
es5-shim: fix groups with quantifiers preventing its exercise
1 parent d855953 commit e44022d

File tree

1 file changed

+80
-7
lines changed

1 file changed

+80
-7
lines changed

es5-shim.js

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,20 +1921,93 @@
19211921
}());
19221922

19231923
if (!replaceReportsGroupsCorrectly) {
1924+
/**
1925+
* @param regexp {RegExp}
1926+
* @returns {Object[]} groups
1927+
* @return {number} groups[].number - The number of group.
1928+
* @return {boolean} groups[].mayBeMissing - The group with quantifiers preventing its exercise, the matched text
1929+
* for a capturing group is now undefined instead of an empty string.
1930+
* The group without quantifiers, may be empty string.
1931+
* @return {boolean} groups[].isResulting - The groups with ?:, ?=, ?! are non-capturing groups.
1932+
*/
1933+
var getExtendedGroups = function getExtendedGroups(regexp) {
1934+
var source = regexp.source;
1935+
var result = [];
1936+
var groupNumberCounter = 0;
1937+
1938+
for (var charIndex in source) {
1939+
var char = source[+charIndex];
1940+
var prevFirst = source[+charIndex - 1] || null;
1941+
var nextFirst = source[+charIndex + 1] || null;
1942+
var nextSecond = source[+charIndex + 2] || null;
1943+
1944+
if (char === '(') {
1945+
if (prevFirst && prevFirst === '\\') {
1946+
continue;
1947+
}
1948+
1949+
if (
1950+
nextFirst && nextFirst === '?' && nextSecond && nextSecond === ':'
1951+
|| nextFirst && nextFirst === '?' && nextSecond && nextSecond === '='
1952+
|| nextFirst && nextFirst === '?' && nextSecond && nextSecond === '!'
1953+
) {
1954+
groupNumberCounter += 1;
1955+
result.push({
1956+
number: groupNumberCounter,
1957+
mayBeMissing: true,
1958+
isResulting: false
1959+
});
1960+
continue;
1961+
}
1962+
1963+
result.push({
1964+
number: ++groupNumberCounter,
1965+
mayBeMissing: false,
1966+
isResulting: true
1967+
});
1968+
}
1969+
1970+
if (char === ')') {
1971+
var groupIndex = groupNumberCounter - 1;
1972+
1973+
if (prevFirst && prevFirst === '\\') {
1974+
continue;
1975+
}
1976+
1977+
if (result[groupIndex] && !result[groupIndex].isResulting) {
1978+
result.splice(groupIndex, 1);
1979+
groupNumberCounter = --groupNumberCounter;
1980+
continue;
1981+
}
1982+
1983+
if (nextFirst && (nextFirst === '?' || nextFirst === '*')) {
1984+
result[groupIndex].mayBeMissing = true;
1985+
}
1986+
}
1987+
}
1988+
1989+
return result;
1990+
};
1991+
19241992
StringPrototype.replace = function replace(searchValue, replaceValue) {
19251993
var isFn = isCallable(replaceValue);
19261994
var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
1995+
var extendedGroups = getExtendedGroups(searchValue);
1996+
19271997
if (!isFn || !hasCapturingGroups) {
19281998
return str_replace.call(this, searchValue, replaceValue);
19291999
} else {
19302000
var wrappedReplaceValue = function (match) {
1931-
var length = arguments.length;
1932-
var originalLastIndex = searchValue.lastIndex;
1933-
searchValue.lastIndex = 0; // eslint-disable-line no-param-reassign
1934-
var args = searchValue.exec(match) || [];
1935-
searchValue.lastIndex = originalLastIndex; // eslint-disable-line no-param-reassign
1936-
pushCall(args, arguments[length - 2], arguments[length - 1]);
1937-
return replaceValue.apply(this, args);
2001+
var groups = ArrayPrototype.slice.call(arguments, 1, -2);
2002+
2003+
for (var i = 0; i < groups.length; i++) {
2004+
var argumentIndex = i + 1;
2005+
if (groups[i] === '' && extendedGroups[i].mayBeMissing) {
2006+
arguments[argumentIndex] = undefined;
2007+
}
2008+
}
2009+
2010+
return replaceValue.apply(this, arguments);
19382011
};
19392012
return str_replace.call(this, searchValue, wrappedReplaceValue);
19402013
}

0 commit comments

Comments
 (0)