Index: src/string.js |
=================================================================== |
--- src/string.js (revision 4081) |
+++ src/string.js (working copy) |
@@ -387,43 +387,68 @@ |
// Unfortunately, that means this code is nearly duplicated, here and in |
// jsregexp.cc. |
if (regexp.global) { |
- var numberOfCaptures = NUMBER_OF_CAPTURES(matchInfo) >> 1; |
var previous = 0; |
- do { |
- var startOfMatch = matchInfo[CAPTURE0]; |
- result.addSpecialSlice(previous, startOfMatch); |
- previous = matchInfo[CAPTURE1]; |
- if (numberOfCaptures == 1) { |
+ var startOfMatch; |
+ if (NUMBER_OF_CAPTURES(matchInfo) == 2) { |
+ // Both branches contain essentially the same loop except for the call |
+ // to the replace function. The branch is put outside of the loop for |
+ // speed |
+ do { |
+ startOfMatch = matchInfo[CAPTURE0]; |
+ result.addSpecialSlice(previous, startOfMatch); |
+ previous = matchInfo[CAPTURE1]; |
var match = SubString(subject, startOfMatch, previous); |
// Don't call directly to avoid exposing the built-in global object. |
result.add(replace.call(null, match, startOfMatch, subject)); |
- } else { |
+ // Can't use matchInfo any more from here, since the function could |
+ // overwrite it. |
+ // Continue with the next match. |
+ // Increment previous if we matched an empty string, as per ECMA-262 |
+ // 15.5.4.10. |
+ if (previous == startOfMatch) { |
+ // Add the skipped character to the output, if any. |
+ if (previous < subject.length) { |
+ result.addSpecialSlice(previous, previous + 1); |
+ } |
+ previous++; |
+ // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
+ // string length, there is no match |
+ if (previous > subject.length) { |
+ return result.generate(); |
+ } |
+ } |
+ matchInfo = DoRegExpExec(regexp, subject, previous); |
+ } while (!IS_NULL(matchInfo)); |
+ } else { |
+ do { |
+ startOfMatch = matchInfo[CAPTURE0]; |
+ result.addSpecialSlice(previous, startOfMatch); |
+ previous = matchInfo[CAPTURE1]; |
result.add(ApplyReplacementFunction(replace, matchInfo, subject)); |
- } |
- // Can't use matchInfo any more from here, since the function could |
- // overwrite it. |
- // Continue with the next match. |
- // Increment previous if we matched an empty string, as per ECMA-262 |
- // 15.5.4.10. |
- if (previous == startOfMatch) { |
- // Add the skipped character to the output, if any. |
- if (previous < subject.length) { |
- result.addSpecialSlice(previous, previous + 1); |
+ // Can't use matchInfo any more from here, since the function could |
+ // overwrite it. |
+ // Continue with the next match. |
+ // Increment previous if we matched an empty string, as per ECMA-262 |
+ // 15.5.4.10. |
+ if (previous == startOfMatch) { |
+ // Add the skipped character to the output, if any. |
+ if (previous < subject.length) { |
+ result.addSpecialSlice(previous, previous + 1); |
+ } |
+ previous++; |
+ // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
+ // string length, there is no match |
+ if (previous > subject.length) { |
+ return result.generate(); |
+ } |
} |
- previous++; |
- } |
+ matchInfo = DoRegExpExec(regexp, subject, previous); |
+ } while (!IS_NULL(matchInfo)); |
+ } |
- // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
- // string length, there is no match |
- matchInfo = (previous > subject.length) |
- ? null |
- : DoRegExpExec(regexp, subject, previous); |
- } while (!IS_NULL(matchInfo)); |
+ // Tack on the final right substring after the last match. |
+ result.addSpecialSlice(previous, subject.length); |
- // Tack on the final right substring after the last match, if necessary. |
- if (previous < subject.length) { |
- result.addSpecialSlice(previous, subject.length); |
- } |
} else { // Not a global regexp, no need to loop. |
result.addSpecialSlice(0, matchInfo[CAPTURE0]); |
var endOfMatch = matchInfo[CAPTURE1]; |