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

Side by Side Diff: src/string.js

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 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 | Annotate | Revision Log
« no previous file with comments | « src/spaces-inl.h ('k') | src/string-stream.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 parts[i + 1] = TO_STRING_INLINE(part); 94 parts[i + 1] = TO_STRING_INLINE(part);
95 } 95 }
96 return %StringBuilderConcat(parts, len + 1, ""); 96 return %StringBuilderConcat(parts, len + 1, "");
97 } 97 }
98 98
99 // Match ES3 and Safari 99 // Match ES3 and Safari
100 %FunctionSetLength(StringConcat, 1); 100 %FunctionSetLength(StringConcat, 1);
101 101
102 102
103 // ECMA-262 section 15.5.4.7 103 // ECMA-262 section 15.5.4.7
104 function StringIndexOf(searchString /* position */) { // length == 1 104 function StringIndexOf(pattern /* position */) { // length == 1
105 var subject_str = TO_STRING_INLINE(this); 105 var subject = TO_STRING_INLINE(this);
106 var pattern_str = TO_STRING_INLINE(searchString); 106 var pattern = TO_STRING_INLINE(pattern);
107 var subject_str_len = subject_str.length; 107 var subject_len = subject.length;
108 var pattern_str_len = pattern_str.length; 108 var pattern_len = pattern.length;
109 var index = 0; 109 var index = 0;
110 if (%_ArgumentsLength() > 1) { 110 if (%_ArgumentsLength() > 1) {
111 var arg1 = %_Arguments(1); // position 111 var arg1 = %_Arguments(1); // position
112 index = TO_INTEGER(arg1); 112 index = TO_INTEGER(arg1);
113 } 113 }
114 if (index < 0) index = 0; 114 if (index < 0) index = 0;
115 if (index > subject_str_len) index = subject_str_len; 115 if (index > subject_len) index = subject_len;
116 if (pattern_str_len + index > subject_str_len) return -1; 116 if (pattern_len + index > subject_len) return -1;
117 return %StringIndexOf(subject_str, pattern_str, index); 117 return %StringIndexOf(subject, pattern, index);
118 } 118 }
119 119
120 120
121 // ECMA-262 section 15.5.4.8 121 // ECMA-262 section 15.5.4.8
122 function StringLastIndexOf(searchString /* position */) { // length == 1 122 function StringLastIndexOf(pat /* position */) { // length == 1
123 var sub = TO_STRING_INLINE(this); 123 var sub = TO_STRING_INLINE(this);
124 var subLength = sub.length; 124 var subLength = sub.length;
125 var pat = TO_STRING_INLINE(searchString); 125 var pat = TO_STRING_INLINE(pat);
126 var patLength = pat.length; 126 var patLength = pat.length;
127 var index = subLength - patLength; 127 var index = subLength - patLength;
128 if (%_ArgumentsLength() > 1) { 128 if (%_ArgumentsLength() > 1) {
129 var position = ToNumber(%_Arguments(1)); 129 var position = ToNumber(%_Arguments(1));
130 if (!$isNaN(position)) { 130 if (!$isNaN(position)) {
131 position = TO_INTEGER(position); 131 position = TO_INTEGER(position);
132 if (position < 0) { 132 if (position < 0) {
133 position = 0; 133 position = 0;
134 } 134 }
135 if (position + patLength < subLength) { 135 if (position + patLength < subLength) {
136 index = position 136 index = position
137 } 137 }
138 } 138 }
139 } 139 }
140 if (index < 0) { 140 if (index < 0) {
141 return -1; 141 return -1;
142 } 142 }
143 return %StringLastIndexOf(sub, pat, index); 143 return %StringLastIndexOf(sub, pat, index);
144 } 144 }
145 145
146 146
147 // ECMA-262 section 15.5.4.9 147 // ECMA-262 section 15.5.4.9
148 // 148 //
149 // This function is implementation specific. For now, we do not 149 // This function is implementation specific. For now, we do not
150 // do anything locale specific. 150 // do anything locale specific.
151 function StringLocaleCompare(other) { 151 function StringLocaleCompare(other) {
152 if (%_ArgumentsLength() === 0) return 0; 152 if (%_ArgumentsLength() === 0) return 0;
153 153 return %StringLocaleCompare(TO_STRING_INLINE(this),
154 var this_str = TO_STRING_INLINE(this); 154 TO_STRING_INLINE(other));
155 var other_str = TO_STRING_INLINE(other);
156 return %StringLocaleCompare(this_str, other_str);
157 } 155 }
158 156
159 157
160 // ECMA-262 section 15.5.4.10 158 // ECMA-262 section 15.5.4.10
161 function StringMatch(regexp) { 159 function StringMatch(regexp) {
162 var subject = TO_STRING_INLINE(this); 160 var subject = TO_STRING_INLINE(this);
163 if (IS_REGEXP(regexp)) { 161 if (IS_REGEXP(regexp)) {
164 if (!regexp.global) return regexp.exec(subject); 162 if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
165 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); 163 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
166 // lastMatchInfo is defined in regexp.js. 164 // lastMatchInfo is defined in regexp.js.
167 return %StringMatch(subject, regexp, lastMatchInfo); 165 return %StringMatch(subject, regexp, lastMatchInfo);
168 } 166 }
169 // Non-regexp argument. 167 // Non-regexp argument.
170 regexp = new $RegExp(regexp); 168 regexp = new $RegExp(regexp);
171 return RegExpExecNoTests(regexp, subject, 0); 169 return RegExpExecNoTests(regexp, subject, 0);
172 } 170 }
173 171
174 172
175 // SubString is an internal function that returns the sub string of 'string'. 173 // SubString is an internal function that returns the sub string of 'string'.
176 // If resulting string is of length 1, we use the one character cache 174 // If resulting string is of length 1, we use the one character cache
177 // otherwise we call the runtime system. 175 // otherwise we call the runtime system.
178 function SubString(string, start, end) { 176 function SubString(string, start, end) {
179 // Use the one character string cache. 177 // Use the one character string cache.
180 if (start + 1 == end) { 178 if (start + 1 == end) return %_StringCharAt(string, start);
181 return %_StringCharAt(string, start);
182 }
183 return %_SubString(string, start, end); 179 return %_SubString(string, start, end);
184 } 180 }
185 181
186 182
187 // This has the same size as the lastMatchInfo array, and can be used for 183 // This has the same size as the lastMatchInfo array, and can be used for
188 // functions that expect that structure to be returned. It is used when the 184 // functions that expect that structure to be returned. It is used when the
189 // needle is a string rather than a regexp. In this case we can't update 185 // needle is a string rather than a regexp. In this case we can't update
190 // lastMatchArray without erroneously affecting the properties on the global 186 // lastMatchArray without erroneously affecting the properties on the global
191 // RegExp object. 187 // RegExp object.
192 var reusableMatchInfo = [2, "", "", -1, -1]; 188 var reusableMatchInfo = [2, "", "", -1, -1];
193 189
194 190
195 // ECMA-262, section 15.5.4.11 191 // ECMA-262, section 15.5.4.11
196 function StringReplace(search, replace) { 192 function StringReplace(search, replace) {
197 var subject = TO_STRING_INLINE(this); 193 var subject = TO_STRING_INLINE(this);
198 194
199 // Delegate to one of the regular expression variants if necessary. 195 // Delegate to one of the regular expression variants if necessary.
200 if (IS_REGEXP(search)) { 196 if (IS_REGEXP(search)) {
201 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); 197 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
202 if (IS_FUNCTION(replace)) { 198 if (IS_FUNCTION(replace)) {
203 if (search.global) { 199 if (search.global) {
204 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); 200 return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
205 } else { 201 } else {
206 return StringReplaceNonGlobalRegExpWithFunction(subject, 202 return StringReplaceNonGlobalRegExpWithFunction(subject,
207 search, 203 search,
208 replace); 204 replace);
209 } 205 }
210 } else { 206 } else {
211 return StringReplaceRegExp(subject, search, replace); 207 return %StringReplaceRegExpWithString(subject,
208 search,
209 TO_STRING_INLINE(replace),
210 lastMatchInfo);
212 } 211 }
213 } 212 }
214 213
215 // Convert the search argument to a string and search for it. 214 // Convert the search argument to a string and search for it.
216 search = TO_STRING_INLINE(search); 215 search = TO_STRING_INLINE(search);
217 var start = %StringIndexOf(subject, search, 0); 216 var start = %StringIndexOf(subject, search, 0);
218 if (start < 0) return subject; 217 if (start < 0) return subject;
219 var end = start + search.length; 218 var end = start + search.length;
220 219
221 var builder = new ReplaceResultBuilder(subject); 220 var builder = new ReplaceResultBuilder(subject);
222 // prefix 221 // prefix
223 builder.addSpecialSlice(0, start); 222 builder.addSpecialSlice(0, start);
224 223
225 // Compute the string to replace with. 224 // Compute the string to replace with.
226 if (IS_FUNCTION(replace)) { 225 if (IS_FUNCTION(replace)) {
227 builder.add(replace.call(null, search, start, subject)); 226 builder.add(%_CallFunction(%GetGlobalReceiver(),
227 search,
228 start,
229 subject,
230 replace));
228 } else { 231 } else {
229 reusableMatchInfo[CAPTURE0] = start; 232 reusableMatchInfo[CAPTURE0] = start;
230 reusableMatchInfo[CAPTURE1] = end; 233 reusableMatchInfo[CAPTURE1] = end;
231 replace = TO_STRING_INLINE(replace); 234 replace = TO_STRING_INLINE(replace);
232 ExpandReplacement(replace, subject, reusableMatchInfo, builder); 235 ExpandReplacement(replace, subject, reusableMatchInfo, builder);
233 } 236 }
234 237
235 // suffix 238 // suffix
236 builder.addSpecialSlice(end, subject.length); 239 builder.addSpecialSlice(end, subject.length);
237 240
238 return builder.generate(); 241 return builder.generate();
239 } 242 }
240 243
241 244
242 // Helper function for regular expressions in String.prototype.replace.
243 function StringReplaceRegExp(subject, regexp, replace) {
244 return %StringReplaceRegExpWithString(subject,
245 regexp,
246 TO_STRING_INLINE(replace),
247 lastMatchInfo);
248 }
249
250
251 // Expand the $-expressions in the string and return a new string with 245 // Expand the $-expressions in the string and return a new string with
252 // the result. 246 // the result.
253 function ExpandReplacement(string, subject, matchInfo, builder) { 247 function ExpandReplacement(string, subject, matchInfo, builder) {
248 var length = string.length;
249 var builder_elements = builder.elements;
254 var next = %StringIndexOf(string, '$', 0); 250 var next = %StringIndexOf(string, '$', 0);
255 if (next < 0) { 251 if (next < 0) {
256 builder.add(string); 252 if (length > 0) builder_elements.push(string);
257 return; 253 return;
258 } 254 }
259 255
260 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. 256 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
261 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match. 257 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match.
262 258
263 if (next > 0) builder.add(SubString(string, 0, next)); 259 if (next > 0) builder_elements.push(SubString(string, 0, next));
264 var length = string.length;
265 260
266 while (true) { 261 while (true) {
267 var expansion = '$'; 262 var expansion = '$';
268 var position = next + 1; 263 var position = next + 1;
269 if (position < length) { 264 if (position < length) {
270 var peek = %_StringCharCodeAt(string, position); 265 var peek = %_StringCharCodeAt(string, position);
271 if (peek == 36) { // $$ 266 if (peek == 36) { // $$
272 ++position; 267 ++position;
273 builder.add('$'); 268 builder_elements.push('$');
274 } else if (peek == 38) { // $& - match 269 } else if (peek == 38) { // $& - match
275 ++position; 270 ++position;
276 builder.addSpecialSlice(matchInfo[CAPTURE0], 271 builder.addSpecialSlice(matchInfo[CAPTURE0],
277 matchInfo[CAPTURE1]); 272 matchInfo[CAPTURE1]);
278 } else if (peek == 96) { // $` - prefix 273 } else if (peek == 96) { // $` - prefix
279 ++position; 274 ++position;
280 builder.addSpecialSlice(0, matchInfo[CAPTURE0]); 275 builder.addSpecialSlice(0, matchInfo[CAPTURE0]);
281 } else if (peek == 39) { // $' - suffix 276 } else if (peek == 39) { // $' - suffix
282 ++position; 277 ++position;
283 builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length); 278 builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length);
(...skipping 16 matching lines...) Expand all
300 } 295 }
301 } 296 }
302 } 297 }
303 if (0 < n && n < m) { 298 if (0 < n && n < m) {
304 addCaptureString(builder, matchInfo, n); 299 addCaptureString(builder, matchInfo, n);
305 } else { 300 } else {
306 // Because of the captures range check in the parsing of two 301 // Because of the captures range check in the parsing of two
307 // digit capture references, we can only enter here when a 302 // digit capture references, we can only enter here when a
308 // single digit capture reference is outside the range of 303 // single digit capture reference is outside the range of
309 // captures. 304 // captures.
310 builder.add('$'); 305 builder_elements.push('$');
311 --position; 306 --position;
312 } 307 }
313 } else { 308 } else {
314 builder.add('$'); 309 builder_elements.push('$');
315 } 310 }
316 } else { 311 } else {
317 builder.add('$'); 312 builder_elements.push('$');
318 } 313 }
319 314
320 // Go the the next $ in the string. 315 // Go the the next $ in the string.
321 next = %StringIndexOf(string, '$', position); 316 next = %StringIndexOf(string, '$', position);
322 317
323 // Return if there are no more $ characters in the string. If we 318 // Return if there are no more $ characters in the string. If we
324 // haven't reached the end, we need to append the suffix. 319 // haven't reached the end, we need to append the suffix.
325 if (next < 0) { 320 if (next < 0) {
326 if (position < length) { 321 if (position < length) {
327 builder.add(SubString(string, position, length)); 322 builder_elements.push(SubString(string, position, length));
328 } 323 }
329 return; 324 return;
330 } 325 }
331 326
332 // Append substring between the previous and the next $ character. 327 // Append substring between the previous and the next $ character.
333 builder.add(SubString(string, position, next)); 328 if (next > position) {
329 builder_elements.push(SubString(string, position, next));
330 }
334 } 331 }
335 }; 332 };
336 333
337 334
338 // Compute the string of a given regular expression capture. 335 // Compute the string of a given regular expression capture.
339 function CaptureString(string, lastCaptureInfo, index) { 336 function CaptureString(string, lastCaptureInfo, index) {
340 // Scale the index. 337 // Scale the index.
341 var scaled = index << 1; 338 var scaled = index << 1;
342 // Compute start and end. 339 // Compute start and end.
343 var start = lastCaptureInfo[CAPTURE(scaled)]; 340 var start = lastCaptureInfo[CAPTURE(scaled)];
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 match_start = (elem >> 11) + (elem & 0x7ff); 398 match_start = (elem >> 11) + (elem & 0x7ff);
402 } else { 399 } else {
403 match_start = res[++i] - elem; 400 match_start = res[++i] - elem;
404 } 401 }
405 } else { 402 } else {
406 override[0] = elem; 403 override[0] = elem;
407 override[1] = match_start; 404 override[1] = match_start;
408 lastMatchInfoOverride = override; 405 lastMatchInfoOverride = override;
409 var func_result = 406 var func_result =
410 %_CallFunction(receiver, elem, match_start, subject, replace); 407 %_CallFunction(receiver, elem, match_start, subject, replace);
411 if (!IS_STRING(func_result)) { 408 func_result = TO_STRING_INLINE(func_result);
412 func_result = NonStringToString(func_result);
413 }
414 res[i] = func_result; 409 res[i] = func_result;
415 match_start += elem.length; 410 match_start += elem.length;
416 } 411 }
417 i++; 412 i++;
418 } 413 }
419 } else { 414 } else {
420 while (i < len) { 415 while (i < len) {
421 var elem = res[i]; 416 var elem = res[i];
422 if (!%_IsSmi(elem)) { 417 if (!%_IsSmi(elem)) {
423 // elem must be an Array. 418 // elem must be an Array.
424 // Use the apply argument as backing for global RegExp properties. 419 // Use the apply argument as backing for global RegExp properties.
425 lastMatchInfoOverride = elem; 420 lastMatchInfoOverride = elem;
426 var func_result = replace.apply(null, elem); 421 var func_result = replace.apply(null, elem);
427 if (!IS_STRING(func_result)) { 422 func_result = TO_STRING_INLINE(func_result);
428 func_result = NonStringToString(func_result);
429 }
430 res[i] = func_result; 423 res[i] = func_result;
431 } 424 }
432 i++; 425 i++;
433 } 426 }
434 } 427 }
435 var resultBuilder = new ReplaceResultBuilder(subject, res); 428 var resultBuilder = new ReplaceResultBuilder(subject, res);
436 var result = resultBuilder.generate(); 429 var result = resultBuilder.generate();
437 resultArray.length = 0; 430 resultArray.length = 0;
438 reusableReplaceArray = resultArray; 431 reusableReplaceArray = resultArray;
439 return result; 432 return result;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 // ECMA-262 section 15.5.4.12 473 // ECMA-262 section 15.5.4.12
481 function StringSearch(re) { 474 function StringSearch(re) {
482 var regexp; 475 var regexp;
483 if (IS_STRING(re)) { 476 if (IS_STRING(re)) {
484 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re); 477 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re);
485 } else if (IS_REGEXP(re)) { 478 } else if (IS_REGEXP(re)) {
486 regexp = re; 479 regexp = re;
487 } else { 480 } else {
488 regexp = new $RegExp(re); 481 regexp = new $RegExp(re);
489 } 482 }
490 var s = TO_STRING_INLINE(this); 483 var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0);
491 var match = DoRegExpExec(regexp, s, 0);
492 if (match) { 484 if (match) {
493 return match[CAPTURE0]; 485 return match[CAPTURE0];
494 } 486 }
495 return -1; 487 return -1;
496 } 488 }
497 489
498 490
499 // ECMA-262 section 15.5.4.13 491 // ECMA-262 section 15.5.4.13
500 function StringSlice(start, end) { 492 function StringSlice(start, end) {
501 var s = TO_STRING_INLINE(this); 493 var s = TO_STRING_INLINE(this);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 555
564 if (length === 0) { 556 if (length === 0) {
565 if (DoRegExpExec(separator, subject, 0, 0) != null) { 557 if (DoRegExpExec(separator, subject, 0, 0) != null) {
566 return []; 558 return [];
567 } 559 }
568 return [subject]; 560 return [subject];
569 } 561 }
570 562
571 var currentIndex = 0; 563 var currentIndex = 0;
572 var startIndex = 0; 564 var startIndex = 0;
565 var startMatch = 0;
573 var result = []; 566 var result = [];
574 567
575 outer_loop: 568 outer_loop:
576 while (true) { 569 while (true) {
577 570
578 if (startIndex === length) { 571 if (startIndex === length) {
579 result[result.length] = subject.slice(currentIndex, length); 572 result.push(SubString(subject, currentIndex, length));
580 break; 573 break;
581 } 574 }
582 575
583 var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); 576 var matchInfo = DoRegExpExec(separator, subject, startIndex);
584 577 if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
585 if (IS_NULL(matchInfo)) { 578 result.push(SubString(subject, currentIndex, length));
586 result[result.length] = subject.slice(currentIndex, length);
587 break; 579 break;
588 } 580 }
589
590 var endIndex = matchInfo[CAPTURE1]; 581 var endIndex = matchInfo[CAPTURE1];
591 582
592 // We ignore a zero-length match at the currentIndex. 583 // We ignore a zero-length match at the currentIndex.
593 if (startIndex === endIndex && endIndex === currentIndex) { 584 if (startIndex === endIndex && endIndex === currentIndex) {
594 startIndex++; 585 startIndex++;
595 continue; 586 continue;
596 } 587 }
597 588
598 result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0] ); 589 if (currentIndex + 1 == startMatch) {
590 result.push(%_StringCharAt(subject, currentIndex));
591 } else {
592 result.push(%_SubString(subject, currentIndex, startMatch));
593 }
594
599 if (result.length === limit) break; 595 if (result.length === limit) break;
600 596
601 var num_captures = NUMBER_OF_CAPTURES(matchInfo); 597 var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
602 for (var i = 2; i < num_captures; i += 2) { 598 for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) {
603 var start = matchInfo[CAPTURE(i)]; 599 var start = matchInfo[i++];
604 var end = matchInfo[CAPTURE(i + 1)]; 600 var end = matchInfo[i++];
605 if (start != -1 && end != -1) { 601 if (end != -1) {
606 result[result.length] = SubString(subject, start, end); 602 if (start + 1 == end) {
603 result.push(%_StringCharAt(subject, start));
604 } else {
605 result.push(%_SubString(subject, start, end));
606 }
607 } else { 607 } else {
608 result[result.length] = void 0; 608 result.push(void 0);
609 } 609 }
610 if (result.length === limit) break outer_loop; 610 if (result.length === limit) break outer_loop;
611 } 611 }
612 612
613 startIndex = currentIndex = endIndex; 613 startIndex = currentIndex = endIndex;
614 } 614 }
615 return result; 615 return result;
616 } 616 }
617 617
618 618
619 // ECMA-262 section 15.5.4.14
620 // Helper function used by split. This version returns the matchInfo
621 // instead of allocating a new array with basically the same information.
622 function splitMatch(separator, subject, current_index, start_index) {
623 var matchInfo = DoRegExpExec(separator, subject, start_index);
624 if (matchInfo == null) return null;
625 // Section 15.5.4.14 paragraph two says that we do not allow zero length
626 // matches at the end of the string.
627 if (matchInfo[CAPTURE0] === subject.length) return null;
628 return matchInfo;
629 }
630
631
632 // ECMA-262 section 15.5.4.15 619 // ECMA-262 section 15.5.4.15
633 function StringSubstring(start, end) { 620 function StringSubstring(start, end) {
634 var s = TO_STRING_INLINE(this); 621 var s = TO_STRING_INLINE(this);
635 var s_len = s.length; 622 var s_len = s.length;
636 623
637 var start_i = TO_INTEGER(start); 624 var start_i = TO_INTEGER(start);
638 if (start_i < 0) { 625 if (start_i < 0) {
639 start_i = 0; 626 start_i = 0;
640 } else if (start_i > s_len) { 627 } else if (start_i > s_len) {
641 start_i = s_len; 628 start_i = s_len;
642 } 629 }
643 630
644 var end_i = s_len; 631 var end_i = s_len;
645 if (!IS_UNDEFINED(end)) { 632 if (!IS_UNDEFINED(end)) {
646 end_i = TO_INTEGER(end); 633 end_i = TO_INTEGER(end);
647 if (end_i > s_len) { 634 if (end_i > s_len) {
648 end_i = s_len; 635 end_i = s_len;
649 } else { 636 } else {
650 if (end_i < 0) end_i = 0; 637 if (end_i < 0) end_i = 0;
651 if (start_i > end_i) { 638 if (start_i > end_i) {
652 var tmp = end_i; 639 var tmp = end_i;
653 end_i = start_i; 640 end_i = start_i;
654 start_i = tmp; 641 start_i = tmp;
655 } 642 }
656 } 643 }
657 } 644 }
658 645
659 return SubString(s, start_i, end_i); 646 return (start_i + 1 == end_i
647 ? %_StringCharAt(s, start_i)
648 : %_SubString(s, start_i, end_i));
660 } 649 }
661 650
662 651
663 // This is not a part of ECMA-262. 652 // This is not a part of ECMA-262.
664 function StringSubstr(start, n) { 653 function StringSubstr(start, n) {
665 var s = TO_STRING_INLINE(this); 654 var s = TO_STRING_INLINE(this);
666 var len; 655 var len;
667 656
668 // Correct n: If not given, set to string length; if explicitly 657 // Correct n: If not given, set to string length; if explicitly
669 // set to undefined, zero, or negative, returns empty string. 658 // set to undefined, zero, or negative, returns empty string.
(...skipping 17 matching lines...) Expand all
687 // use zero. 676 // use zero.
688 if (start < 0) { 677 if (start < 0) {
689 start += s.length; 678 start += s.length;
690 if (start < 0) start = 0; 679 if (start < 0) start = 0;
691 } 680 }
692 } 681 }
693 682
694 var end = start + len; 683 var end = start + len;
695 if (end > s.length) end = s.length; 684 if (end > s.length) end = s.length;
696 685
697 return SubString(s, start, end); 686 return (start + 1 == end
687 ? %_StringCharAt(s, start)
688 : %_SubString(s, start, end));
698 } 689 }
699 690
700 691
701 // ECMA-262, 15.5.4.16 692 // ECMA-262, 15.5.4.16
702 function StringToLowerCase() { 693 function StringToLowerCase() {
703 return %StringToLowerCase(TO_STRING_INLINE(this)); 694 return %StringToLowerCase(TO_STRING_INLINE(this));
704 } 695 }
705 696
706 697
707 // ECMA-262, 15.5.4.17 698 // ECMA-262, 15.5.4.17
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 this.elements = %_Arguments(1); 831 this.elements = %_Arguments(1);
841 } else { 832 } else {
842 this.elements = new $Array(); 833 this.elements = new $Array();
843 } 834 }
844 this.special_string = str; 835 this.special_string = str;
845 } 836 }
846 837
847 838
848 ReplaceResultBuilder.prototype.add = function(str) { 839 ReplaceResultBuilder.prototype.add = function(str) {
849 str = TO_STRING_INLINE(str); 840 str = TO_STRING_INLINE(str);
850 if (str.length > 0) { 841 if (str.length > 0) this.elements.push(str);
851 var elements = this.elements;
852 elements[elements.length] = str;
853 }
854 } 842 }
855 843
856 844
857 ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) { 845 ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
858 var len = end - start; 846 var len = end - start;
859 if (start < 0 || len <= 0) return; 847 if (start < 0 || len <= 0) return;
860 var elements = this.elements;
861 if (start < 0x80000 && len < 0x800) { 848 if (start < 0x80000 && len < 0x800) {
862 elements[elements.length] = (start << 11) | len; 849 this.elements.push((start << 11) | len);
863 } else { 850 } else {
864 // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength, 851 // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
865 // so -len is a smi. 852 // so -len is a smi.
866 elements[elements.length] = -len; 853 var elements = this.elements;
867 elements[elements.length] = start; 854 elements.push(-len);
855 elements.push(start);
868 } 856 }
869 } 857 }
870 858
871 859
872 ReplaceResultBuilder.prototype.generate = function() { 860 ReplaceResultBuilder.prototype.generate = function() {
873 var elements = this.elements; 861 var elements = this.elements;
874 return %StringBuilderConcat(elements, elements.length, this.special_string); 862 return %StringBuilderConcat(elements, elements.length, this.special_string);
875 } 863 }
876 864
877 865
878 function StringToJSON(key) {
879 return CheckJSONPrimitive(this.valueOf());
880 }
881
882
883 // ------------------------------------------------------------------- 866 // -------------------------------------------------------------------
884 867
885 function SetupString() { 868 function SetupString() {
886 // Setup the constructor property on the String prototype object. 869 // Setup the constructor property on the String prototype object.
887 %SetProperty($String.prototype, "constructor", $String, DONT_ENUM); 870 %SetProperty($String.prototype, "constructor", $String, DONT_ENUM);
888 871
889 872
890 // Setup the non-enumerable functions on the String object. 873 // Setup the non-enumerable functions on the String object.
891 InstallFunctions($String, DONT_ENUM, $Array( 874 InstallFunctions($String, DONT_ENUM, $Array(
892 "fromCharCode", StringFromCharCode 875 "fromCharCode", StringFromCharCode
(...skipping 29 matching lines...) Expand all
922 "fontcolor", StringFontcolor, 905 "fontcolor", StringFontcolor,
923 "fontsize", StringFontsize, 906 "fontsize", StringFontsize,
924 "big", StringBig, 907 "big", StringBig,
925 "blink", StringBlink, 908 "blink", StringBlink,
926 "bold", StringBold, 909 "bold", StringBold,
927 "fixed", StringFixed, 910 "fixed", StringFixed,
928 "italics", StringItalics, 911 "italics", StringItalics,
929 "small", StringSmall, 912 "small", StringSmall,
930 "strike", StringStrike, 913 "strike", StringStrike,
931 "sub", StringSub, 914 "sub", StringSub,
932 "sup", StringSup, 915 "sup", StringSup
933 "toJSON", StringToJSON
934 )); 916 ));
935 } 917 }
936 918
937 919
938 SetupString(); 920 SetupString();
OLDNEW
« no previous file with comments | « src/spaces-inl.h ('k') | src/string-stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698