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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-expression-visitor.h" | |
9 #include "src/ast/ast-literal-reindexer.h" | 10 #include "src/ast/ast-literal-reindexer.h" |
10 #include "src/ast/scopeinfo.h" | 11 #include "src/ast/scopeinfo.h" |
11 #include "src/bailout-reason.h" | 12 #include "src/bailout-reason.h" |
12 #include "src/base/platform/platform.h" | 13 #include "src/base/platform/platform.h" |
13 #include "src/bootstrapper.h" | 14 #include "src/bootstrapper.h" |
14 #include "src/char-predicates-inl.h" | 15 #include "src/char-predicates-inl.h" |
15 #include "src/codegen.h" | 16 #include "src/codegen.h" |
16 #include "src/compiler.h" | 17 #include "src/compiler.h" |
17 #include "src/messages.h" | 18 #include "src/messages.h" |
18 #include "src/parsing/parameter-initializer-rewriter.h" | 19 #include "src/parsing/parameter-initializer-rewriter.h" |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
913 // ParseInfo during background parsing. | 914 // ParseInfo during background parsing. |
914 DCHECK(!info->script().is_null() || info->source_stream() != NULL); | 915 DCHECK(!info->script().is_null() || info->source_stream() != NULL); |
915 set_allow_lazy(info->allow_lazy_parsing()); | 916 set_allow_lazy(info->allow_lazy_parsing()); |
916 set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); | 917 set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); |
917 set_allow_harmony_sloppy(FLAG_harmony_sloppy); | 918 set_allow_harmony_sloppy(FLAG_harmony_sloppy); |
918 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function); | 919 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function); |
919 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); | 920 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); |
920 set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters); | 921 set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters); |
921 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); | 922 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); |
922 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); | 923 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); |
924 set_allow_harmony_destructuring_assignment( | |
925 FLAG_harmony_destructuring_assignment); | |
923 set_allow_strong_mode(FLAG_strong_mode); | 926 set_allow_strong_mode(FLAG_strong_mode); |
924 set_allow_legacy_const(FLAG_legacy_const); | 927 set_allow_legacy_const(FLAG_legacy_const); |
925 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); | 928 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); |
926 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | 929 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; |
927 ++feature) { | 930 ++feature) { |
928 use_counts_[feature] = 0; | 931 use_counts_[feature] = 0; |
929 } | 932 } |
930 if (info->ast_value_factory() == NULL) { | 933 if (info->ast_value_factory() == NULL) { |
931 // info takes ownership of AstValueFactory. | 934 // info takes ownership of AstValueFactory. |
932 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); | 935 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1083 if (body->length() != 1 || | 1086 if (body->length() != 1 || |
1084 !body->at(0)->IsExpressionStatement() || | 1087 !body->at(0)->IsExpressionStatement() || |
1085 !body->at(0)->AsExpressionStatement()-> | 1088 !body->at(0)->AsExpressionStatement()-> |
1086 expression()->IsFunctionLiteral()) { | 1089 expression()->IsFunctionLiteral()) { |
1087 ReportMessage(MessageTemplate::kSingleFunctionLiteral); | 1090 ReportMessage(MessageTemplate::kSingleFunctionLiteral); |
1088 ok = false; | 1091 ok = false; |
1089 } | 1092 } |
1090 } | 1093 } |
1091 | 1094 |
1092 if (ok) { | 1095 if (ok) { |
1096 ParserTraits::RewriteDestructuringAssignments(); | |
1093 result = factory()->NewFunctionLiteral( | 1097 result = factory()->NewFunctionLiteral( |
1094 ast_value_factory()->empty_string(), ast_value_factory(), scope_, | 1098 ast_value_factory()->empty_string(), ast_value_factory(), scope_, |
1095 body, function_state.materialized_literal_count(), | 1099 body, function_state.materialized_literal_count(), |
1096 function_state.expected_property_count(), 0, | 1100 function_state.expected_property_count(), 0, |
1097 FunctionLiteral::kNoDuplicateParameters, | 1101 FunctionLiteral::kNoDuplicateParameters, |
1098 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval, | 1102 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval, |
1099 FunctionLiteral::kShouldLazyCompile, FunctionKind::kNormalFunction, | 1103 FunctionLiteral::kShouldLazyCompile, FunctionKind::kNormalFunction, |
1100 0); | 1104 0); |
1101 } | 1105 } |
1102 } | 1106 } |
(...skipping 3287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4390 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | 4394 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
4391 CHECK_OK); | 4395 CHECK_OK); |
4392 } | 4396 } |
4393 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) { | 4397 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) { |
4394 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK); | 4398 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK); |
4395 } | 4399 } |
4396 if (is_strict(language_mode) || allow_harmony_sloppy() || | 4400 if (is_strict(language_mode) || allow_harmony_sloppy() || |
4397 allow_harmony_destructuring_bind()) { | 4401 allow_harmony_destructuring_bind()) { |
4398 CheckConflictingVarDeclarations(scope, CHECK_OK); | 4402 CheckConflictingVarDeclarations(scope, CHECK_OK); |
4399 } | 4403 } |
4404 | |
4405 if (body) { | |
4406 // If body can be inspected, rewrite queued destructuring assignments | |
4407 ParserTraits::RewriteDestructuringAssignments(); | |
4408 } | |
4400 } | 4409 } |
4401 | 4410 |
4402 bool has_duplicate_parameters = | 4411 bool has_duplicate_parameters = |
4403 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); | 4412 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); |
4404 FunctionLiteral::ParameterFlag duplicate_parameters = | 4413 FunctionLiteral::ParameterFlag duplicate_parameters = |
4405 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters | 4414 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters |
4406 : FunctionLiteral::kNoDuplicateParameters; | 4415 : FunctionLiteral::kNoDuplicateParameters; |
4407 | 4416 |
4408 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 4417 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
4409 function_name, ast_value_factory(), scope, body, | 4418 function_name, ast_value_factory(), scope, body, |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4518 RelocInfo::kNoPosition); | 4527 RelocInfo::kNoPosition); |
4519 IfStatement* if_statement = factory()->NewIfStatement( | 4528 IfStatement* if_statement = factory()->NewIfStatement( |
4520 condition, factory()->NewExpressionStatement(throw_type_error, | 4529 condition, factory()->NewExpressionStatement(throw_type_error, |
4521 RelocInfo::kNoPosition), | 4530 RelocInfo::kNoPosition), |
4522 factory()->NewEmptyStatement(RelocInfo::kNoPosition), | 4531 factory()->NewEmptyStatement(RelocInfo::kNoPosition), |
4523 RelocInfo::kNoPosition); | 4532 RelocInfo::kNoPosition); |
4524 return if_statement; | 4533 return if_statement; |
4525 } | 4534 } |
4526 | 4535 |
4527 | 4536 |
4537 class InitializerRewriter : public AstExpressionVisitor { | |
4538 public: | |
4539 InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser, | |
4540 Scope* scope) | |
4541 : AstExpressionVisitor(stack_limit, root), | |
4542 parser_(parser), | |
4543 scope_(scope) {} | |
4544 | |
4545 private: | |
4546 void VisitExpression(Expression* expr) { | |
4547 RewritableExpression* rw = expr->AsRewritableExpression(); | |
adamk
2015/12/01 22:42:56
Naming nit: I like "to_rewrite" better than "rw".
| |
4548 if (!rw || | |
adamk
2015/12/01 22:42:56
to_rewrite == nullptr
| |
4549 !rw->IsRewritableAs(RewritableExpression::kDestructuringAssignment)) { | |
adamk
2015/12/01 22:42:56
It's checks like this that I don't see as terribly
caitp (gmail)
2015/12/01 22:51:00
the check is checking 2 things: 1, that it's "poss
adamk
2015/12/01 22:54:23
Right, sorry, there is that second case. Even so,
| |
4550 return; | |
4551 } | |
4552 | |
4553 bool ok = true; | |
4554 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, rw, scope_, | |
4555 &ok); | |
4556 DCHECK(ok); | |
4557 } | |
4558 | |
4559 private: | |
4560 Parser* parser_; | |
4561 Scope* scope_; | |
4562 }; | |
4563 | |
4564 | |
4565 void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) { | |
4566 InitializerRewriter rewriter(stack_limit_, expr, this, scope); | |
4567 rewriter.Run(); | |
4568 } | |
4569 | |
4570 | |
4528 Block* Parser::BuildParameterInitializationBlock( | 4571 Block* Parser::BuildParameterInitializationBlock( |
4529 const ParserFormalParameters& parameters, bool* ok) { | 4572 const ParserFormalParameters& parameters, bool* ok) { |
4530 DCHECK(!parameters.is_simple); | 4573 DCHECK(!parameters.is_simple); |
4531 DCHECK(scope_->is_function_scope()); | 4574 DCHECK(scope_->is_function_scope()); |
4532 Block* init_block = | 4575 Block* init_block = |
4533 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); | 4576 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); |
4534 for (int i = 0; i < parameters.params.length(); ++i) { | 4577 for (int i = 0; i < parameters.params.length(); ++i) { |
4535 auto parameter = parameters.params[i]; | 4578 auto parameter = parameters.params[i]; |
4536 DeclarationDescriptor descriptor; | 4579 DeclarationDescriptor descriptor; |
4537 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; | 4580 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; |
(...skipping 12 matching lines...) Expand all Loading... | |
4550 // it's just copying from a temp var to the real param var? | 4593 // it's just copying from a temp var to the real param var? |
4551 descriptor.initialization_pos = parameter.pattern->position(); | 4594 descriptor.initialization_pos = parameter.pattern->position(); |
4552 // The initializer position which will end up in, | 4595 // The initializer position which will end up in, |
4553 // Variable::initializer_position(), used for hole check elimination. | 4596 // Variable::initializer_position(), used for hole check elimination. |
4554 int initializer_position = parameter.pattern->position(); | 4597 int initializer_position = parameter.pattern->position(); |
4555 Expression* initial_value = | 4598 Expression* initial_value = |
4556 factory()->NewVariableProxy(parameters.scope->parameter(i)); | 4599 factory()->NewVariableProxy(parameters.scope->parameter(i)); |
4557 if (parameter.initializer != nullptr) { | 4600 if (parameter.initializer != nullptr) { |
4558 // IS_UNDEFINED($param) ? initializer : $param | 4601 // IS_UNDEFINED($param) ? initializer : $param |
4559 DCHECK(!parameter.is_rest); | 4602 DCHECK(!parameter.is_rest); |
4603 | |
4604 // Ensure initializer is rewritten | |
4605 RewriteParameterInitializer(parameter.initializer, scope_); | |
4606 | |
4560 auto condition = factory()->NewCompareOperation( | 4607 auto condition = factory()->NewCompareOperation( |
4561 Token::EQ_STRICT, | 4608 Token::EQ_STRICT, |
4562 factory()->NewVariableProxy(parameters.scope->parameter(i)), | 4609 factory()->NewVariableProxy(parameters.scope->parameter(i)), |
4563 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | 4610 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
4564 RelocInfo::kNoPosition); | 4611 RelocInfo::kNoPosition); |
4565 initial_value = factory()->NewConditional( | 4612 initial_value = factory()->NewConditional( |
4566 condition, parameter.initializer, initial_value, | 4613 condition, parameter.initializer, initial_value, |
4567 RelocInfo::kNoPosition); | 4614 RelocInfo::kNoPosition); |
4568 descriptor.initialization_pos = parameter.initializer->position(); | 4615 descriptor.initialization_pos = parameter.initializer->position(); |
4569 initializer_position = parameter.initializer_end_position; | 4616 initializer_position = parameter.initializer_end_position; |
(...skipping 1883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6453 ++use_counts_[feature]; | 6500 ++use_counts_[feature]; |
6454 scope->SetLanguageMode(mode); | 6501 scope->SetLanguageMode(mode); |
6455 } | 6502 } |
6456 | 6503 |
6457 | 6504 |
6458 void Parser::RaiseLanguageMode(LanguageMode mode) { | 6505 void Parser::RaiseLanguageMode(LanguageMode mode) { |
6459 SetLanguageMode(scope_, | 6506 SetLanguageMode(scope_, |
6460 static_cast<LanguageMode>(scope_->language_mode() | mode)); | 6507 static_cast<LanguageMode>(scope_->language_mode() | mode)); |
6461 } | 6508 } |
6462 | 6509 |
6510 | |
6511 void ParserTraits::RewriteDestructuringAssignments() { | |
6512 parser_->RewriteDestructuringAssignments(); | |
6513 } | |
6514 | |
6515 | |
6516 void Parser::RewriteDestructuringAssignments() { | |
6517 FunctionState* func = function_state_; | |
6518 if (!allow_harmony_destructuring_assignment()) return; | |
6519 const List<DestructuringAssignment>& assignments = | |
6520 func->destructuring_assignments_to_rewrite(); | |
6521 for (int i = assignments.length() - 1; i >= 0; --i) { | |
6522 // Rewrite list in reverse, so that nested assignment patterns are rewritten | |
6523 // correctly. | |
6524 DestructuringAssignment pair = assignments.at(i); | |
6525 RewritableExpression* rw = pair.assignment->AsRewritableExpression(); | |
adamk
2015/12/01 22:42:56
Like the old name better here too
| |
6526 Scope* scope = pair.scope; | |
6527 DCHECK_NOT_NULL(rw); | |
6528 if (rw->IsRewritableAs(RewritableExpression::kDestructuringAssignment)) { | |
6529 bool ok = true; | |
6530 PatternRewriter::RewriteDestructuringAssignment(this, rw, scope, &ok); | |
6531 DCHECK(ok); | |
6532 } | |
6533 } | |
6534 } | |
6535 | |
6536 | |
6537 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { | |
6538 DCHECK(expr->IsRewritableExpression()); | |
6539 DCHECK(expr->AsRewritableExpression()->expression()->IsAssignment()); | |
adamk
2015/12/01 22:42:56
This, too, will go away if you just use the C++ ty
| |
6540 DCHECK(expr->AsRewritableExpression()->hints() & | |
6541 RewritableExpression::kDestructuringAssignment); | |
6542 parser_->function_state_->AddDestructuringAssignment( | |
6543 Parser::DestructuringAssignment(expr, parser_->scope_)); | |
6544 } | |
6545 | |
6546 | |
6463 } // namespace internal | 6547 } // namespace internal |
6464 } // namespace v8 | 6548 } // namespace v8 |
OLD | NEW |