Index: src/string.js |
diff --git a/src/string.js b/src/string.js |
index 1fcabc407aa23584830b0013b34a5b722724f1e9..6115930b6c8ff69568f425b8b996a821bc93cb87 100644 |
--- a/src/string.js |
+++ b/src/string.js |
@@ -277,47 +277,34 @@ function StringReplace(search, replace) { |
if (start < 0) return subject; |
var end = start + search.length; |
- var builder = new ReplaceResultBuilder(subject); |
- // prefix |
- builder.addSpecialSlice(0, start); |
+ var result = SubString(subject, 0, start); |
// Compute the string to replace with. |
if (IS_SPEC_FUNCTION(replace)) { |
var receiver = %GetDefaultReceiver(replace); |
- builder.add(%_CallFunction(receiver, |
- search, |
- start, |
- subject, |
- replace)); |
+ result += %_CallFunction(receiver, search, start, subject, replace); |
} else { |
reusableMatchInfo[CAPTURE0] = start; |
reusableMatchInfo[CAPTURE1] = end; |
replace = TO_STRING_INLINE(replace); |
- ExpandReplacement(replace, subject, reusableMatchInfo, builder); |
+ result = ExpandReplacement(replace, subject, reusableMatchInfo, result); |
} |
- // suffix |
- builder.addSpecialSlice(end, subject.length); |
- |
- return builder.generate(); |
+ return result + SubString(subject, end, subject.length); |
} |
// Expand the $-expressions in the string and return a new string with |
// the result. |
-function ExpandReplacement(string, subject, matchInfo, builder) { |
+function ExpandReplacement(string, subject, matchInfo, result) { |
var length = string.length; |
- var builder_elements = builder.elements; |
var next = %StringIndexOf(string, '$', 0); |
if (next < 0) { |
- if (length > 0) builder_elements.push(string); |
- return; |
+ if (length > 0) result += string; |
+ return result; |
} |
- // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. |
- var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match. |
- |
- if (next > 0) builder_elements.push(SubString(string, 0, next)); |
+ if (next > 0) result += SubString(string, 0, next); |
while (true) { |
var expansion = '$'; |
@@ -326,51 +313,21 @@ function ExpandReplacement(string, subject, matchInfo, builder) { |
var peek = %_StringCharCodeAt(string, position); |
if (peek == 36) { // $$ |
++position; |
- builder_elements.push('$'); |
+ result += '$'; |
} else if (peek == 38) { // $& - match |
++position; |
- builder.addSpecialSlice(matchInfo[CAPTURE0], |
- matchInfo[CAPTURE1]); |
+ result += SubString(subject, matchInfo[CAPTURE0], matchInfo[CAPTURE1]); |
} else if (peek == 96) { // $` - prefix |
++position; |
- builder.addSpecialSlice(0, matchInfo[CAPTURE0]); |
+ result += SubString(subject, 0, matchInfo[CAPTURE0]); |
} else if (peek == 39) { // $' - suffix |
++position; |
- builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length); |
- } else if (peek >= 48 && peek <= 57) { // $n, 0 <= n <= 9 |
- ++position; |
- var n = peek - 48; |
- if (position < length) { |
- peek = %_StringCharCodeAt(string, position); |
- // $nn, 01 <= nn <= 99 |
- if (n != 0 && peek == 48 || peek >= 49 && peek <= 57) { |
- var nn = n * 10 + (peek - 48); |
- if (nn < m) { |
- // If the two digit capture reference is within range of |
- // the captures, we use it instead of the single digit |
- // one. Otherwise, we fall back to using the single |
- // digit reference. This matches the behavior of |
- // SpiderMonkey. |
- ++position; |
- n = nn; |
- } |
- } |
- } |
- if (0 < n && n < m) { |
- addCaptureString(builder, matchInfo, n); |
- } else { |
- // Because of the captures range check in the parsing of two |
- // digit capture references, we can only enter here when a |
- // single digit capture reference is outside the range of |
- // captures. |
- builder_elements.push('$'); |
- --position; |
- } |
+ result += SubString(subject, matchInfo[CAPTURE1], subject.length); |
} else { |
- builder_elements.push('$'); |
+ result += '$'; |
} |
} else { |
- builder_elements.push('$'); |
+ result += '$'; |
} |
// Go the the next $ in the string. |
@@ -380,16 +337,17 @@ function ExpandReplacement(string, subject, matchInfo, builder) { |
// haven't reached the end, we need to append the suffix. |
if (next < 0) { |
if (position < length) { |
- builder_elements.push(SubString(string, position, length)); |
+ result += SubString(string, position, length); |
} |
- return; |
+ return result; |
} |
// Append substring between the previous and the next $ character. |
if (next > position) { |
- builder_elements.push(SubString(string, position, next)); |
+ result += SubString(string, position, next); |
} |
} |
+ return result; |
} |
@@ -406,18 +364,6 @@ function CaptureString(string, lastCaptureInfo, index) { |
} |
-// Add the string of a given regular expression capture to the |
-// ReplaceResultBuilder |
-function addCaptureString(builder, matchInfo, index) { |
- // Scale the index. |
- var scaled = index << 1; |
- // Compute start and end. |
- var start = matchInfo[CAPTURE(scaled)]; |
- if (start < 0) return; |
- var end = matchInfo[CAPTURE(scaled + 1)]; |
- builder.addSpecialSlice(start, end); |
-} |
- |
// TODO(lrn): This array will survive indefinitely if replace is never |
// called again. However, it will be empty, since the contents are cleared |
// in the finally block. |
@@ -506,9 +452,8 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) { |
function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { |
var matchInfo = DoRegExpExec(regexp, subject, 0); |
if (IS_NULL(matchInfo)) return subject; |
- var result = new ReplaceResultBuilder(subject); |
var index = matchInfo[CAPTURE0]; |
- result.addSpecialSlice(0, index); |
+ var result = SubString(subject, 0, index); |
var endOfMatch = matchInfo[CAPTURE1]; |
// Compute the parameter list consisting of the match, captures, index, |
// and subject for the replace function invocation. |
@@ -532,11 +477,10 @@ function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { |
replacement = %Apply(replace, receiver, parameters, 0, j + 2); |
} |
- result.add(replacement); // The add method converts to string if necessary. |
+ result += replacement; // The add method converts to string if necessary. |
// Can't use matchInfo any more from here, since the function could |
// overwrite it. |
- result.addSpecialSlice(endOfMatch, subject.length); |
- return result.generate(); |
+ return result + SubString(subject, endOfMatch, subject.length); |
} |