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 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 TargetScope scope(&this->target_stack_); | 1201 TargetScope scope(&this->target_stack_); |
1202 | 1202 |
1203 DCHECK(body != NULL); | 1203 DCHECK(body != NULL); |
1204 bool directive_prologue = true; // Parsing directive prologue. | 1204 bool directive_prologue = true; // Parsing directive prologue. |
1205 | 1205 |
1206 while (peek() != end_token) { | 1206 while (peek() != end_token) { |
1207 if (directive_prologue && peek() != Token::STRING) { | 1207 if (directive_prologue && peek() != Token::STRING) { |
1208 directive_prologue = false; | 1208 directive_prologue = false; |
1209 } | 1209 } |
1210 | 1210 |
1211 Token::Value token = peek(); | |
1212 Scanner::Location token_loc = scanner()->peek_location(); | 1211 Scanner::Location token_loc = scanner()->peek_location(); |
1213 Scanner::Location old_super_loc = function_state_->super_call_location(); | 1212 Scanner::Location old_this_loc = function_state_->this_location(); |
| 1213 Scanner::Location old_super_loc = function_state_->super_location(); |
1214 Statement* stat = ParseStatementListItem(CHECK_OK); | 1214 Statement* stat = ParseStatementListItem(CHECK_OK); |
1215 Scanner::Location super_loc = function_state_->super_call_location(); | |
1216 | 1215 |
1217 if (is_strong(language_mode()) && | 1216 if (is_strong(language_mode()) && |
1218 i::IsConstructor(function_state_->kind()) && | 1217 scope_->is_function_scope() && |
1219 !old_super_loc.IsValid() && super_loc.IsValid() && | 1218 i::IsConstructor(function_state_->kind())) { |
1220 token != Token::SUPER) { | 1219 Scanner::Location this_loc = function_state_->this_location(); |
1221 // TODO(rossberg): This is more permissive than spec'ed, it allows e.g. | 1220 Scanner::Location super_loc = function_state_->super_location(); |
1222 // super(), 1; | 1221 if (this_loc.beg_pos != old_this_loc.beg_pos && |
1223 // super() + ""; | 1222 this_loc.beg_pos != token_loc.beg_pos) { |
1224 // super() = 0; | 1223 ReportMessageAt(this_loc, "strong_constructor_this"); |
1225 // That should still be safe, though, thanks to left-to-right evaluation. | 1224 *ok = false; |
1226 // The proper check would be difficult to implement in the preparser. | 1225 return nullptr; |
1227 ReportMessageAt(super_loc, "strong_super_call_nested"); | 1226 } |
1228 *ok = false; | 1227 if (super_loc.beg_pos != old_super_loc.beg_pos && |
1229 return NULL; | 1228 super_loc.beg_pos != token_loc.beg_pos) { |
| 1229 ReportMessageAt(super_loc, "strong_constructor_super"); |
| 1230 *ok = false; |
| 1231 return nullptr; |
| 1232 } |
1230 } | 1233 } |
1231 | 1234 |
1232 if (stat == NULL || stat->IsEmpty()) { | 1235 if (stat == NULL || stat->IsEmpty()) { |
1233 directive_prologue = false; // End of directive prologue. | 1236 directive_prologue = false; // End of directive prologue. |
1234 continue; | 1237 continue; |
1235 } | 1238 } |
1236 | 1239 |
1237 if (directive_prologue) { | 1240 if (directive_prologue) { |
1238 // A shot at a directive. | 1241 // A shot at a directive. |
1239 ExpressionStatement* e_stat; | 1242 ExpressionStatement* e_stat; |
(...skipping 1304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2544 | 2547 |
2545 Statement* Parser::ParseExpressionOrLabelledStatement( | 2548 Statement* Parser::ParseExpressionOrLabelledStatement( |
2546 ZoneList<const AstRawString*>* labels, bool* ok) { | 2549 ZoneList<const AstRawString*>* labels, bool* ok) { |
2547 // ExpressionStatement | LabelledStatement :: | 2550 // ExpressionStatement | LabelledStatement :: |
2548 // Expression ';' | 2551 // Expression ';' |
2549 // Identifier ':' Statement | 2552 // Identifier ':' Statement |
2550 // | 2553 // |
2551 // ExpressionStatement[Yield] : | 2554 // ExpressionStatement[Yield] : |
2552 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; | 2555 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; |
2553 | 2556 |
| 2557 int pos = peek_position(); |
| 2558 |
2554 switch (peek()) { | 2559 switch (peek()) { |
2555 case Token::FUNCTION: | 2560 case Token::FUNCTION: |
2556 case Token::LBRACE: | 2561 case Token::LBRACE: |
2557 UNREACHABLE(); // Always handled by the callers. | 2562 UNREACHABLE(); // Always handled by the callers. |
2558 case Token::CLASS: | 2563 case Token::CLASS: |
2559 ReportUnexpectedToken(Next()); | 2564 ReportUnexpectedToken(Next()); |
2560 *ok = false; | 2565 *ok = false; |
2561 return nullptr; | 2566 return nullptr; |
2562 | 2567 |
| 2568 case Token::THIS: |
| 2569 case Token::SUPER: |
| 2570 if (is_strong(language_mode()) && |
| 2571 i::IsConstructor(function_state_->kind())) { |
| 2572 bool is_this = peek() == Token::THIS; |
| 2573 Expression* expr; |
| 2574 if (is_this) { |
| 2575 expr = ParseStrongInitializationExpression(CHECK_OK); |
| 2576 } else { |
| 2577 expr = ParseStrongSuperCallExpression(CHECK_OK); |
| 2578 } |
| 2579 switch (peek()) { |
| 2580 case Token::SEMICOLON: |
| 2581 Consume(Token::SEMICOLON); |
| 2582 break; |
| 2583 case Token::RBRACE: |
| 2584 case Token::EOS: |
| 2585 break; |
| 2586 default: |
| 2587 if (!scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 2588 ReportMessageAt(function_state_->this_location(), |
| 2589 is_this ? "strong_constructor_this" |
| 2590 : "strong_constructor_super"); |
| 2591 *ok = false; |
| 2592 return nullptr; |
| 2593 } |
| 2594 } |
| 2595 return factory()->NewExpressionStatement(expr, pos); |
| 2596 } |
| 2597 break; |
| 2598 |
2563 // TODO(arv): Handle `let [` | 2599 // TODO(arv): Handle `let [` |
2564 // https://code.google.com/p/v8/issues/detail?id=3847 | 2600 // https://code.google.com/p/v8/issues/detail?id=3847 |
2565 | 2601 |
2566 default: | 2602 default: |
2567 break; | 2603 break; |
2568 } | 2604 } |
2569 | 2605 |
2570 int pos = peek_position(); | |
2571 bool starts_with_idenfifier = peek_any_identifier(); | 2606 bool starts_with_idenfifier = peek_any_identifier(); |
2572 Expression* expr = ParseExpression(true, CHECK_OK); | 2607 Expression* expr = ParseExpression(true, CHECK_OK); |
2573 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && | 2608 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && |
2574 expr->AsVariableProxy() != NULL && | 2609 expr->AsVariableProxy() != NULL && |
2575 !expr->AsVariableProxy()->is_this()) { | 2610 !expr->AsVariableProxy()->is_this()) { |
2576 // Expression is a single identifier, and not, e.g., a parenthesized | 2611 // Expression is a single identifier, and not, e.g., a parenthesized |
2577 // identifier. | 2612 // identifier. |
2578 VariableProxy* var = expr->AsVariableProxy(); | 2613 VariableProxy* var = expr->AsVariableProxy(); |
2579 const AstRawString* label = var->raw_name(); | 2614 const AstRawString* label = var->raw_name(); |
2580 // TODO(1240780): We don't check for redeclaration of labels | 2615 // TODO(1240780): We don't check for redeclaration of labels |
(...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3926 // that it will be compiled lazily. | 3961 // that it will be compiled lazily. |
3927 | 3962 |
3928 // To make this additional case work, both Parser and PreParser implement a | 3963 // To make this additional case work, both Parser and PreParser implement a |
3929 // logic where only top-level functions will be parsed lazily. | 3964 // logic where only top-level functions will be parsed lazily. |
3930 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | 3965 bool is_lazily_parsed = (mode() == PARSE_LAZILY && |
3931 scope_->AllowsLazyCompilation() && | 3966 scope_->AllowsLazyCompilation() && |
3932 !parenthesized_function_); | 3967 !parenthesized_function_); |
3933 parenthesized_function_ = false; // The bit was set for this function only. | 3968 parenthesized_function_ = false; // The bit was set for this function only. |
3934 | 3969 |
3935 if (is_lazily_parsed) { | 3970 if (is_lazily_parsed) { |
3936 SkipLazyFunctionBody(function_name, &materialized_literal_count, | 3971 SkipLazyFunctionBody(&materialized_literal_count, |
3937 &expected_property_count, CHECK_OK); | 3972 &expected_property_count, CHECK_OK); |
3938 } else { | 3973 } else { |
3939 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, | 3974 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op, |
3940 kind, CHECK_OK); | 3975 kind, CHECK_OK); |
3941 materialized_literal_count = function_state.materialized_literal_count(); | 3976 materialized_literal_count = function_state.materialized_literal_count(); |
3942 expected_property_count = function_state.expected_property_count(); | 3977 expected_property_count = function_state.expected_property_count(); |
3943 handler_count = function_state.handler_count(); | 3978 handler_count = function_state.handler_count(); |
| 3979 |
| 3980 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { |
| 3981 if (!function_state.super_location().IsValid()) { |
| 3982 ReportMessageAt(function_name_location, |
| 3983 "strong_super_call_missing", kReferenceError); |
| 3984 *ok = false; |
| 3985 return nullptr; |
| 3986 } |
| 3987 } |
3944 } | 3988 } |
3945 | 3989 |
3946 // Validate name and parameter names. We can do this only after parsing the | 3990 // Validate name and parameter names. We can do this only after parsing the |
3947 // function, since the function can declare itself strict. | 3991 // function, since the function can declare itself strict. |
3948 CheckFunctionName(language_mode(), kind, function_name, | 3992 CheckFunctionName(language_mode(), kind, function_name, |
3949 name_is_strict_reserved, function_name_location, | 3993 name_is_strict_reserved, function_name_location, |
3950 CHECK_OK); | 3994 CHECK_OK); |
3951 const bool use_strict_params = is_rest || IsConciseMethod(kind); | 3995 const bool use_strict_params = is_rest || IsConciseMethod(kind); |
3952 CheckFunctionParameterNames(language_mode(), use_strict_params, | 3996 CheckFunctionParameterNames(language_mode(), use_strict_params, |
3953 eval_args_error_loc, dupe_error_loc, | 3997 eval_args_error_loc, dupe_error_loc, |
3954 reserved_error_loc, CHECK_OK); | 3998 reserved_error_loc, CHECK_OK); |
3955 | 3999 |
3956 if (is_strict(language_mode())) { | 4000 if (is_strict(language_mode())) { |
3957 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | 4001 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
3958 CHECK_OK); | 4002 CHECK_OK); |
3959 } | |
3960 if (is_strict(language_mode())) { | |
3961 CheckConflictingVarDeclarations(scope, CHECK_OK); | 4003 CheckConflictingVarDeclarations(scope, CHECK_OK); |
3962 } | 4004 } |
3963 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | |
3964 if (!function_state.super_call_location().IsValid()) { | |
3965 ReportMessageAt(function_name_location, "strong_super_call_missing", | |
3966 kReferenceError); | |
3967 *ok = false; | |
3968 return nullptr; | |
3969 } | |
3970 } | |
3971 } | 4005 } |
3972 | 4006 |
3973 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 4007 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
3974 function_name, ast_value_factory(), scope, body, | 4008 function_name, ast_value_factory(), scope, body, |
3975 materialized_literal_count, expected_property_count, handler_count, | 4009 materialized_literal_count, expected_property_count, handler_count, |
3976 num_parameters, duplicate_parameters, function_type, | 4010 num_parameters, duplicate_parameters, function_type, |
3977 FunctionLiteral::kIsFunction, parenthesized, kind, pos); | 4011 FunctionLiteral::kIsFunction, parenthesized, kind, pos); |
3978 function_literal->set_function_token_position(function_token_pos); | 4012 function_literal->set_function_token_position(function_token_pos); |
3979 | 4013 |
3980 if (scope->has_rest_parameter()) { | 4014 if (scope->has_rest_parameter()) { |
3981 // TODO(caitp): enable optimization of functions with rest params | 4015 // TODO(caitp): enable optimization of functions with rest params |
3982 function_literal->set_dont_optimize_reason(kRestParameter); | 4016 function_literal->set_dont_optimize_reason(kRestParameter); |
3983 } | 4017 } |
3984 | 4018 |
3985 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 4019 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
3986 return function_literal; | 4020 return function_literal; |
3987 } | 4021 } |
3988 | 4022 |
3989 | 4023 |
3990 void Parser::SkipLazyFunctionBody(const AstRawString* function_name, | 4024 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, |
3991 int* materialized_literal_count, | |
3992 int* expected_property_count, | 4025 int* expected_property_count, |
3993 bool* ok) { | 4026 bool* ok) { |
3994 if (produce_cached_parse_data()) CHECK(log_); | 4027 if (produce_cached_parse_data()) CHECK(log_); |
3995 | 4028 |
3996 int function_block_pos = position(); | 4029 int function_block_pos = position(); |
3997 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { | 4030 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { |
3998 // If we have cached data, we use it to skip parsing the function body. The | 4031 // If we have cached data, we use it to skip parsing the function body. The |
3999 // data contains the information we need to construct the lazy function. | 4032 // data contains the information we need to construct the lazy function. |
4000 FunctionEntry entry = | 4033 FunctionEntry entry = |
4001 cached_parse_data_->GetFunctionEntry(function_block_pos); | 4034 cached_parse_data_->GetFunctionEntry(function_block_pos); |
(...skipping 1558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5560 } else { | 5593 } else { |
5561 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 5594 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
5562 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 5595 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
5563 raw_string->length()); | 5596 raw_string->length()); |
5564 } | 5597 } |
5565 } | 5598 } |
5566 | 5599 |
5567 return running_hash; | 5600 return running_hash; |
5568 } | 5601 } |
5569 } } // namespace v8::internal | 5602 } } // namespace v8::internal |
OLD | NEW |