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

Side by Side Diff: src/parser.cc

Issue 1138153003: Use ExpressionClassifier to identify valid arrow function formals (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: Fix ASAN stack-check regression by bumping stack limit in test Created 5 years, 7 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 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 FunctionLiteral::FunctionType function_type = shared_info->is_expression() 1131 FunctionLiteral::FunctionType function_type = shared_info->is_expression()
1132 ? (shared_info->is_anonymous() 1132 ? (shared_info->is_anonymous()
1133 ? FunctionLiteral::ANONYMOUS_EXPRESSION 1133 ? FunctionLiteral::ANONYMOUS_EXPRESSION
1134 : FunctionLiteral::NAMED_EXPRESSION) 1134 : FunctionLiteral::NAMED_EXPRESSION)
1135 : FunctionLiteral::DECLARATION; 1135 : FunctionLiteral::DECLARATION;
1136 bool ok = true; 1136 bool ok = true;
1137 1137
1138 if (shared_info->is_arrow()) { 1138 if (shared_info->is_arrow()) {
1139 Scope* scope = NewScope(scope_, ARROW_SCOPE); 1139 Scope* scope = NewScope(scope_, ARROW_SCOPE);
1140 scope->set_start_position(shared_info->start_position()); 1140 scope->set_start_position(shared_info->start_position());
1141 FormalParameterErrorLocations error_locs; 1141 ExpressionClassifier formals_classifier;
1142 bool has_rest = false; 1142 bool has_rest = false;
1143 if (Check(Token::LPAREN)) { 1143 if (Check(Token::LPAREN)) {
1144 // '(' StrictFormalParameters ')' 1144 // '(' StrictFormalParameters ')'
1145 ParseFormalParameterList(scope, &error_locs, &has_rest, &ok); 1145 ParseFormalParameterList(scope, &has_rest, &formals_classifier, &ok);
1146 if (ok) ok = Check(Token::RPAREN); 1146 if (ok) ok = Check(Token::RPAREN);
1147 } else { 1147 } else {
1148 // BindingIdentifier 1148 // BindingIdentifier
1149 ParseFormalParameter(scope, &error_locs, has_rest, &ok); 1149 ParseFormalParameter(scope, has_rest, &formals_classifier, &ok);
1150 } 1150 }
1151 1151
1152 if (ok) { 1152 if (ok) {
1153 ExpressionClassifier classifier; 1153 Expression* expression =
1154 Expression* expression = ParseArrowFunctionLiteral( 1154 ParseArrowFunctionLiteral(scope, has_rest, formals_classifier, &ok);
1155 scope, error_locs, has_rest, &classifier, &ok);
1156 ValidateExpression(&classifier, &ok);
1157 if (ok) { 1155 if (ok) {
1158 // Scanning must end at the same position that was recorded 1156 // Scanning must end at the same position that was recorded
1159 // previously. If not, parsing has been interrupted due to a stack 1157 // previously. If not, parsing has been interrupted due to a stack
1160 // overflow, at which point the partially parsed arrow function 1158 // overflow, at which point the partially parsed arrow function
1161 // concise body happens to be a valid expression. This is a problem 1159 // concise body happens to be a valid expression. This is a problem
1162 // only for arrow functions with single expression bodies, since there 1160 // only for arrow functions with single expression bodies, since there
1163 // is no end token such as "}" for normal functions. 1161 // is no end token such as "}" for normal functions.
1164 if (scanner()->location().end_pos == shared_info->end_position()) { 1162 if (scanner()->location().end_pos == shared_info->end_position()) {
1165 // The pre-parser saw an arrow function here, so the full parser 1163 // The pre-parser saw an arrow function here, so the full parser
1166 // must produce a FunctionLiteral. 1164 // must produce a FunctionLiteral.
(...skipping 2546 matching lines...) Expand 10 before | Expand all | Expand 10 after
3713 } 3711 }
3714 3712
3715 3713
3716 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { 3714 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3717 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); 3715 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3718 } 3716 }
3719 3717
3720 3718
3721 void ParserTraits::DeclareArrowFunctionParameters( 3719 void ParserTraits::DeclareArrowFunctionParameters(
3722 Scope* scope, Expression* expr, const Scanner::Location& params_loc, 3720 Scope* scope, Expression* expr, const Scanner::Location& params_loc,
3723 FormalParameterErrorLocations* error_locs, bool* ok) { 3721 Scanner::Location* duplicate_loc, bool* ok) {
3724 if (scope->num_parameters() >= Code::kMaxArguments) { 3722 if (scope->num_parameters() >= Code::kMaxArguments) {
3725 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list"); 3723 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3726 *ok = false; 3724 *ok = false;
3727 return; 3725 return;
3728 } 3726 }
3729 3727
3730 // ArrowFunctionFormals :: 3728 // ArrowFunctionFormals ::
3731 // Binary(Token::COMMA, ArrowFunctionFormals, VariableProxy) 3729 // Binary(Token::COMMA, ArrowFunctionFormals, VariableProxy)
3732 // VariableProxy 3730 // VariableProxy
3733 // 3731 //
3734 // As we need to visit the parameters in left-to-right order, we recurse on 3732 // As we need to visit the parameters in left-to-right order, we recurse on
3735 // the left-hand side of comma expressions. 3733 // the left-hand side of comma expressions.
3736 // 3734 //
3737 // Sadly, for the various malformed_arrow_function_parameter_list errors, we 3735 // Sadly, for the various malformed_arrow_function_parameter_list errors, we
3738 // can't be more specific on the error message or on the location because we 3736 // can't be more specific on the error message or on the location because we
3739 // need to match the pre-parser's behavior. 3737 // need to match the pre-parser's behavior.
3740 if (expr->IsBinaryOperation()) { 3738 if (expr->IsBinaryOperation()) {
3741 BinaryOperation* binop = expr->AsBinaryOperation(); 3739 BinaryOperation* binop = expr->AsBinaryOperation();
3740 // TODO(wingo): These checks are now unnecessary, given the classifier.
3742 if (binop->op() != Token::COMMA) { 3741 if (binop->op() != Token::COMMA) {
3743 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list"); 3742 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3744 *ok = false; 3743 *ok = false;
3745 return; 3744 return;
3746 } 3745 }
3747 Expression* left = binop->left(); 3746 Expression* left = binop->left();
3748 Expression* right = binop->right(); 3747 Expression* right = binop->right();
3749 if (left->is_single_parenthesized() || right->is_single_parenthesized()) { 3748 if (left->is_single_parenthesized() || right->is_single_parenthesized()) {
3750 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list"); 3749 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3751 *ok = false; 3750 *ok = false;
3752 return; 3751 return;
3753 } 3752 }
3754 DeclareArrowFunctionParameters(scope, left, params_loc, error_locs, ok); 3753 DeclareArrowFunctionParameters(scope, left, params_loc, duplicate_loc, ok);
3755 if (!*ok) return; 3754 if (!*ok) return;
3756 // LHS of comma expression should be unparenthesized. 3755 // LHS of comma expression should be unparenthesized.
3757 expr = right; 3756 expr = right;
3758 } 3757 }
3759 3758
3760 // TODO(wingo): Support rest parameters. 3759 // TODO(wingo): Support rest parameters.
3761 if (!expr->IsVariableProxy()) { 3760 if (!expr->IsVariableProxy()) {
3762 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list"); 3761 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3763 *ok = false; 3762 *ok = false;
3764 return; 3763 return;
3765 } 3764 }
3766 3765
3767 const AstRawString* raw_name = expr->AsVariableProxy()->raw_name(); 3766 const AstRawString* raw_name = expr->AsVariableProxy()->raw_name();
3768 Scanner::Location param_location(expr->position(), 3767 Scanner::Location param_location(expr->position(),
3769 expr->position() + raw_name->length()); 3768 expr->position() + raw_name->length());
3770 3769
3771 if (expr->AsVariableProxy()->is_this()) { 3770 if (expr->AsVariableProxy()->is_this()) {
3772 ReportMessageAt(param_location, "this_formal_parameter"); 3771 ReportMessageAt(param_location, "this_formal_parameter");
3773 *ok = false; 3772 *ok = false;
3774 return; 3773 return;
3775 } 3774 }
3776 3775
3777 if (!error_locs->eval_or_arguments.IsValid() && IsEvalOrArguments(raw_name))
3778 error_locs->eval_or_arguments = param_location;
3779 if (!error_locs->reserved.IsValid() && IsFutureStrictReserved(raw_name))
3780 error_locs->reserved = param_location;
3781 if (!error_locs->undefined.IsValid() && IsUndefined(raw_name))
3782 error_locs->undefined = param_location;
3783
3784 // When the formal parameter was originally seen, it was parsed as a 3776 // When the formal parameter was originally seen, it was parsed as a
3785 // VariableProxy and recorded as unresolved in the scope. Here we undo that 3777 // VariableProxy and recorded as unresolved in the scope. Here we undo that
3786 // parse-time side-effect. 3778 // parse-time side-effect.
3787 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); 3779 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
3788 3780
3789 bool is_rest = false; 3781 bool is_rest = false;
3790 bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest); 3782 bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest);
3791 3783
3792 if (is_duplicate) { 3784 if (is_duplicate && !duplicate_loc->IsValid()) {
3793 // Arrow function parameter lists are parsed as StrictFormalParameters, 3785 *duplicate_loc = param_location;
3794 // which means that they cannot have duplicates. Note that this is a subset
3795 // of the restrictions placed on parameters to functions whose body is
3796 // strict.
3797 ReportMessageAt(param_location,
3798 "duplicate_arrow_function_formal_parameter");
3799 *ok = false;
3800 return;
3801 } 3786 }
3802 } 3787 }
3803 3788
3804 3789
3805 void ParserTraits::ParseArrowFunctionFormalParameters( 3790 void ParserTraits::ParseArrowFunctionFormalParameters(
3806 Scope* scope, Expression* params, const Scanner::Location& params_loc, 3791 Scope* scope, Expression* params, const Scanner::Location& params_loc,
3807 FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok) { 3792 bool* is_rest, Scanner::Location* duplicate_loc, bool* ok) {
3808 // Too many parentheses around expression: 3793 // Too many parentheses around expression:
3809 // (( ... )) => ... 3794 // (( ... )) => ...
3810 if (params->is_multi_parenthesized()) { 3795 if (params->is_multi_parenthesized()) {
3811 // TODO(wingo): Make a better message. 3796 // TODO(wingo): Make a better message.
3812 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list"); 3797 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3813 *ok = false; 3798 *ok = false;
3814 return; 3799 return;
3815 } 3800 }
3816 3801
3817 DeclareArrowFunctionParameters(scope, params, params_loc, error_locs, ok); 3802 DeclareArrowFunctionParameters(scope, params, params_loc, duplicate_loc, ok);
3818 } 3803 }
3819 3804
3820 3805
3821 FunctionLiteral* Parser::ParseFunctionLiteral( 3806 FunctionLiteral* Parser::ParseFunctionLiteral(
3822 const AstRawString* function_name, Scanner::Location function_name_location, 3807 const AstRawString* function_name, Scanner::Location function_name_location,
3823 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, 3808 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
3824 FunctionLiteral::FunctionType function_type, 3809 FunctionLiteral::FunctionType function_type,
3825 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { 3810 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
3826 // Function :: 3811 // Function ::
3827 // '(' FormalParameterList? ')' '{' FunctionBody '}' 3812 // '(' FormalParameterList? ')' '{' FunctionBody '}'
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3880 Scope* scope = function_type == FunctionLiteral::DECLARATION && 3865 Scope* scope = function_type == FunctionLiteral::DECLARATION &&
3881 is_sloppy(language_mode()) && 3866 is_sloppy(language_mode()) &&
3882 (original_scope_ == original_declaration_scope || 3867 (original_scope_ == original_declaration_scope ||
3883 declaration_scope != original_declaration_scope) 3868 declaration_scope != original_declaration_scope)
3884 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) 3869 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
3885 : NewScope(scope_, FUNCTION_SCOPE, kind); 3870 : NewScope(scope_, FUNCTION_SCOPE, kind);
3886 ZoneList<Statement*>* body = NULL; 3871 ZoneList<Statement*>* body = NULL;
3887 int materialized_literal_count = -1; 3872 int materialized_literal_count = -1;
3888 int expected_property_count = -1; 3873 int expected_property_count = -1;
3889 int handler_count = 0; 3874 int handler_count = 0;
3890 FormalParameterErrorLocations error_locs; 3875 ExpressionClassifier formals_classifier;
3891 FunctionLiteral::EagerCompileHint eager_compile_hint = 3876 FunctionLiteral::EagerCompileHint eager_compile_hint =
3892 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile 3877 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
3893 : FunctionLiteral::kShouldLazyCompile; 3878 : FunctionLiteral::kShouldLazyCompile;
3894 bool should_be_used_once_hint = false; 3879 bool should_be_used_once_hint = false;
3895 // Parse function body. 3880 // Parse function body.
3896 { 3881 {
3897 AstNodeFactory function_factory(ast_value_factory()); 3882 AstNodeFactory function_factory(ast_value_factory());
3898 FunctionState function_state(&function_state_, &scope_, scope, kind, 3883 FunctionState function_state(&function_state_, &scope_, scope, kind,
3899 &function_factory); 3884 &function_factory);
3900 scope_->SetScopeName(function_name); 3885 scope_->SetScopeName(function_name);
3901 3886
3902 if (is_generator) { 3887 if (is_generator) {
3903 // For generators, allocating variables in contexts is currently a win 3888 // For generators, allocating variables in contexts is currently a win
3904 // because it minimizes the work needed to suspend and resume an 3889 // because it minimizes the work needed to suspend and resume an
3905 // activation. 3890 // activation.
3906 scope_->ForceContextAllocation(); 3891 scope_->ForceContextAllocation();
3907 3892
3908 // Calling a generator returns a generator object. That object is stored 3893 // Calling a generator returns a generator object. That object is stored
3909 // in a temporary variable, a definition that is used by "yield" 3894 // in a temporary variable, a definition that is used by "yield"
3910 // expressions. This also marks the FunctionState as a generator. 3895 // expressions. This also marks the FunctionState as a generator.
3911 Variable* temp = scope_->DeclarationScope()->NewTemporary( 3896 Variable* temp = scope_->DeclarationScope()->NewTemporary(
3912 ast_value_factory()->dot_generator_object_string()); 3897 ast_value_factory()->dot_generator_object_string());
3913 function_state.set_generator_object_variable(temp); 3898 function_state.set_generator_object_variable(temp);
3914 } 3899 }
3915 3900
3916 bool has_rest = false; 3901 bool has_rest = false;
3917 Expect(Token::LPAREN, CHECK_OK); 3902 Expect(Token::LPAREN, CHECK_OK);
3918 int start_position = scanner()->location().beg_pos; 3903 int start_position = scanner()->location().beg_pos;
3919 scope_->set_start_position(start_position); 3904 scope_->set_start_position(start_position);
3920 num_parameters = 3905 num_parameters = ParseFormalParameterList(scope, &has_rest,
3921 ParseFormalParameterList(scope, &error_locs, &has_rest, CHECK_OK); 3906 &formals_classifier, CHECK_OK);
3922 Expect(Token::RPAREN, CHECK_OK); 3907 Expect(Token::RPAREN, CHECK_OK);
3923 int formals_end_position = scanner()->location().end_pos; 3908 int formals_end_position = scanner()->location().end_pos;
3924 3909
3925 CheckArityRestrictions(num_parameters, arity_restriction, start_position, 3910 CheckArityRestrictions(num_parameters, arity_restriction, start_position,
3926 formals_end_position, CHECK_OK); 3911 formals_end_position, CHECK_OK);
3927 3912
3928 Expect(Token::LBRACE, CHECK_OK); 3913 Expect(Token::LBRACE, CHECK_OK);
3929 3914
3930 // If we have a named function expression, we add a local variable 3915 // If we have a named function expression, we add a local variable
3931 // declaration to the body of the function with the name of the 3916 // declaration to the body of the function with the name of the
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
4034 } 4019 }
4035 } 4020 }
4036 } 4021 }
4037 4022
4038 // Validate name and parameter names. We can do this only after parsing the 4023 // Validate name and parameter names. We can do this only after parsing the
4039 // function, since the function can declare itself strict. 4024 // function, since the function can declare itself strict.
4040 CheckFunctionName(language_mode(), kind, function_name, 4025 CheckFunctionName(language_mode(), kind, function_name,
4041 name_is_strict_reserved, function_name_location, 4026 name_is_strict_reserved, function_name_location,
4042 CHECK_OK); 4027 CHECK_OK);
4043 const bool use_strict_params = has_rest || IsConciseMethod(kind); 4028 const bool use_strict_params = has_rest || IsConciseMethod(kind);
4044 CheckFunctionParameterNames(language_mode(), use_strict_params, error_locs, 4029 const bool allow_duplicate_parameters =
arv (Not doing code reviews) 2015/05/13 14:13:05 Does this handle patterns? // sloppy function f(x
wingo 2015/05/15 12:30:30 I guess it should but it doesn't. In a similar wa
4045 CHECK_OK); 4030 is_sloppy(language_mode()) && !use_strict_params;
4031 ValidateFormalParameters(&formals_classifier, language_mode(),
4032 allow_duplicate_parameters, CHECK_OK);
4046 4033
4047 if (is_strict(language_mode())) { 4034 if (is_strict(language_mode())) {
4048 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), 4035 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
4049 CHECK_OK); 4036 CHECK_OK);
4050 CheckConflictingVarDeclarations(scope, CHECK_OK); 4037 CheckConflictingVarDeclarations(scope, CHECK_OK);
4051 } 4038 }
4052 } 4039 }
4053 4040
4041 bool has_duplicate_parameters =
4042 !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
4054 FunctionLiteral::ParameterFlag duplicate_parameters = 4043 FunctionLiteral::ParameterFlag duplicate_parameters =
4055 error_locs.duplicate.IsValid() ? FunctionLiteral::kHasDuplicateParameters 4044 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
4056 : FunctionLiteral::kNoDuplicateParameters; 4045 : FunctionLiteral::kNoDuplicateParameters;
4057 4046
4058 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( 4047 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4059 function_name, ast_value_factory(), scope, body, 4048 function_name, ast_value_factory(), scope, body,
4060 materialized_literal_count, expected_property_count, handler_count, 4049 materialized_literal_count, expected_property_count, handler_count,
4061 num_parameters, duplicate_parameters, function_type, 4050 num_parameters, duplicate_parameters, function_type,
4062 FunctionLiteral::kIsFunction, eager_compile_hint, kind, pos); 4051 FunctionLiteral::kIsFunction, eager_compile_hint, kind, pos);
4063 function_literal->set_function_token_position(function_token_pos); 4052 function_literal->set_function_token_position(function_token_pos);
4064 if (should_be_used_once_hint) 4053 if (should_be_used_once_hint)
4065 function_literal->set_should_be_used_once_hint(); 4054 function_literal->set_should_be_used_once_hint();
4066 4055
(...skipping 1708 matching lines...) Expand 10 before | Expand all | Expand 10 after
5775 5764
5776 Expression* Parser::SpreadCallNew(Expression* function, 5765 Expression* Parser::SpreadCallNew(Expression* function,
5777 ZoneList<v8::internal::Expression*>* args, 5766 ZoneList<v8::internal::Expression*>* args,
5778 int pos) { 5767 int pos) {
5779 args->InsertAt(0, function, zone()); 5768 args->InsertAt(0, function, zone());
5780 5769
5781 return factory()->NewCallRuntime( 5770 return factory()->NewCallRuntime(
5782 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5771 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5783 } 5772 }
5784 } } // namespace v8::internal 5773 } } // 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