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

Side by Side Diff: src/scanner.cc

Issue 811113002: ES6 template literals should not use legacy octal strings (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: One more test Created 6 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
« no previous file with comments | « src/scanner.h ('k') | test/mjsunit/harmony/templates.js » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 // Features shared by parsing and pre-parsing scanners. 5 // Features shared by parsing and pre-parsing scanners.
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <cmath> 9 #include <cmath>
10 10
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 // This function is only called to seek to the location 690 // This function is only called to seek to the location
691 // of the end of a function (at the "}" token). It doesn't matter 691 // of the end of a function (at the "}" token). It doesn't matter
692 // whether there was a line terminator in the part we skip. 692 // whether there was a line terminator in the part we skip.
693 has_line_terminator_before_next_ = false; 693 has_line_terminator_before_next_ = false;
694 has_multiline_comment_before_next_ = false; 694 has_multiline_comment_before_next_ = false;
695 } 695 }
696 Scan(); 696 Scan();
697 } 697 }
698 698
699 699
700 template <bool capture_raw> 700 template <bool capture_raw, bool in_template_literal>
701 bool Scanner::ScanEscape() { 701 bool Scanner::ScanEscape() {
702 uc32 c = c0_; 702 uc32 c = c0_;
703 Advance<capture_raw>(); 703 Advance<capture_raw>();
704 704
705 // Skip escaped newlines. 705 // Skip escaped newlines.
706 if (c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) { 706 if (!in_template_literal && c0_ >= 0 && unicode_cache_->IsLineTerminator(c)) {
707 // Allow CR+LF newlines in multiline string literals. 707 // Allow CR+LF newlines in multiline string literals.
708 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>(); 708 if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
709 // Allow LF+CR newlines in multiline string literals. 709 // Allow LF+CR newlines in multiline string literals.
710 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance<capture_raw>(); 710 if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance<capture_raw>();
711 return true; 711 return true;
712 } 712 }
713 713
714 switch (c) { 714 switch (c) {
715 case '\'': // fall through 715 case '\'': // fall through
716 case '"' : // fall through 716 case '"' : // fall through
717 case '\\': break; 717 case '\\': break;
718 case 'b' : c = '\b'; break; 718 case 'b' : c = '\b'; break;
719 case 'f' : c = '\f'; break; 719 case 'f' : c = '\f'; break;
720 case 'n' : c = '\n'; break; 720 case 'n' : c = '\n'; break;
721 case 'r' : c = '\r'; break; 721 case 'r' : c = '\r'; break;
722 case 't' : c = '\t'; break; 722 case 't' : c = '\t'; break;
723 case 'u' : { 723 case 'u' : {
724 c = ScanUnicodeEscape<capture_raw>(); 724 c = ScanUnicodeEscape<capture_raw>();
725 if (c < 0) return false; 725 if (c < 0) return false;
726 break; 726 break;
727 } 727 }
728 case 'v' : c = '\v'; break; 728 case 'v':
729 case 'x' : { 729 c = '\v';
730 break;
731 case 'x': {
730 c = ScanHexNumber<capture_raw>(2); 732 c = ScanHexNumber<capture_raw>(2);
731 if (c < 0) return false; 733 if (c < 0) return false;
732 break; 734 break;
733 } 735 }
734 case '0' : // fall through 736 case '0':
735 case '1' : // fall through 737 if (in_template_literal) {
736 case '2' : // fall through 738 // \ 0 DecimalDigit is never allowed in templates.
737 case '3' : // fall through 739 if (IsDecimalDigit(c0_)) {
738 case '4' : // fall through 740 Advance<capture_raw>(); // Advance to include the problematic char.
739 case '5' : // fall through 741 return false;
740 case '6' : // fall through 742 }
743
744 // The TV of TemplateCharacter :: \ EscapeSequence is the CV of
745 // EscapeSequence.
746 // The CV of EscapeSequence :: 0 is the code unit value 0.
747 c = 0;
748 break;
749 }
750 // Fall through.
751 case '1': // fall through
752 case '2': // fall through
753 case '3': // fall through
754 case '4': // fall through
755 case '5': // fall through
756 case '6': // fall through
741 case '7': 757 case '7':
742 c = ScanOctalEscape<capture_raw>(c, 2); 758 if (!in_template_literal) {
743 break; 759 c = ScanOctalEscape<capture_raw>(c, 2);
760 break;
761 }
762 // Fall through
763 case '8':
764 case '9':
765 if (in_template_literal) return false;
744 } 766 }
745 767
746 // According to ECMA-262, section 7.8.4, characters not covered by the 768 // According to ECMA-262, section 7.8.4, characters not covered by the
747 // above cases should be illegal, but they are commonly handled as 769 // above cases should be illegal, but they are commonly handled as
748 // non-escaped characters by JS VMs. 770 // non-escaped characters by JS VMs.
749 AddLiteralChar(c); 771 AddLiteralChar(c);
750 return true; 772 return true;
751 } 773 }
752 774
753 775
(...skipping 26 matching lines...) Expand all
780 Token::Value Scanner::ScanString() { 802 Token::Value Scanner::ScanString() {
781 uc32 quote = c0_; 803 uc32 quote = c0_;
782 Advance(); // consume quote 804 Advance(); // consume quote
783 805
784 LiteralScope literal(this); 806 LiteralScope literal(this);
785 while (c0_ != quote && c0_ >= 0 807 while (c0_ != quote && c0_ >= 0
786 && !unicode_cache_->IsLineTerminator(c0_)) { 808 && !unicode_cache_->IsLineTerminator(c0_)) {
787 uc32 c = c0_; 809 uc32 c = c0_;
788 Advance(); 810 Advance();
789 if (c == '\\') { 811 if (c == '\\') {
790 if (c0_ < 0 || !ScanEscape<false>()) return Token::ILLEGAL; 812 if (c0_ < 0 || !ScanEscape<false, false>()) return Token::ILLEGAL;
791 } else { 813 } else {
792 AddLiteralChar(c); 814 AddLiteralChar(c);
793 } 815 }
794 } 816 }
795 if (c0_ != quote) return Token::ILLEGAL; 817 if (c0_ != quote) return Token::ILLEGAL;
796 literal.Complete(); 818 literal.Complete();
797 819
798 Advance(); // consume quote 820 Advance(); // consume quote
799 return Token::STRING; 821 return Token::STRING;
800 } 822 }
(...skipping 10 matching lines...) Expand all
811 // | } LiteralChar* ` 833 // | } LiteralChar* `
812 // 834 //
813 // A TEMPLATE_SPAN should always be followed by an Expression, while a 835 // A TEMPLATE_SPAN should always be followed by an Expression, while a
814 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be 836 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
815 // followed by an Expression. 837 // followed by an Expression.
816 838
817 Token::Value result = Token::TEMPLATE_SPAN; 839 Token::Value result = Token::TEMPLATE_SPAN;
818 LiteralScope literal(this); 840 LiteralScope literal(this);
819 StartRawLiteral(); 841 StartRawLiteral();
820 const bool capture_raw = true; 842 const bool capture_raw = true;
843 const bool in_template_literal = true;
821 844
822 while (true) { 845 while (true) {
823 uc32 c = c0_; 846 uc32 c = c0_;
824 Advance<capture_raw>(); 847 Advance<capture_raw>();
825 if (c == '`') { 848 if (c == '`') {
826 result = Token::TEMPLATE_TAIL; 849 result = Token::TEMPLATE_TAIL;
827 ReduceRawLiteralLength(1); 850 ReduceRawLiteralLength(1);
828 break; 851 break;
829 } else if (c == '$' && c0_ == '{') { 852 } else if (c == '$' && c0_ == '{') {
830 Advance<capture_raw>(); // Consume '{' 853 Advance<capture_raw>(); // Consume '{'
831 ReduceRawLiteralLength(2); 854 ReduceRawLiteralLength(2);
832 break; 855 break;
833 } else if (c == '\\') { 856 } else if (c == '\\') {
834 if (unicode_cache_->IsLineTerminator(c0_)) { 857 if (unicode_cache_->IsLineTerminator(c0_)) {
835 // The TV of LineContinuation :: \ LineTerminatorSequence is the empty 858 // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
836 // code unit sequence. 859 // code unit sequence.
837 uc32 lastChar = c0_; 860 uc32 lastChar = c0_;
838 Advance<capture_raw>(); 861 Advance<capture_raw>();
839 if (lastChar == '\r') { 862 if (lastChar == '\r') {
840 ReduceRawLiteralLength(1); // Remove \r 863 ReduceRawLiteralLength(1); // Remove \r
841 if (c0_ == '\n') { 864 if (c0_ == '\n') {
842 Advance<capture_raw>(); // Adds \n 865 Advance<capture_raw>(); // Adds \n
843 } else { 866 } else {
844 AddRawLiteralChar('\n'); 867 AddRawLiteralChar('\n');
845 } 868 }
846 } 869 }
847 } else if (c0_ == '0') { 870 } else if (!ScanEscape<capture_raw, in_template_literal>()) {
848 Advance<capture_raw>(); 871 return Token::ILLEGAL;
849 AddLiteralChar('0');
850 } else {
851 ScanEscape<true>();
852 } 872 }
853 } else if (c < 0) { 873 } else if (c < 0) {
854 // Unterminated template literal 874 // Unterminated template literal
855 PushBack(c); 875 PushBack(c);
856 break; 876 break;
857 } else { 877 } else {
858 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A. 878 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
859 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence 879 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
860 // consisting of the CV 0x000A. 880 // consisting of the CV 0x000A.
861 if (c == '\r') { 881 if (c == '\r') {
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 } 1498 }
1479 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u)); 1499 backing_store_.Add(static_cast<uint8_t>((one_byte_length >> 7) | 0x80u));
1480 } 1500 }
1481 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f)); 1501 backing_store_.Add(static_cast<uint8_t>(one_byte_length & 0x7f));
1482 1502
1483 backing_store_.AddBlock(bytes); 1503 backing_store_.AddBlock(bytes);
1484 return backing_store_.EndSequence().start(); 1504 return backing_store_.EndSequence().start();
1485 } 1505 }
1486 1506
1487 } } // namespace v8::internal 1507 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scanner.h ('k') | test/mjsunit/harmony/templates.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698