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 ArrayIndexOf; | 12 var ArrayIndexOf; |
13 var ArrayJoin; | 13 var ArrayJoin; |
14 var GlobalRegExp = global.RegExp; | 14 var GlobalRegExp = global.RegExp; |
15 var GlobalString = global.String; | 15 var GlobalString = global.String; |
16 var InternalArray = utils.InternalArray; | 16 var InternalArray = utils.InternalArray; |
17 var InternalPackedArray = utils.InternalPackedArray; | 17 var InternalPackedArray = utils.InternalPackedArray; |
18 var MakeRangeError; | 18 var MakeRangeError; |
19 var MakeTypeError; | 19 var MakeTypeError; |
20 var RegExpExec; | 20 var RegExpExec; |
21 var RegExpExecNoTests; | 21 var RegExpExecNoTests; |
22 var RegExpLastMatchInfo; | 22 var RegExpLastMatchInfo; |
| 23 var splitSymbol = utils.ImportNow("split_symbol"); |
23 | 24 |
24 utils.Import(function(from) { | 25 utils.Import(function(from) { |
25 ArrayIndexOf = from.ArrayIndexOf; | 26 ArrayIndexOf = from.ArrayIndexOf; |
26 ArrayJoin = from.ArrayJoin; | 27 ArrayJoin = from.ArrayJoin; |
27 MakeRangeError = from.MakeRangeError; | 28 MakeRangeError = from.MakeRangeError; |
28 MakeTypeError = from.MakeTypeError; | 29 MakeTypeError = from.MakeTypeError; |
29 RegExpExec = from.RegExpExec; | 30 RegExpExec = from.RegExpExec; |
30 RegExpExecNoTests = from.RegExpExecNoTests; | 31 RegExpExecNoTests = from.RegExpExecNoTests; |
31 RegExpLastMatchInfo = from.RegExpLastMatchInfo; | 32 RegExpLastMatchInfo = from.RegExpLastMatchInfo; |
32 }); | 33 }); |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 } | 548 } |
548 | 549 |
549 if (end_i <= start_i) { | 550 if (end_i <= start_i) { |
550 return ''; | 551 return ''; |
551 } | 552 } |
552 | 553 |
553 return %_SubString(s, start_i, end_i); | 554 return %_SubString(s, start_i, end_i); |
554 } | 555 } |
555 | 556 |
556 | 557 |
557 // ECMA-262 section 15.5.4.14 | 558 // ES6 21.1.3.17. |
558 function StringSplitJS(separator, limit) { | 559 function StringSplitJS(separator, limit) { |
559 CHECK_OBJECT_COERCIBLE(this, "String.prototype.split"); | 560 CHECK_OBJECT_COERCIBLE(this, "String.prototype.split"); |
560 | 561 |
| 562 if (!IS_NULL_OR_UNDEFINED(separator)) { |
| 563 var splitter = separator[splitSymbol]; |
| 564 if (!IS_UNDEFINED(splitter)) { |
| 565 if (!IS_CALLABLE(splitter)) { |
| 566 throw MakeTypeError(kCalledNonCallable, splitter); |
| 567 } |
| 568 return %_Call(splitter, separator, this, limit); |
| 569 } |
| 570 } |
| 571 |
561 var subject = TO_STRING(this); | 572 var subject = TO_STRING(this); |
562 limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit); | 573 limit = (IS_UNDEFINED(limit)) ? kMaxUint32 : TO_UINT32(limit); |
563 | 574 |
564 var length = subject.length; | 575 var length = subject.length; |
565 if (!IS_REGEXP(separator)) { | 576 var separator_string = TO_STRING(separator); |
566 var separator_string = TO_STRING(separator); | |
567 | |
568 if (limit === 0) return []; | |
569 | |
570 // ECMA-262 says that if separator is undefined, the result should | |
571 // be an array of size 1 containing the entire string. | |
572 if (IS_UNDEFINED(separator)) return [subject]; | |
573 | |
574 var separator_length = separator_string.length; | |
575 | |
576 // If the separator string is empty then return the elements in the subject. | |
577 if (separator_length === 0) return %StringToArray(subject, limit); | |
578 | |
579 var result = %StringSplit(subject, separator_string, limit); | |
580 | |
581 return result; | |
582 } | |
583 | 577 |
584 if (limit === 0) return []; | 578 if (limit === 0) return []; |
585 | 579 |
586 // Separator is a regular expression. | 580 // ECMA-262 says that if separator is undefined, the result should |
587 return StringSplitOnRegExp(subject, separator, limit, length); | 581 // be an array of size 1 containing the entire string. |
| 582 if (IS_UNDEFINED(separator)) return [subject]; |
| 583 |
| 584 var separator_length = separator_string.length; |
| 585 |
| 586 // If the separator string is empty then return the elements in the subject. |
| 587 if (separator_length === 0) return %StringToArray(subject, limit); |
| 588 |
| 589 return %StringSplit(subject, separator_string, limit); |
588 } | 590 } |
589 | 591 |
590 | 592 |
591 function StringSplitOnRegExp(subject, separator, limit, length) { | |
592 if (length === 0) { | |
593 if (RegExpExec(separator, subject, 0, 0) != null) { | |
594 return []; | |
595 } | |
596 return [subject]; | |
597 } | |
598 | |
599 var currentIndex = 0; | |
600 var startIndex = 0; | |
601 var startMatch = 0; | |
602 var result = new InternalArray(); | |
603 | |
604 outer_loop: | |
605 while (true) { | |
606 | |
607 if (startIndex === length) { | |
608 result[result.length] = %_SubString(subject, currentIndex, length); | |
609 break; | |
610 } | |
611 | |
612 var matchInfo = RegExpExec(separator, subject, startIndex); | |
613 if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) { | |
614 result[result.length] = %_SubString(subject, currentIndex, length); | |
615 break; | |
616 } | |
617 var endIndex = matchInfo[CAPTURE1]; | |
618 | |
619 // We ignore a zero-length match at the currentIndex. | |
620 if (startIndex === endIndex && endIndex === currentIndex) { | |
621 startIndex++; | |
622 continue; | |
623 } | |
624 | |
625 result[result.length] = %_SubString(subject, currentIndex, startMatch); | |
626 | |
627 if (result.length === limit) break; | |
628 | |
629 var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; | |
630 for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) { | |
631 var start = matchInfo[i++]; | |
632 var end = matchInfo[i++]; | |
633 if (end != -1) { | |
634 result[result.length] = %_SubString(subject, start, end); | |
635 } else { | |
636 result[result.length] = UNDEFINED; | |
637 } | |
638 if (result.length === limit) break outer_loop; | |
639 } | |
640 | |
641 startIndex = currentIndex = endIndex; | |
642 } | |
643 var array_result = []; | |
644 %MoveArrayContents(result, array_result); | |
645 return array_result; | |
646 } | |
647 | |
648 | |
649 // ECMA-262 section 15.5.4.15 | 593 // ECMA-262 section 15.5.4.15 |
650 function StringSubstring(start, end) { | 594 function StringSubstring(start, end) { |
651 CHECK_OBJECT_COERCIBLE(this, "String.prototype.subString"); | 595 CHECK_OBJECT_COERCIBLE(this, "String.prototype.subString"); |
652 | 596 |
653 var s = TO_STRING(this); | 597 var s = TO_STRING(this); |
654 var s_len = s.length; | 598 var s_len = s.length; |
655 | 599 |
656 var start_i = TO_INTEGER(start); | 600 var start_i = TO_INTEGER(start); |
657 if (start_i < 0) { | 601 if (start_i < 0) { |
658 start_i = 0; | 602 start_i = 0; |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 to.StringLastIndexOf = StringLastIndexOfJS; | 1109 to.StringLastIndexOf = StringLastIndexOfJS; |
1166 to.StringMatch = StringMatchJS; | 1110 to.StringMatch = StringMatchJS; |
1167 to.StringReplace = StringReplace; | 1111 to.StringReplace = StringReplace; |
1168 to.StringSlice = StringSlice; | 1112 to.StringSlice = StringSlice; |
1169 to.StringSplit = StringSplitJS; | 1113 to.StringSplit = StringSplitJS; |
1170 to.StringSubstr = StringSubstr; | 1114 to.StringSubstr = StringSubstr; |
1171 to.StringSubstring = StringSubstring; | 1115 to.StringSubstring = StringSubstring; |
1172 }); | 1116 }); |
1173 | 1117 |
1174 }) | 1118 }) |
OLD | NEW |