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

Side by Side Diff: src/string.js

Issue 5862002: Version 3.0.2. (Closed)
Patch Set: Created 10 years 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
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(pattern /* position */) { // length == 1 104 function StringIndexOf(searchString /* position */) { // length == 1
105 var subject = TO_STRING_INLINE(this); 105 var subject_str = TO_STRING_INLINE(this);
106 var pattern = TO_STRING_INLINE(pattern); 106 var pattern_str = TO_STRING_INLINE(searchString);
107 var subject_len = subject.length; 107 var subject_str_len = subject_str.length;
108 var pattern_len = pattern.length; 108 var pattern_str_len = pattern_str.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_len) index = subject_len; 115 if (index > subject_str_len) index = subject_str_len;
116 if (pattern_len + index > subject_len) return -1; 116 if (pattern_str_len + index > subject_str_len) return -1;
117 return %StringIndexOf(subject, pattern, index); 117 return %StringIndexOf(subject_str, pattern_str, 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(pat /* position */) { // length == 1 122 function StringLastIndexOf(searchString /* 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(pat); 125 var pat = TO_STRING_INLINE(searchString);
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 return %StringLocaleCompare(TO_STRING_INLINE(this), 153
154 TO_STRING_INLINE(other)); 154 var this_str = TO_STRING_INLINE(this);
155 var other_str = TO_STRING_INLINE(other);
156 return %StringLocaleCompare(this_str, other_str);
155 } 157 }
156 158
157 159
158 // ECMA-262 section 15.5.4.10 160 // ECMA-262 section 15.5.4.10
159 function StringMatch(regexp) { 161 function StringMatch(regexp) {
160 var subject = TO_STRING_INLINE(this); 162 var subject = TO_STRING_INLINE(this);
161 if (IS_REGEXP(regexp)) { 163 if (IS_REGEXP(regexp)) {
162 if (!regexp.global) return regexp.exec(subject); 164 if (!regexp.global) return regexp.exec(subject);
163 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); 165 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
164 // lastMatchInfo is defined in regexp.js. 166 // lastMatchInfo is defined in regexp.js.
165 return %StringMatch(subject, regexp, lastMatchInfo); 167 return %StringMatch(subject, regexp, lastMatchInfo);
166 } 168 }
167 // Non-regexp argument. 169 // Non-regexp argument.
168 regexp = new $RegExp(regexp); 170 regexp = new $RegExp(regexp);
169 return RegExpExecNoTests(regexp, subject, 0); 171 return RegExpExecNoTests(regexp, subject, 0);
170 } 172 }
171 173
172 174
173 // SubString is an internal function that returns the sub string of 'string'. 175 // SubString is an internal function that returns the sub string of 'string'.
174 // If resulting string is of length 1, we use the one character cache 176 // If resulting string is of length 1, we use the one character cache
175 // otherwise we call the runtime system. 177 // otherwise we call the runtime system.
176 function SubString(string, start, end) { 178 function SubString(string, start, end) {
177 // Use the one character string cache. 179 // Use the one character string cache.
178 if (start + 1 == end) return %_StringCharAt(string, start); 180 if (start + 1 == end) {
181 return %_StringCharAt(string, start);
182 }
179 return %_SubString(string, start, end); 183 return %_SubString(string, start, end);
180 } 184 }
181 185
182 186
183 // This has the same size as the lastMatchInfo array, and can be used for 187 // This has the same size as the lastMatchInfo array, and can be used for
184 // functions that expect that structure to be returned. It is used when the 188 // functions that expect that structure to be returned. It is used when the
185 // needle is a string rather than a regexp. In this case we can't update 189 // needle is a string rather than a regexp. In this case we can't update
186 // lastMatchArray without erroneously affecting the properties on the global 190 // lastMatchArray without erroneously affecting the properties on the global
187 // RegExp object. 191 // RegExp object.
188 var reusableMatchInfo = [2, "", "", -1, -1]; 192 var reusableMatchInfo = [2, "", "", -1, -1];
189 193
190 194
191 // ECMA-262, section 15.5.4.11 195 // ECMA-262, section 15.5.4.11
192 function StringReplace(search, replace) { 196 function StringReplace(search, replace) {
193 var subject = TO_STRING_INLINE(this); 197 var subject = TO_STRING_INLINE(this);
194 198
195 // Delegate to one of the regular expression variants if necessary. 199 // Delegate to one of the regular expression variants if necessary.
196 if (IS_REGEXP(search)) { 200 if (IS_REGEXP(search)) {
197 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); 201 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
198 if (IS_FUNCTION(replace)) { 202 if (IS_FUNCTION(replace)) {
199 if (search.global) { 203 if (search.global) {
200 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); 204 return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
201 } else { 205 } else {
202 return StringReplaceNonGlobalRegExpWithFunction(subject, 206 return StringReplaceNonGlobalRegExpWithFunction(subject,
203 search, 207 search,
204 replace); 208 replace);
205 } 209 }
206 } else { 210 } else {
207 return %StringReplaceRegExpWithString(subject, 211 return StringReplaceRegExp(subject, search, replace);
208 search,
209 TO_STRING_INLINE(replace),
210 lastMatchInfo);
211 } 212 }
212 } 213 }
213 214
214 // Convert the search argument to a string and search for it. 215 // Convert the search argument to a string and search for it.
215 search = TO_STRING_INLINE(search); 216 search = TO_STRING_INLINE(search);
216 var start = %StringIndexOf(subject, search, 0); 217 var start = %StringIndexOf(subject, search, 0);
217 if (start < 0) return subject; 218 if (start < 0) return subject;
218 var end = start + search.length; 219 var end = start + search.length;
219 220
220 var builder = new ReplaceResultBuilder(subject); 221 var builder = new ReplaceResultBuilder(subject);
221 // prefix 222 // prefix
222 builder.addSpecialSlice(0, start); 223 builder.addSpecialSlice(0, start);
223 224
224 // Compute the string to replace with. 225 // Compute the string to replace with.
225 if (IS_FUNCTION(replace)) { 226 if (IS_FUNCTION(replace)) {
226 builder.add(%_CallFunction(%GetGlobalReceiver(), 227 builder.add(replace.call(null, search, start, subject));
227 search,
228 start,
229 subject,
230 replace));
231 } else { 228 } else {
232 reusableMatchInfo[CAPTURE0] = start; 229 reusableMatchInfo[CAPTURE0] = start;
233 reusableMatchInfo[CAPTURE1] = end; 230 reusableMatchInfo[CAPTURE1] = end;
234 replace = TO_STRING_INLINE(replace); 231 replace = TO_STRING_INLINE(replace);
235 ExpandReplacement(replace, subject, reusableMatchInfo, builder); 232 ExpandReplacement(replace, subject, reusableMatchInfo, builder);
236 } 233 }
237 234
238 // suffix 235 // suffix
239 builder.addSpecialSlice(end, subject.length); 236 builder.addSpecialSlice(end, subject.length);
240 237
241 return builder.generate(); 238 return builder.generate();
242 } 239 }
243 240
244 241
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
245 // Expand the $-expressions in the string and return a new string with 251 // Expand the $-expressions in the string and return a new string with
246 // the result. 252 // the result.
247 function ExpandReplacement(string, subject, matchInfo, builder) { 253 function ExpandReplacement(string, subject, matchInfo, builder) {
248 var next = %StringIndexOf(string, '$', 0); 254 var next = %StringIndexOf(string, '$', 0);
249 if (next < 0) { 255 if (next < 0) {
250 builder.add(string); 256 builder.add(string);
251 return; 257 return;
252 } 258 }
253 259
254 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. 260 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 match_start = (elem >> 11) + (elem & 0x7ff); 401 match_start = (elem >> 11) + (elem & 0x7ff);
396 } else { 402 } else {
397 match_start = res[++i] - elem; 403 match_start = res[++i] - elem;
398 } 404 }
399 } else { 405 } else {
400 override[0] = elem; 406 override[0] = elem;
401 override[1] = match_start; 407 override[1] = match_start;
402 lastMatchInfoOverride = override; 408 lastMatchInfoOverride = override;
403 var func_result = 409 var func_result =
404 %_CallFunction(receiver, elem, match_start, subject, replace); 410 %_CallFunction(receiver, elem, match_start, subject, replace);
405 func_result = TO_STRING_INLINE(func_result); 411 if (!IS_STRING(func_result)) {
412 func_result = NonStringToString(func_result);
413 }
406 res[i] = func_result; 414 res[i] = func_result;
407 match_start += elem.length; 415 match_start += elem.length;
408 } 416 }
409 i++; 417 i++;
410 } 418 }
411 } else { 419 } else {
412 while (i < len) { 420 while (i < len) {
413 var elem = res[i]; 421 var elem = res[i];
414 if (!%_IsSmi(elem)) { 422 if (!%_IsSmi(elem)) {
415 // elem must be an Array. 423 // elem must be an Array.
416 // Use the apply argument as backing for global RegExp properties. 424 // Use the apply argument as backing for global RegExp properties.
417 lastMatchInfoOverride = elem; 425 lastMatchInfoOverride = elem;
418 var func_result = replace.apply(null, elem); 426 var func_result = replace.apply(null, elem);
419 func_result = TO_STRING_INLINE(func_result); 427 if (!IS_STRING(func_result)) {
428 func_result = NonStringToString(func_result);
429 }
420 res[i] = func_result; 430 res[i] = func_result;
421 } 431 }
422 i++; 432 i++;
423 } 433 }
424 } 434 }
425 var resultBuilder = new ReplaceResultBuilder(subject, res); 435 var resultBuilder = new ReplaceResultBuilder(subject, res);
426 var result = resultBuilder.generate(); 436 var result = resultBuilder.generate();
427 resultArray.length = 0; 437 resultArray.length = 0;
428 reusableReplaceArray = resultArray; 438 reusableReplaceArray = resultArray;
429 return result; 439 return result;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 // ECMA-262 section 15.5.4.12 480 // ECMA-262 section 15.5.4.12
471 function StringSearch(re) { 481 function StringSearch(re) {
472 var regexp; 482 var regexp;
473 if (IS_STRING(re)) { 483 if (IS_STRING(re)) {
474 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re); 484 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re);
475 } else if (IS_REGEXP(re)) { 485 } else if (IS_REGEXP(re)) {
476 regexp = re; 486 regexp = re;
477 } else { 487 } else {
478 regexp = new $RegExp(re); 488 regexp = new $RegExp(re);
479 } 489 }
480 var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0); 490 var s = TO_STRING_INLINE(this);
491 var match = DoRegExpExec(regexp, s, 0);
481 if (match) { 492 if (match) {
482 return match[CAPTURE0]; 493 return match[CAPTURE0];
483 } 494 }
484 return -1; 495 return -1;
485 } 496 }
486 497
487 498
488 // ECMA-262 section 15.5.4.13 499 // ECMA-262 section 15.5.4.13
489 function StringSlice(start, end) { 500 function StringSlice(start, end) {
490 var s = TO_STRING_INLINE(this); 501 var s = TO_STRING_INLINE(this);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 } 569 }
559 570
560 var currentIndex = 0; 571 var currentIndex = 0;
561 var startIndex = 0; 572 var startIndex = 0;
562 var result = []; 573 var result = [];
563 574
564 outer_loop: 575 outer_loop:
565 while (true) { 576 while (true) {
566 577
567 if (startIndex === length) { 578 if (startIndex === length) {
568 result.push(subject.slice(currentIndex, length)); 579 result[result.length] = subject.slice(currentIndex, length);
569 break; 580 break;
570 } 581 }
571 582
572 var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); 583 var matchInfo = splitMatch(separator, subject, currentIndex, startIndex);
573 584
574 if (IS_NULL(matchInfo)) { 585 if (IS_NULL(matchInfo)) {
575 result.push(subject.slice(currentIndex, length)); 586 result[result.length] = subject.slice(currentIndex, length);
576 break; 587 break;
577 } 588 }
578 589
579 var endIndex = matchInfo[CAPTURE1]; 590 var endIndex = matchInfo[CAPTURE1];
580 591
581 // We ignore a zero-length match at the currentIndex. 592 // We ignore a zero-length match at the currentIndex.
582 if (startIndex === endIndex && endIndex === currentIndex) { 593 if (startIndex === endIndex && endIndex === currentIndex) {
583 startIndex++; 594 startIndex++;
584 continue; 595 continue;
585 } 596 }
586 597
587 result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0])); 598 result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0] );
588 if (result.length === limit) break; 599 if (result.length === limit) break;
589 600
590 var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; 601 var num_captures = NUMBER_OF_CAPTURES(matchInfo);
591 for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) { 602 for (var i = 2; i < num_captures; i += 2) {
592 var start = matchInfo[i++]; 603 var start = matchInfo[CAPTURE(i)];
593 var end = matchInfo[i++]; 604 var end = matchInfo[CAPTURE(i + 1)];
594 if (end != -1) { 605 if (start != -1 && end != -1) {
595 if (start + 1 == end) { 606 result[result.length] = SubString(subject, start, end);
596 result.push(%_StringCharAt(subject, start));
597 } else {
598 result.push(%_SubString(subject, start, end));
599 }
600 } else { 607 } else {
601 result.push(void 0); 608 result[result.length] = void 0;
602 } 609 }
603 if (result.length === limit) break outer_loop; 610 if (result.length === limit) break outer_loop;
604 } 611 }
605 612
606 startIndex = currentIndex = endIndex; 613 startIndex = currentIndex = endIndex;
607 } 614 }
608 return result; 615 return result;
609 } 616 }
610 617
611 618
(...skipping 30 matching lines...) Expand all
642 } else { 649 } else {
643 if (end_i < 0) end_i = 0; 650 if (end_i < 0) end_i = 0;
644 if (start_i > end_i) { 651 if (start_i > end_i) {
645 var tmp = end_i; 652 var tmp = end_i;
646 end_i = start_i; 653 end_i = start_i;
647 start_i = tmp; 654 start_i = tmp;
648 } 655 }
649 } 656 }
650 } 657 }
651 658
652 return (start_i + 1 == end_i 659 return SubString(s, start_i, end_i);
653 ? %_StringCharAt(s, start_i)
654 : %_SubString(s, start_i, end_i));
655 } 660 }
656 661
657 662
658 // This is not a part of ECMA-262. 663 // This is not a part of ECMA-262.
659 function StringSubstr(start, n) { 664 function StringSubstr(start, n) {
660 var s = TO_STRING_INLINE(this); 665 var s = TO_STRING_INLINE(this);
661 var len; 666 var len;
662 667
663 // Correct n: If not given, set to string length; if explicitly 668 // Correct n: If not given, set to string length; if explicitly
664 // set to undefined, zero, or negative, returns empty string. 669 // set to undefined, zero, or negative, returns empty string.
(...skipping 17 matching lines...) Expand all
682 // use zero. 687 // use zero.
683 if (start < 0) { 688 if (start < 0) {
684 start += s.length; 689 start += s.length;
685 if (start < 0) start = 0; 690 if (start < 0) start = 0;
686 } 691 }
687 } 692 }
688 693
689 var end = start + len; 694 var end = start + len;
690 if (end > s.length) end = s.length; 695 if (end > s.length) end = s.length;
691 696
692 return (start + 1 == end 697 return SubString(s, start, end);
693 ? %_StringCharAt(s, start)
694 : %_SubString(s, start, end));
695 } 698 }
696 699
697 700
698 // ECMA-262, 15.5.4.16 701 // ECMA-262, 15.5.4.16
699 function StringToLowerCase() { 702 function StringToLowerCase() {
700 return %StringToLowerCase(TO_STRING_INLINE(this)); 703 return %StringToLowerCase(TO_STRING_INLINE(this));
701 } 704 }
702 705
703 706
704 // ECMA-262, 15.5.4.17 707 // ECMA-262, 15.5.4.17
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 "small", StringSmall, 929 "small", StringSmall,
927 "strike", StringStrike, 930 "strike", StringStrike,
928 "sub", StringSub, 931 "sub", StringSub,
929 "sup", StringSup, 932 "sup", StringSup,
930 "toJSON", StringToJSON 933 "toJSON", StringToJSON
931 )); 934 ));
932 } 935 }
933 936
934 937
935 SetupString(); 938 SetupString();
OLDNEW
« ChangeLog ('K') | « src/spaces-inl.h ('k') | src/v8natives.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698