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