Index: src/js/string.js |
diff --git a/src/js/string.js b/src/js/string.js |
index da1643b06c9c2fb787acbb99d76261ef72431706..706fa5d207a9c21a1785d6357900c131e0051798 100644 |
--- a/src/js/string.js |
+++ b/src/js/string.js |
@@ -10,6 +10,7 @@ |
// Imports |
var ArrayJoin; |
+var GetSubstitution; |
var GlobalRegExp = global.RegExp; |
var GlobalString = global.String; |
var IsRegExp; |
@@ -23,6 +24,7 @@ var splitSymbol = utils.ImportNow("split_symbol"); |
utils.Import(function(from) { |
ArrayJoin = from.ArrayJoin; |
+ GetSubstitution = from.GetSubstitution; |
IsRegExp = from.IsRegExp; |
MaxSimple = from.MaxSimple; |
MinSimple = from.MinSimple; |
@@ -107,14 +109,6 @@ function StringMatchJS(pattern) { |
} |
-// This has the same size as the RegExpLastMatchInfo array, and can be used |
-// for functions that expect that structure to be returned. It is used when |
-// the needle is a string rather than a regexp. In this case we can't update |
-// lastMatchArray without erroneously affecting the properties on the global |
-// RegExp object. |
-var reusableMatchInfo = [2, "", "", -1, -1]; |
- |
- |
// ES6, section 21.1.3.14 |
function StringReplace(search, replace) { |
CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace"); |
@@ -166,101 +160,18 @@ function StringReplace(search, replace) { |
if (IS_CALLABLE(replace)) { |
result += replace(search, start, subject); |
} else { |
- reusableMatchInfo[CAPTURE0] = start; |
- reusableMatchInfo[CAPTURE1] = end; |
- result = ExpandReplacement(TO_STRING(replace), |
- subject, |
- reusableMatchInfo, |
- result); |
+ // In this case, we don't have any capture groups and can get away with |
+ // faking the captures object by simply setting its length to 1. |
+ const captures = { length: 1 }; |
+ const matched = %_SubString(subject, start, end); |
+ result += GetSubstitution(matched, subject, start, captures, |
+ TO_STRING(replace)); |
} |
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, result) { |
- var length = string.length; |
- var next = %StringIndexOf(string, '$', 0); |
- if (next < 0) { |
- if (length > 0) result += string; |
- return result; |
- } |
- |
- if (next > 0) result += %_SubString(string, 0, next); |
- |
- while (true) { |
- var expansion = '$'; |
- var position = next + 1; |
- if (position < length) { |
- var peek = %_StringCharCodeAt(string, position); |
- if (peek == 36) { // $$ |
- ++position; |
- result += '$'; |
- } else if (peek == 38) { // $& - match |
- ++position; |
- result += |
- %_SubString(subject, matchInfo[CAPTURE0], matchInfo[CAPTURE1]); |
- } else if (peek == 96) { // $` - prefix |
- ++position; |
- result += %_SubString(subject, 0, matchInfo[CAPTURE0]); |
- } else if (peek == 39) { // $' - suffix |
- ++position; |
- result += %_SubString(subject, matchInfo[CAPTURE1], subject.length); |
- } else if (peek >= 48 && peek <= 57) { |
- // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99 |
- var scaled_index = (peek - 48) << 1; |
- var advance = 1; |
- var number_of_captures = NUMBER_OF_CAPTURES(matchInfo); |
- if (position + 1 < string.length) { |
- var next = %_StringCharCodeAt(string, position + 1); |
- if (next >= 48 && next <= 57) { |
- var new_scaled_index = scaled_index * 10 + ((next - 48) << 1); |
- if (new_scaled_index < number_of_captures) { |
- scaled_index = new_scaled_index; |
- advance = 2; |
- } |
- } |
- } |
- if (scaled_index != 0 && scaled_index < number_of_captures) { |
- var start = matchInfo[CAPTURE(scaled_index)]; |
- if (start >= 0) { |
- result += |
- %_SubString(subject, start, matchInfo[CAPTURE(scaled_index + 1)]); |
- } |
- position += advance; |
- } else { |
- result += '$'; |
- } |
- } else { |
- result += '$'; |
- } |
- } else { |
- result += '$'; |
- } |
- |
- // Go the the next $ in the string. |
- next = %StringIndexOf(string, '$', position); |
- |
- // Return if there are no more $ characters in the string. If we |
- // haven't reached the end, we need to append the suffix. |
- if (next < 0) { |
- if (position < length) { |
- result += %_SubString(string, position, length); |
- } |
- return result; |
- } |
- |
- // Append substring between the previous and the next $ character. |
- if (next > position) { |
- result += %_SubString(string, position, next); |
- } |
- } |
- return result; |
-} |
- |
- |
// ES6 21.1.3.15. |
function StringSearch(pattern) { |
CHECK_OBJECT_COERCIBLE(this, "String.prototype.search"); |
@@ -736,7 +647,6 @@ utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [ |
// Exports |
utils.Export(function(to) { |
- to.ExpandReplacement = ExpandReplacement; |
to.StringIndexOf = StringIndexOf; |
to.StringLastIndexOf = StringLastIndexOf; |
to.StringMatch = StringMatchJS; |