| OLD | NEW |
| 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 3716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 bool CheckAndDeclareArrowParameter(ParserTraits* traits, Expression* expression, |
| 3736 Scope* scope, int* num_params, | 3736 Scope* scope, int* num_params, |
| 3737 Scanner::Location* undefined_loc, | 3737 FormalParameterErrorLocations* locs) { |
| 3738 Scanner::Location* dupe_loc) { | |
| 3739 // Case for empty parameter lists: | 3738 // Case for empty parameter lists: |
| 3740 // () => ... | 3739 // () => ... |
| 3741 if (expression == NULL) return true; | 3740 if (expression == NULL) return true; |
| 3742 | 3741 |
| 3743 // Too many parentheses around expression: | 3742 // Too many parentheses around expression: |
| 3744 // (( ... )) => ... | 3743 // (( ... )) => ... |
| 3745 if (expression->is_multi_parenthesized()) return false; | 3744 if (expression->is_multi_parenthesized()) return false; |
| 3746 | 3745 |
| 3747 // Case for a single parameter: | 3746 // Case for a single parameter: |
| 3748 // (foo) => ... | 3747 // (foo) => ... |
| 3749 // foo => ... | 3748 // foo => ... |
| 3750 if (expression->IsVariableProxy()) { | 3749 if (expression->IsVariableProxy()) { |
| 3751 if (expression->AsVariableProxy()->is_this()) return false; | 3750 if (expression->AsVariableProxy()->is_this()) return false; |
| 3752 | 3751 |
| 3753 const AstRawString* raw_name = expression->AsVariableProxy()->raw_name(); | 3752 const AstRawString* raw_name = expression->AsVariableProxy()->raw_name(); |
| 3754 if (traits->IsEvalOrArguments(raw_name) || | 3753 if (traits->IsEvalOrArguments(raw_name) || |
| 3755 traits->IsFutureStrictReserved(raw_name)) | 3754 traits->IsFutureStrictReserved(raw_name)) |
| 3756 return false; | 3755 return false; |
| 3757 if (traits->IsUndefined(raw_name) && !undefined_loc->IsValid()) { | 3756 if (traits->IsUndefined(raw_name) && !locs->undefined.IsValid()) { |
| 3758 *undefined_loc = Scanner::Location( | 3757 locs->undefined = Scanner::Location( |
| 3759 expression->position(), expression->position() + raw_name->length()); | 3758 expression->position(), expression->position() + raw_name->length()); |
| 3760 } | 3759 } |
| 3761 if (scope->IsDeclared(raw_name)) { | |
| 3762 *dupe_loc = Scanner::Location( | |
| 3763 expression->position(), expression->position() + raw_name->length()); | |
| 3764 return false; | |
| 3765 } | |
| 3766 | 3760 |
| 3767 // When the variable was seen, it was recorded as unresolved in the outer | 3761 // When the variable was seen, it was recorded as unresolved in the outer |
| 3768 // scope. But it's really not unresolved. | 3762 // scope. But it's really not unresolved. |
| 3769 scope->outer_scope()->RemoveUnresolved(expression->AsVariableProxy()); | 3763 scope->outer_scope()->RemoveUnresolved(expression->AsVariableProxy()); |
| 3770 | 3764 |
| 3771 scope->DeclareParameter(raw_name, VAR); | 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 |
| 3772 ++(*num_params); | 3774 ++(*num_params); |
| 3773 return true; | 3775 return true; |
| 3774 } | 3776 } |
| 3775 | 3777 |
| 3776 // Case for more than one parameter: | 3778 // Case for more than one parameter: |
| 3777 // (foo, bar [, ...]) => ... | 3779 // (foo, bar [, ...]) => ... |
| 3778 if (expression->IsBinaryOperation()) { | 3780 if (expression->IsBinaryOperation()) { |
| 3779 BinaryOperation* binop = expression->AsBinaryOperation(); | 3781 BinaryOperation* binop = expression->AsBinaryOperation(); |
| 3780 if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() || | 3782 if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() || |
| 3781 binop->right()->is_parenthesized()) | 3783 binop->right()->is_parenthesized()) |
| 3782 return false; | 3784 return false; |
| 3783 | 3785 |
| 3784 return CheckAndDeclareArrowParameter(traits, binop->left(), scope, | 3786 return CheckAndDeclareArrowParameter(traits, binop->left(), scope, |
| 3785 num_params, undefined_loc, dupe_loc) && | 3787 num_params, locs) && |
| 3786 CheckAndDeclareArrowParameter(traits, binop->right(), scope, | 3788 CheckAndDeclareArrowParameter(traits, binop->right(), scope, |
| 3787 num_params, undefined_loc, dupe_loc); | 3789 num_params, locs); |
| 3788 } | 3790 } |
| 3789 | 3791 |
| 3790 // Any other kind of expression is not a valid parameter list. | 3792 // Any other kind of expression is not a valid parameter list. |
| 3791 return false; | 3793 return false; |
| 3792 } | 3794 } |
| 3793 | 3795 |
| 3794 | 3796 |
| 3795 int ParserTraits::DeclareArrowParametersFromExpression( | 3797 int ParserTraits::DeclareArrowParametersFromExpression( |
| 3796 Expression* expression, Scope* scope, Scanner::Location* undefined_loc, | 3798 Expression* expression, Scope* scope, FormalParameterErrorLocations* locs, |
| 3797 Scanner::Location* dupe_loc, bool* ok) { | 3799 bool* ok) { |
| 3798 int num_params = 0; | 3800 int num_params = 0; |
| 3799 // Always reset the flag: It only needs to be set for the first expression | 3801 // Always reset the flag: It only needs to be set for the first expression |
| 3800 // parsed as arrow function parameter list, because only top-level functions | 3802 // parsed as arrow function parameter list, because only top-level functions |
| 3801 // are parsed lazily. | 3803 // are parsed lazily. |
| 3802 parser_->parsing_lazy_arrow_parameters_ = false; | 3804 parser_->parsing_lazy_arrow_parameters_ = false; |
| 3803 *ok = CheckAndDeclareArrowParameter(this, expression, scope, &num_params, | 3805 *ok = |
| 3804 undefined_loc, dupe_loc); | 3806 CheckAndDeclareArrowParameter(this, expression, scope, &num_params, locs); |
| 3805 return num_params; | 3807 return num_params; |
| 3806 } | 3808 } |
| 3807 | 3809 |
| 3808 | 3810 |
| 3809 FunctionLiteral* Parser::ParseFunctionLiteral( | 3811 FunctionLiteral* Parser::ParseFunctionLiteral( |
| 3810 const AstRawString* function_name, Scanner::Location function_name_location, | 3812 const AstRawString* function_name, Scanner::Location function_name_location, |
| 3811 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, | 3813 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, |
| 3812 FunctionLiteral::FunctionType function_type, | 3814 FunctionLiteral::FunctionType function_type, |
| 3813 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { | 3815 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { |
| 3814 // Function :: | 3816 // Function :: |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3868 Scope* scope = function_type == FunctionLiteral::DECLARATION && | 3870 Scope* scope = function_type == FunctionLiteral::DECLARATION && |
| 3869 is_sloppy(language_mode()) && | 3871 is_sloppy(language_mode()) && |
| 3870 (original_scope_ == original_declaration_scope || | 3872 (original_scope_ == original_declaration_scope || |
| 3871 declaration_scope != original_declaration_scope) | 3873 declaration_scope != original_declaration_scope) |
| 3872 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) | 3874 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) |
| 3873 : NewScope(scope_, FUNCTION_SCOPE, kind); | 3875 : NewScope(scope_, FUNCTION_SCOPE, kind); |
| 3874 ZoneList<Statement*>* body = NULL; | 3876 ZoneList<Statement*>* body = NULL; |
| 3875 int materialized_literal_count = -1; | 3877 int materialized_literal_count = -1; |
| 3876 int expected_property_count = -1; | 3878 int expected_property_count = -1; |
| 3877 int handler_count = 0; | 3879 int handler_count = 0; |
| 3878 FunctionLiteral::ParameterFlag duplicate_parameters = | 3880 FormalParameterErrorLocations error_locs; |
| 3879 FunctionLiteral::kNoDuplicateParameters; | |
| 3880 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ | 3881 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ |
| 3881 ? FunctionLiteral::kIsParenthesized | 3882 ? FunctionLiteral::kIsParenthesized |
| 3882 : FunctionLiteral::kNotParenthesized; | 3883 : FunctionLiteral::kNotParenthesized; |
| 3883 // Parse function body. | 3884 // Parse function body. |
| 3884 { | 3885 { |
| 3885 AstNodeFactory function_factory(ast_value_factory()); | 3886 AstNodeFactory function_factory(ast_value_factory()); |
| 3886 FunctionState function_state(&function_state_, &scope_, scope, kind, | 3887 FunctionState function_state(&function_state_, &scope_, scope, kind, |
| 3887 &function_factory); | 3888 &function_factory); |
| 3888 scope_->SetScopeName(function_name); | 3889 scope_->SetScopeName(function_name); |
| 3889 | 3890 |
| 3890 if (is_generator) { | 3891 if (is_generator) { |
| 3891 // For generators, allocating variables in contexts is currently a win | 3892 // For generators, allocating variables in contexts is currently a win |
| 3892 // because it minimizes the work needed to suspend and resume an | 3893 // because it minimizes the work needed to suspend and resume an |
| 3893 // activation. | 3894 // activation. |
| 3894 scope_->ForceContextAllocation(); | 3895 scope_->ForceContextAllocation(); |
| 3895 | 3896 |
| 3896 // Calling a generator returns a generator object. That object is stored | 3897 // Calling a generator returns a generator object. That object is stored |
| 3897 // in a temporary variable, a definition that is used by "yield" | 3898 // in a temporary variable, a definition that is used by "yield" |
| 3898 // expressions. This also marks the FunctionState as a generator. | 3899 // expressions. This also marks the FunctionState as a generator. |
| 3899 Variable* temp = scope_->DeclarationScope()->NewTemporary( | 3900 Variable* temp = scope_->DeclarationScope()->NewTemporary( |
| 3900 ast_value_factory()->dot_generator_object_string()); | 3901 ast_value_factory()->dot_generator_object_string()); |
| 3901 function_state.set_generator_object_variable(temp); | 3902 function_state.set_generator_object_variable(temp); |
| 3902 } | 3903 } |
| 3903 | 3904 |
| 3904 // FormalParameterList :: | 3905 bool has_rest = false; |
| 3905 // '(' (Identifier)*[','] ')' | |
| 3906 Expect(Token::LPAREN, CHECK_OK); | 3906 Expect(Token::LPAREN, CHECK_OK); |
| 3907 scope->set_start_position(scanner()->location().beg_pos); | 3907 int start_position = scanner()->location().beg_pos; |
| 3908 scope_->set_start_position(start_position); |
| 3909 num_parameters = |
| 3910 ParseFormalParameterList(scope, &error_locs, &has_rest, CHECK_OK); |
| 3911 Expect(Token::RPAREN, CHECK_OK); |
| 3912 int formals_end_position = scanner()->location().end_pos; |
| 3908 | 3913 |
| 3909 // We don't yet know if the function will be strict, so we cannot yet | 3914 CheckArityRestrictions(num_parameters, arity_restriction, start_position, |
| 3910 // produce errors for parameter names or duplicates. However, we remember | 3915 formals_end_position, CHECK_OK); |
| 3911 // the locations of these errors if they occur and produce the errors later. | |
| 3912 Scanner::Location eval_args_loc = Scanner::Location::invalid(); | |
| 3913 Scanner::Location dupe_loc = Scanner::Location::invalid(); | |
| 3914 Scanner::Location reserved_loc = Scanner::Location::invalid(); | |
| 3915 | |
| 3916 // Similarly for strong mode. | |
| 3917 Scanner::Location undefined_loc = Scanner::Location::invalid(); | |
| 3918 | |
| 3919 bool is_rest = false; | |
| 3920 bool done = arity_restriction == FunctionLiteral::GETTER_ARITY || | |
| 3921 (peek() == Token::RPAREN && | |
| 3922 arity_restriction != FunctionLiteral::SETTER_ARITY); | |
| 3923 while (!done) { | |
| 3924 bool is_strict_reserved = false; | |
| 3925 is_rest = peek() == Token::ELLIPSIS && allow_harmony_rest_params(); | |
| 3926 if (is_rest) { | |
| 3927 Consume(Token::ELLIPSIS); | |
| 3928 } | |
| 3929 | |
| 3930 const AstRawString* param_name = | |
| 3931 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | |
| 3932 | |
| 3933 // Store locations for possible future error reports. | |
| 3934 if (!eval_args_loc.IsValid() && IsEvalOrArguments(param_name)) { | |
| 3935 eval_args_loc = scanner()->location(); | |
| 3936 } | |
| 3937 if (!undefined_loc.IsValid() && IsUndefined(param_name)) { | |
| 3938 undefined_loc = scanner()->location(); | |
| 3939 } | |
| 3940 if (!reserved_loc.IsValid() && is_strict_reserved) { | |
| 3941 reserved_loc = scanner()->location(); | |
| 3942 } | |
| 3943 if (!dupe_loc.IsValid() && | |
| 3944 scope_->IsDeclaredParameter(param_name)) { | |
| 3945 duplicate_parameters = FunctionLiteral::kHasDuplicateParameters; | |
| 3946 dupe_loc = scanner()->location(); | |
| 3947 } | |
| 3948 | |
| 3949 Variable* var = scope_->DeclareParameter(param_name, VAR, is_rest); | |
| 3950 if (is_sloppy(scope->language_mode())) { | |
| 3951 // TODO(sigurds) Mark every parameter as maybe assigned. This is a | |
| 3952 // conservative approximation necessary to account for parameters | |
| 3953 // that are assigned via the arguments array. | |
| 3954 var->set_maybe_assigned(); | |
| 3955 } | |
| 3956 | |
| 3957 num_parameters++; | |
| 3958 if (num_parameters > Code::kMaxArguments) { | |
| 3959 ReportMessage("too_many_parameters"); | |
| 3960 *ok = false; | |
| 3961 return NULL; | |
| 3962 } | |
| 3963 if (arity_restriction == FunctionLiteral::SETTER_ARITY) break; | |
| 3964 done = (peek() == Token::RPAREN); | |
| 3965 if (!done) { | |
| 3966 if (is_rest) { | |
| 3967 ReportMessageAt(scanner()->peek_location(), "param_after_rest"); | |
| 3968 *ok = false; | |
| 3969 return NULL; | |
| 3970 } | |
| 3971 Expect(Token::COMMA, CHECK_OK); | |
| 3972 } | |
| 3973 } | |
| 3974 Expect(Token::RPAREN, CHECK_OK); | |
| 3975 | 3916 |
| 3976 Expect(Token::LBRACE, CHECK_OK); | 3917 Expect(Token::LBRACE, CHECK_OK); |
| 3977 | 3918 |
| 3978 // If we have a named function expression, we add a local variable | 3919 // If we have a named function expression, we add a local variable |
| 3979 // declaration to the body of the function with the name of the | 3920 // declaration to the body of the function with the name of the |
| 3980 // function and let it refer to the function itself (closure). | 3921 // function and let it refer to the function itself (closure). |
| 3981 // NOTE: We create a proxy and resolve it here so that in the | 3922 // NOTE: We create a proxy and resolve it here so that in the |
| 3982 // future we can change the AST to only refer to VariableProxies | 3923 // future we can change the AST to only refer to VariableProxies |
| 3983 // instead of Variables and Proxis as is the case now. | 3924 // instead of Variables and Proxis as is the case now. |
| 3984 Variable* fvar = NULL; | 3925 Variable* fvar = NULL; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4046 materialized_literal_count = function_state.materialized_literal_count(); | 3987 materialized_literal_count = function_state.materialized_literal_count(); |
| 4047 expected_property_count = function_state.expected_property_count(); | 3988 expected_property_count = function_state.expected_property_count(); |
| 4048 handler_count = function_state.handler_count(); | 3989 handler_count = function_state.handler_count(); |
| 4049 } | 3990 } |
| 4050 | 3991 |
| 4051 // Validate name and parameter names. We can do this only after parsing the | 3992 // Validate name and parameter names. We can do this only after parsing the |
| 4052 // function, since the function can declare itself strict. | 3993 // function, since the function can declare itself strict. |
| 4053 CheckFunctionName(language_mode(), kind, function_name, | 3994 CheckFunctionName(language_mode(), kind, function_name, |
| 4054 name_is_strict_reserved, function_name_location, | 3995 name_is_strict_reserved, function_name_location, |
| 4055 CHECK_OK); | 3996 CHECK_OK); |
| 4056 const bool use_strict_params = is_rest || IsConciseMethod(kind); | 3997 const bool use_strict_params = has_rest || IsConciseMethod(kind); |
| 4057 CheckFunctionParameterNames(language_mode(), use_strict_params, | 3998 CheckFunctionParameterNames(language_mode(), use_strict_params, error_locs, |
| 4058 eval_args_loc, undefined_loc, dupe_loc, | 3999 CHECK_OK); |
| 4059 reserved_loc, CHECK_OK); | |
| 4060 | 4000 |
| 4061 if (is_strict(language_mode())) { | 4001 if (is_strict(language_mode())) { |
| 4062 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | 4002 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
| 4063 CHECK_OK); | 4003 CHECK_OK); |
| 4064 } | 4004 } |
| 4065 if (is_strict(language_mode())) { | 4005 if (is_strict(language_mode())) { |
| 4066 CheckConflictingVarDeclarations(scope, CHECK_OK); | 4006 CheckConflictingVarDeclarations(scope, CHECK_OK); |
| 4067 } | 4007 } |
| 4068 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { | 4008 if (is_strong(language_mode()) && IsSubclassConstructor(kind)) { |
| 4069 if (!function_state.super_call_location().IsValid()) { | 4009 if (!function_state.super_call_location().IsValid()) { |
| 4070 ReportMessageAt(function_name_location, "strong_super_call_missing", | 4010 ReportMessageAt(function_name_location, "strong_super_call_missing", |
| 4071 kReferenceError); | 4011 kReferenceError); |
| 4072 *ok = false; | 4012 *ok = false; |
| 4073 return nullptr; | 4013 return nullptr; |
| 4074 } | 4014 } |
| 4075 } | 4015 } |
| 4076 } | 4016 } |
| 4077 | 4017 |
| 4018 FunctionLiteral::ParameterFlag duplicate_parameters = |
| 4019 error_locs.duplicate.IsValid() ? FunctionLiteral::kHasDuplicateParameters |
| 4020 : FunctionLiteral::kNoDuplicateParameters; |
| 4021 |
| 4078 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | 4022 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( |
| 4079 function_name, ast_value_factory(), scope, body, | 4023 function_name, ast_value_factory(), scope, body, |
| 4080 materialized_literal_count, expected_property_count, handler_count, | 4024 materialized_literal_count, expected_property_count, handler_count, |
| 4081 num_parameters, duplicate_parameters, function_type, | 4025 num_parameters, duplicate_parameters, function_type, |
| 4082 FunctionLiteral::kIsFunction, parenthesized, kind, pos); | 4026 FunctionLiteral::kIsFunction, parenthesized, kind, pos); |
| 4083 function_literal->set_function_token_position(function_token_pos); | 4027 function_literal->set_function_token_position(function_token_pos); |
| 4084 | 4028 |
| 4085 if (scope->has_rest_parameter()) { | 4029 if (scope->has_rest_parameter()) { |
| 4086 // TODO(caitp): enable optimization of functions with rest params | 4030 // TODO(caitp): enable optimization of functions with rest params |
| 4087 function_literal->set_dont_optimize_reason(kRestParameter); | 4031 function_literal->set_dont_optimize_reason(kRestParameter); |
| (...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5779 | 5723 |
| 5780 Expression* Parser::SpreadCallNew(Expression* function, | 5724 Expression* Parser::SpreadCallNew(Expression* function, |
| 5781 ZoneList<v8::internal::Expression*>* args, | 5725 ZoneList<v8::internal::Expression*>* args, |
| 5782 int pos) { | 5726 int pos) { |
| 5783 args->InsertAt(0, function, zone()); | 5727 args->InsertAt(0, function, zone()); |
| 5784 | 5728 |
| 5785 return factory()->NewCallRuntime( | 5729 return factory()->NewCallRuntime( |
| 5786 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5730 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
| 5787 } | 5731 } |
| 5788 } } // namespace v8::internal | 5732 } } // namespace v8::internal |
| OLD | NEW |