Chromium Code Reviews| Index: src/string.js |
| =================================================================== |
| --- src/string.js (revision 11415) |
| +++ src/string.js (working copy) |
| @@ -237,10 +237,27 @@ |
| replace); |
| } |
| } else { |
| - return %StringReplaceRegExpWithString(subject, |
| - search, |
| - TO_STRING_INLINE(replace), |
| - lastMatchInfo); |
| + if (lastMatchInfoOverride == null) { |
| + return %StringReplaceRegExpWithString(subject, |
| + search, |
| + TO_STRING_INLINE(replace), |
| + lastMatchInfo); |
| + } else { |
| + // We use this hack to detect whether StringReplaceRegExpWithString found |
|
ulan
2012/04/23 16:59:23
Long line
Erik Corry
2012/04/23 18:54:02
Done.
|
| + // at least one hit. In that case we need to remove any override. |
| + var saved_subject = lastMatchInfo[LAST_SUBJECT_INDEX]; |
| + lastMatchInfo[LAST_SUBJECT_INDEX] = 0; |
|
ulan
2012/04/23 16:59:23
This is sad, but I don't see a better way.
Erik Corry
2012/04/23 18:54:02
Me neither.
|
| + var answer = %StringReplaceRegExpWithString(subject, |
| + search, |
| + TO_STRING_INLINE(replace), |
| + lastMatchInfo); |
| + if (%_IsSmi(lastMatchInfo[LAST_SUBJECT_INDEX])) { |
| + lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject; |
| + } else { |
| + lastMatchInfoOverride = null; |
| + } |
| + return answer; |
| + } |
| } |
| } |
| @@ -431,12 +448,22 @@ |
| var len = res.length; |
| var i = 0; |
| if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) { |
| + // If the number of captures is two then there are no explicit captures in |
| + // the regexp, just the implicit capture that captures the whole match. In |
| + // this case we can simplify quite a bit and end up with something faster. |
| + // The builder will consist of some integers that indicate slices of the |
| + // input string and some replacements that were returned from the replace |
| + // function. |
| var match_start = 0; |
| var override = new InternalArray(null, 0, subject); |
| var receiver = %GetDefaultReceiver(replace); |
| - while (i < len) { |
| + // i is 0. |
| + for ( ; i < len; i++) { |
|
ulan
2012/04/23 16:59:23
Can we make i local in the loop?
Erik Corry
2012/04/23 18:54:02
Well not really. This is JS, after all. But we c
|
| var elem = res[i]; |
| if (%_IsSmi(elem)) { |
| + // Integers represent slices of the original string. Use these to |
| + // get the offsets we need for the override array (so things like |
| + // RegExp.leftContext work during the callback function. |
| if (elem > 0) { |
| match_start = (elem >> 11) + (elem & 0x7ff); |
| } else { |
| @@ -448,23 +475,26 @@ |
| lastMatchInfoOverride = override; |
| var func_result = |
| %_CallFunction(receiver, elem, match_start, subject, replace); |
| + // Overwrite the i'th element in the results with the string we got |
| + // back from the callback function. |
| res[i] = TO_STRING_INLINE(func_result); |
| match_start += elem.length; |
| } |
| - i++; |
| } |
| } else { |
| var receiver = %GetDefaultReceiver(replace); |
| - while (i < len) { |
| + // i is 0. |
| + for ( ; i < len; i++) { |
|
ulan
2012/04/23 16:59:23
Can we make i local in the loop?
Erik Corry
2012/04/23 18:54:02
As above.
|
| var elem = res[i]; |
| if (!%_IsSmi(elem)) { |
| // elem must be an Array. |
| // Use the apply argument as backing for global RegExp properties. |
| lastMatchInfoOverride = elem; |
| var func_result = %Apply(replace, receiver, elem, 0, elem.length); |
| + // Overwrite the i'th element in the results with the string we got |
| + // back from the callback function. |
| res[i] = TO_STRING_INLINE(func_result); |
| } |
| - i++; |
| } |
| } |
| var resultBuilder = new ReplaceResultBuilder(subject, res); |