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

Side by Side Diff: src/parser.cc

Issue 1061983004: Allow eval/arguments in arrow functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: Rename "result" parameter 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 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 return NULL; 780 return NULL;
781 } 781 }
782 782
783 783
784 Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name, 784 Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
785 int start_position, 785 int start_position,
786 int end_position, 786 int end_position,
787 Scope* scope, 787 Scope* scope,
788 AstNodeFactory* factory) { 788 AstNodeFactory* factory) {
789 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name); 789 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
790 790 return scope->NewUnresolved(factory, name, start_position, end_position);
791 // Arrow function parameters are parsed as an expression. When
792 // parsing lazily, it is enough to create a VariableProxy in order
793 // for Traits::DeclareArrowParametersFromExpression() to be able to
794 // pick the names of the parameters.
795 return parser_->parsing_lazy_arrow_parameters_
796 ? factory->NewVariableProxy(name, Variable::NORMAL, start_position,
797 end_position)
798 : scope->NewUnresolved(factory, name, start_position,
799 end_position);
800 } 791 }
801 792
802 793
803 Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner, 794 Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
804 AstNodeFactory* factory) { 795 AstNodeFactory* factory) {
805 const AstRawString* symbol = GetSymbol(scanner); 796 const AstRawString* symbol = GetSymbol(scanner);
806 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol); 797 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
807 return factory->NewStringLiteral(symbol, pos); 798 return factory->NewStringLiteral(symbol, pos);
808 } 799 }
809 800
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 Parser::Parser(ParseInfo* info) 845 Parser::Parser(ParseInfo* info)
855 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(), 846 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
856 info->extension(), info->ast_value_factory(), 847 info->extension(), info->ast_value_factory(),
857 NULL, this), 848 NULL, this),
858 scanner_(info->unicode_cache()), 849 scanner_(info->unicode_cache()),
859 reusable_preparser_(NULL), 850 reusable_preparser_(NULL),
860 original_scope_(NULL), 851 original_scope_(NULL),
861 target_stack_(NULL), 852 target_stack_(NULL),
862 compile_options_(info->compile_options()), 853 compile_options_(info->compile_options()),
863 cached_parse_data_(NULL), 854 cached_parse_data_(NULL),
864 parsing_lazy_arrow_parameters_(false),
865 total_preparse_skipped_(0), 855 total_preparse_skipped_(0),
866 pre_parse_timer_(NULL), 856 pre_parse_timer_(NULL),
867 parsing_on_main_thread_(true) { 857 parsing_on_main_thread_(true) {
868 // Even though we were passed ParseInfo, we should not store it in 858 // Even though we were passed ParseInfo, we should not store it in
869 // Parser - this makes sure that Isolate is not accidentally accessed via 859 // Parser - this makes sure that Isolate is not accidentally accessed via
870 // ParseInfo during background parsing. 860 // ParseInfo during background parsing.
871 DCHECK(!info->script().is_null() || info->source_stream() != NULL); 861 DCHECK(!info->script().is_null() || info->source_stream() != NULL);
872 set_allow_lazy(info->allow_lazy_parsing()); 862 set_allow_lazy(info->allow_lazy_parsing());
873 set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); 863 set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
874 set_allow_harmony_modules(!info->is_native() && FLAG_harmony_modules); 864 set_allow_harmony_modules(!info->is_native() && FLAG_harmony_modules);
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 DCHECK(info->language_mode() == shared_info->language_mode()); 1123 DCHECK(info->language_mode() == shared_info->language_mode());
1134 scope->SetLanguageMode(shared_info->language_mode()); 1124 scope->SetLanguageMode(shared_info->language_mode());
1135 FunctionLiteral::FunctionType function_type = shared_info->is_expression() 1125 FunctionLiteral::FunctionType function_type = shared_info->is_expression()
1136 ? (shared_info->is_anonymous() 1126 ? (shared_info->is_anonymous()
1137 ? FunctionLiteral::ANONYMOUS_EXPRESSION 1127 ? FunctionLiteral::ANONYMOUS_EXPRESSION
1138 : FunctionLiteral::NAMED_EXPRESSION) 1128 : FunctionLiteral::NAMED_EXPRESSION)
1139 : FunctionLiteral::DECLARATION; 1129 : FunctionLiteral::DECLARATION;
1140 bool ok = true; 1130 bool ok = true;
1141 1131
1142 if (shared_info->is_arrow()) { 1132 if (shared_info->is_arrow()) {
1143 // The first expression being parsed is the parameter list of the arrow 1133 FormalParameterErrorLocations error_locs;
1144 // function. Setting this avoids prevents ExpressionFromIdentifier() 1134 bool has_rest = false;
1145 // from creating unresolved variables in already-resolved scopes. 1135 ZoneList<const AstRawString*>* params;
1146 parsing_lazy_arrow_parameters_ = true; 1136 if (Check(Token::LPAREN)) {
1147 Expression* expression = ParseExpression(false, &ok); 1137 // '(' StrictFormalParameters ')'
1138 params = ParseFormalParameterList(&error_locs, &has_rest, &ok);
1139 if (ok) ok = Check(Token::RPAREN);
1140 } else {
1141 // BindingIdentifier
1142 params = NewFormalParameterList(1, zone());
1143 DuplicateFinder* null_duplicate_finder = nullptr;
1144 const AstRawString* single_param =
1145 ParseFormalParameter(null_duplicate_finder, &error_locs, &ok);
1146 if (ok) params->Add(single_param, zone());
1147 }
1148
1148 if (ok) { 1149 if (ok) {
1149 // Scanning must end at the same position that was recorded 1150 Expression* expression = ParseArrowFunctionLiteral(
1150 // previously. If not, parsing has been interrupted due to a 1151 shared_info->start_position(), params, error_locs, has_rest, &ok);
1151 // stack overflow, at which point the partially parsed arrow 1152 if (ok) {
1152 // function concise body happens to be a valid expression. This 1153 // Scanning must end at the same position that was recorded
1153 // is a problem only for arrow functions with single statement 1154 // previously. If not, parsing has been interrupted due to a stack
1154 // bodies, since there is no end token such as "}" for normal 1155 // overflow, at which point the partially parsed arrow function
1155 // functions. 1156 // concise body happens to be a valid expression. This is a problem
1156 if (scanner()->location().end_pos == shared_info->end_position()) { 1157 // only for arrow functions with single expression bodies, since there
1157 // The pre-parser saw an arrow function here, so the full parser 1158 // is no end token such as "}" for normal functions.
1158 // must produce a FunctionLiteral. 1159 if (scanner()->location().end_pos == shared_info->end_position()) {
1159 DCHECK(expression->IsFunctionLiteral()); 1160 // The pre-parser saw an arrow function here, so the full parser
1160 result = expression->AsFunctionLiteral(); 1161 // must produce a FunctionLiteral.
1161 } else { 1162 DCHECK(expression->IsFunctionLiteral());
1162 result = NULL; 1163 result = expression->AsFunctionLiteral();
1163 ok = false; 1164 } else {
1165 ok = false;
1166 }
1164 } 1167 }
1165 } 1168 }
1166 } else if (shared_info->is_default_constructor()) { 1169 } else if (shared_info->is_default_constructor()) {
1167 result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()), 1170 result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()),
1168 scope, shared_info->start_position(), 1171 scope, shared_info->start_position(),
1169 shared_info->end_position()); 1172 shared_info->end_position());
1170 } else { 1173 } else {
1171 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), 1174 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
1172 false, // Strict mode name already checked. 1175 false, // Strict mode name already checked.
1173 shared_info->kind(), RelocInfo::kNoPosition, 1176 shared_info->kind(), RelocInfo::kNoPosition,
(...skipping 2523 matching lines...) Expand 10 before | Expand all | Expand 10 after
3697 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); 3700 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3698 return static_cast<LiteralType>(literal_type->value()); 3701 return static_cast<LiteralType>(literal_type->value());
3699 } 3702 }
3700 3703
3701 3704
3702 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { 3705 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3703 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); 3706 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3704 } 3707 }
3705 3708
3706 3709
3707 bool CheckAndDeclareArrowParameter(ParserTraits* traits, Expression* expression, 3710 void ParserTraits::RecordArrowFunctionParameter(
3708 Scope* scope, int* num_params, 3711 ZoneList<const AstRawString*>* params, VariableProxy* proxy,
3709 FormalParameterErrorLocations* locs) { 3712 FormalParameterErrorLocations* error_locs, bool* ok) {
3710 // Case for empty parameter lists: 3713 const AstRawString* raw_name = proxy->raw_name();
3711 // () => ... 3714 Scanner::Location param_location(proxy->position(),
3712 if (expression == NULL) return true; 3715 proxy->position() + raw_name->length());
3716
3717 if (proxy->is_this()) {
3718 ReportMessageAt(param_location, "this_formal_parameter");
3719 *ok = false;
3720 return;
3721 }
3722
3723 if (!error_locs->eval_or_arguments_.IsValid() && IsEvalOrArguments(raw_name))
3724 error_locs->eval_or_arguments_ = param_location;
3725 if (!error_locs->reserved_.IsValid() && IsFutureStrictReserved(raw_name))
3726 error_locs->reserved_ = param_location;
3727 if (!error_locs->undefined_.IsValid() && IsUndefined(raw_name))
3728 error_locs->undefined_ = param_location;
3729
3730 // TODO(wingo): Fix quadratic check. (Scope::IsDeclaredParameter has the same
3731 // issue.)
3732 for (int i = 0; i < params->length(); i++) {
3733 // Eagerly report the error here; duplicate formal parameter names are never
3734 // allowed in arrow functions.
3735 if (raw_name == params->at(i)) {
3736 ReportMessageAt(param_location,
3737 "duplicate_arrow_function_formal_parameter");
3738 *ok = false;
3739 return;
3740 }
3741 }
3742
3743 // When the formal parameter was originally seen, it was parsed as a
3744 // VariableProxy and recorded as unresolved in the scope. Here we undo that
3745 // parse-time side-effect.
3746 parser_->scope_->RemoveUnresolved(proxy);
3747
3748 params->Add(raw_name, parser_->zone());
3749 }
3750
3751
3752 // Arrow function parameter lists are parsed as StrictFormalParameters, which
3753 // means that they cannot have duplicates. Note that this is a subset of the
3754 // restrictions placed on parameters to functions whose body is strict.
3755 ZoneList<const AstRawString*>*
3756 ParserTraits::ParseArrowFunctionFormalParameterList(
3757 Expression* params, const Scanner::Location& params_loc,
3758 FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok) {
3759 ZoneList<const AstRawString*>* result =
3760 NewFormalParameterList(4, parser_->zone());
3761
3762 DCHECK_NOT_NULL(params);
3713 3763
3714 // Too many parentheses around expression: 3764 // Too many parentheses around expression:
3715 // (( ... )) => ... 3765 // (( ... )) => ...
3716 if (expression->is_multi_parenthesized()) return false; 3766 if (params->is_multi_parenthesized()) {
3767 // TODO(wingo): Make a better message.
3768 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3769 *ok = false;
3770 return NULL;
3771 }
3717 3772
3718 // Case for a single parameter: 3773 // ArrowFunctionFormals ::
3719 // (foo) => ... 3774 // VariableProxy
3720 // foo => ... 3775 // Binary(Token::COMMA, ArrowFunctionFormals, VariableProxy)
3721 if (expression->IsVariableProxy()) { 3776 //
3722 if (expression->AsVariableProxy()->is_this()) return false; 3777 // To stay iterative we'll process arguments in right-to-left order, then
3723 3778 // reverse the list in place.
3724 const AstRawString* raw_name = expression->AsVariableProxy()->raw_name(); 3779 //
3725 if (traits->IsEvalOrArguments(raw_name) || 3780 // Sadly, for the various malformed_arrow_function_parameter_list errors, we
3726 traits->IsFutureStrictReserved(raw_name)) 3781 // can't be more specific on the error message or on the location because we
3727 return false; 3782 // need to match the pre-parser's behavior.
3728 if (traits->IsUndefined(raw_name) && !locs->undefined_.IsValid()) { 3783 while (params->IsBinaryOperation()) {
3729 locs->undefined_ = Scanner::Location( 3784 BinaryOperation* binop = params->AsBinaryOperation();
3730 expression->position(), expression->position() + raw_name->length()); 3785 Expression* left = binop->left();
3786 Expression* right = binop->right();
3787 if (binop->op() != Token::COMMA) {
3788 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3789 *ok = false;
3790 return NULL;
3731 } 3791 }
3732 if (scope->IsDeclared(raw_name)) { 3792 // RHS of comma expression should be an unparenthesized variable proxy.
3733 locs->duplicate_ = Scanner::Location( 3793 if (right->is_parenthesized() || !right->IsVariableProxy()) {
3734 expression->position(), expression->position() + raw_name->length()); 3794 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3735 return false; 3795 *ok = false;
3796 return NULL;
3797 }
3798 RecordArrowFunctionParameter(result, right->AsVariableProxy(), error_locs,
3799 CHECK_OK);
3800 // LHS of comma expression should be unparenthesized.
3801 params = left;
3802 if (params->is_parenthesized()) {
3803 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3804 *ok = false;
3805 return NULL;
3736 } 3806 }
3737 3807
3738 // When the variable was seen, it was recorded as unresolved in the outer 3808 if (result->length() > Code::kMaxArguments) {
3739 // scope. But it's really not unresolved. 3809 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3740 scope->outer_scope()->RemoveUnresolved(expression->AsVariableProxy()); 3810 *ok = false;
3741 3811 return NULL;
3742 scope->DeclareParameter(raw_name, VAR); 3812 }
3743 ++(*num_params);
3744 return true;
3745 } 3813 }
3746 3814
3747 // Case for more than one parameter: 3815 if (params->IsVariableProxy()) {
3748 // (foo, bar [, ...]) => ... 3816 RecordArrowFunctionParameter(result, params->AsVariableProxy(), error_locs,
3749 if (expression->IsBinaryOperation()) { 3817 CHECK_OK);
3750 BinaryOperation* binop = expression->AsBinaryOperation(); 3818 } else {
3751 if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() || 3819 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3752 binop->right()->is_parenthesized()) 3820 *ok = false;
3753 return false; 3821 return NULL;
3754
3755 return CheckAndDeclareArrowParameter(traits, binop->left(), scope,
3756 num_params, locs) &&
3757 CheckAndDeclareArrowParameter(traits, binop->right(), scope,
3758 num_params, locs);
3759 } 3822 }
3760 3823
3761 // Any other kind of expression is not a valid parameter list. 3824 // Reverse in place.
3762 return false; 3825 std::reverse(result->begin(), result->end());
3826
3827 return result;
3763 } 3828 }
3764 3829
3765 3830
3766 int ParserTraits::DeclareArrowParametersFromExpression( 3831 int ParserTraits::DeclareFormalParameters(ZoneList<const AstRawString*>* params,
3767 Expression* expression, Scope* scope, FormalParameterErrorLocations* locs, 3832 Scope* scope, bool has_rest) {
3768 bool* ok) { 3833 for (int i = 0; i < params->length(); i++) {
3769 int num_params = 0; 3834 const AstRawString* param_name = params->at(i);
3770 // Always reset the flag: It only needs to be set for the first expression 3835 int is_rest = has_rest && i == params->length() - 1;
3771 // parsed as arrow function parameter list, because only top-level functions 3836 Variable* var = scope->DeclareParameter(param_name, VAR, is_rest);
3772 // are parsed lazily. 3837 if (is_sloppy(scope->language_mode())) {
3773 parser_->parsing_lazy_arrow_parameters_ = false; 3838 // TODO(sigurds) Mark every parameter as maybe assigned. This is a
3774 *ok = 3839 // conservative approximation necessary to account for parameters
3775 CheckAndDeclareArrowParameter(this, expression, scope, &num_params, locs); 3840 // that are assigned via the arguments array.
3776 return num_params; 3841 var->set_maybe_assigned();
3842 }
3843 }
3844 return params->length();
3777 } 3845 }
3778 3846
3779 3847
3780 FunctionLiteral* Parser::ParseFunctionLiteral( 3848 FunctionLiteral* Parser::ParseFunctionLiteral(
3781 const AstRawString* function_name, Scanner::Location function_name_location, 3849 const AstRawString* function_name, Scanner::Location function_name_location,
3782 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, 3850 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
3783 FunctionLiteral::FunctionType function_type, 3851 FunctionLiteral::FunctionType function_type,
3784 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { 3852 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
3785 // Function :: 3853 // Function ::
3786 // '(' FormalParameterList? ')' '{' FunctionBody '}' 3854 // '(' FormalParameterList? ')' '{' FunctionBody '}'
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
3879 ZoneList<const AstRawString*>* params = 3947 ZoneList<const AstRawString*>* params =
3880 ParseFormalParameterList(&error_locs, &has_rest, CHECK_OK); 3948 ParseFormalParameterList(&error_locs, &has_rest, CHECK_OK);
3881 Expect(Token::RPAREN, CHECK_OK); 3949 Expect(Token::RPAREN, CHECK_OK);
3882 int formals_end_position = scanner()->location().end_pos; 3950 int formals_end_position = scanner()->location().end_pos;
3883 3951
3884 CheckArityRestrictions(params->length(), arity_restriction, start_position, 3952 CheckArityRestrictions(params->length(), arity_restriction, start_position,
3885 formals_end_position, CHECK_OK); 3953 formals_end_position, CHECK_OK);
3886 3954
3887 scope->set_start_position(start_position); 3955 scope->set_start_position(start_position);
3888 3956
3889 num_parameters = params->length(); 3957 num_parameters = DeclareFormalParameters(params, scope_, has_rest);
3890 if (error_locs.duplicate_.IsValid()) { 3958 if (error_locs.duplicate_.IsValid()) {
3891 duplicate_parameters = FunctionLiteral::kHasDuplicateParameters; 3959 duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
3892 } 3960 }
3893 3961
3894 for (int i = 0; i < params->length(); i++) {
3895 const AstRawString* param_name = params->at(i);
3896 int is_rest = has_rest && i == params->length() - 1;
3897 Variable* var = scope_->DeclareParameter(param_name, VAR, is_rest);
3898 if (is_sloppy(scope->language_mode())) {
3899 // TODO(sigurds) Mark every parameter as maybe assigned. This is a
3900 // conservative approximation necessary to account for parameters
3901 // that are assigned via the arguments array.
3902 var->set_maybe_assigned();
3903 }
3904 }
3905 3962
3906 Expect(Token::LBRACE, CHECK_OK); 3963 Expect(Token::LBRACE, CHECK_OK);
3907 3964
3908 // If we have a named function expression, we add a local variable 3965 // If we have a named function expression, we add a local variable
3909 // declaration to the body of the function with the name of the 3966 // declaration to the body of the function with the name of the
3910 // function and let it refer to the function itself (closure). 3967 // function and let it refer to the function itself (closure).
3911 // NOTE: We create a proxy and resolve it here so that in the 3968 // NOTE: We create a proxy and resolve it here so that in the
3912 // future we can change the AST to only refer to VariableProxies 3969 // future we can change the AST to only refer to VariableProxies
3913 // instead of Variables and Proxis as is the case now. 3970 // instead of Variables and Proxis as is the case now.
3914 Variable* fvar = NULL; 3971 Variable* fvar = NULL;
(...skipping 1801 matching lines...) Expand 10 before | Expand all | Expand 10 after
5716 5773
5717 Expression* Parser::SpreadCallNew(Expression* function, 5774 Expression* Parser::SpreadCallNew(Expression* function,
5718 ZoneList<v8::internal::Expression*>* args, 5775 ZoneList<v8::internal::Expression*>* args,
5719 int pos) { 5776 int pos) {
5720 args->InsertAt(0, function, zone()); 5777 args->InsertAt(0, function, zone());
5721 5778
5722 return factory()->NewCallRuntime( 5779 return factory()->NewCallRuntime(
5723 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5780 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5724 } 5781 }
5725 } } // namespace v8::internal 5782 } } // 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