OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 (function(global, utils) { | 5 (function(global, utils) { |
6 | 6 |
7 %CheckIsBootstrapping(); | 7 %CheckIsBootstrapping(); |
8 | 8 |
9 // ------------------------------------------------------------------- | 9 // ------------------------------------------------------------------- |
10 // Imports | 10 // Imports |
11 | 11 |
12 var ArrayJoin; | 12 var ArrayJoin; |
13 var GetSubstitution; | |
14 var GlobalRegExp = global.RegExp; | 13 var GlobalRegExp = global.RegExp; |
15 var GlobalString = global.String; | 14 var GlobalString = global.String; |
16 var MaxSimple; | 15 var MaxSimple; |
17 var MinSimple; | 16 var MinSimple; |
18 var matchSymbol = utils.ImportNow("match_symbol"); | 17 var matchSymbol = utils.ImportNow("match_symbol"); |
19 var replaceSymbol = utils.ImportNow("replace_symbol"); | 18 var replaceSymbol = utils.ImportNow("replace_symbol"); |
20 var searchSymbol = utils.ImportNow("search_symbol"); | 19 var searchSymbol = utils.ImportNow("search_symbol"); |
21 var splitSymbol = utils.ImportNow("split_symbol"); | 20 var splitSymbol = utils.ImportNow("split_symbol"); |
22 | 21 |
23 utils.Import(function(from) { | 22 utils.Import(function(from) { |
24 ArrayJoin = from.ArrayJoin; | 23 ArrayJoin = from.ArrayJoin; |
25 GetSubstitution = from.GetSubstitution; | |
26 MaxSimple = from.MaxSimple; | 24 MaxSimple = from.MaxSimple; |
27 MinSimple = from.MinSimple; | 25 MinSimple = from.MinSimple; |
28 }); | 26 }); |
29 | 27 |
30 //------------------------------------------------------------------- | 28 //------------------------------------------------------------------- |
31 | 29 |
32 // ECMA-262, section 15.5.4.6 | 30 // ECMA-262, section 15.5.4.6 |
33 function StringConcat(other /* and more */) { // length == 1 | 31 function StringConcat(other /* and more */) { // length == 1 |
34 "use strict"; | 32 "use strict"; |
35 CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat"); | 33 CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat"); |
(...skipping 17 matching lines...) Expand all Loading... |
53 } | 51 } |
54 } | 52 } |
55 | 53 |
56 var subject = TO_STRING(this); | 54 var subject = TO_STRING(this); |
57 | 55 |
58 // Equivalent to RegExpCreate (ES#sec-regexpcreate) | 56 // Equivalent to RegExpCreate (ES#sec-regexpcreate) |
59 var regexp = %RegExpCreate(pattern); | 57 var regexp = %RegExpCreate(pattern); |
60 return regexp[matchSymbol](subject); | 58 return regexp[matchSymbol](subject); |
61 } | 59 } |
62 | 60 |
| 61 // ES#sec-getsubstitution |
| 62 // GetSubstitution(matched, str, position, captures, replacement) |
| 63 // Expand the $-expressions in the string and return a new string with |
| 64 // the result. |
| 65 function GetSubstitution(matched, string, position, captures, replacement) { |
| 66 var matchLength = matched.length; |
| 67 var stringLength = string.length; |
| 68 var capturesLength = captures.length; |
| 69 var tailPos = position + matchLength; |
| 70 var result = ""; |
| 71 var pos, expansion, peek, next, scaledIndex, advance, newScaledIndex; |
| 72 |
| 73 var next = %StringIndexOf(replacement, '$', 0); |
| 74 if (next < 0) { |
| 75 result += replacement; |
| 76 return result; |
| 77 } |
| 78 |
| 79 if (next > 0) result += %_SubString(replacement, 0, next); |
| 80 |
| 81 while (true) { |
| 82 expansion = '$'; |
| 83 pos = next + 1; |
| 84 if (pos < replacement.length) { |
| 85 peek = %_StringCharCodeAt(replacement, pos); |
| 86 if (peek == 36) { // $$ |
| 87 ++pos; |
| 88 result += '$'; |
| 89 } else if (peek == 38) { // $& - match |
| 90 ++pos; |
| 91 result += matched; |
| 92 } else if (peek == 96) { // $` - prefix |
| 93 ++pos; |
| 94 result += %_SubString(string, 0, position); |
| 95 } else if (peek == 39) { // $' - suffix |
| 96 ++pos; |
| 97 result += %_SubString(string, tailPos, stringLength); |
| 98 } else if (peek >= 48 && peek <= 57) { |
| 99 // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99 |
| 100 scaledIndex = (peek - 48); |
| 101 advance = 1; |
| 102 if (pos + 1 < replacement.length) { |
| 103 next = %_StringCharCodeAt(replacement, pos + 1); |
| 104 if (next >= 48 && next <= 57) { |
| 105 newScaledIndex = scaledIndex * 10 + ((next - 48)); |
| 106 if (newScaledIndex < capturesLength) { |
| 107 scaledIndex = newScaledIndex; |
| 108 advance = 2; |
| 109 } |
| 110 } |
| 111 } |
| 112 if (scaledIndex != 0 && scaledIndex < capturesLength) { |
| 113 var capture = captures.at(scaledIndex); |
| 114 if (!IS_UNDEFINED(capture)) result += capture; |
| 115 pos += advance; |
| 116 } else { |
| 117 result += '$'; |
| 118 } |
| 119 } else { |
| 120 result += '$'; |
| 121 } |
| 122 } else { |
| 123 result += '$'; |
| 124 } |
| 125 |
| 126 // Go the the next $ in the replacement. |
| 127 next = %StringIndexOf(replacement, '$', pos); |
| 128 |
| 129 // Return if there are no more $ characters in the replacement. If we |
| 130 // haven't reached the end, we need to append the suffix. |
| 131 if (next < 0) { |
| 132 if (pos < replacement.length) { |
| 133 result += %_SubString(replacement, pos, replacement.length); |
| 134 } |
| 135 return result; |
| 136 } |
| 137 |
| 138 // Append substring between the previous and the next $ character. |
| 139 if (next > pos) { |
| 140 result += %_SubString(replacement, pos, next); |
| 141 } |
| 142 } |
| 143 return result; |
| 144 } |
63 | 145 |
64 // ES6, section 21.1.3.14 | 146 // ES6, section 21.1.3.14 |
65 function StringReplace(search, replace) { | 147 function StringReplace(search, replace) { |
66 CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace"); | 148 CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace"); |
67 | 149 |
68 // Decision tree for dispatch | 150 // Decision tree for dispatch |
69 // .. regexp search (in src/js/regexp.js, RegExpReplace) | 151 // .. regexp search (in src/js/regexp.js, RegExpReplace) |
70 // .... string replace | 152 // .... string replace |
71 // ...... non-global search | 153 // ...... non-global search |
72 // ........ empty string replace | 154 // ........ empty string replace |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 // Exports | 543 // Exports |
462 | 544 |
463 utils.Export(function(to) { | 545 utils.Export(function(to) { |
464 to.StringMatch = StringMatchJS; | 546 to.StringMatch = StringMatchJS; |
465 to.StringReplace = StringReplace; | 547 to.StringReplace = StringReplace; |
466 to.StringSlice = StringSlice; | 548 to.StringSlice = StringSlice; |
467 to.StringSplit = StringSplitJS; | 549 to.StringSplit = StringSplitJS; |
468 }); | 550 }); |
469 | 551 |
470 }) | 552 }) |
OLD | NEW |