Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: src/parser.cc

Issue 1024063002: [strong] checking of this & super in constructors (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase again Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698