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

Side by Side Diff: src/parsing/scanner.cc

Issue 2665513002: [parser] Lift template literal invalid escape restriction (Closed)
Patch Set: add test 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
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 "src/parsing/scanner.h" 7 #include "src/parsing/scanner.h"
8 8
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after
941 case '2': // fall through 941 case '2': // fall through
942 case '3': // fall through 942 case '3': // fall through
943 case '4': // fall through 943 case '4': // fall through
944 case '5': // fall through 944 case '5': // fall through
945 case '6': // fall through 945 case '6': // fall through
946 case '7': 946 case '7':
947 c = ScanOctalEscape<capture_raw>(c, 2); 947 c = ScanOctalEscape<capture_raw>(c, 2);
948 break; 948 break;
949 } 949 }
950 950
951 // According to ECMA-262, section 7.8.4, characters not covered by the 951 // Other escaped characters are interpreted as their non-escaped version.
952 // above cases should be illegal, but they are commonly handled as
953 // non-escaped characters by JS VMs.
954 AddLiteralChar(c); 952 AddLiteralChar(c);
955 return true; 953 return true;
956 } 954 }
957 955
958 956
959 // Octal escapes of the forms '\0xx' and '\xxx' are not a part of
960 // ECMA-262. Other JS VMs support them.
961 template <bool capture_raw> 957 template <bool capture_raw>
962 uc32 Scanner::ScanOctalEscape(uc32 c, int length) { 958 uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
963 uc32 x = c - '0'; 959 uc32 x = c - '0';
964 int i = 0; 960 int i = 0;
965 for (; i < length; i++) { 961 for (; i < length; i++) {
966 int d = c0_ - '0'; 962 int d = c0_ - '0';
967 if (d < 0 || d > 7) break; 963 if (d < 0 || d > 7) break;
968 int nx = x * 8 + d; 964 int nx = x * 8 + d;
969 if (nx >= 256) break; 965 if (nx >= 256) break;
970 x = nx; 966 x = nx;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 // | } LiteralChars* ${ 1028 // | } LiteralChars* ${
1033 // 1029 //
1034 // TEMPLATE_TAIL :: 1030 // TEMPLATE_TAIL ::
1035 // ` LiteralChars* ` 1031 // ` LiteralChars* `
1036 // | } LiteralChar* ` 1032 // | } LiteralChar* `
1037 // 1033 //
1038 // A TEMPLATE_SPAN should always be followed by an Expression, while a 1034 // A TEMPLATE_SPAN should always be followed by an Expression, while a
1039 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be 1035 // TEMPLATE_TAIL terminates a TemplateLiteral and does not need to be
1040 // followed by an Expression. 1036 // followed by an Expression.
1041 1037
1038 MessageTemplate::Template old_scanner_error = scanner_error_;
1039 Location old_scanner_error_location = scanner_error_location_;
1040 scanner_error_ = MessageTemplate::kNone;
1041 scanner_error_location_ = Location::invalid();
vogelheim 2017/02/20 11:23:20 This logic (here & below) is a bit obtuse. I don't
bakkot1 2017/02/21 21:54:15 Added a ErrorState scoped helper which does this.
vogelheim 2017/02/22 10:03:02 Thanks.
1042
1043 MessageTemplate::Template old_octal_message = octal_message_;
1044 Location old_octal_pos = octal_pos_;
1045 octal_message_ = MessageTemplate::kNone;
1046 octal_pos_ = Location::invalid();
1047
1042 Token::Value result = Token::TEMPLATE_SPAN; 1048 Token::Value result = Token::TEMPLATE_SPAN;
1043 LiteralScope literal(this); 1049 LiteralScope literal(this);
1044 StartRawLiteral(); 1050 StartRawLiteral();
1045 const bool capture_raw = true; 1051 const bool capture_raw = true;
1046 const bool in_template_literal = true; 1052 const bool in_template_literal = true;
1047 while (true) { 1053 while (true) {
1048 uc32 c = c0_; 1054 uc32 c = c0_;
1049 Advance<capture_raw>(); 1055 Advance<capture_raw>();
1050 if (c == '`') { 1056 if (c == '`') {
1051 result = Token::TEMPLATE_TAIL; 1057 result = Token::TEMPLATE_TAIL;
(...skipping 10 matching lines...) Expand all
1062 uc32 lastChar = c0_; 1068 uc32 lastChar = c0_;
1063 Advance<capture_raw>(); 1069 Advance<capture_raw>();
1064 if (lastChar == '\r') { 1070 if (lastChar == '\r') {
1065 ReduceRawLiteralLength(1); // Remove \r 1071 ReduceRawLiteralLength(1); // Remove \r
1066 if (c0_ == '\n') { 1072 if (c0_ == '\n') {
1067 Advance<capture_raw>(); // Adds \n 1073 Advance<capture_raw>(); // Adds \n
1068 } else { 1074 } else {
1069 AddRawLiteralChar('\n'); 1075 AddRawLiteralChar('\n');
1070 } 1076 }
1071 } 1077 }
1072 } else if (!ScanEscape<capture_raw, in_template_literal>()) { 1078 } else {
1073 return Token::ILLEGAL; 1079 ScanEscape<capture_raw, in_template_literal>();
1080 // For templates, invalid escape sequence checking is handled in the
1081 // parser.
1082 if (has_error()) {
1083 if (!has_invalid_template_escape()) {
1084 invalid_template_escape_message_ = scanner_error_;
1085 invalid_template_escape_location_ = scanner_error_location_;
1086 }
1087 scanner_error_ = MessageTemplate::kNone;
1088 scanner_error_location_ = Location::invalid();
1089 }
1090 if (octal_message_ != MessageTemplate::kNone) {
1091 if (!has_invalid_template_escape()) {
1092 invalid_template_escape_message_ =
1093 MessageTemplate::kTemplateOctalLiteral;
1094 invalid_template_escape_location_ = octal_pos_;
1095 }
1096 octal_message_ = MessageTemplate::kNone;
1097 octal_pos_ = Location::invalid();
1098 }
1074 } 1099 }
1075 } else if (c < 0) { 1100 } else if (c < 0) {
1076 // Unterminated template literal 1101 // Unterminated template literal
1077 PushBack(c); 1102 PushBack(c);
1078 break; 1103 break;
1079 } else { 1104 } else {
1080 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A. 1105 // The TRV of LineTerminatorSequence :: <CR> is the CV 0x000A.
1081 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence 1106 // The TRV of LineTerminatorSequence :: <CR><LF> is the sequence
1082 // consisting of the CV 0x000A. 1107 // consisting of the CV 0x000A.
1083 if (c == '\r') { 1108 if (c == '\r') {
1084 ReduceRawLiteralLength(1); // Remove \r 1109 ReduceRawLiteralLength(1); // Remove \r
1085 if (c0_ == '\n') { 1110 if (c0_ == '\n') {
1086 Advance<capture_raw>(); // Adds \n 1111 Advance<capture_raw>(); // Adds \n
1087 } else { 1112 } else {
1088 AddRawLiteralChar('\n'); 1113 AddRawLiteralChar('\n');
1089 } 1114 }
1090 c = '\n'; 1115 c = '\n';
1091 } 1116 }
1092 AddLiteralChar(c); 1117 AddLiteralChar(c);
1093 } 1118 }
1094 } 1119 }
1095 literal.Complete(); 1120 literal.Complete();
1096 next_.location.end_pos = source_pos(); 1121 next_.location.end_pos = source_pos();
1097 next_.token = result; 1122 next_.token = result;
1123
1124 scanner_error_ = old_scanner_error;
1125 scanner_error_location_ = old_scanner_error_location;
1126 octal_message_ = old_octal_message;
1127 octal_pos_ = old_octal_pos;
1098 return result; 1128 return result;
1099 } 1129 }
1100 1130
1101 1131
1102 Token::Value Scanner::ScanTemplateStart() { 1132 Token::Value Scanner::ScanTemplateStart() {
1103 DCHECK(next_next_.token == Token::UNINITIALIZED); 1133 DCHECK(next_next_.token == Token::UNINITIALIZED);
1104 DCHECK(c0_ == '`'); 1134 DCHECK(c0_ == '`');
1105 next_.location.beg_pos = source_pos(); 1135 next_.location.beg_pos = source_pos();
1106 Advance(); // Consume ` 1136 Advance(); // Consume `
1107 return ScanTemplateSpan(); 1137 return ScanTemplateSpan();
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 // 2, reset the source to the desired position, 1721 // 2, reset the source to the desired position,
1692 source_->Seek(position); 1722 source_->Seek(position);
1693 // 3, re-scan, by scanning the look-ahead char + 1 token (next_). 1723 // 3, re-scan, by scanning the look-ahead char + 1 token (next_).
1694 c0_ = source_->Advance(); 1724 c0_ = source_->Advance();
1695 Next(); 1725 Next();
1696 DCHECK_EQ(next_.location.beg_pos, static_cast<int>(position)); 1726 DCHECK_EQ(next_.location.beg_pos, static_cast<int>(position));
1697 } 1727 }
1698 1728
1699 } // namespace internal 1729 } // namespace internal
1700 } // namespace v8 1730 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698