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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast.h" | 8 #include "src/ast.h" |
9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 2277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2288 const Declaration& declaration = declarations.at(0); | 2288 const Declaration& declaration = declarations.at(0); |
2289 if (declaration.pattern->IsVariableProxy()) { | 2289 if (declaration.pattern->IsVariableProxy()) { |
2290 return declaration.pattern->AsVariableProxy()->raw_name(); | 2290 return declaration.pattern->AsVariableProxy()->raw_name(); |
2291 } | 2291 } |
2292 return nullptr; | 2292 return nullptr; |
2293 } | 2293 } |
2294 | 2294 |
2295 | 2295 |
2296 Block* Parser::DeclarationParsingResult::BuildInitializationBlock( | 2296 Block* Parser::DeclarationParsingResult::BuildInitializationBlock( |
2297 ZoneList<const AstRawString*>* names, bool* ok) { | 2297 ZoneList<const AstRawString*>* names, bool* ok) { |
2298 Block* result = | 2298 Block* result = descriptor.parser->factory()->NewBlock( |
2299 descriptor.parser->factory()->NewBlock(NULL, 1, true, descriptor.pos); | 2299 NULL, 1, true, descriptor.declaration_pos); |
2300 for (auto declaration : declarations) { | 2300 for (auto declaration : declarations) { |
2301 PatternRewriter::DeclareAndInitializeVariables( | 2301 PatternRewriter::DeclareAndInitializeVariables( |
2302 result, &descriptor, &declaration, names, CHECK_OK); | 2302 result, &descriptor, &declaration, names, CHECK_OK); |
2303 } | 2303 } |
2304 return result; | 2304 return result; |
2305 } | 2305 } |
2306 | 2306 |
2307 | 2307 |
2308 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | 2308 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
2309 ZoneList<const AstRawString*>* names, | 2309 ZoneList<const AstRawString*>* names, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2343 // ConstDeclaration :: | 2343 // ConstDeclaration :: |
2344 // const ConstBinding (',' ConstBinding)* ';' | 2344 // const ConstBinding (',' ConstBinding)* ';' |
2345 // ConstBinding :: | 2345 // ConstBinding :: |
2346 // Identifier '=' AssignmentExpression | 2346 // Identifier '=' AssignmentExpression |
2347 // | 2347 // |
2348 // TODO(ES6): | 2348 // TODO(ES6): |
2349 // ConstBinding :: | 2349 // ConstBinding :: |
2350 // BindingPattern '=' AssignmentExpression | 2350 // BindingPattern '=' AssignmentExpression |
2351 | 2351 |
2352 parsing_result->descriptor.parser = this; | 2352 parsing_result->descriptor.parser = this; |
2353 parsing_result->descriptor.pos = peek_position(); | 2353 parsing_result->descriptor.declaration_pos = peek_position(); |
| 2354 parsing_result->descriptor.initialization_pos = peek_position(); |
2354 parsing_result->descriptor.mode = VAR; | 2355 parsing_result->descriptor.mode = VAR; |
2355 // True if the binding needs initialization. 'let' and 'const' declared | 2356 // True if the binding needs initialization. 'let' and 'const' declared |
2356 // bindings are created uninitialized by their declaration nodes and | 2357 // bindings are created uninitialized by their declaration nodes and |
2357 // need initialization. 'var' declared bindings are always initialized | 2358 // need initialization. 'var' declared bindings are always initialized |
2358 // immediately by their declaration nodes. | 2359 // immediately by their declaration nodes. |
2359 parsing_result->descriptor.needs_init = false; | 2360 parsing_result->descriptor.needs_init = false; |
2360 parsing_result->descriptor.is_const = false; | 2361 parsing_result->descriptor.is_const = false; |
2361 parsing_result->descriptor.init_op = Token::INIT_VAR; | 2362 parsing_result->descriptor.init_op = Token::INIT_VAR; |
2362 if (peek() == Token::VAR) { | 2363 if (peek() == Token::VAR) { |
2363 if (is_strong(language_mode())) { | 2364 if (is_strong(language_mode())) { |
(...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3410 // Create an in-between scope for let-bound iteration variables. | 3411 // Create an in-between scope for let-bound iteration variables. |
3411 Scope* saved_scope = scope_; | 3412 Scope* saved_scope = scope_; |
3412 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3413 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
3413 scope_ = for_scope; | 3414 scope_ = for_scope; |
3414 Expect(Token::FOR, CHECK_OK); | 3415 Expect(Token::FOR, CHECK_OK); |
3415 Expect(Token::LPAREN, CHECK_OK); | 3416 Expect(Token::LPAREN, CHECK_OK); |
3416 for_scope->set_start_position(scanner()->location().beg_pos); | 3417 for_scope->set_start_position(scanner()->location().beg_pos); |
3417 bool is_let_identifier_expression = false; | 3418 bool is_let_identifier_expression = false; |
3418 DeclarationParsingResult parsing_result; | 3419 DeclarationParsingResult parsing_result; |
3419 if (peek() != Token::SEMICOLON) { | 3420 if (peek() != Token::SEMICOLON) { |
3420 if (peek() == Token::VAR || | 3421 if (peek() == Token::VAR || peek() == Token::CONST || |
3421 (peek() == Token::CONST && is_sloppy(language_mode()))) { | 3422 (peek() == Token::LET && is_strict(language_mode()))) { |
3422 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | 3423 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); |
3423 Block* variable_statement = | 3424 is_const = parsing_result.descriptor.mode == CONST; |
3424 parsing_result.BuildInitializationBlock(nullptr, CHECK_OK); | |
3425 | 3425 |
3426 int num_decl = parsing_result.declarations.length(); | 3426 int num_decl = parsing_result.declarations.length(); |
3427 bool accept_IN = num_decl >= 1; | 3427 bool accept_IN = num_decl >= 1; |
3428 bool accept_OF = true; | 3428 bool accept_OF = true; |
3429 ForEachStatement::VisitMode mode; | 3429 ForEachStatement::VisitMode mode; |
3430 int each_beg_pos = scanner()->location().beg_pos; | 3430 int each_beg_pos = scanner()->location().beg_pos; |
3431 int each_end_pos = scanner()->location().end_pos; | 3431 int each_end_pos = scanner()->location().end_pos; |
3432 | 3432 |
3433 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | 3433 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
3434 if (!*ok) return nullptr; | 3434 if (!*ok) return nullptr; |
(...skipping 12 matching lines...) Expand all Loading... |
3447 ReportMessageAt(parsing_result.first_initializer_loc, | 3447 ReportMessageAt(parsing_result.first_initializer_loc, |
3448 MessageTemplate::kForOfLoopInitializer); | 3448 MessageTemplate::kForOfLoopInitializer); |
3449 } else { | 3449 } else { |
3450 // TODO(caitp): This should be an error in sloppy mode too. | 3450 // TODO(caitp): This should be an error in sloppy mode too. |
3451 ReportMessageAt(parsing_result.first_initializer_loc, | 3451 ReportMessageAt(parsing_result.first_initializer_loc, |
3452 MessageTemplate::kForInLoopInitializer); | 3452 MessageTemplate::kForInLoopInitializer); |
3453 } | 3453 } |
3454 *ok = false; | 3454 *ok = false; |
3455 return nullptr; | 3455 return nullptr; |
3456 } | 3456 } |
| 3457 |
| 3458 DCHECK(parsing_result.declarations.length() == 1); |
| 3459 Block* init_block = nullptr; |
| 3460 |
| 3461 // special case for legacy for (var/const x =.... in) |
| 3462 if (is_sloppy(language_mode()) && |
| 3463 !IsLexicalVariableMode(parsing_result.descriptor.mode) && |
| 3464 parsing_result.declarations[0].initializer != nullptr) { |
| 3465 VariableProxy* single_var = scope_->NewUnresolved( |
| 3466 factory(), parsing_result.SingleName(), Variable::NORMAL, |
| 3467 each_beg_pos, each_end_pos); |
| 3468 init_block = factory()->NewBlock( |
| 3469 nullptr, 2, true, parsing_result.descriptor.declaration_pos); |
| 3470 init_block->AddStatement( |
| 3471 factory()->NewExpressionStatement( |
| 3472 factory()->NewAssignment( |
| 3473 Token::ASSIGN, single_var, |
| 3474 parsing_result.declarations[0].initializer, |
| 3475 RelocInfo::kNoPosition), |
| 3476 RelocInfo::kNoPosition), |
| 3477 zone()); |
| 3478 } |
| 3479 |
| 3480 // Rewrite a for-in/of statement of the form |
| 3481 // |
| 3482 // for (let/const/var x in/of e) b |
| 3483 // |
| 3484 // into |
| 3485 // |
| 3486 // <let x' be a temporary variable> |
| 3487 // for (x' in/of e) { |
| 3488 // let/const/var x; |
| 3489 // x = x'; |
| 3490 // b; |
| 3491 // } |
| 3492 |
| 3493 Variable* temp = scope_->DeclarationScope()->NewTemporary( |
| 3494 ast_value_factory()->dot_for_string()); |
3457 ForEachStatement* loop = | 3495 ForEachStatement* loop = |
3458 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3496 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3459 Target target(&this->target_stack_, loop); | 3497 Target target(&this->target_stack_, loop); |
3460 | 3498 |
3461 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3499 // The expression does not see the lexical loop variables. |
3462 Expect(Token::RPAREN, CHECK_OK); | |
3463 | |
3464 VariableProxy* each = | |
3465 scope_->NewUnresolved(factory(), parsing_result.SingleName(), | |
3466 Variable::NORMAL, each_beg_pos, each_end_pos); | |
3467 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3468 InitializeForEachStatement(loop, each, enumerable, body); | |
3469 Block* result = | |
3470 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | |
3471 result->AddStatement(variable_statement, zone()); | |
3472 result->AddStatement(loop, zone()); | |
3473 scope_ = saved_scope; | |
3474 for_scope->set_end_position(scanner()->location().end_pos); | |
3475 for_scope = for_scope->FinalizeBlockScope(); | |
3476 DCHECK(for_scope == NULL); | |
3477 // Parsed for-in loop w/ variable/const declaration. | |
3478 return result; | |
3479 } else { | |
3480 init = variable_statement; | |
3481 } | |
3482 } else if ((peek() == Token::LET || peek() == Token::CONST) && | |
3483 is_strict(language_mode())) { | |
3484 is_const = peek() == Token::CONST; | |
3485 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | |
3486 DCHECK(parsing_result.descriptor.pos != RelocInfo::kNoPosition); | |
3487 | |
3488 int num_decl = parsing_result.declarations.length(); | |
3489 bool accept_IN = num_decl >= 1; | |
3490 bool accept_OF = true; | |
3491 ForEachStatement::VisitMode mode; | |
3492 int each_beg_pos = scanner()->location().beg_pos; | |
3493 int each_end_pos = scanner()->location().end_pos; | |
3494 | |
3495 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | |
3496 if (!*ok) return nullptr; | |
3497 if (num_decl != 1) { | |
3498 const char* loop_type = | |
3499 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; | |
3500 ParserTraits::ReportMessageAt( | |
3501 parsing_result.bindings_loc, | |
3502 MessageTemplate::kForInOfLoopMultiBindings, loop_type); | |
3503 *ok = false; | |
3504 return nullptr; | |
3505 } | |
3506 if (parsing_result.first_initializer_loc.IsValid() && | |
3507 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { | |
3508 if (mode == ForEachStatement::ITERATE) { | |
3509 ReportMessageAt(parsing_result.first_initializer_loc, | |
3510 MessageTemplate::kForOfLoopInitializer); | |
3511 } else { | |
3512 ReportMessageAt(parsing_result.first_initializer_loc, | |
3513 MessageTemplate::kForInLoopInitializer); | |
3514 } | |
3515 *ok = false; | |
3516 return nullptr; | |
3517 } | |
3518 // Rewrite a for-in statement of the form | |
3519 // | |
3520 // for (let/const x in e) b | |
3521 // | |
3522 // into | |
3523 // | |
3524 // <let x' be a temporary variable> | |
3525 // for (x' in e) { | |
3526 // let/const x; | |
3527 // x = x'; | |
3528 // b; | |
3529 // } | |
3530 | |
3531 // TODO(keuchel): Move the temporary variable to the block scope, after | |
3532 // implementing stack allocated block scoped variables. | |
3533 Variable* temp = scope_->DeclarationScope()->NewTemporary( | |
3534 ast_value_factory()->dot_for_string()); | |
3535 VariableProxy* temp_proxy = | |
3536 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
3537 ForEachStatement* loop = | |
3538 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
3539 Target target(&this->target_stack_, loop); | |
3540 | |
3541 // The expression does not see the loop variable. | |
3542 scope_ = saved_scope; | 3500 scope_ = saved_scope; |
3543 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3501 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3544 scope_ = for_scope; | 3502 scope_ = for_scope; |
3545 Expect(Token::RPAREN, CHECK_OK); | 3503 Expect(Token::RPAREN, CHECK_OK); |
3546 | 3504 |
3547 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3505 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
| 3506 |
3548 Block* body_block = | 3507 Block* body_block = |
3549 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | 3508 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
3550 | 3509 |
3551 auto each_initialization_block = factory()->NewBlock( | 3510 auto each_initialization_block = |
3552 nullptr, 1, true, parsing_result.descriptor.pos); | 3511 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); |
3553 { | 3512 { |
3554 DCHECK(parsing_result.declarations.length() == 1); | 3513 DCHECK(parsing_result.declarations.length() == 1); |
3555 DeclarationParsingResult::Declaration decl = | 3514 DeclarationParsingResult::Declaration decl = |
3556 parsing_result.declarations[0]; | 3515 parsing_result.declarations[0]; |
3557 decl.initializer = temp_proxy; | 3516 auto descriptor = parsing_result.descriptor; |
| 3517 descriptor.declaration_pos = RelocInfo::kNoPosition; |
| 3518 decl.initializer = factory()->NewVariableProxy(temp); |
| 3519 |
3558 PatternRewriter::DeclareAndInitializeVariables( | 3520 PatternRewriter::DeclareAndInitializeVariables( |
3559 each_initialization_block, &parsing_result.descriptor, &decl, | 3521 each_initialization_block, &descriptor, &decl, |
3560 &lexical_bindings, CHECK_OK); | 3522 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings |
| 3523 : nullptr, |
| 3524 CHECK_OK); |
3561 } | 3525 } |
3562 | 3526 |
3563 body_block->AddStatement(each_initialization_block, zone()); | 3527 body_block->AddStatement(each_initialization_block, zone()); |
3564 body_block->AddStatement(body, zone()); | 3528 body_block->AddStatement(body, zone()); |
| 3529 VariableProxy* temp_proxy = |
| 3530 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); |
3565 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); | 3531 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); |
3566 scope_ = saved_scope; | 3532 scope_ = saved_scope; |
3567 for_scope->set_end_position(scanner()->location().end_pos); | 3533 for_scope->set_end_position(scanner()->location().end_pos); |
3568 for_scope = for_scope->FinalizeBlockScope(); | 3534 for_scope = for_scope->FinalizeBlockScope(); |
3569 body_block->set_scope(for_scope); | 3535 if (for_scope != nullptr) { |
3570 // Parsed for-in loop w/ let declaration. | 3536 body_block->set_scope(for_scope); |
3571 return loop; | 3537 } |
| 3538 // Parsed for-in loop w/ variable declarations. |
| 3539 if (init_block != nullptr) { |
| 3540 init_block->AddStatement(loop, zone()); |
| 3541 return init_block; |
| 3542 } else { |
| 3543 return loop; |
| 3544 } |
3572 } else { | 3545 } else { |
3573 init = parsing_result.BuildInitializationBlock(&lexical_bindings, | 3546 init = parsing_result.BuildInitializationBlock( |
3574 CHECK_OK); | 3547 IsLexicalVariableMode(parsing_result.descriptor.mode) |
| 3548 ? &lexical_bindings |
| 3549 : nullptr, |
| 3550 CHECK_OK); |
3575 } | 3551 } |
3576 } else { | 3552 } else { |
3577 Scanner::Location lhs_location = scanner()->peek_location(); | 3553 Scanner::Location lhs_location = scanner()->peek_location(); |
3578 Expression* expression = ParseExpression(false, CHECK_OK); | 3554 Expression* expression = ParseExpression(false, CHECK_OK); |
3579 ForEachStatement::VisitMode mode; | 3555 ForEachStatement::VisitMode mode; |
3580 bool accept_OF = expression->IsVariableProxy(); | 3556 bool accept_OF = expression->IsVariableProxy(); |
3581 is_let_identifier_expression = | 3557 is_let_identifier_expression = |
3582 expression->IsVariableProxy() && | 3558 expression->IsVariableProxy() && |
3583 expression->AsVariableProxy()->raw_name() == | 3559 expression->AsVariableProxy()->raw_name() == |
3584 ast_value_factory()->let_string(); | 3560 ast_value_factory()->let_string(); |
3585 | 3561 |
3586 if (CheckInOrOf(accept_OF, &mode, ok)) { | 3562 if (CheckInOrOf(accept_OF, &mode, ok)) { |
3587 if (!*ok) return nullptr; | 3563 if (!*ok) return nullptr; |
3588 expression = this->CheckAndRewriteReferenceExpression( | 3564 expression = this->CheckAndRewriteReferenceExpression( |
3589 expression, lhs_location, MessageTemplate::kInvalidLhsInFor, | 3565 expression, lhs_location, MessageTemplate::kInvalidLhsInFor, |
3590 CHECK_OK); | 3566 CHECK_OK); |
3591 | 3567 |
3592 ForEachStatement* loop = | 3568 ForEachStatement* loop = |
3593 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3569 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3594 Target target(&this->target_stack_, loop); | 3570 Target target(&this->target_stack_, loop); |
(...skipping 2213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5808 | 5784 |
5809 Expression* Parser::SpreadCallNew(Expression* function, | 5785 Expression* Parser::SpreadCallNew(Expression* function, |
5810 ZoneList<v8::internal::Expression*>* args, | 5786 ZoneList<v8::internal::Expression*>* args, |
5811 int pos) { | 5787 int pos) { |
5812 args->InsertAt(0, function, zone()); | 5788 args->InsertAt(0, function, zone()); |
5813 | 5789 |
5814 return factory()->NewCallRuntime( | 5790 return factory()->NewCallRuntime( |
5815 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5791 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5816 } | 5792 } |
5817 } } // namespace v8::internal | 5793 } } // namespace v8::internal |
OLD | NEW |