Chromium Code Reviews| 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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 CheckStrictOctalLiteral(start_position, end_pos, &ok); | 133 CheckStrictOctalLiteral(start_position, end_pos, &ok); |
| 134 if (!ok) return kPreParseSuccess; | 134 if (!ok) return kPreParseSuccess; |
| 135 } | 135 } |
| 136 } | 136 } |
| 137 return kPreParseSuccess; | 137 return kPreParseSuccess; |
| 138 } | 138 } |
| 139 | 139 |
| 140 | 140 |
| 141 PreParserExpression PreParserTraits::ParseClassLiteral( | 141 PreParserExpression PreParserTraits::ParseClassLiteral( |
| 142 PreParserIdentifier name, Scanner::Location class_name_location, | 142 PreParserIdentifier name, Scanner::Location class_name_location, |
| 143 bool name_is_strict_reserved, int pos, bool* ok) { | 143 bool name_is_strict_reserved, int pos, bool ambient, bool* ok) { |
| 144 return pre_parser_->ParseClassLiteral(name, class_name_location, | 144 return pre_parser_->ParseClassLiteral( |
| 145 name_is_strict_reserved, pos, ok); | 145 name, class_name_location, name_is_strict_reserved, pos, ambient, ok); |
| 146 } | 146 } |
| 147 | 147 |
| 148 | 148 |
| 149 // Preparsing checks a JavaScript program and emits preparse-data that helps | 149 // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 150 // a later parsing to be faster. | 150 // a later parsing to be faster. |
| 151 // See preparser-data.h for the data. | 151 // See preparser-data.h for the data. |
| 152 | 152 |
| 153 // The PreParser checks that the syntax follows the grammar for JavaScript, | 153 // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 154 // and collects some information about the program along the way. | 154 // and collects some information about the program along the way. |
| 155 // The grammar check is only performed in order to understand the program | 155 // The grammar check is only performed in order to understand the program |
| 156 // sufficiently to deduce some information about it, that can be used | 156 // sufficiently to deduce some information about it, that can be used |
| 157 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 157 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 158 // rather it is to speed up properly written and correct programs. | 158 // rather it is to speed up properly written and correct programs. |
| 159 // That means that contextual checks (like a label being declared where | 159 // That means that contextual checks (like a label being declared where |
| 160 // it is used) are generally omitted. | 160 // it is used) are generally omitted. |
| 161 | 161 |
| 162 | 162 |
| 163 PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { | 163 PreParser::Statement PreParser::ParseStatementListItem(bool top_level, |
| 164 bool* ok) { | |
| 164 // ECMA 262 6th Edition | 165 // ECMA 262 6th Edition |
| 165 // StatementListItem[Yield, Return] : | 166 // StatementListItem[Yield, Return] : |
| 166 // Statement[?Yield, ?Return] | 167 // Statement[?Yield, ?Return] |
| 167 // Declaration[?Yield] | 168 // Declaration[?Yield] |
| 168 // | 169 // |
| 169 // Declaration[Yield] : | 170 // Declaration[Yield] : |
| 170 // HoistableDeclaration[?Yield] | 171 // HoistableDeclaration[?Yield] |
| 171 // ClassDeclaration[?Yield] | 172 // ClassDeclaration[?Yield] |
| 172 // LexicalDeclaration[In, ?Yield] | 173 // LexicalDeclaration[In, ?Yield] |
| 173 // | 174 // |
| 174 // HoistableDeclaration[Yield, Default] : | 175 // HoistableDeclaration[Yield, Default] : |
| 175 // FunctionDeclaration[?Yield, ?Default] | 176 // FunctionDeclaration[?Yield, ?Default] |
| 176 // GeneratorDeclaration[?Yield, ?Default] | 177 // GeneratorDeclaration[?Yield, ?Default] |
| 177 // | 178 // |
| 178 // LexicalDeclaration[In, Yield] : | 179 // LexicalDeclaration[In, Yield] : |
| 179 // LetOrConst BindingList[?In, ?Yield] ; | 180 // LetOrConst BindingList[?In, ?Yield] ; |
| 180 | 181 |
| 182 // Allow ambient variable, function, and class declarations. | |
| 183 bool ambient = | |
| 184 scope_->typed() && CheckContextualKeyword(CStrVector("declare")); | |
| 185 if (ambient && !top_level) { | |
| 186 *ok = false; | |
| 187 ReportMessage(MessageTemplate::kIllegalDeclare); | |
| 188 return Statement::Default(); | |
| 189 } | |
| 181 switch (peek()) { | 190 switch (peek()) { |
| 182 case Token::FUNCTION: | 191 case Token::FUNCTION: |
| 183 return ParseFunctionDeclaration(ok); | 192 return ParseFunctionDeclaration(ambient, ok); |
| 184 case Token::CLASS: | 193 case Token::CLASS: |
| 185 return ParseClassDeclaration(ok); | 194 return ParseClassDeclaration(ambient, ok); |
| 186 case Token::CONST: | 195 case Token::CONST: |
| 187 if (allow_const()) { | 196 if (allow_const()) { |
| 188 return ParseVariableStatement(kStatementListItem, ok); | 197 return ParseVariableStatement(kStatementListItem, ambient, ok); |
| 189 } | 198 } |
| 190 break; | 199 break; |
| 200 case Token::VAR: | |
| 201 return ParseVariableStatement(kStatementListItem, ambient, ok); | |
| 191 case Token::LET: | 202 case Token::LET: |
| 192 if (IsNextLetKeyword()) { | 203 if (IsNextLetKeyword()) { |
| 193 return ParseVariableStatement(kStatementListItem, ok); | 204 return ParseVariableStatement(kStatementListItem, ambient, ok); |
| 194 } | 205 } |
| 195 break; | 206 break; |
| 196 case Token::IDENTIFIER: | 207 case Token::IDENTIFIER: |
| 197 case Token::FUTURE_STRICT_RESERVED_WORD: { | 208 case Token::FUTURE_STRICT_RESERVED_WORD: { |
| 198 if (!scope_->typed()) break; | 209 if (!scope_->typed() || ambient) break; |
| 199 int pos = peek_position(); | 210 int pos = peek_position(); |
| 200 if (CheckContextualKeyword(CStrVector("type"))) { | 211 if (CheckContextualKeyword(CStrVector("type"))) { |
| 201 return ParseTypeAliasDeclaration(pos, ok); | 212 return ParseTypeAliasDeclaration(pos, ok); |
| 202 } else if (CheckContextualKeyword(CStrVector("interface"))) { | 213 } else if (CheckContextualKeyword(CStrVector("interface"))) { |
| 203 return ParseInterfaceDeclaration(pos, ok); | 214 return ParseInterfaceDeclaration(pos, ok); |
| 204 } | 215 } |
| 205 break; | 216 break; |
| 206 } | 217 } |
| 207 // TODO(nikolaos): ambient | |
| 208 default: | 218 default: |
| 209 break; | 219 break; |
| 210 } | 220 } |
| 221 if (ambient) { | |
| 222 *ok = false; | |
| 223 ReportMessageAt(scanner()->peek_location(), | |
| 224 MessageTemplate::kBadAmbientDeclaration); | |
| 225 return Statement::Default(); | |
| 226 } | |
| 211 return ParseStatement(kAllowLabelledFunctionStatement, ok); | 227 return ParseStatement(kAllowLabelledFunctionStatement, ok); |
| 212 } | 228 } |
| 213 | 229 |
| 214 | 230 |
| 215 void PreParser::ParseStatementList(int end_token, bool* ok, | 231 void PreParser::ParseStatementList(int end_token, bool top_level, bool* ok, |
| 216 Scanner::BookmarkScope* bookmark) { | 232 Scanner::BookmarkScope* bookmark) { |
| 217 // SourceElements :: | 233 // SourceElements :: |
| 218 // (Statement)* <end_token> | 234 // (Statement)* <end_token> |
| 219 | 235 |
| 220 // Bookkeeping for trial parse if bookmark is set: | 236 // Bookkeeping for trial parse if bookmark is set: |
| 221 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); | 237 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); |
| 222 bool maybe_reset = bookmark != nullptr; | 238 bool maybe_reset = bookmark != nullptr; |
| 223 int count_statements = 0; | 239 int count_statements = 0; |
| 224 | 240 |
| 225 bool directive_prologue = true; | 241 bool directive_prologue = true; |
| 226 while (peek() != end_token) { | 242 while (peek() != end_token) { |
| 227 if (directive_prologue && peek() != Token::STRING) { | 243 if (directive_prologue && peek() != Token::STRING) { |
| 228 directive_prologue = false; | 244 directive_prologue = false; |
| 229 } | 245 } |
| 230 bool starts_with_identifier = peek() == Token::IDENTIFIER; | 246 bool starts_with_identifier = peek() == Token::IDENTIFIER; |
| 231 Scanner::Location token_loc = scanner()->peek_location(); | 247 Scanner::Location token_loc = scanner()->peek_location(); |
| 232 Statement statement = ParseStatementListItem(ok); | 248 Statement statement = ParseStatementListItem(top_level, ok); |
| 233 if (!*ok) return; | 249 if (!*ok) return; |
| 234 | 250 |
| 235 if (directive_prologue) { | 251 if (directive_prologue) { |
| 236 bool use_strict_found = statement.IsUseStrictLiteral(); | 252 bool use_strict_found = statement.IsUseStrictLiteral(); |
| 237 bool use_types_found = | 253 bool use_types_found = |
| 238 statement.IsUseTypesLiteral() && allow_harmony_types(); | 254 statement.IsUseTypesLiteral() && allow_harmony_types(); |
| 239 | 255 |
| 240 if (use_strict_found) { | 256 if (use_strict_found) { |
| 241 scope_->SetLanguageMode( | 257 scope_->SetLanguageMode( |
| 242 static_cast<LanguageMode>(scope_->language_mode() | STRICT)); | 258 static_cast<LanguageMode>(scope_->language_mode() | STRICT)); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 return Statement::Default(); | 317 return Statement::Default(); |
| 302 } | 318 } |
| 303 return ParseSubStatement(allow_function, ok); | 319 return ParseSubStatement(allow_function, ok); |
| 304 } | 320 } |
| 305 | 321 |
| 306 PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) { | 322 PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) { |
| 307 if (is_strict(language_mode()) || peek() != Token::FUNCTION || | 323 if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
| 308 (legacy && allow_harmony_restrictive_declarations())) { | 324 (legacy && allow_harmony_restrictive_declarations())) { |
| 309 return ParseSubStatement(kDisallowLabelledFunctionStatement, ok); | 325 return ParseSubStatement(kDisallowLabelledFunctionStatement, ok); |
| 310 } else { | 326 } else { |
| 311 return ParseFunctionDeclaration(CHECK_OK); | 327 return ParseFunctionDeclaration(false, CHECK_OK); |
| 312 } | 328 } |
| 313 } | 329 } |
| 314 | 330 |
| 315 PreParser::Statement PreParser::ParseSubStatement( | 331 PreParser::Statement PreParser::ParseSubStatement( |
| 316 AllowLabelledFunctionStatement allow_function, bool* ok) { | 332 AllowLabelledFunctionStatement allow_function, bool* ok) { |
| 317 // Statement :: | 333 // Statement :: |
| 318 // Block | 334 // Block |
| 319 // VariableStatement | 335 // VariableStatement |
| 320 // EmptyStatement | 336 // EmptyStatement |
| 321 // ExpressionStatement | 337 // ExpressionStatement |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 is_strict(language_mode()) | 406 is_strict(language_mode()) |
| 391 ? MessageTemplate::kStrictFunction | 407 ? MessageTemplate::kStrictFunction |
| 392 : MessageTemplate::kSloppyFunction); | 408 : MessageTemplate::kSloppyFunction); |
| 393 *ok = false; | 409 *ok = false; |
| 394 return Statement::Default(); | 410 return Statement::Default(); |
| 395 | 411 |
| 396 case Token::DEBUGGER: | 412 case Token::DEBUGGER: |
| 397 return ParseDebuggerStatement(ok); | 413 return ParseDebuggerStatement(ok); |
| 398 | 414 |
| 399 case Token::VAR: | 415 case Token::VAR: |
| 400 return ParseVariableStatement(kStatement, ok); | 416 return ParseVariableStatement(kStatement, false, ok); |
| 401 | 417 |
| 402 default: | 418 default: |
| 403 return ParseExpressionOrLabelledStatement(allow_function, ok); | 419 return ParseExpressionOrLabelledStatement(allow_function, ok); |
| 404 } | 420 } |
| 405 } | 421 } |
| 406 | 422 |
| 407 | 423 |
| 408 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 424 PreParser::Statement PreParser::ParseFunctionDeclaration(bool ambient, |
| 425 bool* ok) { | |
| 409 // FunctionDeclaration :: | 426 // FunctionDeclaration :: |
| 410 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 427 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 411 // GeneratorDeclaration :: | 428 // GeneratorDeclaration :: |
| 412 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 429 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
| 413 // '{' FunctionBody '}' | 430 // '{' FunctionBody '}' |
| 414 Expect(Token::FUNCTION, CHECK_OK); | 431 Expect(Token::FUNCTION, CHECK_OK); |
| 415 int pos = position(); | 432 int pos = position(); |
| 416 bool is_generator = Check(Token::MUL); | 433 bool is_generator = Check(Token::MUL); |
| 417 bool is_strict_reserved = false; | 434 bool is_strict_reserved = false; |
| 418 Identifier name = ParseIdentifierOrStrictReservedWord( | 435 Identifier name = ParseIdentifierOrStrictReservedWord( |
| 419 &is_strict_reserved, CHECK_OK); | 436 &is_strict_reserved, CHECK_OK); |
| 437 typesystem::TypeFlags type_flags = | |
| 438 ambient ? typesystem::kAmbient : typesystem::kAllowSignature; | |
| 420 ParseFunctionLiteral(name, scanner()->location(), | 439 ParseFunctionLiteral(name, scanner()->location(), |
| 421 is_strict_reserved ? kFunctionNameIsStrictReserved | 440 is_strict_reserved ? kFunctionNameIsStrictReserved |
| 422 : kFunctionNameValidityUnknown, | 441 : kFunctionNameValidityUnknown, |
| 423 is_generator ? FunctionKind::kGeneratorFunction | 442 is_generator ? FunctionKind::kGeneratorFunction |
| 424 : FunctionKind::kNormalFunction, | 443 : FunctionKind::kNormalFunction, |
| 425 pos, FunctionLiteral::kDeclaration, language_mode(), | 444 pos, FunctionLiteral::kDeclaration, language_mode(), |
| 426 typesystem::kAllowSignature, CHECK_OK); | 445 type_flags, CHECK_OK); |
| 427 return Statement::FunctionDeclaration(); | 446 return Statement::FunctionDeclaration(); |
| 428 } | 447 } |
| 429 | 448 |
| 430 | 449 |
| 431 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { | 450 PreParser::Statement PreParser::ParseClassDeclaration(bool ambient, bool* ok) { |
| 432 Expect(Token::CLASS, CHECK_OK); | 451 Expect(Token::CLASS, CHECK_OK); |
| 433 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { | 452 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { |
| 434 ReportMessage(MessageTemplate::kSloppyLexical); | 453 ReportMessage(MessageTemplate::kSloppyLexical); |
| 435 *ok = false; | 454 *ok = false; |
| 436 return Statement::Default(); | 455 return Statement::Default(); |
| 437 } | 456 } |
| 438 | 457 |
| 439 int pos = position(); | 458 int pos = position(); |
| 440 bool is_strict_reserved = false; | 459 bool is_strict_reserved = false; |
| 441 Identifier name = | 460 Identifier name = |
| 442 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 461 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 443 ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, | 462 ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, |
| 444 CHECK_OK); | 463 ambient, CHECK_OK); |
| 445 return Statement::Default(); | 464 return Statement::Default(); |
| 446 } | 465 } |
| 447 | 466 |
| 448 | 467 |
| 449 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 468 PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 450 // Block :: | 469 // Block :: |
| 451 // '{' StatementList '}' | 470 // '{' StatementList '}' |
| 452 | 471 |
| 453 Expect(Token::LBRACE, CHECK_OK); | 472 Expect(Token::LBRACE, CHECK_OK); |
| 454 Statement final = Statement::Default(); | 473 Statement final = Statement::Default(); |
| 455 while (peek() != Token::RBRACE) { | 474 while (peek() != Token::RBRACE) { |
| 456 final = ParseStatementListItem(CHECK_OK); | 475 final = ParseStatementListItem(false, CHECK_OK); |
| 457 } | 476 } |
| 458 Expect(Token::RBRACE, ok); | 477 Expect(Token::RBRACE, ok); |
| 459 return final; | 478 return final; |
| 460 } | 479 } |
| 461 | 480 |
| 462 | 481 |
| 463 PreParser::Statement PreParser::ParseVariableStatement( | 482 PreParser::Statement PreParser::ParseVariableStatement( |
| 464 VariableDeclarationContext var_context, | 483 VariableDeclarationContext var_context, bool ambient, bool* ok) { |
| 465 bool* ok) { | |
| 466 // VariableStatement :: | 484 // VariableStatement :: |
| 467 // VariableDeclarations ';' | 485 // VariableDeclarations ';' |
| 468 | 486 |
| 469 Statement result = ParseVariableDeclarations( | 487 Statement result = |
| 470 var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK); | 488 ParseVariableDeclarations(var_context, nullptr, nullptr, nullptr, nullptr, |
| 489 nullptr, ambient, CHECK_OK); | |
| 471 ExpectSemicolon(CHECK_OK); | 490 ExpectSemicolon(CHECK_OK); |
| 472 return result; | 491 return result; |
| 473 } | 492 } |
| 474 | 493 |
| 475 | 494 |
| 476 // If the variable declaration declares exactly one non-const | 495 // If the variable declaration declares exactly one non-const |
| 477 // variable, then *var is set to that variable. In all other cases, | 496 // variable, then *var is set to that variable. In all other cases, |
| 478 // *var is untouched; in particular, it is the caller's responsibility | 497 // *var is untouched; in particular, it is the caller's responsibility |
| 479 // to initialize it properly. This mechanism is also used for the parsing | 498 // to initialize it properly. This mechanism is also used for the parsing |
| 480 // of 'for-in' loops. | 499 // of 'for-in' loops. |
| 481 PreParser::Statement PreParser::ParseVariableDeclarations( | 500 PreParser::Statement PreParser::ParseVariableDeclarations( |
| 482 VariableDeclarationContext var_context, int* num_decl, bool* is_lexical, | 501 VariableDeclarationContext var_context, int* num_decl, bool* is_lexical, |
| 483 bool* is_binding_pattern, Scanner::Location* first_initializer_loc, | 502 bool* is_binding_pattern, Scanner::Location* first_initializer_loc, |
| 484 Scanner::Location* bindings_loc, bool* ok) { | 503 Scanner::Location* bindings_loc, bool ambient, bool* ok) { |
| 485 // VariableDeclarations :: | 504 // VariableDeclarations :: |
| 486 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 505 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 487 // | 506 // |
| 488 // The ES6 Draft Rev3 specifies the following grammar for const declarations | 507 // The ES6 Draft Rev3 specifies the following grammar for const declarations |
| 489 // | 508 // |
| 490 // ConstDeclaration :: | 509 // ConstDeclaration :: |
| 491 // const ConstBinding (',' ConstBinding)* ';' | 510 // const ConstBinding (',' ConstBinding)* ';' |
| 492 // ConstBinding :: | 511 // ConstBinding :: |
| 493 // Identifier '=' AssignmentExpression | 512 // Identifier '=' AssignmentExpression |
| 494 // | 513 // |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 547 } | 566 } |
| 548 } | 567 } |
| 549 | 568 |
| 550 is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); | 569 is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); |
| 551 | 570 |
| 552 // Parse optional type annotation. | 571 // Parse optional type annotation. |
| 553 if (scope_->typed() && Check(Token::COLON)) { // Braces required here. | 572 if (scope_->typed() && Check(Token::COLON)) { // Braces required here. |
| 554 ParseValidType(CHECK_OK); | 573 ParseValidType(CHECK_OK); |
| 555 } | 574 } |
| 556 | 575 |
| 576 // Skip initializers, for ambient declarations. | |
|
rossberg
2016/04/20 15:16:35
Nit: maybe don't say "skip initializers", but "no
nickie
2016/04/21 13:57:10
Done.
| |
| 577 if (ambient) { | |
| 578 nvars++; | |
| 579 continue; | |
| 580 } | |
| 581 | |
| 557 Scanner::Location variable_loc = scanner()->location(); | 582 Scanner::Location variable_loc = scanner()->location(); |
| 558 nvars++; | 583 nvars++; |
| 559 if (Check(Token::ASSIGN)) { | 584 if (Check(Token::ASSIGN)) { |
| 560 ExpressionClassifier classifier(this); | 585 ExpressionClassifier classifier(this); |
| 561 ParseAssignmentExpression(var_context != kForStatement, &classifier, | 586 ParseAssignmentExpression(var_context != kForStatement, &classifier, |
| 562 CHECK_OK); | 587 CHECK_OK); |
| 563 ValidateExpression(&classifier, CHECK_OK); | 588 ValidateExpression(&classifier, CHECK_OK); |
| 564 | 589 |
| 565 variable_loc.end_pos = scanner()->location().end_pos; | 590 variable_loc.end_pos = scanner()->location().end_pos; |
| 566 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | 591 if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 618 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { | 643 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { |
| 619 // Expression is a single identifier, and not, e.g., a parenthesized | 644 // Expression is a single identifier, and not, e.g., a parenthesized |
| 620 // identifier. | 645 // identifier. |
| 621 DCHECK(!expr.AsIdentifier().IsFutureReserved()); | 646 DCHECK(!expr.AsIdentifier().IsFutureReserved()); |
| 622 DCHECK(is_sloppy(language_mode()) || | 647 DCHECK(is_sloppy(language_mode()) || |
| 623 !IsFutureStrictReserved(expr.AsIdentifier())); | 648 !IsFutureStrictReserved(expr.AsIdentifier())); |
| 624 Consume(Token::COLON); | 649 Consume(Token::COLON); |
| 625 // ES#sec-labelled-function-declarations Labelled Function Declarations | 650 // ES#sec-labelled-function-declarations Labelled Function Declarations |
| 626 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | 651 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { |
| 627 if (allow_function == kAllowLabelledFunctionStatement) { | 652 if (allow_function == kAllowLabelledFunctionStatement) { |
| 628 return ParseFunctionDeclaration(ok); | 653 return ParseFunctionDeclaration(false, ok); |
| 629 } else { | 654 } else { |
| 630 return ParseScopedStatement(true, ok); | 655 return ParseScopedStatement(true, ok); |
| 631 } | 656 } |
| 632 } | 657 } |
| 633 Statement statement = | 658 Statement statement = |
| 634 ParseStatement(kDisallowLabelledFunctionStatement, ok); | 659 ParseStatement(kDisallowLabelledFunctionStatement, ok); |
| 635 return statement.IsJumpStatement() ? Statement::Default() : statement; | 660 return statement.IsJumpStatement() ? Statement::Default() : statement; |
| 636 // Preparsing is disabled for extensions (because the extension details | 661 // Preparsing is disabled for extensions (because the extension details |
| 637 // aren't passed to lazily compiled functions), so we don't | 662 // aren't passed to lazily compiled functions), so we don't |
| 638 // accept "native function" in the preparser. | 663 // accept "native function" in the preparser. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 ParseExpression(true, CHECK_OK); | 797 ParseExpression(true, CHECK_OK); |
| 773 } else { | 798 } else { |
| 774 Expect(Token::DEFAULT, CHECK_OK); | 799 Expect(Token::DEFAULT, CHECK_OK); |
| 775 } | 800 } |
| 776 Expect(Token::COLON, CHECK_OK); | 801 Expect(Token::COLON, CHECK_OK); |
| 777 token = peek(); | 802 token = peek(); |
| 778 Statement statement = Statement::Jump(); | 803 Statement statement = Statement::Jump(); |
| 779 while (token != Token::CASE && | 804 while (token != Token::CASE && |
| 780 token != Token::DEFAULT && | 805 token != Token::DEFAULT && |
| 781 token != Token::RBRACE) { | 806 token != Token::RBRACE) { |
| 782 statement = ParseStatementListItem(CHECK_OK); | 807 statement = ParseStatementListItem(false, CHECK_OK); |
| 783 token = peek(); | 808 token = peek(); |
| 784 } | 809 } |
| 785 } | 810 } |
| 786 Expect(Token::RBRACE, ok); | 811 Expect(Token::RBRACE, ok); |
| 787 return Statement::Default(); | 812 return Statement::Default(); |
| 788 } | 813 } |
| 789 | 814 |
| 790 | 815 |
| 791 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { | 816 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { |
| 792 // DoStatement :: | 817 // DoStatement :: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 ForEachStatement::VisitMode mode; | 852 ForEachStatement::VisitMode mode; |
| 828 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || | 853 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || |
| 829 (peek() == Token::LET && IsNextLetKeyword())) { | 854 (peek() == Token::LET && IsNextLetKeyword())) { |
| 830 int decl_count; | 855 int decl_count; |
| 831 bool is_lexical; | 856 bool is_lexical; |
| 832 bool is_binding_pattern; | 857 bool is_binding_pattern; |
| 833 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); | 858 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
| 834 Scanner::Location bindings_loc = Scanner::Location::invalid(); | 859 Scanner::Location bindings_loc = Scanner::Location::invalid(); |
| 835 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, | 860 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, |
| 836 &is_binding_pattern, &first_initializer_loc, | 861 &is_binding_pattern, &first_initializer_loc, |
| 837 &bindings_loc, CHECK_OK); | 862 &bindings_loc, false, CHECK_OK); |
| 838 if (CheckInOrOf(&mode, ok)) { | 863 if (CheckInOrOf(&mode, ok)) { |
| 839 if (!*ok) return Statement::Default(); | 864 if (!*ok) return Statement::Default(); |
| 840 if (decl_count != 1) { | 865 if (decl_count != 1) { |
| 841 PreParserTraits::ReportMessageAt( | 866 PreParserTraits::ReportMessageAt( |
| 842 bindings_loc, MessageTemplate::kForInOfLoopMultiBindings, | 867 bindings_loc, MessageTemplate::kForInOfLoopMultiBindings, |
| 843 ForEachStatement::VisitModeString(mode)); | 868 ForEachStatement::VisitModeString(mode)); |
| 844 *ok = false; | 869 *ok = false; |
| 845 return Statement::Default(); | 870 return Statement::Default(); |
| 846 } | 871 } |
| 847 if (first_initializer_loc.IsValid() && | 872 if (first_initializer_loc.IsValid() && |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1048 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, | 1073 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, |
| 1049 formals_end_position, CHECK_OK); | 1074 formals_end_position, CHECK_OK); |
| 1050 | 1075 |
| 1051 // See Parser::ParseFunctionLiteral for more information about lazy parsing | 1076 // See Parser::ParseFunctionLiteral for more information about lazy parsing |
| 1052 // and lazy compilation. | 1077 // and lazy compilation. |
| 1053 bool is_lazily_parsed = | 1078 bool is_lazily_parsed = |
| 1054 (outer_is_script_scope && allow_lazy() && !parenthesized_function_); | 1079 (outer_is_script_scope && allow_lazy() && !parenthesized_function_); |
| 1055 parenthesized_function_ = false; | 1080 parenthesized_function_ = false; |
| 1056 | 1081 |
| 1057 // Parse optional type annotation. | 1082 // Parse optional type annotation. |
| 1058 if (scope_->typed() && | 1083 if (scope_->typed() && !(type_flags & typesystem::kDisallowTypeAnnotation) && |
| 1059 !(type_flags & typesystem::kDisallowTypeAnnotation) && | |
| 1060 Check(Token::COLON)) { // Braces required here. | 1084 Check(Token::COLON)) { // Braces required here. |
| 1061 ParseValidType(CHECK_OK); | 1085 ParseValidType(CHECK_OK); |
| 1062 } | 1086 } |
| 1063 | 1087 |
| 1064 // Allow for a function signature (i.e., a literal without body). | 1088 // Allow or even enforce a function signature (i.e., literal without body), |
| 1065 if (peek() != Token::LBRACE && scope_->typed() && | 1089 // In that case, return a nullptr instead of a function literal. |
| 1066 (type_flags & typesystem::kAllowSignature)) { | 1090 if ((type_flags & typesystem::kDisallowBody) || |
| 1091 (peek() != Token::LBRACE && scope_->typed() && | |
| 1092 (type_flags & typesystem::kAllowSignature))) { | |
| 1067 ExpectSemicolon(CHECK_OK); | 1093 ExpectSemicolon(CHECK_OK); |
| 1068 return this->EmptyExpression(); | 1094 return this->EmptyExpression(); |
| 1069 } | 1095 } |
| 1070 | 1096 |
| 1071 Expect(Token::LBRACE, CHECK_OK); | 1097 Expect(Token::LBRACE, CHECK_OK); |
| 1072 if (is_lazily_parsed) { | 1098 if (is_lazily_parsed) { |
| 1073 ParseLazyFunctionLiteralBody(CHECK_OK); | 1099 ParseLazyFunctionLiteralBody(CHECK_OK); |
| 1074 } else { | 1100 } else { |
| 1075 ParseStatementList(Token::RBRACE, CHECK_OK); | 1101 ParseStatementList(Token::RBRACE, false, CHECK_OK); |
| 1076 } | 1102 } |
| 1077 Expect(Token::RBRACE, CHECK_OK); | 1103 Expect(Token::RBRACE, CHECK_OK); |
| 1078 | 1104 |
| 1079 // Parsing the body may change the language mode in our scope. | 1105 // Parsing the body may change the language mode in our scope. |
| 1080 language_mode = function_scope->language_mode(); | 1106 language_mode = function_scope->language_mode(); |
| 1081 | 1107 |
| 1082 // Validate name and parameter names. We can do this only after parsing the | 1108 // Validate name and parameter names. We can do this only after parsing the |
| 1083 // function, since the function can declare itself strict. | 1109 // function, since the function can declare itself strict. |
| 1084 CheckFunctionName(language_mode, function_name, function_name_validity, | 1110 CheckFunctionName(language_mode, function_name, function_name_validity, |
| 1085 function_name_location, CHECK_OK); | 1111 function_name_location, CHECK_OK); |
| 1086 const bool allow_duplicate_parameters = | 1112 const bool allow_duplicate_parameters = |
| 1087 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); | 1113 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); |
| 1088 ValidateFormalParameters(&formals_classifier, language_mode, | 1114 ValidateFormalParameters(&formals_classifier, language_mode, |
| 1089 allow_duplicate_parameters, CHECK_OK); | 1115 allow_duplicate_parameters, CHECK_OK); |
| 1090 | 1116 |
| 1091 if (is_strict(language_mode)) { | 1117 if (is_strict(language_mode)) { |
| 1092 int end_position = scanner()->location().end_pos; | 1118 int end_position = scanner()->location().end_pos; |
| 1093 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); | 1119 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); |
| 1094 } | 1120 } |
| 1095 | 1121 |
| 1096 return Expression::Default(); | 1122 return Expression::Default(); |
| 1097 } | 1123 } |
| 1098 | 1124 |
| 1099 | 1125 |
| 1100 void PreParser::ParseLazyFunctionLiteralBody(bool* ok, | 1126 void PreParser::ParseLazyFunctionLiteralBody(bool* ok, |
| 1101 Scanner::BookmarkScope* bookmark) { | 1127 Scanner::BookmarkScope* bookmark) { |
| 1102 int body_start = position(); | 1128 int body_start = position(); |
| 1103 ParseStatementList(Token::RBRACE, ok, bookmark); | 1129 ParseStatementList(Token::RBRACE, false, ok, bookmark); |
| 1104 if (!*ok) return; | 1130 if (!*ok) return; |
| 1105 if (bookmark && bookmark->HasBeenReset()) return; | 1131 if (bookmark && bookmark->HasBeenReset()) return; |
| 1106 | 1132 |
| 1107 // Position right after terminal '}'. | 1133 // Position right after terminal '}'. |
| 1108 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 1134 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
| 1109 int body_end = scanner()->peek_location().end_pos; | 1135 int body_end = scanner()->peek_location().end_pos; |
| 1110 log_->LogFunction(body_start, body_end, | 1136 log_->LogFunction(body_start, body_end, |
| 1111 function_state_->materialized_literal_count(), | 1137 function_state_->materialized_literal_count(), |
| 1112 function_state_->expected_property_count(), language_mode(), | 1138 function_state_->expected_property_count(), language_mode(), |
| 1113 scope_->uses_super_property(), scope_->calls_eval()); | 1139 scope_->uses_super_property(), scope_->calls_eval()); |
| 1114 } | 1140 } |
| 1115 | 1141 |
| 1116 | 1142 |
| 1117 PreParserExpression PreParser::ParseClassLiteral( | 1143 PreParserExpression PreParser::ParseClassLiteral( |
| 1118 PreParserIdentifier name, Scanner::Location class_name_location, | 1144 PreParserIdentifier name, Scanner::Location class_name_location, |
| 1119 bool name_is_strict_reserved, int pos, bool* ok) { | 1145 bool name_is_strict_reserved, int pos, bool ambient, bool* ok) { |
| 1120 // All parts of a ClassDeclaration and ClassExpression are strict code. | 1146 // All parts of a ClassDeclaration and ClassExpression are strict code. |
| 1121 if (name_is_strict_reserved) { | 1147 if (name_is_strict_reserved) { |
| 1122 ReportMessageAt(class_name_location, | 1148 ReportMessageAt(class_name_location, |
| 1123 MessageTemplate::kUnexpectedStrictReserved); | 1149 MessageTemplate::kUnexpectedStrictReserved); |
| 1124 *ok = false; | 1150 *ok = false; |
| 1125 return EmptyExpression(); | 1151 return EmptyExpression(); |
| 1126 } | 1152 } |
| 1127 if (IsEvalOrArguments(name)) { | 1153 if (IsEvalOrArguments(name)) { |
| 1128 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); | 1154 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); |
| 1129 *ok = false; | 1155 *ok = false; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1165 while (peek() != Token::RBRACE) { | 1191 while (peek() != Token::RBRACE) { |
| 1166 if (Check(Token::SEMICOLON)) continue; | 1192 if (Check(Token::SEMICOLON)) continue; |
| 1167 const bool in_class = true; | 1193 const bool in_class = true; |
| 1168 const bool is_static = false; | 1194 const bool is_static = false; |
| 1169 bool is_computed_name = false; // Classes do not care about computed | 1195 bool is_computed_name = false; // Classes do not care about computed |
| 1170 // property names here. | 1196 // property names here. |
| 1171 Identifier name; | 1197 Identifier name; |
| 1172 ExpressionClassifier classifier(this); | 1198 ExpressionClassifier classifier(this); |
| 1173 ParsePropertyDefinition(&checker, in_class, has_extends, is_static, | 1199 ParsePropertyDefinition(&checker, in_class, has_extends, is_static, |
| 1174 &is_computed_name, &has_seen_constructor, | 1200 &is_computed_name, &has_seen_constructor, |
| 1175 &classifier, &name, CHECK_OK); | 1201 &classifier, &name, ambient, CHECK_OK); |
| 1176 ValidateExpression(&classifier, CHECK_OK); | 1202 ValidateExpression(&classifier, CHECK_OK); |
| 1177 } | 1203 } |
| 1178 | 1204 |
| 1179 Expect(Token::RBRACE, CHECK_OK); | 1205 Expect(Token::RBRACE, CHECK_OK); |
| 1180 | 1206 |
| 1181 return Expression::Default(); | 1207 return Expression::Default(); |
| 1182 } | 1208 } |
| 1183 | 1209 |
| 1184 | 1210 |
| 1185 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { | 1211 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1205 | 1231 |
| 1206 PreParserExpression PreParser::ParseDoExpression(bool* ok) { | 1232 PreParserExpression PreParser::ParseDoExpression(bool* ok) { |
| 1207 // AssignmentExpression :: | 1233 // AssignmentExpression :: |
| 1208 // do '{' StatementList '}' | 1234 // do '{' StatementList '}' |
| 1209 Expect(Token::DO, CHECK_OK); | 1235 Expect(Token::DO, CHECK_OK); |
| 1210 Expect(Token::LBRACE, CHECK_OK); | 1236 Expect(Token::LBRACE, CHECK_OK); |
| 1211 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 1237 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
| 1212 { | 1238 { |
| 1213 BlockState block_state(&scope_, block_scope); | 1239 BlockState block_state(&scope_, block_scope); |
| 1214 while (peek() != Token::RBRACE) { | 1240 while (peek() != Token::RBRACE) { |
| 1215 ParseStatementListItem(CHECK_OK); | 1241 ParseStatementListItem(false, CHECK_OK); |
| 1216 } | 1242 } |
| 1217 Expect(Token::RBRACE, CHECK_OK); | 1243 Expect(Token::RBRACE, CHECK_OK); |
| 1218 return PreParserExpression::Default(); | 1244 return PreParserExpression::Default(); |
| 1219 } | 1245 } |
| 1220 } | 1246 } |
| 1221 | 1247 |
| 1222 #undef CHECK_OK | 1248 #undef CHECK_OK |
| 1223 | 1249 |
| 1224 | 1250 |
| 1225 } // namespace internal | 1251 } // namespace internal |
| 1226 } // namespace v8 | 1252 } // namespace v8 |
| OLD | NEW |