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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
(...skipping 1736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1747 DCHECK_NOT_NULL(catch_info.scope); | 1747 DCHECK_NOT_NULL(catch_info.scope); |
1748 DCHECK_NOT_NULL(catch_info.variable); | 1748 DCHECK_NOT_NULL(catch_info.variable); |
1749 return factory()->NewTryCatchStatement( | 1749 return factory()->NewTryCatchStatement( |
1750 try_block, catch_info.scope, catch_info.variable, catch_block, pos); | 1750 try_block, catch_info.scope, catch_info.variable, catch_block, pos); |
1751 } else { | 1751 } else { |
1752 DCHECK_NOT_NULL(finally_block); | 1752 DCHECK_NOT_NULL(finally_block); |
1753 return factory()->NewTryFinallyStatement(try_block, finally_block, pos); | 1753 return factory()->NewTryFinallyStatement(try_block, finally_block, pos); |
1754 } | 1754 } |
1755 } | 1755 } |
1756 | 1756 |
| 1757 void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind, |
| 1758 ZoneList<Statement*>* body, |
| 1759 bool* ok) { |
| 1760 // We produce: |
| 1761 // |
| 1762 // try { InitialYield; ...body...; return {value: undefined, done: true} } |
| 1763 // finally { %_GeneratorClose(generator) } |
| 1764 // |
| 1765 // - InitialYield yields the actual generator object. |
| 1766 // - Any return statement inside the body will have its argument wrapped |
| 1767 // in a "done" iterator result object. |
| 1768 // - If the generator terminates for whatever reason, we must close it. |
| 1769 // Hence the finally clause. |
| 1770 |
| 1771 Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
| 1772 Expression* initial_yield = BuildInitialYield(pos, kind); |
| 1773 try_block->statements()->Add( |
| 1774 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), |
| 1775 zone()); |
| 1776 ParseStatementList(try_block->statements(), Token::RBRACE, ok); |
| 1777 if (!*ok) return; |
| 1778 |
| 1779 Statement* final_return = factory()->NewReturnStatement( |
| 1780 BuildIteratorResult(nullptr, true), kNoSourcePosition); |
| 1781 try_block->statements()->Add(final_return, zone()); |
| 1782 |
| 1783 Block* finally_block = |
| 1784 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 1785 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); |
| 1786 VariableProxy* call_proxy = |
| 1787 factory()->NewVariableProxy(function_state_->generator_object_variable()); |
| 1788 args->Add(call_proxy, zone()); |
| 1789 Expression* call = factory()->NewCallRuntime(Runtime::kInlineGeneratorClose, |
| 1790 args, kNoSourcePosition); |
| 1791 finally_block->statements()->Add( |
| 1792 factory()->NewExpressionStatement(call, kNoSourcePosition), zone()); |
| 1793 |
| 1794 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, |
| 1795 kNoSourcePosition), |
| 1796 zone()); |
| 1797 } |
| 1798 |
| 1799 void Parser::CreateFunctionNameAssignment( |
| 1800 const AstRawString* function_name, int pos, |
| 1801 FunctionLiteral::FunctionType function_type, |
| 1802 DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) { |
| 1803 if (function_type == FunctionLiteral::kNamedExpression) { |
| 1804 StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition); |
| 1805 if (function_scope->LookupLocal(function_name) == nullptr) { |
| 1806 // Now that we know the language mode, we can create the const assignment |
| 1807 // in the previously reserved spot. |
| 1808 DCHECK_EQ(function_scope, scope()); |
| 1809 Variable* fvar = function_scope->DeclareFunctionVar(function_name); |
| 1810 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
| 1811 statement = factory()->NewExpressionStatement( |
| 1812 factory()->NewAssignment(Token::INIT, fproxy, |
| 1813 factory()->NewThisFunction(pos), |
| 1814 kNoSourcePosition), |
| 1815 kNoSourcePosition); |
| 1816 } |
| 1817 result->Set(index, statement); |
| 1818 } |
| 1819 } |
| 1820 |
1757 // !%_IsJSReceiver(result = iterator.next()) && | 1821 // !%_IsJSReceiver(result = iterator.next()) && |
1758 // %ThrowIteratorResultNotAnObject(result) | 1822 // %ThrowIteratorResultNotAnObject(result) |
1759 Expression* Parser::BuildIteratorNextResult(Expression* iterator, | 1823 Expression* Parser::BuildIteratorNextResult(Expression* iterator, |
1760 Variable* result, int pos) { | 1824 Variable* result, int pos) { |
1761 Expression* next_literal = factory()->NewStringLiteral( | 1825 Expression* next_literal = factory()->NewStringLiteral( |
1762 ast_value_factory()->next_string(), kNoSourcePosition); | 1826 ast_value_factory()->next_string(), kNoSourcePosition); |
1763 Expression* next_property = | 1827 Expression* next_property = |
1764 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); | 1828 factory()->NewProperty(iterator, next_literal, kNoSourcePosition); |
1765 ZoneList<Expression*>* next_arguments = | 1829 ZoneList<Expression*>* next_arguments = |
1766 new (zone()) ZoneList<Expression*>(0, zone()); | 1830 new (zone()) ZoneList<Expression*>(0, zone()); |
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2913 if (param_scope != nullptr) { | 2977 if (param_scope != nullptr) { |
2914 CheckConflictingVarDeclarations(param_scope, CHECK_OK); | 2978 CheckConflictingVarDeclarations(param_scope, CHECK_OK); |
2915 } | 2979 } |
2916 init_block->statements()->Add(param_block, zone()); | 2980 init_block->statements()->Add(param_block, zone()); |
2917 } | 2981 } |
2918 ++index; | 2982 ++index; |
2919 } | 2983 } |
2920 return init_block; | 2984 return init_block; |
2921 } | 2985 } |
2922 | 2986 |
2923 Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { | 2987 Block* Parser::BuildRejectPromiseOnException(Block* inner_block) { |
2924 // .promise = %AsyncFunctionPromiseCreate(); | 2988 // .promise = %AsyncFunctionPromiseCreate(); |
2925 // try { | 2989 // try { |
2926 // <inner_block> | 2990 // <inner_block> |
2927 // } catch (.catch) { | 2991 // } catch (.catch) { |
2928 // %RejectPromise(.promise, .catch); | 2992 // %RejectPromise(.promise, .catch); |
2929 // return .promise; | 2993 // return .promise; |
2930 // } finally { | 2994 // } finally { |
2931 // %AsyncFunctionPromiseRelease(.promise); | 2995 // %AsyncFunctionPromiseRelease(.promise); |
2932 // } | 2996 // } |
2933 Block* result = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition); | 2997 Block* result = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3075 Expect(Token::RPAREN, CHECK_OK); | 3139 Expect(Token::RPAREN, CHECK_OK); |
3076 int formals_end_position = scanner()->location().end_pos; | 3140 int formals_end_position = scanner()->location().end_pos; |
3077 *num_parameters = formals.num_parameters(); | 3141 *num_parameters = formals.num_parameters(); |
3078 *function_length = formals.function_length; | 3142 *function_length = formals.function_length; |
3079 | 3143 |
3080 CheckArityRestrictions(formals.arity, kind, formals.has_rest, | 3144 CheckArityRestrictions(formals.arity, kind, formals.has_rest, |
3081 function_scope->start_position(), formals_end_position, | 3145 function_scope->start_position(), formals_end_position, |
3082 CHECK_OK); | 3146 CHECK_OK); |
3083 Expect(Token::LBRACE, CHECK_OK); | 3147 Expect(Token::LBRACE, CHECK_OK); |
3084 | 3148 |
3085 ZoneList<Statement*>* body = ParseEagerFunctionBody( | 3149 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone()); |
3086 function_name, pos, formals, kind, function_type, ok); | 3150 ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok); |
3087 | 3151 |
3088 // Validate parameter names. We can do this only after parsing the function, | 3152 // Validate parameter names. We can do this only after parsing the function, |
3089 // since the function can declare itself strict. | 3153 // since the function can declare itself strict. |
3090 const bool allow_duplicate_parameters = | 3154 const bool allow_duplicate_parameters = |
3091 is_sloppy(function_scope->language_mode()) && formals.is_simple && | 3155 is_sloppy(function_scope->language_mode()) && formals.is_simple && |
3092 !IsConciseMethod(kind); | 3156 !IsConciseMethod(kind); |
3093 ValidateFormalParameters(function_scope->language_mode(), | 3157 ValidateFormalParameters(function_scope->language_mode(), |
3094 allow_duplicate_parameters, CHECK_OK); | 3158 allow_duplicate_parameters, CHECK_OK); |
3095 | 3159 |
3096 RewriteDestructuringAssignments(); | 3160 RewriteDestructuringAssignments(); |
3097 | 3161 |
3098 *has_duplicate_parameters = | 3162 *has_duplicate_parameters = |
3099 !classifier()->is_valid_formal_parameter_list_without_duplicates(); | 3163 !classifier()->is_valid_formal_parameter_list_without_duplicates(); |
3100 | 3164 |
3101 *materialized_literal_count = function_state.materialized_literal_count(); | 3165 *materialized_literal_count = function_state.materialized_literal_count(); |
3102 *expected_property_count = function_state.expected_property_count(); | 3166 *expected_property_count = function_state.expected_property_count(); |
3103 return body; | 3167 return body; |
3104 } | 3168 } |
3105 | 3169 |
3106 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | |
3107 const AstRawString* function_name, int pos, | |
3108 const ParserFormalParameters& parameters, FunctionKind kind, | |
3109 FunctionLiteral::FunctionType function_type, bool* ok) { | |
3110 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | |
3111 | |
3112 static const int kFunctionNameAssignmentIndex = 0; | |
3113 if (function_type == FunctionLiteral::kNamedExpression) { | |
3114 DCHECK(function_name != NULL); | |
3115 // If we have a named function expression, we add a local variable | |
3116 // declaration to the body of the function with the name of the | |
3117 // function and let it refer to the function itself (closure). | |
3118 // Not having parsed the function body, the language mode may still change, | |
3119 // so we reserve a spot and create the actual const assignment later. | |
3120 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); | |
3121 result->Add(NULL, zone()); | |
3122 } | |
3123 | |
3124 ZoneList<Statement*>* body = result; | |
3125 DeclarationScope* function_scope = scope()->AsDeclarationScope(); | |
3126 DeclarationScope* inner_scope = function_scope; | |
3127 Block* inner_block = nullptr; | |
3128 if (!parameters.is_simple) { | |
3129 inner_scope = NewVarblockScope(); | |
3130 inner_scope->set_start_position(scanner()->location().beg_pos); | |
3131 inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); | |
3132 inner_block->set_scope(inner_scope); | |
3133 body = inner_block->statements(); | |
3134 } | |
3135 | |
3136 { | |
3137 BlockState block_state(&scope_state_, inner_scope); | |
3138 | |
3139 if (IsGeneratorFunction(kind)) { | |
3140 // We produce: | |
3141 // | |
3142 // try { InitialYield; ...body...; return {value: undefined, done: true} } | |
3143 // finally { %_GeneratorClose(generator) } | |
3144 // | |
3145 // - InitialYield yields the actual generator object. | |
3146 // - Any return statement inside the body will have its argument wrapped | |
3147 // in a "done" iterator result object. | |
3148 // - If the generator terminates for whatever reason, we must close it. | |
3149 // Hence the finally clause. | |
3150 | |
3151 Block* try_block = | |
3152 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); | |
3153 Expression* initial_yield = BuildInitialYield(pos, kind); | |
3154 try_block->statements()->Add( | |
3155 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), | |
3156 zone()); | |
3157 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); | |
3158 | |
3159 Statement* final_return = factory()->NewReturnStatement( | |
3160 BuildIteratorResult(nullptr, true), kNoSourcePosition); | |
3161 try_block->statements()->Add(final_return, zone()); | |
3162 | |
3163 Block* finally_block = | |
3164 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | |
3165 ZoneList<Expression*>* args = | |
3166 new (zone()) ZoneList<Expression*>(1, zone()); | |
3167 VariableProxy* call_proxy = factory()->NewVariableProxy( | |
3168 function_state_->generator_object_variable()); | |
3169 args->Add(call_proxy, zone()); | |
3170 Expression* call = factory()->NewCallRuntime( | |
3171 Runtime::kInlineGeneratorClose, args, kNoSourcePosition); | |
3172 finally_block->statements()->Add( | |
3173 factory()->NewExpressionStatement(call, kNoSourcePosition), zone()); | |
3174 | |
3175 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, | |
3176 kNoSourcePosition), | |
3177 zone()); | |
3178 } else if (IsAsyncFunction(kind)) { | |
3179 const bool accept_IN = true; | |
3180 ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal, | |
3181 accept_IN, pos, CHECK_OK); | |
3182 } else { | |
3183 ParseStatementList(body, Token::RBRACE, CHECK_OK); | |
3184 } | |
3185 | |
3186 if (IsDerivedConstructor(kind)) { | |
3187 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), | |
3188 kNoSourcePosition), | |
3189 zone()); | |
3190 } | |
3191 } | |
3192 | |
3193 Expect(Token::RBRACE, CHECK_OK); | |
3194 scope()->set_end_position(scanner()->location().end_pos); | |
3195 | |
3196 if (!parameters.is_simple) { | |
3197 DCHECK_NOT_NULL(inner_scope); | |
3198 DCHECK_EQ(function_scope, scope()); | |
3199 DCHECK_EQ(function_scope, inner_scope->outer_scope()); | |
3200 DCHECK_EQ(body, inner_block->statements()); | |
3201 SetLanguageMode(function_scope, inner_scope->language_mode()); | |
3202 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | |
3203 | |
3204 if (is_sloppy(inner_scope->language_mode())) { | |
3205 InsertSloppyBlockFunctionVarBindings(inner_scope); | |
3206 } | |
3207 | |
3208 // TODO(littledan): Merge the two rejection blocks into one | |
3209 if (IsAsyncFunction(kind)) { | |
3210 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); | |
3211 } | |
3212 | |
3213 DCHECK_NOT_NULL(init_block); | |
3214 | |
3215 inner_scope->set_end_position(scanner()->location().end_pos); | |
3216 if (inner_scope->FinalizeBlockScope() != nullptr) { | |
3217 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | |
3218 InsertShadowingVarBindingInitializers(inner_block); | |
3219 } | |
3220 inner_scope = nullptr; | |
3221 | |
3222 result->Add(init_block, zone()); | |
3223 result->Add(inner_block, zone()); | |
3224 } else { | |
3225 DCHECK_EQ(inner_scope, function_scope); | |
3226 if (is_sloppy(function_scope->language_mode())) { | |
3227 InsertSloppyBlockFunctionVarBindings(function_scope); | |
3228 } | |
3229 } | |
3230 | |
3231 if (!IsArrowFunction(kind)) { | |
3232 // Declare arguments after parsing the function since lexical 'arguments' | |
3233 // masks the arguments object. Declare arguments before declaring the | |
3234 // function var since the arguments object masks 'function arguments'. | |
3235 function_scope->DeclareArguments(ast_value_factory()); | |
3236 } | |
3237 | |
3238 if (function_type == FunctionLiteral::kNamedExpression) { | |
3239 Statement* statement; | |
3240 if (function_scope->LookupLocal(function_name) == nullptr) { | |
3241 // Now that we know the language mode, we can create the const assignment | |
3242 // in the previously reserved spot. | |
3243 DCHECK_EQ(function_scope, scope()); | |
3244 Variable* fvar = function_scope->DeclareFunctionVar(function_name); | |
3245 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | |
3246 statement = factory()->NewExpressionStatement( | |
3247 factory()->NewAssignment(Token::INIT, fproxy, | |
3248 factory()->NewThisFunction(pos), | |
3249 kNoSourcePosition), | |
3250 kNoSourcePosition); | |
3251 } else { | |
3252 statement = factory()->NewEmptyStatement(kNoSourcePosition); | |
3253 } | |
3254 result->Set(kFunctionNameAssignmentIndex, statement); | |
3255 } | |
3256 | |
3257 MarkCollectedTailCallExpressions(); | |
3258 return result; | |
3259 } | |
3260 | |
3261 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, | 3170 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, |
3262 ClassInfo* class_info, int class_token_pos, | 3171 ClassInfo* class_info, int class_token_pos, |
3263 bool* ok) { | 3172 bool* ok) { |
3264 #ifdef DEBUG | 3173 #ifdef DEBUG |
3265 scope()->SetScopeName(name); | 3174 scope()->SetScopeName(name); |
3266 #endif | 3175 #endif |
3267 | 3176 |
3268 if (name != nullptr) { | 3177 if (name != nullptr) { |
3269 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); | 3178 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); |
3270 Declaration* declaration = factory()->NewVariableDeclaration( | 3179 Declaration* declaration = factory()->NewVariableDeclaration( |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3873 // BuildRejectPromiseOnException({ | 3782 // BuildRejectPromiseOnException({ |
3874 // ... block ... | 3783 // ... block ... |
3875 // return %ResolvePromise(.promise, expr), .promise; | 3784 // return %ResolvePromise(.promise, expr), .promise; |
3876 // }) | 3785 // }) |
3877 // } | 3786 // } |
3878 | 3787 |
3879 return_value = BuildResolvePromise(return_value, return_value->position()); | 3788 return_value = BuildResolvePromise(return_value, return_value->position()); |
3880 block->statements()->Add( | 3789 block->statements()->Add( |
3881 factory()->NewReturnStatement(return_value, return_value->position()), | 3790 factory()->NewReturnStatement(return_value, return_value->position()), |
3882 zone()); | 3791 zone()); |
3883 block = BuildRejectPromiseOnException(block, CHECK_OK_VOID); | 3792 block = BuildRejectPromiseOnException(block); |
3884 body->Add(block, zone()); | 3793 body->Add(block, zone()); |
3885 } | 3794 } |
3886 | 3795 |
3887 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) { | 3796 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) { |
3888 // yield do { | 3797 // yield do { |
3889 // tmp = <operand>; | 3798 // tmp = <operand>; |
3890 // %AsyncFunctionAwait(.generator_object, tmp, .promise); | 3799 // %AsyncFunctionAwait(.generator_object, tmp, .promise); |
3891 // .promise | 3800 // .promise |
3892 // } | 3801 // } |
3893 // The value of the expression is returned to the caller of the async | 3802 // The value of the expression is returned to the caller of the async |
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5116 | 5025 |
5117 return final_loop; | 5026 return final_loop; |
5118 } | 5027 } |
5119 | 5028 |
5120 #undef CHECK_OK | 5029 #undef CHECK_OK |
5121 #undef CHECK_OK_VOID | 5030 #undef CHECK_OK_VOID |
5122 #undef CHECK_FAILED | 5031 #undef CHECK_FAILED |
5123 | 5032 |
5124 } // namespace internal | 5033 } // namespace internal |
5125 } // namespace v8 | 5034 } // namespace v8 |
OLD | NEW |