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

Side by Side Diff: src/parser.cc

Issue 1077153005: Allow eval/arguments in arrow functions (Closed) Base URL: https://chromium.googlesource.com/v8/v8@master
Patch Set: 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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 DCHECK(info->language_mode() == shared_info->language_mode()); 1125 DCHECK(info->language_mode() == shared_info->language_mode());
1136 scope->SetLanguageMode(shared_info->language_mode()); 1126 scope->SetLanguageMode(shared_info->language_mode());
1137 FunctionLiteral::FunctionType function_type = shared_info->is_expression() 1127 FunctionLiteral::FunctionType function_type = shared_info->is_expression()
1138 ? (shared_info->is_anonymous() 1128 ? (shared_info->is_anonymous()
1139 ? FunctionLiteral::ANONYMOUS_EXPRESSION 1129 ? FunctionLiteral::ANONYMOUS_EXPRESSION
1140 : FunctionLiteral::NAMED_EXPRESSION) 1130 : FunctionLiteral::NAMED_EXPRESSION)
1141 : FunctionLiteral::DECLARATION; 1131 : FunctionLiteral::DECLARATION;
1142 bool ok = true; 1132 bool ok = true;
1143 1133
1144 if (shared_info->is_arrow()) { 1134 if (shared_info->is_arrow()) {
1145 // The first expression being parsed is the parameter list of the arrow 1135 Scope* scope = NewScope(scope_, ARROW_SCOPE);
1146 // function. Setting this avoids prevents ExpressionFromIdentifier() 1136 scope->set_start_position(shared_info->start_position());
1147 // from creating unresolved variables in already-resolved scopes. 1137 FormalParameterErrorLocations error_locs;
1148 parsing_lazy_arrow_parameters_ = true; 1138 bool has_rest = false;
1149 Expression* expression = ParseExpression(false, &ok); 1139 if (Check(Token::LPAREN)) {
1140 // '(' StrictFormalParameters ')'
1141 ParseFormalParameterList(scope, &error_locs, &has_rest, &ok);
1142 if (ok) ok = Check(Token::RPAREN);
1143 } else {
1144 // BindingIdentifier
1145 ParseFormalParameter(scope, &error_locs, has_rest, &ok);
1146 }
1147
1150 if (ok) { 1148 if (ok) {
1151 // Scanning must end at the same position that was recorded 1149 Expression* expression =
1152 // previously. If not, parsing has been interrupted due to a 1150 ParseArrowFunctionLiteral(scope, error_locs, has_rest, &ok);
1153 // stack overflow, at which point the partially parsed arrow 1151 if (ok) {
1154 // function concise body happens to be a valid expression. This 1152 // Scanning must end at the same position that was recorded
1155 // is a problem only for arrow functions with single statement 1153 // previously. If not, parsing has been interrupted due to a stack
1156 // bodies, since there is no end token such as "}" for normal 1154 // overflow, at which point the partially parsed arrow function
1157 // functions. 1155 // concise body happens to be a valid expression. This is a problem
1158 if (scanner()->location().end_pos == shared_info->end_position()) { 1156 // only for arrow functions with single expression bodies, since there
1159 // The pre-parser saw an arrow function here, so the full parser 1157 // is no end token such as "}" for normal functions.
1160 // must produce a FunctionLiteral. 1158 if (scanner()->location().end_pos == shared_info->end_position()) {
1161 DCHECK(expression->IsFunctionLiteral()); 1159 // The pre-parser saw an arrow function here, so the full parser
1162 result = expression->AsFunctionLiteral(); 1160 // must produce a FunctionLiteral.
1163 } else { 1161 DCHECK(expression->IsFunctionLiteral());
1164 result = NULL; 1162 result = expression->AsFunctionLiteral();
1165 ok = false; 1163 } else {
1164 ok = false;
1165 }
1166 } 1166 }
1167 } 1167 }
1168 } else if (shared_info->is_default_constructor()) { 1168 } else if (shared_info->is_default_constructor()) {
1169 result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()), 1169 result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()),
1170 scope, shared_info->start_position(), 1170 scope, shared_info->start_position(),
1171 shared_info->end_position()); 1171 shared_info->end_position());
1172 } else { 1172 } else {
1173 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), 1173 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
1174 false, // Strict mode name already checked. 1174 false, // Strict mode name already checked.
1175 shared_info->kind(), RelocInfo::kNoPosition, 1175 shared_info->kind(), RelocInfo::kNoPosition,
(...skipping 2549 matching lines...) Expand 10 before | Expand all | Expand 10 after
3725 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); 3725 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3726 return static_cast<LiteralType>(literal_type->value()); 3726 return static_cast<LiteralType>(literal_type->value());
3727 } 3727 }
3728 3728
3729 3729
3730 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { 3730 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3731 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); 3731 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3732 } 3732 }
3733 3733
3734 3734
3735 bool CheckAndDeclareArrowParameter(ParserTraits* traits, Expression* expression, 3735 void ParserTraits::DeclareArrowFunctionParameters(
3736 Scope* scope, int* num_params, 3736 Scope* scope, Expression* expr, const Scanner::Location& params_loc,
3737 FormalParameterErrorLocations* locs) { 3737 FormalParameterErrorLocations* error_locs, bool* ok) {
3738 // Case for empty parameter lists: 3738 if (scope->num_parameters() >= Code::kMaxArguments) {
3739 // () => ... 3739 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3740 if (expression == NULL) return true; 3740 *ok = false;
3741 3741 return;
3742 // Too many parentheses around expression:
3743 // (( ... )) => ...
3744 if (expression->is_multi_parenthesized()) return false;
3745
3746 // Case for a single parameter:
3747 // (foo) => ...
3748 // foo => ...
3749 if (expression->IsVariableProxy()) {
3750 if (expression->AsVariableProxy()->is_this()) return false;
3751
3752 const AstRawString* raw_name = expression->AsVariableProxy()->raw_name();
3753 if (traits->IsEvalOrArguments(raw_name) ||
3754 traits->IsFutureStrictReserved(raw_name))
3755 return false;
3756 if (traits->IsUndefined(raw_name) && !locs->undefined.IsValid()) {
3757 locs->undefined = Scanner::Location(
3758 expression->position(), expression->position() + raw_name->length());
3759 }
3760
3761 // When the variable was seen, it was recorded as unresolved in the outer
3762 // scope. But it's really not unresolved.
3763 scope->outer_scope()->RemoveUnresolved(expression->AsVariableProxy());
3764
3765 bool is_rest = false;
3766 bool is_duplicate = false;
3767 scope->DeclareParameter(raw_name, VAR, is_rest, &is_duplicate);
3768 if (is_duplicate) {
3769 locs->duplicate = Scanner::Location(
3770 expression->position(), expression->position() + raw_name->length());
3771 return false;
3772 }
3773
3774 ++(*num_params);
3775 return true;
3776 } 3742 }
3777 3743
3778 // Case for more than one parameter: 3744 // ArrowFunctionFormals ::
3779 // (foo, bar [, ...]) => ... 3745 // Binary(Token::COMMA, ArrowFunctionFormals, VariableProxy)
3780 if (expression->IsBinaryOperation()) { 3746 // VariableProxy
3781 BinaryOperation* binop = expression->AsBinaryOperation(); 3747 //
3782 if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() || 3748 // As we need to visit the parameters in left-to-right order, we recurse on
3783 binop->right()->is_parenthesized()) 3749 // the left-hand side of comma expressions.
3784 return false; 3750 //
3785 3751 // Sadly, for the various malformed_arrow_function_parameter_list errors, we
3786 return CheckAndDeclareArrowParameter(traits, binop->left(), scope, 3752 // can't be more specific on the error message or on the location because we
3787 num_params, locs) && 3753 // need to match the pre-parser's behavior.
3788 CheckAndDeclareArrowParameter(traits, binop->right(), scope, 3754 if (expr->IsBinaryOperation()) {
3789 num_params, locs); 3755 BinaryOperation* binop = expr->AsBinaryOperation();
3756 if (binop->op() != Token::COMMA) {
3757 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3758 *ok = false;
3759 return;
3760 }
3761 Expression* left = binop->left();
3762 Expression* right = binop->right();
3763 if (left->is_parenthesized() || right->is_parenthesized()) {
3764 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3765 *ok = false;
3766 return;
3767 }
3768 DeclareArrowFunctionParameters(scope, left, params_loc, error_locs, ok);
3769 if (!*ok) return;
3770 // LHS of comma expression should be unparenthesized.
3771 expr = right;
3790 } 3772 }
3791 3773
3792 // Any other kind of expression is not a valid parameter list. 3774 // TODO(wingo): Support rest parameters.
3793 return false; 3775 if (!expr->IsVariableProxy()) {
3776 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3777 *ok = false;
3778 return;
3779 }
3780
3781 const AstRawString* raw_name = expr->AsVariableProxy()->raw_name();
3782 Scanner::Location param_location(expr->position(),
3783 expr->position() + raw_name->length());
3784
3785 if (expr->AsVariableProxy()->is_this()) {
3786 ReportMessageAt(param_location, "this_formal_parameter");
3787 *ok = false;
3788 return;
3789 }
3790
3791 if (!error_locs->eval_or_arguments.IsValid() && IsEvalOrArguments(raw_name))
3792 error_locs->eval_or_arguments = param_location;
3793 if (!error_locs->reserved.IsValid() && IsFutureStrictReserved(raw_name))
3794 error_locs->reserved = param_location;
3795 if (!error_locs->undefined.IsValid() && IsUndefined(raw_name))
3796 error_locs->undefined = param_location;
3797
3798 // When the formal parameter was originally seen, it was parsed as a
3799 // VariableProxy and recorded as unresolved in the scope. Here we undo that
3800 // parse-time side-effect.
3801 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
3802
3803 bool is_rest = false;
3804 bool is_duplicate = DeclareFormalParameter(scope, raw_name, is_rest);
3805
3806 if (is_duplicate) {
3807 // Arrow function parameter lists are parsed as StrictFormalParameters,
3808 // which means that they cannot have duplicates. Note that this is a subset
3809 // of the restrictions placed on parameters to functions whose body is
3810 // strict.
3811 ReportMessageAt(param_location,
3812 "duplicate_arrow_function_formal_parameter");
3813 *ok = false;
3814 return;
3815 }
3794 } 3816 }
3795 3817
3796 3818
3797 int ParserTraits::DeclareArrowParametersFromExpression( 3819 void ParserTraits::ParseArrowFunctionFormalParameters(
3798 Expression* expression, Scope* scope, FormalParameterErrorLocations* locs, 3820 Scope* scope, Expression* params, const Scanner::Location& params_loc,
3799 bool* ok) { 3821 FormalParameterErrorLocations* error_locs, bool* is_rest, bool* ok) {
3800 int num_params = 0; 3822 // Too many parentheses around expression:
3801 // Always reset the flag: It only needs to be set for the first expression 3823 // (( ... )) => ...
3802 // parsed as arrow function parameter list, because only top-level functions 3824 if (params->is_multi_parenthesized()) {
3803 // are parsed lazily. 3825 // TODO(wingo): Make a better message.
3804 parser_->parsing_lazy_arrow_parameters_ = false; 3826 ReportMessageAt(params_loc, "malformed_arrow_function_parameter_list");
3805 *ok = 3827 *ok = false;
3806 CheckAndDeclareArrowParameter(this, expression, scope, &num_params, locs); 3828 return;
3807 return num_params; 3829 }
3830
3831 DeclareArrowFunctionParameters(scope, params, params_loc, error_locs, ok);
3808 } 3832 }
3809 3833
3810 3834
3811 FunctionLiteral* Parser::ParseFunctionLiteral( 3835 FunctionLiteral* Parser::ParseFunctionLiteral(
3812 const AstRawString* function_name, Scanner::Location function_name_location, 3836 const AstRawString* function_name, Scanner::Location function_name_location,
3813 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, 3837 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
3814 FunctionLiteral::FunctionType function_type, 3838 FunctionLiteral::FunctionType function_type,
3815 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { 3839 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
3816 // Function :: 3840 // Function ::
3817 // '(' FormalParameterList? ')' '{' FunctionBody '}' 3841 // '(' FormalParameterList? ')' '{' FunctionBody '}'
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after
5723 5747
5724 Expression* Parser::SpreadCallNew(Expression* function, 5748 Expression* Parser::SpreadCallNew(Expression* function,
5725 ZoneList<v8::internal::Expression*>* args, 5749 ZoneList<v8::internal::Expression*>* args,
5726 int pos) { 5750 int pos) {
5727 args->InsertAt(0, function, zone()); 5751 args->InsertAt(0, function, zone());
5728 5752
5729 return factory()->NewCallRuntime( 5753 return factory()->NewCallRuntime(
5730 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5754 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5731 } 5755 }
5732 } } // namespace v8::internal 5756 } } // 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