OLD | NEW |
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 #include <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 return PreParserIdentifier::Await(); | 44 return PreParserIdentifier::Await(); |
45 } else if (scanner->current_token() == | 45 } else if (scanner->current_token() == |
46 Token::FUTURE_STRICT_RESERVED_WORD) { | 46 Token::FUTURE_STRICT_RESERVED_WORD) { |
47 return PreParserIdentifier::FutureStrictReserved(); | 47 return PreParserIdentifier::FutureStrictReserved(); |
48 } else if (scanner->current_token() == Token::LET) { | 48 } else if (scanner->current_token() == Token::LET) { |
49 return PreParserIdentifier::Let(); | 49 return PreParserIdentifier::Let(); |
50 } else if (scanner->current_token() == Token::STATIC) { | 50 } else if (scanner->current_token() == Token::STATIC) { |
51 return PreParserIdentifier::Static(); | 51 return PreParserIdentifier::Static(); |
52 } else if (scanner->current_token() == Token::YIELD) { | 52 } else if (scanner->current_token() == Token::YIELD) { |
53 return PreParserIdentifier::Yield(); | 53 return PreParserIdentifier::Yield(); |
| 54 } else if (scanner->current_token() == Token::ASYNC) { |
| 55 return PreParserIdentifier::Async(); |
54 } | 56 } |
55 if (scanner->UnescapedLiteralMatches("eval", 4)) { | 57 if (scanner->UnescapedLiteralMatches("eval", 4)) { |
56 return PreParserIdentifier::Eval(); | 58 return PreParserIdentifier::Eval(); |
57 } | 59 } |
58 if (scanner->UnescapedLiteralMatches("arguments", 9)) { | 60 if (scanner->UnescapedLiteralMatches("arguments", 9)) { |
59 return PreParserIdentifier::Arguments(); | 61 return PreParserIdentifier::Arguments(); |
60 } | 62 } |
61 if (scanner->UnescapedLiteralMatches("undefined", 9)) { | 63 if (scanner->UnescapedLiteralMatches("undefined", 9)) { |
62 return PreParserIdentifier::Undefined(); | 64 return PreParserIdentifier::Undefined(); |
63 } | 65 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 &top_factory); | 116 &top_factory); |
115 scope_->SetLanguageMode(language_mode); | 117 scope_->SetLanguageMode(language_mode); |
116 Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind); | 118 Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind); |
117 if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters(); | 119 if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters(); |
118 PreParserFactory function_factory(NULL); | 120 PreParserFactory function_factory(NULL); |
119 FunctionState function_state(&function_state_, &scope_, function_scope, kind, | 121 FunctionState function_state(&function_state_, &scope_, function_scope, kind, |
120 &function_factory); | 122 &function_factory); |
121 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | 123 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
122 bool ok = true; | 124 bool ok = true; |
123 int start_position = peek_position(); | 125 int start_position = peek_position(); |
| 126 function_state.set_parse_phase(FunctionParsePhase::FunctionBody); |
124 ParseLazyFunctionLiteralBody(&ok, bookmark); | 127 ParseLazyFunctionLiteralBody(&ok, bookmark); |
125 use_counts_ = nullptr; | 128 use_counts_ = nullptr; |
126 if (bookmark && bookmark->HasBeenReset()) { | 129 if (bookmark && bookmark->HasBeenReset()) { |
127 // Do nothing, as we've just aborted scanning this function. | 130 // Do nothing, as we've just aborted scanning this function. |
128 } else if (stack_overflow()) { | 131 } else if (stack_overflow()) { |
129 return kPreParseStackOverflow; | 132 return kPreParseStackOverflow; |
130 } else if (!ok) { | 133 } else if (!ok) { |
131 ReportUnexpectedToken(scanner()->current_token()); | 134 ReportUnexpectedToken(scanner()->current_token()); |
132 } else { | 135 } else { |
133 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 136 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 return ParseHoistableDeclaration(ok); | 189 return ParseHoistableDeclaration(ok); |
187 case Token::CLASS: | 190 case Token::CLASS: |
188 return ParseClassDeclaration(ok); | 191 return ParseClassDeclaration(ok); |
189 case Token::CONST: | 192 case Token::CONST: |
190 return ParseVariableStatement(kStatementListItem, ok); | 193 return ParseVariableStatement(kStatementListItem, ok); |
191 case Token::LET: | 194 case Token::LET: |
192 if (IsNextLetKeyword()) { | 195 if (IsNextLetKeyword()) { |
193 return ParseVariableStatement(kStatementListItem, ok); | 196 return ParseVariableStatement(kStatementListItem, ok); |
194 } | 197 } |
195 break; | 198 break; |
| 199 case Token::ASYNC: |
| 200 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && |
| 201 !scanner()->HasAnyLineTerminatorAfterNext()) { |
| 202 Consume(Token::ASYNC); |
| 203 return ParseAsyncFunctionDeclaration(ok); |
| 204 } |
| 205 /* falls through */ |
196 default: | 206 default: |
197 break; | 207 break; |
198 } | 208 } |
199 return ParseStatement(kAllowLabelledFunctionStatement, ok); | 209 return ParseStatement(kAllowLabelledFunctionStatement, ok); |
200 } | 210 } |
201 | 211 |
202 | 212 |
203 void PreParser::ParseStatementList(int end_token, bool* ok, | 213 void PreParser::ParseStatementList(int end_token, bool* ok, |
204 Scanner::BookmarkScope* bookmark) { | 214 Scanner::BookmarkScope* bookmark) { |
205 // SourceElements :: | 215 // SourceElements :: |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 ParseFunctionLiteral(name, scanner()->location(), | 400 ParseFunctionLiteral(name, scanner()->location(), |
391 is_strict_reserved ? kFunctionNameIsStrictReserved | 401 is_strict_reserved ? kFunctionNameIsStrictReserved |
392 : kFunctionNameValidityUnknown, | 402 : kFunctionNameValidityUnknown, |
393 is_generator ? FunctionKind::kGeneratorFunction | 403 is_generator ? FunctionKind::kGeneratorFunction |
394 : FunctionKind::kNormalFunction, | 404 : FunctionKind::kNormalFunction, |
395 pos, FunctionLiteral::kDeclaration, language_mode(), | 405 pos, FunctionLiteral::kDeclaration, language_mode(), |
396 CHECK_OK); | 406 CHECK_OK); |
397 return Statement::FunctionDeclaration(); | 407 return Statement::FunctionDeclaration(); |
398 } | 408 } |
399 | 409 |
| 410 PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) { |
| 411 // AsyncFunctionDeclaration :: |
| 412 // async [no LineTerminator here] function BindingIdentifier[Await] |
| 413 // ( FormalParameters[Await] ) { AsyncFunctionBody } |
| 414 DCHECK_EQ(scanner()->current_token(), Token::ASYNC); |
| 415 int pos = position(); |
| 416 Expect(Token::FUNCTION, CHECK_OK); |
| 417 bool is_strict_reserved = false; |
| 418 Identifier name = |
| 419 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 420 if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) { |
| 421 ReportMessageAt(scanner()->location(), |
| 422 MessageTemplate::kAwaitBindingIdentifier); |
| 423 *ok = false; |
| 424 return Statement::Default(); |
| 425 } |
| 426 ParseFunctionLiteral(name, scanner()->location(), |
| 427 is_strict_reserved ? kFunctionNameIsStrictReserved |
| 428 : kFunctionNameValidityUnknown, |
| 429 FunctionKind::kAsyncFunction, pos, |
| 430 FunctionLiteral::kDeclaration, language_mode(), |
| 431 CHECK_OK); |
| 432 return Statement::FunctionDeclaration(); |
| 433 } |
400 | 434 |
401 PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { | 435 PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { |
402 // FunctionDeclaration :: | 436 // FunctionDeclaration :: |
403 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 437 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
404 // GeneratorDeclaration :: | 438 // GeneratorDeclaration :: |
405 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 439 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
406 // '{' FunctionBody '}' | 440 // '{' FunctionBody '}' |
407 Expect(Token::FUNCTION, CHECK_OK); | 441 Expect(Token::FUNCTION, CHECK_OK); |
408 int pos = position(); | 442 int pos = position(); |
409 bool is_generator = Check(Token::MUL); | 443 bool is_generator = Check(Token::MUL); |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 PreParserFactory factory(NULL); | 1098 PreParserFactory factory(NULL); |
1065 FunctionState function_state(&function_state_, &scope_, function_scope, kind, | 1099 FunctionState function_state(&function_state_, &scope_, function_scope, kind, |
1066 &factory); | 1100 &factory); |
1067 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 1101 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
1068 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 1102 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
1069 | 1103 |
1070 Expect(Token::LPAREN, CHECK_OK); | 1104 Expect(Token::LPAREN, CHECK_OK); |
1071 int start_position = scanner()->location().beg_pos; | 1105 int start_position = scanner()->location().beg_pos; |
1072 function_scope->set_start_position(start_position); | 1106 function_scope->set_start_position(start_position); |
1073 PreParserFormalParameters formals(function_scope); | 1107 PreParserFormalParameters formals(function_scope); |
| 1108 function_state.set_parse_phase(FunctionParsePhase::FormalParameters); |
1074 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); | 1109 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); |
1075 Expect(Token::RPAREN, CHECK_OK); | 1110 Expect(Token::RPAREN, CHECK_OK); |
1076 int formals_end_position = scanner()->location().end_pos; | 1111 int formals_end_position = scanner()->location().end_pos; |
1077 | 1112 |
1078 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, | 1113 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, |
1079 formals_end_position, CHECK_OK); | 1114 formals_end_position, CHECK_OK); |
1080 | 1115 |
1081 // See Parser::ParseFunctionLiteral for more information about lazy parsing | 1116 // See Parser::ParseFunctionLiteral for more information about lazy parsing |
1082 // and lazy compilation. | 1117 // and lazy compilation. |
1083 bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && | 1118 bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && |
1084 !function_state_->this_function_is_parenthesized()); | 1119 !function_state_->this_function_is_parenthesized()); |
1085 | 1120 |
1086 Expect(Token::LBRACE, CHECK_OK); | 1121 Expect(Token::LBRACE, CHECK_OK); |
| 1122 function_state.set_parse_phase(FunctionParsePhase::FunctionBody); |
1087 if (is_lazily_parsed) { | 1123 if (is_lazily_parsed) { |
1088 ParseLazyFunctionLiteralBody(CHECK_OK); | 1124 ParseLazyFunctionLiteralBody(CHECK_OK); |
1089 } else { | 1125 } else { |
1090 ParseStatementList(Token::RBRACE, CHECK_OK); | 1126 ParseStatementList(Token::RBRACE, CHECK_OK); |
1091 } | 1127 } |
1092 Expect(Token::RBRACE, CHECK_OK); | 1128 Expect(Token::RBRACE, CHECK_OK); |
1093 | 1129 |
1094 // Parsing the body may change the language mode in our scope. | 1130 // Parsing the body may change the language mode in our scope. |
1095 language_mode = function_scope->language_mode(); | 1131 language_mode = function_scope->language_mode(); |
1096 | 1132 |
1097 // Validate name and parameter names. We can do this only after parsing the | 1133 // Validate name and parameter names. We can do this only after parsing the |
1098 // function, since the function can declare itself strict. | 1134 // function, since the function can declare itself strict. |
1099 CheckFunctionName(language_mode, function_name, function_name_validity, | 1135 CheckFunctionName(language_mode, function_name, function_name_validity, |
1100 function_name_location, CHECK_OK); | 1136 function_name_location, CHECK_OK); |
1101 const bool allow_duplicate_parameters = | 1137 const bool allow_duplicate_parameters = |
1102 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); | 1138 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); |
1103 ValidateFormalParameters(&formals_classifier, language_mode, | 1139 ValidateFormalParameters(&formals_classifier, language_mode, |
1104 allow_duplicate_parameters, CHECK_OK); | 1140 allow_duplicate_parameters, CHECK_OK); |
1105 | 1141 |
1106 if (is_strict(language_mode)) { | 1142 if (is_strict(language_mode)) { |
1107 int end_position = scanner()->location().end_pos; | 1143 int end_position = scanner()->location().end_pos; |
1108 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); | 1144 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); |
1109 } | 1145 } |
1110 | 1146 |
1111 return Expression::Default(); | 1147 return Expression::Default(); |
1112 } | 1148 } |
1113 | 1149 |
| 1150 PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) { |
| 1151 // AsyncFunctionDeclaration :: |
| 1152 // async [no LineTerminator here] function ( FormalParameters[Await] ) |
| 1153 // { AsyncFunctionBody } |
| 1154 // |
| 1155 // async [no LineTerminator here] function BindingIdentifier[Await] |
| 1156 // ( FormalParameters[Await] ) { AsyncFunctionBody } |
| 1157 int pos = position(); |
| 1158 Expect(Token::FUNCTION, CHECK_OK); |
| 1159 bool is_strict_reserved = false; |
| 1160 Identifier name; |
| 1161 FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression; |
| 1162 |
| 1163 if (peek_any_identifier()) { |
| 1164 type = FunctionLiteral::kNamedExpression; |
| 1165 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 1166 if (this->IsAwait(name)) { |
| 1167 ReportMessageAt(scanner()->location(), |
| 1168 MessageTemplate::kAwaitBindingIdentifier); |
| 1169 *ok = false; |
| 1170 return Expression::Default(); |
| 1171 } |
| 1172 } |
| 1173 |
| 1174 ParseFunctionLiteral(name, scanner()->location(), |
| 1175 is_strict_reserved ? kFunctionNameIsStrictReserved |
| 1176 : kFunctionNameValidityUnknown, |
| 1177 FunctionKind::kAsyncFunction, pos, type, language_mode(), |
| 1178 CHECK_OK); |
| 1179 return Expression::Default(); |
| 1180 } |
1114 | 1181 |
1115 void PreParser::ParseLazyFunctionLiteralBody(bool* ok, | 1182 void PreParser::ParseLazyFunctionLiteralBody(bool* ok, |
1116 Scanner::BookmarkScope* bookmark) { | 1183 Scanner::BookmarkScope* bookmark) { |
1117 int body_start = position(); | 1184 int body_start = position(); |
1118 ParseStatementList(Token::RBRACE, ok, bookmark); | 1185 ParseStatementList(Token::RBRACE, ok, bookmark); |
1119 if (!*ok) return; | 1186 if (!*ok) return; |
1120 if (bookmark && bookmark->HasBeenReset()) return; | 1187 if (bookmark && bookmark->HasBeenReset()) return; |
1121 | 1188 |
1122 // Position right after terminal '}'. | 1189 // Position right after terminal '}'. |
1123 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 1190 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 } | 1232 } |
1166 } | 1233 } |
1167 | 1234 |
1168 ClassLiteralChecker checker(this); | 1235 ClassLiteralChecker checker(this); |
1169 bool has_seen_constructor = false; | 1236 bool has_seen_constructor = false; |
1170 | 1237 |
1171 Expect(Token::LBRACE, CHECK_OK); | 1238 Expect(Token::LBRACE, CHECK_OK); |
1172 while (peek() != Token::RBRACE) { | 1239 while (peek() != Token::RBRACE) { |
1173 if (Check(Token::SEMICOLON)) continue; | 1240 if (Check(Token::SEMICOLON)) continue; |
1174 const bool in_class = true; | 1241 const bool in_class = true; |
1175 const bool is_static = false; | |
1176 bool is_computed_name = false; // Classes do not care about computed | 1242 bool is_computed_name = false; // Classes do not care about computed |
1177 // property names here. | 1243 // property names here. |
1178 Identifier name; | 1244 Identifier name; |
1179 ExpressionClassifier property_classifier(this); | 1245 ExpressionClassifier property_classifier(this); |
1180 ParsePropertyDefinition(&checker, in_class, has_extends, is_static, | 1246 ParsePropertyDefinition(&checker, in_class, has_extends, MethodKind::Normal, |
1181 &is_computed_name, &has_seen_constructor, | 1247 &is_computed_name, &has_seen_constructor, |
1182 &property_classifier, &name, CHECK_OK); | 1248 &property_classifier, &name, CHECK_OK); |
1183 ValidateExpression(&property_classifier, CHECK_OK); | 1249 ValidateExpression(&property_classifier, CHECK_OK); |
1184 if (classifier != nullptr) { | 1250 if (classifier != nullptr) { |
1185 classifier->Accumulate(&property_classifier, | 1251 classifier->Accumulate(&property_classifier, |
1186 ExpressionClassifier::ExpressionProductions); | 1252 ExpressionClassifier::ExpressionProductions); |
1187 } | 1253 } |
1188 } | 1254 } |
1189 | 1255 |
1190 Expect(Token::RBRACE, CHECK_OK); | 1256 Expect(Token::RBRACE, CHECK_OK); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 } | 1290 } |
1225 Expect(Token::RBRACE, CHECK_OK); | 1291 Expect(Token::RBRACE, CHECK_OK); |
1226 return PreParserExpression::Default(); | 1292 return PreParserExpression::Default(); |
1227 } | 1293 } |
1228 | 1294 |
1229 #undef CHECK_OK | 1295 #undef CHECK_OK |
1230 | 1296 |
1231 | 1297 |
1232 } // namespace internal | 1298 } // namespace internal |
1233 } // namespace v8 | 1299 } // namespace v8 |
OLD | NEW |