| 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;
|
|
|