Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: src/js/string.js

Issue 2663803002: [string] Migrate String.prototype.{split,replace} to TF (Closed)
Patch Set: Remove debug-evaluate whitelisting Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-string.cc ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
13 var GlobalRegExp = global.RegExp;
14 var GlobalString = global.String; 12 var GlobalString = global.String;
15 var MaxSimple;
16 var MinSimple;
17 var matchSymbol = utils.ImportNow("match_symbol"); 13 var matchSymbol = utils.ImportNow("match_symbol");
18 var replaceSymbol = utils.ImportNow("replace_symbol");
19 var searchSymbol = utils.ImportNow("search_symbol"); 14 var searchSymbol = utils.ImportNow("search_symbol");
20 var splitSymbol = utils.ImportNow("split_symbol");
21
22 utils.Import(function(from) {
23 ArrayJoin = from.ArrayJoin;
24 MaxSimple = from.MaxSimple;
25 MinSimple = from.MinSimple;
26 });
27 15
28 //------------------------------------------------------------------- 16 //-------------------------------------------------------------------
29 17
30 // ECMA-262, section 15.5.4.6 18 // ECMA-262, section 15.5.4.6
31 function StringConcat(other /* and more */) { // length == 1 19 function StringConcat(other /* and more */) { // length == 1
32 "use strict"; 20 "use strict";
33 CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat"); 21 CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat");
34 var s = TO_STRING(this); 22 var s = TO_STRING(this);
35 var len = arguments.length; 23 var len = arguments.length;
36 for (var i = 0; i < len; ++i) { 24 for (var i = 0; i < len; ++i) {
(...skipping 14 matching lines...) Expand all
51 } 39 }
52 } 40 }
53 41
54 var subject = TO_STRING(this); 42 var subject = TO_STRING(this);
55 43
56 // Equivalent to RegExpCreate (ES#sec-regexpcreate) 44 // Equivalent to RegExpCreate (ES#sec-regexpcreate)
57 var regexp = %RegExpCreate(pattern); 45 var regexp = %RegExpCreate(pattern);
58 return regexp[matchSymbol](subject); 46 return regexp[matchSymbol](subject);
59 } 47 }
60 48
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 }
145
146 // ES6, section 21.1.3.14
147 function StringReplace(search, replace) {
148 CHECK_OBJECT_COERCIBLE(this, "String.prototype.replace");
149
150 // Decision tree for dispatch
151 // .. regexp search (in src/js/regexp.js, RegExpReplace)
152 // .... string replace
153 // ...... non-global search
154 // ........ empty string replace
155 // ........ non-empty string replace (with $-expansion)
156 // ...... global search
157 // ........ no need to circumvent last match info override
158 // ........ need to circument last match info override
159 // .... function replace
160 // ...... global search
161 // ...... non-global search
162 // .. string search
163 // .... special case that replaces with one single character
164 // ...... function replace
165 // ...... string replace (with $-expansion)
166
167 if (!IS_NULL_OR_UNDEFINED(search)) {
168 var replacer = search[replaceSymbol];
169 if (!IS_UNDEFINED(replacer)) {
170 return %_Call(replacer, search, this, replace);
171 }
172 }
173
174 var subject = TO_STRING(this);
175
176 search = TO_STRING(search);
177
178 if (search.length == 1 &&
179 subject.length > 0xFF &&
180 IS_STRING(replace) &&
181 %StringIndexOf(replace, '$', 0) < 0) {
182 // Searching by traversing a cons string tree and replace with cons of
183 // slices works only when the replaced string is a single character, being
184 // replaced by a simple string and only pays off for long strings.
185 return %StringReplaceOneCharWithString(subject, search, replace);
186 }
187 var start = %StringIndexOf(subject, search, 0);
188 if (start < 0) return subject;
189 var end = start + search.length;
190
191 var result = %_SubString(subject, 0, start);
192
193 // Compute the string to replace with.
194 if (IS_CALLABLE(replace)) {
195 result += replace(search, start, subject);
196 } else {
197 // In this case, we don't have any capture groups and can get away with
198 // faking the captures object by simply setting its length to 1.
199 const captures = { length: 1 };
200 const matched = %_SubString(subject, start, end);
201 result += GetSubstitution(matched, subject, start, captures,
202 TO_STRING(replace));
203 }
204
205 return result + %_SubString(subject, end, subject.length);
206 }
207
208
209 // ES6 21.1.3.15. 49 // ES6 21.1.3.15.
210 function StringSearch(pattern) { 50 function StringSearch(pattern) {
211 CHECK_OBJECT_COERCIBLE(this, "String.prototype.search"); 51 CHECK_OBJECT_COERCIBLE(this, "String.prototype.search");
212 52
213 if (!IS_NULL_OR_UNDEFINED(pattern)) { 53 if (!IS_NULL_OR_UNDEFINED(pattern)) {
214 var searcher = pattern[searchSymbol]; 54 var searcher = pattern[searchSymbol];
215 if (!IS_UNDEFINED(searcher)) { 55 if (!IS_UNDEFINED(searcher)) {
216 return %_Call(searcher, pattern, this); 56 return %_Call(searcher, pattern, this);
217 } 57 }
218 } 58 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 } 99 }
260 } 100 }
261 101
262 if (end_i <= start_i) { 102 if (end_i <= start_i) {
263 return ''; 103 return '';
264 } 104 }
265 105
266 return %_SubString(s, start_i, end_i); 106 return %_SubString(s, start_i, end_i);
267 } 107 }
268 108
269
270 // ES6 21.1.3.17.
271 function StringSplitJS(separator, limit) {
272 CHECK_OBJECT_COERCIBLE(this, "String.prototype.split");
273
274 if (!IS_NULL_OR_UNDEFINED(separator)) {
275 var splitter = separator[splitSymbol];
276 if (!IS_UNDEFINED(splitter)) {
277 return %_Call(splitter, separator, this, limit);
278 }
279 }
280
281 var subject = TO_STRING(this);
282 limit = (IS_UNDEFINED(limit)) ? kMaxUint32 : TO_UINT32(limit);
283
284 var length = subject.length;
285 var separator_string = TO_STRING(separator);
286
287 if (limit === 0) return [];
288
289 // ECMA-262 says that if separator is undefined, the result should
290 // be an array of size 1 containing the entire string.
291 if (IS_UNDEFINED(separator)) return [subject];
292
293 var separator_length = separator_string.length;
294
295 // If the separator string is empty then return the elements in the subject.
296 if (separator_length === 0) return %StringToArray(subject, limit);
297
298 return %StringSplit(subject, separator_string, limit);
299 }
300
301
302 // ECMA-262, 15.5.4.16 109 // ECMA-262, 15.5.4.16
303 function StringToLowerCaseJS() { 110 function StringToLowerCaseJS() {
304 CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase"); 111 CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
305 112
306 return %StringToLowerCase(TO_STRING(this)); 113 return %StringToLowerCase(TO_STRING(this));
307 } 114 }
308 115
309 116
310 // ECMA-262, 15.5.4.17 117 // ECMA-262, 15.5.4.17
311 function StringToLocaleLowerCase() { 118 function StringToLocaleLowerCase() {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 utils.InstallFunctions(GlobalString, DONT_ENUM, [ 315 utils.InstallFunctions(GlobalString, DONT_ENUM, [
509 "raw", StringRaw 316 "raw", StringRaw
510 ]); 317 ]);
511 318
512 // Set up the non-enumerable functions on the String prototype object. 319 // Set up the non-enumerable functions on the String prototype object.
513 utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [ 320 utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [
514 "codePointAt", StringCodePointAt, 321 "codePointAt", StringCodePointAt,
515 "concat", StringConcat, 322 "concat", StringConcat,
516 "match", StringMatchJS, 323 "match", StringMatchJS,
517 "repeat", StringRepeat, 324 "repeat", StringRepeat,
518 "replace", StringReplace,
519 "search", StringSearch, 325 "search", StringSearch,
520 "slice", StringSlice, 326 "slice", StringSlice,
521 "split", StringSplitJS,
522 "toLowerCase", StringToLowerCaseJS, 327 "toLowerCase", StringToLowerCaseJS,
523 "toLocaleLowerCase", StringToLocaleLowerCase, 328 "toLocaleLowerCase", StringToLocaleLowerCase,
524 "toUpperCase", StringToUpperCaseJS, 329 "toUpperCase", StringToUpperCaseJS,
525 "toLocaleUpperCase", StringToLocaleUpperCase, 330 "toLocaleUpperCase", StringToLocaleUpperCase,
526 331
527 "link", StringLink, 332 "link", StringLink,
528 "anchor", StringAnchor, 333 "anchor", StringAnchor,
529 "fontcolor", StringFontcolor, 334 "fontcolor", StringFontcolor,
530 "fontsize", StringFontsize, 335 "fontsize", StringFontsize,
531 "big", StringBig, 336 "big", StringBig,
532 "blink", StringBlink, 337 "blink", StringBlink,
533 "bold", StringBold, 338 "bold", StringBold,
534 "fixed", StringFixed, 339 "fixed", StringFixed,
535 "italics", StringItalics, 340 "italics", StringItalics,
536 "small", StringSmall, 341 "small", StringSmall,
537 "strike", StringStrike, 342 "strike", StringStrike,
538 "sub", StringSub, 343 "sub", StringSub,
539 "sup", StringSup 344 "sup", StringSup
540 ]); 345 ]);
541 346
542 // -------------------------------------------------------------------
543 // Exports
544
545 utils.Export(function(to) {
546 to.StringMatch = StringMatchJS;
547 to.StringReplace = StringReplace;
548 to.StringSlice = StringSlice;
549 to.StringSplit = StringSplitJS;
550 });
551
552 }) 347 })
OLDNEW
« no previous file with comments | « src/builtins/builtins-string.cc ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698