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

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: Comments 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') | src/preparser.h » ('J')
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 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/preparser.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698