OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 | 744 |
745 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { | 745 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { |
746 return parser_->ParseV8Intrinsic(ok); | 746 return parser_->ParseV8Intrinsic(ok); |
747 } | 747 } |
748 | 748 |
749 | 749 |
750 FunctionLiteral* ParserTraits::ParseFunctionLiteral( | 750 FunctionLiteral* ParserTraits::ParseFunctionLiteral( |
751 Handle<String> name, | 751 Handle<String> name, |
752 Scanner::Location function_name_location, | 752 Scanner::Location function_name_location, |
753 bool name_is_strict_reserved, | 753 bool name_is_strict_reserved, |
754 bool is_generator, | 754 FunctionParsingMode parsing_mode, |
755 Expression* params_ast, | |
755 int function_token_position, | 756 int function_token_position, |
756 FunctionLiteral::FunctionType type, | 757 FunctionLiteral::FunctionType type, |
757 bool* ok) { | 758 bool* ok) { |
758 return parser_->ParseFunctionLiteral(name, function_name_location, | 759 return parser_->ParseFunctionLiteral(name, function_name_location, |
759 name_is_strict_reserved, is_generator, | 760 name_is_strict_reserved, parsing_mode, |
760 function_token_position, type, ok); | 761 params_ast, function_token_position, |
762 type, ok); | |
761 } | 763 } |
762 | 764 |
763 | 765 |
764 Parser::Parser(CompilationInfo* info) | 766 Parser::Parser(CompilationInfo* info) |
765 : ParserBase<ParserTraits>(&scanner_, | 767 : ParserBase<ParserTraits>(&scanner_, |
766 info->isolate()->stack_guard()->real_climit(), | 768 info->isolate()->stack_guard()->real_climit(), |
767 info->extension(), | 769 info->extension(), |
768 NULL, | 770 NULL, |
769 info->zone(), | 771 info->zone(), |
770 this), | 772 this), |
771 isolate_(info->isolate()), | 773 isolate_(info->isolate()), |
772 symbol_cache_(0, info->zone()), | 774 symbol_cache_(0, info->zone()), |
773 script_(info->script()), | 775 script_(info->script()), |
774 scanner_(isolate_->unicode_cache()), | 776 scanner_(isolate_->unicode_cache()), |
775 reusable_preparser_(NULL), | 777 reusable_preparser_(NULL), |
776 original_scope_(NULL), | 778 original_scope_(NULL), |
777 target_stack_(NULL), | 779 target_stack_(NULL), |
778 cached_data_(NULL), | 780 cached_data_(NULL), |
779 cached_data_mode_(NO_CACHED_DATA), | 781 cached_data_mode_(NO_CACHED_DATA), |
780 info_(info) { | 782 info_(info) { |
781 ASSERT(!script_.is_null()); | 783 ASSERT(!script_.is_null()); |
782 isolate_->set_ast_node_id(0); | 784 isolate_->set_ast_node_id(0); |
783 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); | 785 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); |
784 set_allow_modules(!info->is_native() && FLAG_harmony_modules); | 786 set_allow_modules(!info->is_native() && FLAG_harmony_modules); |
785 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); | 787 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); |
786 set_allow_lazy(false); // Must be explicitly enabled. | 788 set_allow_lazy(false); // Must be explicitly enabled. |
787 set_allow_generators(FLAG_harmony_generators); | 789 set_allow_generators(FLAG_harmony_generators); |
788 set_allow_for_of(FLAG_harmony_iteration); | 790 set_allow_for_of(FLAG_harmony_iteration); |
791 set_allow_arrow_functions(FLAG_harmony_arrow_functions); | |
789 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); | 792 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); |
790 } | 793 } |
791 | 794 |
792 | 795 |
793 FunctionLiteral* Parser::ParseProgram() { | 796 FunctionLiteral* Parser::ParseProgram() { |
794 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, | 797 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, |
795 // see comment for HistogramTimerScope class. | 798 // see comment for HistogramTimerScope class. |
796 HistogramTimerScope timer_scope(isolate()->counters()->parse(), true); | 799 HistogramTimerScope timer_scope(isolate()->counters()->parse(), true); |
797 Handle<String> source(String::cast(script_->source())); | 800 Handle<String> source(String::cast(script_->source())); |
798 isolate()->counters()->total_parse_size()->Increment(source->length()); | 801 isolate()->counters()->total_parse_size()->Increment(source->length()); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
914 body, | 917 body, |
915 function_state.materialized_literal_count(), | 918 function_state.materialized_literal_count(), |
916 function_state.expected_property_count(), | 919 function_state.expected_property_count(), |
917 function_state.handler_count(), | 920 function_state.handler_count(), |
918 0, | 921 0, |
919 FunctionLiteral::kNoDuplicateParameters, | 922 FunctionLiteral::kNoDuplicateParameters, |
920 FunctionLiteral::ANONYMOUS_EXPRESSION, | 923 FunctionLiteral::ANONYMOUS_EXPRESSION, |
921 FunctionLiteral::kGlobalOrEval, | 924 FunctionLiteral::kGlobalOrEval, |
922 FunctionLiteral::kNotParenthesized, | 925 FunctionLiteral::kNotParenthesized, |
923 FunctionLiteral::kNotGenerator, | 926 FunctionLiteral::kNotGenerator, |
927 FunctionLiteral::kNotArrow, | |
924 0); | 928 0); |
925 result->set_ast_properties(factory()->visitor()->ast_properties()); | 929 result->set_ast_properties(factory()->visitor()->ast_properties()); |
926 result->set_slot_processor(factory()->visitor()->slot_processor()); | 930 result->set_slot_processor(factory()->visitor()->slot_processor()); |
927 result->set_dont_optimize_reason( | 931 result->set_dont_optimize_reason( |
928 factory()->visitor()->dont_optimize_reason()); | 932 factory()->visitor()->dont_optimize_reason()); |
929 } else if (stack_overflow()) { | 933 } else if (stack_overflow()) { |
930 isolate()->StackOverflow(); | 934 isolate()->StackOverflow(); |
931 } | 935 } |
932 } | 936 } |
933 | 937 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
999 original_scope_ = scope; | 1003 original_scope_ = scope; |
1000 FunctionState function_state(&function_state_, &scope_, scope, zone()); | 1004 FunctionState function_state(&function_state_, &scope_, scope, zone()); |
1001 ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT); | 1005 ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT); |
1002 ASSERT(info()->strict_mode() == shared_info->strict_mode()); | 1006 ASSERT(info()->strict_mode() == shared_info->strict_mode()); |
1003 scope->SetStrictMode(shared_info->strict_mode()); | 1007 scope->SetStrictMode(shared_info->strict_mode()); |
1004 FunctionLiteral::FunctionType function_type = shared_info->is_expression() | 1008 FunctionLiteral::FunctionType function_type = shared_info->is_expression() |
1005 ? (shared_info->is_anonymous() | 1009 ? (shared_info->is_anonymous() |
1006 ? FunctionLiteral::ANONYMOUS_EXPRESSION | 1010 ? FunctionLiteral::ANONYMOUS_EXPRESSION |
1007 : FunctionLiteral::NAMED_EXPRESSION) | 1011 : FunctionLiteral::NAMED_EXPRESSION) |
1008 : FunctionLiteral::DECLARATION; | 1012 : FunctionLiteral::DECLARATION; |
1013 FunctionParsingMode parsing_mode = shared_info->is_generator() | |
rossberg
2014/03/25 12:35:34
Nit: I'd prefer formatting this like
FunctionPars
| |
1014 ? kGeneratorFunction | |
1015 : (shared_info->is_arrow() ? kArrowFunction : kNormalFunction); | |
1009 bool ok = true; | 1016 bool ok = true; |
1010 result = ParseFunctionLiteral(name, | 1017 result = ParseFunctionLiteral(name, |
1011 Scanner::Location::invalid(), | 1018 Scanner::Location::invalid(), |
1012 false, // Strict mode name already checked. | 1019 false, // Strict mode name already checked. |
1013 shared_info->is_generator(), | 1020 parsing_mode, |
1021 EmptyExpression(), | |
1014 RelocInfo::kNoPosition, | 1022 RelocInfo::kNoPosition, |
1015 function_type, | 1023 function_type, |
1016 &ok); | 1024 &ok); |
1017 // Make sure the results agree. | 1025 // Make sure the results agree. |
1018 ASSERT(ok == (result != NULL)); | 1026 ASSERT(ok == (result != NULL)); |
1019 } | 1027 } |
1020 | 1028 |
1021 // Make sure the target stack is empty. | 1029 // Make sure the target stack is empty. |
1022 ASSERT(target_stack_ == NULL); | 1030 ASSERT(target_stack_ == NULL); |
1023 | 1031 |
(...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1852 | 1860 |
1853 | 1861 |
1854 Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { | 1862 Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) { |
1855 // FunctionDeclaration :: | 1863 // FunctionDeclaration :: |
1856 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 1864 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
1857 // GeneratorDeclaration :: | 1865 // GeneratorDeclaration :: |
1858 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 1866 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
1859 // '{' FunctionBody '}' | 1867 // '{' FunctionBody '}' |
1860 Expect(Token::FUNCTION, CHECK_OK); | 1868 Expect(Token::FUNCTION, CHECK_OK); |
1861 int pos = position(); | 1869 int pos = position(); |
1862 bool is_generator = allow_generators() && Check(Token::MUL); | 1870 FunctionParsingMode parsing_mode = (allow_generators() && Check(Token::MUL)) |
1871 ? kGeneratorFunction | |
1872 : kNormalFunction; | |
1863 bool is_strict_reserved = false; | 1873 bool is_strict_reserved = false; |
1864 Handle<String> name = ParseIdentifierOrStrictReservedWord( | 1874 Handle<String> name = ParseIdentifierOrStrictReservedWord( |
1865 &is_strict_reserved, CHECK_OK); | 1875 &is_strict_reserved, CHECK_OK); |
1866 FunctionLiteral* fun = ParseFunctionLiteral(name, | 1876 FunctionLiteral* fun = ParseFunctionLiteral(name, |
1867 scanner()->location(), | 1877 scanner()->location(), |
1868 is_strict_reserved, | 1878 is_strict_reserved, |
1869 is_generator, | 1879 parsing_mode, |
1880 EmptyExpression(), | |
1870 pos, | 1881 pos, |
1871 FunctionLiteral::DECLARATION, | 1882 FunctionLiteral::DECLARATION, |
1872 CHECK_OK); | 1883 CHECK_OK); |
1873 // Even if we're not at the top-level of the global or a function | 1884 // Even if we're not at the top-level of the global or a function |
1874 // scope, we treat it as such and introduce the function with its | 1885 // scope, we treat it as such and introduce the function with its |
1875 // initial value upon entering the corresponding scope. | 1886 // initial value upon entering the corresponding scope. |
1876 // In extended mode, a function behaves as a lexical binding, except in the | 1887 // In extended mode, a function behaves as a lexical binding, except in the |
1877 // global scope. | 1888 // global scope. |
1878 VariableMode mode = | 1889 VariableMode mode = |
1879 FLAG_harmony_scoping && | 1890 FLAG_harmony_scoping && |
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3118 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); | 3129 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); |
3119 return static_cast<LiteralType>(literal_type->value()); | 3130 return static_cast<LiteralType>(literal_type->value()); |
3120 } | 3131 } |
3121 | 3132 |
3122 | 3133 |
3123 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { | 3134 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { |
3124 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); | 3135 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); |
3125 } | 3136 } |
3126 | 3137 |
3127 | 3138 |
3139 Vector<VariableProxy*> Parser::ParameterListFromExpression( | |
rossberg
2014/03/25 12:35:34
How does this rule out illegal parenthesis? For ex
aperez
2014/04/09 08:47:16
True, this case is tricky to implement when re-int
| |
3140 Expression* expression, bool* ok) { | |
3141 if (expression == NULL) | |
marja
2014/03/24 09:04:06
Normally having expression == NULL would be an err
aperez
2014/04/09 08:47:16
Yes, when the argument list is empty, “expression”
| |
3142 return Vector<VariableProxy*>::empty(); | |
3143 | |
3144 Collector<VariableProxy*> collector; | |
3145 while (expression->IsBinaryOperation()) { | |
3146 BinaryOperation* binop = expression->AsBinaryOperation(); | |
3147 | |
3148 if (binop->op() != Token::COMMA) { | |
3149 const char* token_name = Token::String(binop->op()); | |
3150 int pos = binop->position(); | |
3151 ParserTraits::ReportMessageAt(Scanner::Location(pos, pos), | |
rossberg
2014/03/25 12:35:34
Can we refactor this a little to avoid all the err
aperez
2014/04/09 08:47:16
Sure.
| |
3152 "unexpected_token", | |
3153 Vector<const char*>(&token_name, 1)); | |
3154 *ok = false; | |
3155 return Vector<VariableProxy*>::empty(); | |
3156 } | |
3157 | |
3158 if (!binop->right()->IsVariableProxy()) { | |
3159 const char* token_name = Token::String(binop->op()); | |
3160 int pos = binop->position(); | |
3161 ParserTraits::ReportMessageAt(Scanner::Location(pos, pos), | |
3162 "unexpected_token", | |
3163 Vector<const char*>(&token_name, 1)); | |
3164 *ok = false; | |
3165 return Vector<VariableProxy*>::empty(); | |
3166 } | |
3167 | |
3168 if (binop->right()->AsVariableProxy()->is_this()) { | |
3169 const char* token_name = Token::String(Token::THIS); | |
3170 int pos = binop->right()->position(); | |
3171 ParserTraits::ReportMessageAt(Scanner::Location(pos, pos + 4), | |
3172 "unexpected_token", | |
3173 Vector<const char*>(&token_name, 1)); | |
3174 *ok = false; | |
3175 return Vector<VariableProxy*>::empty(); | |
3176 } | |
3177 | |
3178 collector.Add(binop->right()->AsVariableProxy()); | |
3179 expression = binop->left(); | |
3180 } | |
3181 | |
3182 if (!expression->IsVariableProxy()) { | |
3183 int pos = expression->position(); | |
3184 ParserTraits::ReportMessageAt(Scanner::Location(pos, pos), | |
3185 "unexpected_token", | |
3186 Vector<const char*>()); | |
3187 *ok = false; | |
3188 return Vector<VariableProxy*>::empty(); | |
3189 } | |
3190 | |
3191 if (expression->AsVariableProxy()->is_this()) { | |
3192 const char* token_name = Token::String(Token::THIS); | |
3193 int pos = expression->position(); | |
3194 ParserTraits::ReportMessageAt(Scanner::Location(pos, pos + 4), | |
3195 "unexpected_token", | |
3196 Vector<const char*>(&token_name, 1)); | |
3197 *ok = false; | |
3198 return Vector<VariableProxy*>::empty(); | |
3199 } | |
3200 | |
3201 collector.Add(expression->AsVariableProxy()); | |
3202 | |
3203 return collector.ToVector(); | |
3204 } | |
3205 | |
3128 FunctionLiteral* Parser::ParseFunctionLiteral( | 3206 FunctionLiteral* Parser::ParseFunctionLiteral( |
3129 Handle<String> function_name, | 3207 Handle<String> function_name, |
3130 Scanner::Location function_name_location, | 3208 Scanner::Location function_name_location, |
3131 bool name_is_strict_reserved, | 3209 bool name_is_strict_reserved, |
3132 bool is_generator, | 3210 FunctionParsingMode func_parsing_mode, |
3211 Expression* params_ast, | |
3133 int function_token_pos, | 3212 int function_token_pos, |
3134 FunctionLiteral::FunctionType function_type, | 3213 FunctionLiteral::FunctionType function_type, |
3135 bool* ok) { | 3214 bool* ok) { |
3136 // Function :: | 3215 // Function :: |
3137 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 3216 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
3138 | 3217 |
3139 int pos = function_token_pos == RelocInfo::kNoPosition | 3218 int pos = function_token_pos == RelocInfo::kNoPosition |
3140 ? peek_position() : function_token_pos; | 3219 ? peek_position() : function_token_pos; |
3141 | 3220 |
3142 // Anonymous functions were passed either the empty symbol or a null | 3221 // Anonymous functions were passed either the empty symbol or a null |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3188 : NewScope(scope_, FUNCTION_SCOPE); | 3267 : NewScope(scope_, FUNCTION_SCOPE); |
3189 ZoneList<Statement*>* body = NULL; | 3268 ZoneList<Statement*>* body = NULL; |
3190 int materialized_literal_count = -1; | 3269 int materialized_literal_count = -1; |
3191 int expected_property_count = -1; | 3270 int expected_property_count = -1; |
3192 int handler_count = 0; | 3271 int handler_count = 0; |
3193 FunctionLiteral::ParameterFlag duplicate_parameters = | 3272 FunctionLiteral::ParameterFlag duplicate_parameters = |
3194 FunctionLiteral::kNoDuplicateParameters; | 3273 FunctionLiteral::kNoDuplicateParameters; |
3195 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ | 3274 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ |
3196 ? FunctionLiteral::kIsParenthesized | 3275 ? FunctionLiteral::kIsParenthesized |
3197 : FunctionLiteral::kNotParenthesized; | 3276 : FunctionLiteral::kNotParenthesized; |
3198 FunctionLiteral::IsGeneratorFlag generator = is_generator | 3277 FunctionLiteral::IsGeneratorFlag generator = |
3199 ? FunctionLiteral::kIsGenerator | 3278 (func_parsing_mode == kGeneratorFunction) |
3200 : FunctionLiteral::kNotGenerator; | 3279 ? FunctionLiteral::kIsGenerator |
3280 : FunctionLiteral::kNotGenerator; | |
3281 FunctionLiteral::IsArrowFlag arrow = (func_parsing_mode == kArrowFunction) | |
3282 ? FunctionLiteral::kIsArrow | |
3283 : FunctionLiteral::kNotArrow; | |
3201 DeferredFeedbackSlotProcessor* slot_processor; | 3284 DeferredFeedbackSlotProcessor* slot_processor; |
3202 AstProperties ast_properties; | 3285 AstProperties ast_properties; |
3203 BailoutReason dont_optimize_reason = kNoReason; | 3286 BailoutReason dont_optimize_reason = kNoReason; |
3204 // Parse function body. | 3287 // Parse function body. |
3205 { FunctionState function_state(&function_state_, &scope_, scope, zone()); | 3288 { FunctionState function_state(&function_state_, &scope_, scope, zone()); |
3206 scope_->SetScopeName(function_name); | 3289 scope_->SetScopeName(function_name); |
3207 | 3290 |
3208 if (is_generator) { | 3291 if (func_parsing_mode == kGeneratorFunction) { |
3209 // For generators, allocating variables in contexts is currently a win | 3292 // For generators, allocating variables in contexts is currently a win |
3210 // because it minimizes the work needed to suspend and resume an | 3293 // because it minimizes the work needed to suspend and resume an |
3211 // activation. | 3294 // activation. |
3212 scope_->ForceContextAllocation(); | 3295 scope_->ForceContextAllocation(); |
3213 | 3296 |
3214 // Calling a generator returns a generator object. That object is stored | 3297 // Calling a generator returns a generator object. That object is stored |
3215 // in a temporary variable, a definition that is used by "yield" | 3298 // in a temporary variable, a definition that is used by "yield" |
3216 // expressions. This also marks the FunctionState as a generator. | 3299 // expressions. This also marks the FunctionState as a generator. |
3217 Variable* temp = scope_->DeclarationScope()->NewTemporary( | 3300 Variable* temp = scope_->DeclarationScope()->NewTemporary( |
3218 isolate()->factory()->dot_generator_object_string()); | 3301 isolate()->factory()->dot_generator_object_string()); |
3219 function_state.set_generator_object_variable(temp); | 3302 function_state.set_generator_object_variable(temp); |
3220 } | 3303 } |
3221 | 3304 |
3222 // FormalParameterList :: | |
3223 // '(' (Identifier)*[','] ')' | |
3224 Expect(Token::LPAREN, CHECK_OK); | |
3225 scope->set_start_position(scanner()->location().beg_pos); | |
3226 | |
3227 // We don't yet know if the function will be strict, so we cannot yet | 3305 // We don't yet know if the function will be strict, so we cannot yet |
3228 // produce errors for parameter names or duplicates. However, we remember | 3306 // produce errors for parameter names or duplicates. However, we remember |
3229 // the locations of these errors if they occur and produce the errors later. | 3307 // the locations of these errors if they occur and produce the errors later. |
3230 Scanner::Location eval_args_error_log = Scanner::Location::invalid(); | 3308 Scanner::Location eval_args_error_log = Scanner::Location::invalid(); |
3231 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); | 3309 Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
3232 Scanner::Location reserved_loc = Scanner::Location::invalid(); | 3310 Scanner::Location reserved_loc = Scanner::Location::invalid(); |
3233 | 3311 |
3234 bool done = (peek() == Token::RPAREN); | 3312 // FormalParameterList :: |
marja
2014/03/24 09:04:06
This ParseFunctionLiteral is pretty monstrous as i
rossberg
2014/03/25 12:35:34
+1. The arrow function case is parsing quite diffe
aperez
2014/04/09 08:47:16
I am in the process of moving parsing of arrow fun
| |
3235 while (!done) { | 3313 // '(' (Identifier)*[','] ')' |
3236 bool is_strict_reserved = false; | 3314 |
3237 Handle<String> param_name = | 3315 if (func_parsing_mode == kArrowFunction && peek() == Token::ARROW) { |
rossberg
2014/03/25 12:35:34
Can it ever happen that the first condition is tru
aperez
2014/04/09 08:47:16
It could happen when the function is parsed lazily
| |
3238 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 3316 // The parameter list has already been scanned and turned into an AST |
3239 | 3317 // and it is passed as "params_ast". Re-interpreting the AST avoids |
3240 // Store locations for possible future error reports. | 3318 // needing to rewind and re-parse the parameter list. The starting |
3241 if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) { | 3319 // position of the parameter list is passed as "function_token_pos". |
3242 eval_args_error_log = scanner()->location(); | 3320 scope->set_start_position(function_token_pos); |
3243 } | 3321 Vector<VariableProxy*> params = ParameterListFromExpression(params_ast, |
3244 if (!reserved_loc.IsValid() && is_strict_reserved) { | 3322 CHECK_OK); |
3245 reserved_loc = scanner()->location(); | 3323 |
3246 } | 3324 if ((num_parameters = params.length()) > Code::kMaxArguments) { |
3247 if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) { | 3325 ReportMessageAt(Scanner::Location(params_ast->position(), position()), |
3248 duplicate_parameters = FunctionLiteral::kHasDuplicateParameters; | 3326 "too_many_parameters"); |
3249 dupe_error_loc = scanner()->location(); | |
3250 } | |
3251 | |
3252 scope_->DeclareParameter(param_name, VAR); | |
3253 num_parameters++; | |
3254 if (num_parameters > Code::kMaxArguments) { | |
3255 ReportMessageAt(scanner()->location(), "too_many_parameters"); | |
3256 *ok = false; | 3327 *ok = false; |
3257 return NULL; | 3328 return NULL; |
3258 } | 3329 } |
3259 done = (peek() == Token::RPAREN); | 3330 |
3260 if (!done) Expect(Token::COMMA, CHECK_OK); | 3331 // The vector has the items in reverse order |
3332 for (int i = params.length() - 1; i >= 0; --i) { | |
3333 Handle<String> param_name = params.at(i)->name(); | |
3334 int param_pos = params.at(i)->position(); | |
3335 | |
3336 if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) { | |
3337 eval_args_error_log = | |
3338 Scanner::Location(param_pos, param_pos + param_name->length()); | |
3339 } | |
3340 if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) { | |
3341 dupe_error_loc = | |
3342 Scanner::Location(param_pos, param_pos + param_name->length()); | |
3343 duplicate_parameters = FunctionLiteral::kHasDuplicateParameters; | |
3344 } | |
3345 | |
3346 scope_->DeclareParameter(param_name, VAR); | |
3347 } | |
3348 } else { | |
3349 bool arrow_single_param = | |
3350 (func_parsing_mode == kArrowFunction && peek() != Token::LPAREN); | |
3351 | |
3352 if (!arrow_single_param) { | |
3353 Expect(Token::LPAREN, CHECK_OK); | |
3354 } | |
3355 | |
3356 scope->set_start_position(scanner()->location().beg_pos); | |
3357 | |
3358 bool done = (peek() == Token::RPAREN); | |
3359 while (!done) { | |
3360 bool is_strict_reserved = false; | |
3361 Handle<String> param_name = | |
3362 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | |
3363 | |
3364 // Store locations for possible future error reports. | |
3365 if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) { | |
3366 eval_args_error_log = scanner()->location(); | |
3367 } | |
3368 if (!reserved_loc.IsValid() && is_strict_reserved) { | |
3369 reserved_loc = scanner()->location(); | |
3370 } | |
3371 if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) { | |
3372 duplicate_parameters = FunctionLiteral::kHasDuplicateParameters; | |
3373 dupe_error_loc = scanner()->location(); | |
3374 } | |
3375 | |
3376 scope_->DeclareParameter(param_name, VAR); | |
3377 num_parameters++; | |
3378 if (num_parameters > Code::kMaxArguments) { | |
3379 ReportMessageAt(scanner()->location(), "too_many_parameters"); | |
3380 *ok = false; | |
3381 return NULL; | |
3382 } | |
3383 | |
3384 done = (peek() == Token::RPAREN); | |
3385 if (arrow_single_param) break; | |
3386 if (!done) Expect(Token::COMMA, CHECK_OK); | |
3387 } | |
3388 | |
3389 if (!arrow_single_param) { | |
3390 Expect(Token::RPAREN, CHECK_OK); | |
3391 } | |
3261 } | 3392 } |
3262 Expect(Token::RPAREN, CHECK_OK); | 3393 |
3263 | 3394 if (func_parsing_mode == kArrowFunction) { |
3264 Expect(Token::LBRACE, CHECK_OK); | 3395 Expect(Token::ARROW, CHECK_OK); |
3265 | 3396 |
3266 // If we have a named function expression, we add a local variable | 3397 // The arrow function has a single-expression body |
3267 // declaration to the body of the function with the name of the | 3398 if (peek() != Token::LBRACE) { |
3268 // function and let it refer to the function itself (closure). | 3399 int pos = position(); |
3269 // NOTE: We create a proxy and resolve it here so that in the | 3400 Expression* expression = ParseExpression(true, CHECK_OK); |
rossberg
2014/03/25 12:35:34
Shouldn't this be ParseAssignmentExpression?
aperez
2014/04/09 08:47:16
Indeed.
| |
3270 // future we can change the AST to only refer to VariableProxies | 3401 body = new(zone()) ZoneList<Statement*>(1, zone()); |
3271 // instead of Variables and Proxis as is the case now. | 3402 body->Add(factory()->NewReturnStatement(expression, pos), zone()); |
3272 Variable* fvar = NULL; | 3403 |
3273 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; | 3404 materialized_literal_count = |
3274 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | 3405 function_state.materialized_literal_count(); |
3275 if (FLAG_harmony_scoping && strict_mode() == STRICT) { | 3406 expected_property_count = function_state.expected_property_count(); |
3276 fvar_init_op = Token::INIT_CONST; | 3407 handler_count = function_state.handler_count(); |
3277 } | 3408 |
3278 VariableMode fvar_mode = FLAG_harmony_scoping && strict_mode() == STRICT | 3409 scope->set_end_position(scanner()->location().end_pos); |
3279 ? CONST : CONST_LEGACY; | 3410 } |
3280 fvar = new(zone()) Variable(scope_, | |
3281 function_name, fvar_mode, true /* is valid LHS */, | |
3282 Variable::NORMAL, kCreatedInitialized, Interface::NewConst()); | |
3283 VariableProxy* proxy = factory()->NewVariableProxy(fvar); | |
3284 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( | |
3285 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); | |
3286 scope_->DeclareFunctionVar(fvar_declaration); | |
3287 } | 3411 } |
3288 | 3412 |
3289 // Determine if the function can be parsed lazily. Lazy parsing is different | 3413 // If an arrow function has a single-expression body, |
3290 // from lazy compilation; we need to parse more eagerly than we compile. | 3414 // it was already parsed above and "body" is non-NULL. |
3291 | 3415 if (body == NULL) { |
3292 // We can only parse lazily if we also compile lazily. The heuristics for | 3416 Expect(Token::LBRACE, CHECK_OK); |
3293 // lazy compilation are: | 3417 |
3294 // - It must not have been prohibited by the caller to Parse (some callers | 3418 // If we have a named function expression, we add a local variable |
3295 // need a full AST). | 3419 // declaration to the body of the function with the name of the |
3296 // - The outer scope must allow lazy compilation of inner functions. | 3420 // function and let it refer to the function itself (closure). |
3297 // - The function mustn't be a function expression with an open parenthesis | 3421 // NOTE: We create a proxy and resolve it here so that in the |
3298 // before; we consider that a hint that the function will be called | 3422 // future we can change the AST to only refer to VariableProxies |
3299 // immediately, and it would be a waste of time to make it lazily | 3423 // instead of Variables and Proxis as is the case now. |
3300 // compiled. | 3424 Variable* fvar = NULL; |
3301 // These are all things we can know at this point, without looking at the | 3425 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; |
3302 // function itself. | 3426 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
3303 | 3427 if (FLAG_harmony_scoping && strict_mode() == STRICT) { |
3304 // In addition, we need to distinguish between these cases: | 3428 fvar_init_op = Token::INIT_CONST; |
3305 // (function foo() { | 3429 } |
3306 // bar = function() { return 1; } | 3430 VariableMode fvar_mode = FLAG_harmony_scoping && strict_mode() == STRICT |
3307 // })(); | 3431 ? CONST : CONST_LEGACY; |
3308 // and | 3432 fvar = new(zone()) Variable(scope_, |
3309 // (function foo() { | 3433 function_name, fvar_mode, true /* is valid LHS */, |
3310 // var a = 1; | 3434 Variable::NORMAL, kCreatedInitialized, Interface::NewConst()); |
3311 // bar = function() { return a; } | 3435 VariableProxy* proxy = factory()->NewVariableProxy(fvar); |
3312 // })(); | 3436 VariableDeclaration* fvar_declaration = |
3313 | 3437 factory()->NewVariableDeclaration(proxy, fvar_mode, scope_, |
3314 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume | 3438 RelocInfo::kNoPosition); |
3315 // parenthesis before the function means that it will be called | 3439 scope_->DeclareFunctionVar(fvar_declaration); |
3316 // immediately). The inner function *must* be parsed eagerly to resolve the | 3440 } |
3317 // possible reference to the variable in foo's scope. However, it's possible | 3441 |
3318 // that it will be compiled lazily. | 3442 // Determine if the function can be parsed lazily. Lazy parsing is |
3319 | 3443 // different from lazy compilation; we need to parse more eagerly than |
3320 // To make this additional case work, both Parser and PreParser implement a | 3444 // we compile. |
3321 // logic where only top-level functions will be parsed lazily. | 3445 |
3322 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | 3446 // We can only parse lazily if we also compile lazily. The heuristics for |
3323 scope_->AllowsLazyCompilation() && | 3447 // lazy compilation are: |
3324 !parenthesized_function_); | 3448 // - It must not have been prohibited by the caller to Parse (some |
3325 parenthesized_function_ = false; // The bit was set for this function only. | 3449 // callers need a full AST). |
3326 | 3450 // - The outer scope must allow lazy compilation of inner functions. |
3327 if (is_lazily_parsed) { | 3451 // - The function mustn't be a function expression with an open |
3328 int function_block_pos = position(); | 3452 // parenthesis before; we consider that a hint that the function will |
3329 FunctionEntry entry; | 3453 // be called immediately, and it would be a waste of time to make it |
3330 if (cached_data_mode_ == CONSUME_CACHED_DATA) { | 3454 // lazily compiled. |
3331 // If we have cached data, we use it to skip parsing the function body. | 3455 // These are all things we can know at this point, without looking at |
3332 // The data contains the information we need to construct the lazy | 3456 // the function itself. |
3333 // function. | 3457 |
3334 entry = (*cached_data())->GetFunctionEntry(function_block_pos); | 3458 // In addition, we need to distinguish between these cases: |
3335 if (entry.is_valid()) { | 3459 // (function foo() { |
3336 if (entry.end_pos() <= function_block_pos) { | 3460 // bar = function() { return 1; } |
3337 // End position greater than end of stream is safe, and hard | 3461 // })(); |
3338 // to check. | 3462 // and |
3339 ReportInvalidPreparseData(function_name, CHECK_OK); | 3463 // (function foo() { |
3464 // var a = 1; | |
3465 // bar = function() { return a; } | |
3466 // })(); | |
3467 | |
3468 // Now foo will be parsed eagerly and compiled eagerly (optimization: | |
3469 // assume parenthesis before the function means that it will be called | |
3470 // immediately). The inner function *must* be parsed eagerly to resolve | |
3471 // the possible reference to the variable in foo's scope. However, it's | |
3472 // possible that it will be compiled lazily. | |
3473 | |
3474 // To make this additional case work, both Parser and PreParser implement | |
3475 // a logic where only top-level functions will be parsed lazily. | |
3476 bool is_lazily_parsed = (mode() == PARSE_LAZILY && | |
3477 scope_->AllowsLazyCompilation() && | |
3478 !parenthesized_function_ && | |
3479 (func_parsing_mode != kArrowFunction)); | |
3480 | |
3481 // The bit was set for this function only. | |
3482 parenthesized_function_ = false; | |
3483 | |
3484 if (is_lazily_parsed) { | |
3485 int function_block_pos = position(); | |
3486 FunctionEntry entry; | |
3487 if (cached_data_mode_ == CONSUME_CACHED_DATA) { | |
3488 // If we have cached data, we use it to skip parsing the function | |
3489 // body. The data contains the information we need to construct the | |
3490 // lazy function. | |
3491 entry = (*cached_data())->GetFunctionEntry(function_block_pos); | |
3492 if (entry.is_valid()) { | |
3493 if (entry.end_pos() <= function_block_pos) { | |
3494 // End position greater than end of stream is safe, and hard | |
3495 // to check. | |
3496 ReportInvalidPreparseData(function_name, CHECK_OK); | |
3497 } | |
3498 scanner()->SeekForward(entry.end_pos() - 1); | |
3499 | |
3500 scope->set_end_position(entry.end_pos()); | |
3501 Expect(Token::RBRACE, CHECK_OK); | |
3502 isolate()->counters()->total_preparse_skipped()->Increment( | |
3503 scope->end_position() - function_block_pos); | |
3504 materialized_literal_count = entry.literal_count(); | |
3505 expected_property_count = entry.property_count(); | |
3506 scope_->SetStrictMode(entry.strict_mode()); | |
3507 } else { | |
3508 // This case happens when we have preparse data but it doesn't | |
3509 // contain an entry for the function. As a safety net, fall back | |
3510 // to eager parsing. It is unclear whether PreParser's laziness | |
3511 // analysis can produce different results than the Parser's | |
3512 // laziness analysis (see https://codereview.chromium.org/7565003). | |
3513 // In this case, we must discard all the preparse data, since the | |
3514 // symbol data will be wrong. | |
3515 is_lazily_parsed = false; | |
3516 cached_data_mode_ = NO_CACHED_DATA; | |
3340 } | 3517 } |
3341 scanner()->SeekForward(entry.end_pos() - 1); | 3518 } else { |
3342 | 3519 // With no cached data, we partially parse the function, without |
3343 scope->set_end_position(entry.end_pos()); | 3520 // building an AST. This gathers the data needed to build a lazy |
3521 // function. | |
3522 // FIXME(marja): Now the PreParser doesn't need to log functions / | |
3523 // symbols; only errors -> clean that up. | |
3524 SingletonLogger logger; | |
3525 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger); | |
3526 if (result == PreParser::kPreParseStackOverflow) { | |
3527 // Propagate stack overflow. | |
3528 set_stack_overflow(); | |
3529 *ok = false; | |
3530 return NULL; | |
3531 } | |
3532 if (logger.has_error()) { | |
3533 const char* arg = logger.argument_opt(); | |
3534 Vector<const char*> args; | |
3535 if (arg != NULL) { | |
3536 args = Vector<const char*>(&arg, 1); | |
3537 } | |
3538 ParserTraits::ReportMessageAt( | |
3539 Scanner::Location(logger.start(), logger.end()), | |
3540 logger.message(), | |
3541 args); | |
3542 *ok = false; | |
3543 return NULL; | |
3544 } | |
3545 scope->set_end_position(logger.end()); | |
3344 Expect(Token::RBRACE, CHECK_OK); | 3546 Expect(Token::RBRACE, CHECK_OK); |
3345 isolate()->counters()->total_preparse_skipped()->Increment( | 3547 isolate()->counters()->total_preparse_skipped()->Increment( |
3346 scope->end_position() - function_block_pos); | 3548 scope->end_position() - function_block_pos); |
3347 materialized_literal_count = entry.literal_count(); | 3549 materialized_literal_count = logger.literals(); |
3348 expected_property_count = entry.property_count(); | 3550 expected_property_count = logger.properties(); |
3349 scope_->SetStrictMode(entry.strict_mode()); | 3551 scope_->SetStrictMode(logger.strict_mode()); |
3350 } else { | 3552 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { |
3351 // This case happens when we have preparse data but it doesn't contain | 3553 ASSERT(log_); |
3352 // an entry for the function. As a safety net, fall back to eager | 3554 // Position right after terminal '}'. |
3353 // parsing. It is unclear whether PreParser's laziness analysis can | 3555 int body_end = scanner()->location().end_pos; |
3354 // produce different results than the Parser's laziness analysis (see | 3556 log_->LogFunction(function_block_pos, body_end, |
3355 // https://codereview.chromium.org/7565003 ). In this case, we must | 3557 materialized_literal_count, |
3356 // discard all the preparse data, since the symbol data will be wrong. | 3558 expected_property_count, |
3357 is_lazily_parsed = false; | 3559 scope_->strict_mode()); |
3358 cached_data_mode_ = NO_CACHED_DATA; | |
3359 } | |
3360 } else { | |
3361 // With no cached data, we partially parse the function, without | |
3362 // building an AST. This gathers the data needed to build a lazy | |
3363 // function. | |
3364 // FIXME(marja): Now the PreParser doesn't need to log functions / | |
3365 // symbols; only errors -> clean that up. | |
3366 SingletonLogger logger; | |
3367 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger); | |
3368 if (result == PreParser::kPreParseStackOverflow) { | |
3369 // Propagate stack overflow. | |
3370 set_stack_overflow(); | |
3371 *ok = false; | |
3372 return NULL; | |
3373 } | |
3374 if (logger.has_error()) { | |
3375 const char* arg = logger.argument_opt(); | |
3376 Vector<const char*> args; | |
3377 if (arg != NULL) { | |
3378 args = Vector<const char*>(&arg, 1); | |
3379 } | 3560 } |
3380 ParserTraits::ReportMessageAt( | 3561 } |
3381 Scanner::Location(logger.start(), logger.end()), | 3562 } |
3382 logger.message(), | 3563 |
3383 args); | 3564 if (!is_lazily_parsed) { |
3384 *ok = false; | 3565 // Everything inside an eagerly parsed function will be parsed eagerly |
3385 return NULL; | 3566 // (see comment above). |
3386 } | 3567 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
3387 scope->set_end_position(logger.end()); | 3568 body = new(zone()) ZoneList<Statement*>(8, zone()); |
3569 if (fvar != NULL) { | |
3570 VariableProxy* fproxy = scope_->NewUnresolved( | |
3571 factory(), function_name, Interface::NewConst()); | |
3572 fproxy->BindTo(fvar); | |
3573 body->Add(factory()->NewExpressionStatement( | |
3574 factory()->NewAssignment(fvar_init_op, | |
3575 fproxy, | |
3576 factory()->NewThisFunction(pos), | |
3577 RelocInfo::kNoPosition), | |
3578 RelocInfo::kNoPosition), zone()); | |
3579 } | |
3580 | |
3581 // For generators, allocate and yield an iterator on function entry. | |
3582 if (func_parsing_mode == kGeneratorFunction) { | |
3583 ZoneList<Expression*>* arguments = | |
3584 new(zone()) ZoneList<Expression*>(0, zone()); | |
3585 CallRuntime* allocation = factory()->NewCallRuntime( | |
3586 isolate()->factory()->empty_string(), | |
3587 Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), | |
3588 arguments, pos); | |
3589 VariableProxy* init_proxy = factory()->NewVariableProxy( | |
3590 function_state_->generator_object_variable()); | |
3591 Assignment* assignment = factory()->NewAssignment( | |
3592 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); | |
3593 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
3594 function_state_->generator_object_variable()); | |
3595 Yield* yield = factory()->NewYield( | |
3596 get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition); | |
3597 body->Add(factory()->NewExpressionStatement( | |
3598 yield, RelocInfo::kNoPosition), zone()); | |
3599 } | |
3600 | |
3601 ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK); | |
3602 | |
3603 if (func_parsing_mode == kGeneratorFunction) { | |
3604 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
3605 function_state_->generator_object_variable()); | |
3606 Expression *undefined = factory()->NewLiteral( | |
3607 isolate()->factory()->undefined_value(), RelocInfo::kNoPosition); | |
3608 Yield* yield = factory()->NewYield( | |
3609 get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition); | |
3610 body->Add(factory()->NewExpressionStatement( | |
3611 yield, RelocInfo::kNoPosition), zone()); | |
3612 } | |
3613 | |
3614 materialized_literal_count = | |
3615 function_state.materialized_literal_count(); | |
3616 expected_property_count = function_state.expected_property_count(); | |
3617 handler_count = function_state.handler_count(); | |
3618 | |
3388 Expect(Token::RBRACE, CHECK_OK); | 3619 Expect(Token::RBRACE, CHECK_OK); |
3389 isolate()->counters()->total_preparse_skipped()->Increment( | 3620 scope->set_end_position(scanner()->location().end_pos); |
3390 scope->end_position() - function_block_pos); | 3621 } |
3391 materialized_literal_count = logger.literals(); | |
3392 expected_property_count = logger.properties(); | |
3393 scope_->SetStrictMode(logger.strict_mode()); | |
3394 if (cached_data_mode_ == PRODUCE_CACHED_DATA) { | |
3395 ASSERT(log_); | |
3396 // Position right after terminal '}'. | |
3397 int body_end = scanner()->location().end_pos; | |
3398 log_->LogFunction(function_block_pos, body_end, | |
3399 materialized_literal_count, | |
3400 expected_property_count, | |
3401 scope_->strict_mode()); | |
3402 } | |
3403 } | |
3404 } | |
3405 | |
3406 if (!is_lazily_parsed) { | |
3407 // Everything inside an eagerly parsed function will be parsed eagerly | |
3408 // (see comment above). | |
3409 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | |
3410 body = new(zone()) ZoneList<Statement*>(8, zone()); | |
3411 if (fvar != NULL) { | |
3412 VariableProxy* fproxy = scope_->NewUnresolved( | |
3413 factory(), function_name, Interface::NewConst()); | |
3414 fproxy->BindTo(fvar); | |
3415 body->Add(factory()->NewExpressionStatement( | |
3416 factory()->NewAssignment(fvar_init_op, | |
3417 fproxy, | |
3418 factory()->NewThisFunction(pos), | |
3419 RelocInfo::kNoPosition), | |
3420 RelocInfo::kNoPosition), zone()); | |
3421 } | |
3422 | |
3423 // For generators, allocate and yield an iterator on function entry. | |
3424 if (is_generator) { | |
3425 ZoneList<Expression*>* arguments = | |
3426 new(zone()) ZoneList<Expression*>(0, zone()); | |
3427 CallRuntime* allocation = factory()->NewCallRuntime( | |
3428 isolate()->factory()->empty_string(), | |
3429 Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), | |
3430 arguments, pos); | |
3431 VariableProxy* init_proxy = factory()->NewVariableProxy( | |
3432 function_state_->generator_object_variable()); | |
3433 Assignment* assignment = factory()->NewAssignment( | |
3434 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); | |
3435 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
3436 function_state_->generator_object_variable()); | |
3437 Yield* yield = factory()->NewYield( | |
3438 get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition); | |
3439 body->Add(factory()->NewExpressionStatement( | |
3440 yield, RelocInfo::kNoPosition), zone()); | |
3441 } | |
3442 | |
3443 ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK); | |
3444 | |
3445 if (is_generator) { | |
3446 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
3447 function_state_->generator_object_variable()); | |
3448 Expression *undefined = factory()->NewLiteral( | |
3449 isolate()->factory()->undefined_value(), RelocInfo::kNoPosition); | |
3450 Yield* yield = factory()->NewYield( | |
3451 get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition); | |
3452 body->Add(factory()->NewExpressionStatement( | |
3453 yield, RelocInfo::kNoPosition), zone()); | |
3454 } | |
3455 | |
3456 materialized_literal_count = function_state.materialized_literal_count(); | |
3457 expected_property_count = function_state.expected_property_count(); | |
3458 handler_count = function_state.handler_count(); | |
3459 | |
3460 Expect(Token::RBRACE, CHECK_OK); | |
3461 scope->set_end_position(scanner()->location().end_pos); | |
3462 } | 3622 } |
3463 | 3623 |
3464 // Validate strict mode. We can do this only after parsing the function, | 3624 // Validate strict mode. We can do this only after parsing the function, |
3465 // since the function can declare itself strict. | 3625 // since the function can declare itself strict. |
3466 if (strict_mode() == STRICT) { | 3626 if (strict_mode() == STRICT) { |
3467 if (IsEvalOrArguments(function_name)) { | 3627 if (IsEvalOrArguments(function_name)) { |
3468 ReportMessageAt(function_name_location, "strict_eval_arguments"); | 3628 ReportMessageAt(function_name_location, "strict_eval_arguments"); |
3469 *ok = false; | 3629 *ok = false; |
3470 return NULL; | 3630 return NULL; |
3471 } | 3631 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3508 body, | 3668 body, |
3509 materialized_literal_count, | 3669 materialized_literal_count, |
3510 expected_property_count, | 3670 expected_property_count, |
3511 handler_count, | 3671 handler_count, |
3512 num_parameters, | 3672 num_parameters, |
3513 duplicate_parameters, | 3673 duplicate_parameters, |
3514 function_type, | 3674 function_type, |
3515 FunctionLiteral::kIsFunction, | 3675 FunctionLiteral::kIsFunction, |
3516 parenthesized, | 3676 parenthesized, |
3517 generator, | 3677 generator, |
3678 arrow, | |
3518 pos); | 3679 pos); |
3519 function_literal->set_function_token_position(function_token_pos); | 3680 function_literal->set_function_token_position(function_token_pos); |
3520 function_literal->set_ast_properties(&ast_properties); | 3681 function_literal->set_ast_properties(&ast_properties); |
3521 function_literal->set_slot_processor(slot_processor); | 3682 function_literal->set_slot_processor(slot_processor); |
3522 function_literal->set_dont_optimize_reason(dont_optimize_reason); | 3683 function_literal->set_dont_optimize_reason(dont_optimize_reason); |
3523 | 3684 |
3524 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | 3685 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); |
3525 return function_literal; | 3686 return function_literal; |
3526 } | 3687 } |
3527 | 3688 |
3528 | 3689 |
3529 PreParser::PreParseResult Parser::LazyParseFunctionLiteral( | 3690 PreParser::PreParseResult Parser::LazyParseFunctionLiteral( |
3530 SingletonLogger* logger) { | 3691 SingletonLogger* logger) { |
3531 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse()); | 3692 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse()); |
3532 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); | 3693 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); |
3533 | 3694 |
3534 if (reusable_preparser_ == NULL) { | 3695 if (reusable_preparser_ == NULL) { |
3535 intptr_t stack_limit = isolate()->stack_guard()->real_climit(); | 3696 intptr_t stack_limit = isolate()->stack_guard()->real_climit(); |
3536 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit); | 3697 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit); |
3537 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); | 3698 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); |
3538 reusable_preparser_->set_allow_modules(allow_modules()); | 3699 reusable_preparser_->set_allow_modules(allow_modules()); |
3539 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); | 3700 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); |
3540 reusable_preparser_->set_allow_lazy(true); | 3701 reusable_preparser_->set_allow_lazy(true); |
3541 reusable_preparser_->set_allow_generators(allow_generators()); | 3702 reusable_preparser_->set_allow_generators(allow_generators()); |
3542 reusable_preparser_->set_allow_for_of(allow_for_of()); | 3703 reusable_preparser_->set_allow_for_of(allow_for_of()); |
3704 reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions()); | |
3543 reusable_preparser_->set_allow_harmony_numeric_literals( | 3705 reusable_preparser_->set_allow_harmony_numeric_literals( |
3544 allow_harmony_numeric_literals()); | 3706 allow_harmony_numeric_literals()); |
3545 } | 3707 } |
3546 PreParser::PreParseResult result = | 3708 PreParser::PreParseResult result = |
3547 reusable_preparser_->PreParseLazyFunction(strict_mode(), | 3709 reusable_preparser_->PreParseLazyFunction(strict_mode(), |
3548 is_generator(), | 3710 is_generator(), |
3549 logger); | 3711 logger); |
3550 return result; | 3712 return result; |
3551 } | 3713 } |
3552 | 3714 |
(...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4617 ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate, | 4779 ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate, |
4618 Utf16CharacterStream* source) { | 4780 Utf16CharacterStream* source) { |
4619 CompleteParserRecorder recorder; | 4781 CompleteParserRecorder recorder; |
4620 HistogramTimerScope timer(isolate->counters()->pre_parse()); | 4782 HistogramTimerScope timer(isolate->counters()->pre_parse()); |
4621 Scanner scanner(isolate->unicode_cache()); | 4783 Scanner scanner(isolate->unicode_cache()); |
4622 intptr_t stack_limit = isolate->stack_guard()->real_climit(); | 4784 intptr_t stack_limit = isolate->stack_guard()->real_climit(); |
4623 PreParser preparser(&scanner, &recorder, stack_limit); | 4785 PreParser preparser(&scanner, &recorder, stack_limit); |
4624 preparser.set_allow_lazy(true); | 4786 preparser.set_allow_lazy(true); |
4625 preparser.set_allow_generators(FLAG_harmony_generators); | 4787 preparser.set_allow_generators(FLAG_harmony_generators); |
4626 preparser.set_allow_for_of(FLAG_harmony_iteration); | 4788 preparser.set_allow_for_of(FLAG_harmony_iteration); |
4789 preparser.set_allow_arrow_functions(FLAG_harmony_arrow_functions); | |
4627 preparser.set_allow_harmony_scoping(FLAG_harmony_scoping); | 4790 preparser.set_allow_harmony_scoping(FLAG_harmony_scoping); |
4628 preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); | 4791 preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); |
4629 scanner.Initialize(source); | 4792 scanner.Initialize(source); |
4630 PreParser::PreParseResult result = preparser.PreParseProgram(); | 4793 PreParser::PreParseResult result = preparser.PreParseProgram(); |
4631 if (result == PreParser::kPreParseStackOverflow) { | 4794 if (result == PreParser::kPreParseStackOverflow) { |
4632 isolate->StackOverflow(); | 4795 isolate->StackOverflow(); |
4633 return NULL; | 4796 return NULL; |
4634 } | 4797 } |
4635 | 4798 |
4636 // Extract the accumulated data from the recorder as a single | 4799 // Extract the accumulated data from the recorder as a single |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4690 ASSERT(info()->isolate()->has_pending_exception()); | 4853 ASSERT(info()->isolate()->has_pending_exception()); |
4691 } else { | 4854 } else { |
4692 result = ParseProgram(); | 4855 result = ParseProgram(); |
4693 } | 4856 } |
4694 } | 4857 } |
4695 info()->SetFunction(result); | 4858 info()->SetFunction(result); |
4696 return (result != NULL); | 4859 return (result != NULL); |
4697 } | 4860 } |
4698 | 4861 |
4699 } } // namespace v8::internal | 4862 } } // namespace v8::internal |
OLD | NEW |