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 1192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1203 TargetScope scope(&this->target_stack_); | 1203 TargetScope scope(&this->target_stack_); |
1204 | 1204 |
1205 DCHECK(body != NULL); | 1205 DCHECK(body != NULL); |
1206 bool directive_prologue = true; // Parsing directive prologue. | 1206 bool directive_prologue = true; // Parsing directive prologue. |
1207 | 1207 |
1208 while (peek() != end_token) { | 1208 while (peek() != end_token) { |
1209 if (directive_prologue && peek() != Token::STRING) { | 1209 if (directive_prologue && peek() != Token::STRING) { |
1210 directive_prologue = false; | 1210 directive_prologue = false; |
1211 } | 1211 } |
1212 | 1212 |
1213 Token::Value token = peek(); | |
1214 Scanner::Location token_loc = scanner()->peek_location(); | 1213 Scanner::Location token_loc = scanner()->peek_location(); |
1215 Scanner::Location old_super_loc = function_state_->super_call_location(); | 1214 Scanner::Location old_this_loc = function_state_->this_location(); |
| 1215 Scanner::Location old_super_loc = function_state_->super_location(); |
1216 Statement* stat = ParseStatementListItem(CHECK_OK); | 1216 Statement* stat = ParseStatementListItem(CHECK_OK); |
1217 Scanner::Location super_loc = function_state_->super_call_location(); | |
1218 | 1217 |
1219 if (is_strong(language_mode()) && | 1218 if (is_strong(language_mode()) && |
1220 i::IsConstructor(function_state_->kind()) && | 1219 scope_->is_function_scope() && |
1221 !old_super_loc.IsValid() && super_loc.IsValid() && | 1220 i::IsConstructor(function_state_->kind())) { |
1222 token != Token::SUPER) { | 1221 Scanner::Location this_loc = function_state_->this_location(); |
1223 // TODO(rossberg): This is more permissive than spec'ed, it allows e.g. | 1222 Scanner::Location super_loc = function_state_->super_location(); |
1224 // super(), 1; | 1223 if (this_loc.beg_pos != old_this_loc.beg_pos && |
1225 // super() + ""; | 1224 this_loc.beg_pos != token_loc.beg_pos) { |
1226 // super() = 0; | 1225 ReportMessageAt(this_loc, "strong_constructor_this"); |
1227 // That should still be safe, though, thanks to left-to-right evaluation. | 1226 *ok = false; |
1228 // The proper check would be difficult to implement in the preparser. | 1227 return nullptr; |
1229 ReportMessageAt(super_loc, "strong_super_call_nested"); | 1228 } |
1230 *ok = false; | 1229 if (super_loc.beg_pos != old_super_loc.beg_pos && |
1231 return NULL; | 1230 super_loc.beg_pos != token_loc.beg_pos) { |
| 1231 ReportMessageAt(super_loc, "strong_constructor_super"); |
| 1232 *ok = false; |
| 1233 return nullptr; |
| 1234 } |
1232 } | 1235 } |
1233 | 1236 |
1234 if (stat == NULL || stat->IsEmpty()) { | 1237 if (stat == NULL || stat->IsEmpty()) { |
1235 directive_prologue = false; // End of directive prologue. | 1238 directive_prologue = false; // End of directive prologue. |
1236 continue; | 1239 continue; |
1237 } | 1240 } |
1238 | 1241 |
1239 if (directive_prologue) { | 1242 if (directive_prologue) { |
1240 // A shot at a directive. | 1243 // A shot at a directive. |
1241 ExpressionStatement* e_stat; | 1244 ExpressionStatement* e_stat; |
(...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2586 | 2589 |
2587 Statement* Parser::ParseExpressionOrLabelledStatement( | 2590 Statement* Parser::ParseExpressionOrLabelledStatement( |
2588 ZoneList<const AstRawString*>* labels, bool* ok) { | 2591 ZoneList<const AstRawString*>* labels, bool* ok) { |
2589 // ExpressionStatement | LabelledStatement :: | 2592 // ExpressionStatement | LabelledStatement :: |
2590 // Expression ';' | 2593 // Expression ';' |
2591 // Identifier ':' Statement | 2594 // Identifier ':' Statement |
2592 // | 2595 // |
2593 // ExpressionStatement[Yield] : | 2596 // ExpressionStatement[Yield] : |
2594 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; | 2597 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; |
2595 | 2598 |
| 2599 int pos = peek_position(); |
| 2600 |
2596 switch (peek()) { | 2601 switch (peek()) { |
2597 case Token::FUNCTION: | 2602 case Token::FUNCTION: |
2598 case Token::LBRACE: | 2603 case Token::LBRACE: |
2599 UNREACHABLE(); // Always handled by the callers. | 2604 UNREACHABLE(); // Always handled by the callers. |
2600 case Token::CLASS: | 2605 case Token::CLASS: |
2601 ReportUnexpectedToken(Next()); | 2606 ReportUnexpectedToken(Next()); |
2602 *ok = false; | 2607 *ok = false; |
2603 return nullptr; | 2608 return nullptr; |
2604 | 2609 |
| 2610 case Token::THIS: |
| 2611 case Token::SUPER: |
| 2612 if (is_strong(language_mode()) && |
| 2613 i::IsConstructor(function_state_->kind())) { |
| 2614 bool is_this = peek() == Token::THIS; |
| 2615 Expression* expr; |
| 2616 if (is_this) { |
| 2617 expr = ParseStrongInitializationExpression(CHECK_OK); |
| 2618 } else { |
| 2619 expr = ParseStrongSuperCallExpression(CHECK_OK); |
| 2620 } |
| 2621 switch (peek()) { |
| 2622 case Token::SEMICOLON: |
| 2623 Consume(Token::SEMICOLON); |
| 2624 break; |
| 2625 case Token::RBRACE: |
| 2626 case Token::EOS: |
| 2627 break; |
| 2628 default: |
| 2629 if (!scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 2630 ReportMessageAt(function_state_->this_location(), |
| 2631 is_this ? "strong_constructor_this" |
| 2632 : "strong_constructor_super"); |
| 2633 *ok = false; |
| 2634 return nullptr; |
| 2635 } |
| 2636 } |
| 2637 return factory()->NewExpressionStatement(expr, pos); |
| 2638 } |
| 2639 break; |
| 2640 |
2605 // TODO(arv): Handle `let [` | 2641 // TODO(arv): Handle `let [` |
2606 // https://code.google.com/p/v8/issues/detail?id=3847 | 2642 // https://code.google.com/p/v8/issues/detail?id=3847 |
2607 | 2643 |
2608 default: | 2644 default: |
2609 break; | 2645 break; |
2610 } | 2646 } |
2611 | 2647 |
2612 int pos = peek_position(); | |
2613 bool starts_with_idenfifier = peek_any_identifier(); | 2648 bool starts_with_idenfifier = peek_any_identifier(); |
2614 Expression* expr = ParseExpression(true, CHECK_OK); | 2649 Expression* expr = ParseExpression(true, CHECK_OK); |
2615 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && | 2650 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && |
2616 expr->AsVariableProxy() != NULL && | 2651 expr->AsVariableProxy() != NULL && |
2617 !expr->AsVariableProxy()->is_this()) { | 2652 !expr->AsVariableProxy()->is_this()) { |
2618 // Expression is a single identifier, and not, e.g., a parenthesized | 2653 // Expression is a single identifier, and not, e.g., a parenthesized |
2619 // identifier. | 2654 // identifier. |
2620 VariableProxy* var = expr->AsVariableProxy(); | 2655 VariableProxy* var = expr->AsVariableProxy(); |
2621 const AstRawString* label = var->raw_name(); | 2656 const AstRawString* label = var->raw_name(); |
2622 // TODO(1240780): We don't check for redeclaration of labels | 2657 // TODO(1240780): We don't check for redeclaration of labels |
(...skipping 1373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3996 // that it will be compiled lazily. | 4031 // that it will be compiled lazily. |
3997 | 4032 |
3998 // To make this additional case work, both Parser and PreParser implement a | 4033 // To make this additional case work, both Parser and PreParser implement a |
3999 // logic where only top-level functions will be parsed lazily. | 4034 // logic where only top-level functions will be parsed lazily. |
4000 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | 4035 bool is_lazily_parsed = (mode() == PARSE_LAZILY && |
4001 scope_->AllowsLazyCompilation() && | 4036 scope_->AllowsLazyCompilation() && |
4002 !parenthesized_function_); | 4037 !parenthesized_function_); |
4003 parenthesized_function_ = false; // The bit was set for this function only. | 4038 parenthesized_function_ = false; // The bit was set for this function only. |
4004 | 4039 |
4005 if (is_lazily_parsed) { | 4040 if (is_lazily_parsed) { |
4006 SkipLazyFunctionBody(function_name, &materialized_literal_count, | 4041 SkipLazyFunctionBody(&materialized_literal_count, |
4007 &expected_property_count, CHECK_OK); | 4042 &expected_property_count, CHECK_OK); |
4008 } else { | 4043 } else { |
4009 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | 4044 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, |
4010 kind, CHECK_OK); | 4045 kind, CHECK_OK); |
4011 materialized_literal_count = function_state.materialized_literal_count(); | 4046 materialized_literal_count = function_state.materialized_literal_count(); |
4012 expected_property_count = function_state.expected_property_count(); | 4047 expected_property_count = function_state.expected_property_count(); |
4013 handler_count = function_state.handler_count(); | 4048 handler_count = function_state.handler_count(); |
| 4049 |
| 4050 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { |
| 4051 if (!function_state.super_location().IsValid()) { |
| 4052 ReportMessageAt(function_name_location, |
| 4053 "strong_super_call_missing", kReferenceError); |
| 4054 *ok = false; |
| 4055 return nullptr; |
| 4056 } |
| 4057 } |
4014 } | 4058 } |
4015 | 4059 |
4016 // Validate name and parameter names. We can do this only after parsing the | 4060 // Validate name and parameter names. We can do this only after parsing the |
4017 // function, since the function can declare itself strict. | 4061 // function, since the function can declare itself strict. |
4018 CheckFunctionName(language_mode(), kind, function_name, | 4062 CheckFunctionName(language_mode(), kind, function_name, |
4019 name_is_strict_reserved, function_name_location, | 4063 name_is_strict_reserved, function_name_location, |
4020 CHECK_OK); | 4064 CHECK_OK); |
4021 const bool use_strict_params = has_rest || IsConciseMethod(kind); | 4065 const bool use_strict_params = has_rest || IsConciseMethod(kind); |
4022 CheckFunctionParameterNames(language_mode(), use_strict_params, error_locs, | 4066 CheckFunctionParameterNames(language_mode(), use_strict_params, error_locs, |
4023 CHECK_OK); | 4067 CHECK_OK); |
4024 | 4068 |
4025 if (is_strict(language_mode())) { | 4069 if (is_strict(language_mode())) { |
4026 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | 4070 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
4027 CHECK_OK); | 4071 CHECK_OK); |
4028 } | |
4029 if (is_strict(language_mode())) { | |
4030 CheckConflictingVarDeclarations(scope, CHECK_OK); | 4072 CheckConflictingVarDeclarations(scope, CHECK_OK); |
4031 } | 4073 } |
4032 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | |
4033 if (!function_state.super_call_location().IsValid()) { | |
4034 ReportMessageAt(function_name_location, "strong_super_call_missing", | |
4035 kReferenceError); | |
4036 *ok = false; | |
4037 return nullptr; | |
4038 } | |
4039 } | |
4040 } | 4074 } |
4041 | 4075 |
4042 FunctionLiteral::ParameterFlag duplicate_parameters = | 4076 FunctionLiteral::ParameterFlag duplicate_parameters = |
4043 error_locs.duplicate.IsValid() ? FunctionLiteral::kHasDuplicateParameters | 4077 error_locs.duplicate.IsValid() ? FunctionLiteral::kHasDuplicateParameters |
4044 : FunctionLiteral::kNoDuplicateParameters; | 4078 : FunctionLiteral::kNoDuplicateParameters; |
4045 | 4079 |
4046 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 4080 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
4047 function_name, ast_value_factory(), scope, body, | 4081 function_name, ast_value_factory(), scope, body, |
4048 materialized_literal_count, expected_property_count, handler_count, | 4082 materialized_literal_count, expected_property_count, handler_count, |
4049 num_parameters, duplicate_parameters, function_type, | 4083 num_parameters, duplicate_parameters, function_type, |
4050 FunctionLiteral::kIsFunction, parenthesized, kind, pos); | 4084 FunctionLiteral::kIsFunction, parenthesized, kind, pos); |
4051 function_literal->set_function_token_position(function_token_pos); | 4085 function_literal->set_function_token_position(function_token_pos); |
4052 | 4086 |
4053 if (scope->has_rest_parameter()) { | 4087 if (scope->has_rest_parameter()) { |
4054 // TODO(caitp): enable optimization of functions with rest params | 4088 // TODO(caitp): enable optimization of functions with rest params |
4055 function_literal->set_dont_optimize_reason(kRestParameter); | 4089 function_literal->set_dont_optimize_reason(kRestParameter); |
4056 } | 4090 } |
4057 | 4091 |
4058 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 4092 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
4059 return function_literal; | 4093 return function_literal; |
4060 } | 4094 } |
4061 | 4095 |
4062 | 4096 |
4063 void Parser::SkipLazyFunctionBody(const AstRawString* function_name, | 4097 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, |
4064 int* materialized_literal_count, | |
4065 int* expected_property_count, | 4098 int* expected_property_count, |
4066 bool* ok) { | 4099 bool* ok) { |
4067 if (produce_cached_parse_data()) CHECK(log_); | 4100 if (produce_cached_parse_data()) CHECK(log_); |
4068 | 4101 |
4069 int function_block_pos = position(); | 4102 int function_block_pos = position(); |
4070 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { | 4103 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { |
4071 // If we have cached data, we use it to skip parsing the function body. The | 4104 // If we have cached data, we use it to skip parsing the function body. The |
4072 // data contains the information we need to construct the lazy function. | 4105 // data contains the information we need to construct the lazy function. |
4073 FunctionEntry entry = | 4106 FunctionEntry entry = |
4074 cached_parse_data_->GetFunctionEntry(function_block_pos); | 4107 cached_parse_data_->GetFunctionEntry(function_block_pos); |
(...skipping 1672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5747 | 5780 |
5748 Expression* Parser::SpreadCallNew(Expression* function, | 5781 Expression* Parser::SpreadCallNew(Expression* function, |
5749 ZoneList<v8::internal::Expression*>* args, | 5782 ZoneList<v8::internal::Expression*>* args, |
5750 int pos) { | 5783 int pos) { |
5751 args->InsertAt(0, function, zone()); | 5784 args->InsertAt(0, function, zone()); |
5752 | 5785 |
5753 return factory()->NewCallRuntime( | 5786 return factory()->NewCallRuntime( |
5754 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5787 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5755 } | 5788 } |
5756 } } // namespace v8::internal | 5789 } } // namespace v8::internal |
OLD | NEW |