@@ -1701,10 +1701,17 @@ Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
1701
1701
return_value = factory ()->NewConditional (is_undefined, ThisExpression (pos),
1702
1702
is_object_conditional, pos);
1703
1703
}
1704
+
1704
1705
if (is_generator ()) {
1705
1706
return_value = BuildIteratorResult (return_value, true );
1706
1707
} else if (is_async_function ()) {
1707
- return_value = BuildResolvePromise (return_value, return_value->position ());
1708
+ // In an async function,
1709
+ // return expr;
1710
+ // is rewritten as
1711
+ // return .async_return_value = expr;
1712
+ return_value = factory ()->NewAssignment (
1713
+ Token::ASSIGN, factory ()->NewVariableProxy (AsyncReturnVariable ()),
1714
+ return_value, kNoSourcePosition );
1708
1715
}
1709
1716
return return_value;
1710
1717
}
@@ -2991,72 +2998,168 @@ Block* Parser::BuildParameterInitializationBlock(
2991
2998
return init_block;
2992
2999
}
2993
3000
3001
+ Block* Parser::BuildRejectPromiseOnExceptionForParameters (Block* inner_block) {
3002
+ // .promise = %AsyncFunctionPromiseCreate();
3003
+ // try {
3004
+ // <inner_block>
3005
+ // } catch (.catch) {
3006
+ // return %RejectPromise(.promise, .catch), .promise;
3007
+ // }
3008
+ Block* result = factory ()->NewBlock (nullptr , 2 , true , kNoSourcePosition );
3009
+ {
3010
+ // .promise = %AsyncFunctionPromiseCreate();
3011
+ Expression* create_promise = factory ()->NewCallRuntime (
3012
+ Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX,
3013
+ new (zone ()) ZoneList<Expression*>(0 , zone ()), kNoSourcePosition );
3014
+ Assignment* assign_promise = factory ()->NewAssignment (
3015
+ Token::INIT, factory ()->NewVariableProxy (PromiseVariable ()),
3016
+ create_promise, kNoSourcePosition );
3017
+ Statement* set_promise =
3018
+ factory ()->NewExpressionStatement (assign_promise, kNoSourcePosition );
3019
+ result->statements ()->Add (set_promise, zone ());
3020
+ }
3021
+ // catch (.catch) {
3022
+ // return %RejectPromise(.promise, .catch), .promise;
3023
+ // }
3024
+ Scope* catch_scope = NewScope (CATCH_SCOPE);
3025
+ catch_scope->set_is_hidden ();
3026
+ Variable* catch_variable =
3027
+ catch_scope->DeclareLocal (ast_value_factory ()->dot_catch_string (), VAR,
3028
+ kCreatedInitialized , NORMAL_VARIABLE);
3029
+ Block* catch_block = factory ()->NewBlock (nullptr , 1 , true , kNoSourcePosition );
3030
+ {
3031
+ // return %RejectPromise(.promise, .catch), .promise;
3032
+ Expression* reject_return_promise = factory ()->NewBinaryOperation (
3033
+ Token::COMMA, BuildRejectPromise (catch_variable),
3034
+ factory ()->NewVariableProxy (PromiseVariable (), kNoSourcePosition ),
3035
+ kNoSourcePosition );
3036
+ catch_block->statements ()->Add (
3037
+ factory ()->NewReturnStatement (reject_return_promise, kNoSourcePosition ),
3038
+ zone ());
3039
+ }
3040
+ TryStatement* try_catch_statement =
3041
+ factory ()->NewTryCatchStatementForAsyncAwait (inner_block, catch_scope,
3042
+ catch_variable, catch_block,
3043
+ kNoSourcePosition );
3044
+ result->statements ()->Add (try_catch_statement, zone ());
3045
+ return result;
3046
+ }
3047
+
2994
3048
Block* Parser::BuildRejectPromiseOnException (Block* inner_block, bool * ok) {
3049
+ // .is_rejection = false;
2995
3050
// .promise = %AsyncFunctionPromiseCreate();
2996
3051
// try {
2997
3052
// <inner_block>
2998
3053
// } catch (.catch) {
2999
- // %RejectPromise(.promise, .catch) ;
3000
- // return .promise ;
3054
+ // .is_rejection = true ;
3055
+ // .async_return_value = .catch ;
3001
3056
// } finally {
3057
+ // .is_rejection
3058
+ // ? %RejectPromise(.promise, .async_return_value)
3059
+ // : %ResolvePromise(.promise, .async_return_value);
3002
3060
// %AsyncFunctionPromiseRelease(.promise);
3061
+ // return .promise;
3003
3062
// }
3004
- Block* result = factory ()->NewBlock (nullptr , 2 , true , kNoSourcePosition );
3063
+ Block* result = factory ()->NewBlock (nullptr , 3 , true , kNoSourcePosition );
3005
3064
3006
- // .promise = %AsyncFunctionPromiseCreate();
3007
- Statement* set_promise ;
3065
+ Variable* is_rejection_var =
3066
+ scope ()-> NewTemporary ( ast_value_factory ()-> empty_string ()) ;
3008
3067
{
3068
+ // .is_rejection = false;
3069
+ Assignment* set_is_rejection = factory ()->NewAssignment (
3070
+ Token::INIT, factory ()->NewVariableProxy (is_rejection_var),
3071
+ factory ()->NewBooleanLiteral (false , kNoSourcePosition ),
3072
+ kNoSourcePosition );
3073
+ result->statements ()->Add (
3074
+ factory ()->NewExpressionStatement (set_is_rejection, kNoSourcePosition ),
3075
+ zone ());
3076
+ // .promise = %AsyncFunctionPromiseCreate();
3009
3077
Expression* create_promise = factory ()->NewCallRuntime (
3010
3078
Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX,
3011
3079
new (zone ()) ZoneList<Expression*>(0 , zone ()), kNoSourcePosition );
3012
3080
Assignment* assign_promise = factory ()->NewAssignment (
3013
3081
Token::INIT, factory ()->NewVariableProxy (PromiseVariable ()),
3014
3082
create_promise, kNoSourcePosition );
3015
- set_promise =
3083
+ Statement* set_promise =
3016
3084
factory ()->NewExpressionStatement (assign_promise, kNoSourcePosition );
3085
+ result->statements ()->Add (set_promise, zone ());
3017
3086
}
3018
- result->statements ()->Add (set_promise, zone ());
3019
3087
3020
- // catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
3088
+ // catch (.catch) {
3089
+ // .is_rejection = true;
3090
+ // .async_return_value = .catch;
3091
+ // }
3021
3092
Scope* catch_scope = NewScope (CATCH_SCOPE);
3022
3093
catch_scope->set_is_hidden ();
3023
3094
Variable* catch_variable =
3024
3095
catch_scope->DeclareLocal (ast_value_factory ()->dot_catch_string (), VAR,
3025
3096
kCreatedInitialized , NORMAL_VARIABLE);
3026
3097
Block* catch_block = factory ()->NewBlock (nullptr , 1 , true , kNoSourcePosition );
3027
-
3028
- Expression* promise_reject = BuildRejectPromise (
3029
- factory ()->NewVariableProxy (catch_variable), kNoSourcePosition );
3030
- ReturnStatement* return_promise_reject =
3031
- factory ()->NewReturnStatement (promise_reject, kNoSourcePosition );
3032
- catch_block->statements ()->Add (return_promise_reject, zone ());
3098
+ {
3099
+ // .is_rejection = true;
3100
+ DCHECK_NOT_NULL (is_rejection_var);
3101
+ Assignment* set_is_rejection = factory ()->NewAssignment (
3102
+ Token::ASSIGN, factory ()->NewVariableProxy (is_rejection_var),
3103
+ factory ()->NewBooleanLiteral (true , kNoSourcePosition ),
3104
+ kNoSourcePosition );
3105
+ catch_block->statements ()->Add (
3106
+ factory ()->NewExpressionStatement (set_is_rejection, kNoSourcePosition ),
3107
+ zone ());
3108
+ // .async_return_value = .catch;
3109
+ Assignment* set_async_return_var = factory ()->NewAssignment (
3110
+ Token::ASSIGN, factory ()->NewVariableProxy (AsyncReturnVariable ()),
3111
+ factory ()->NewVariableProxy (catch_variable), kNoSourcePosition );
3112
+ catch_block->statements ()->Add (factory ()->NewExpressionStatement (
3113
+ set_async_return_var, kNoSourcePosition ),
3114
+ zone ());
3115
+ }
3033
3116
3034
3117
TryStatement* try_catch_statement =
3035
3118
factory ()->NewTryCatchStatementForAsyncAwait (inner_block, catch_scope,
3036
3119
catch_variable, catch_block,
3037
3120
kNoSourcePosition );
3038
-
3039
- // There is no TryCatchFinally node, so wrap it in an outer try/finally
3040
3121
Block* outer_try_block =
3041
3122
factory ()->NewBlock (nullptr , 1 , true , kNoSourcePosition );
3042
3123
outer_try_block->statements ()->Add (try_catch_statement, zone ());
3043
3124
3044
- // finally { %AsyncFunctionPromiseRelease(.promise) }
3125
+ // finally {
3126
+ // .is_rejection
3127
+ // ? %RejectPromise(.promise, .async_return_value)
3128
+ // : %ResolvePromise(.promise, .async_return_value);
3129
+ // %AsyncFunctionPromiseRelease(.promise);
3130
+ // return .promise;
3131
+ // }
3045
3132
Block* finally_block =
3046
3133
factory ()->NewBlock (nullptr , 1 , true , kNoSourcePosition );
3047
3134
{
3135
+ // .is_rejection
3136
+ // ? %RejectPromise(.promise, .async_return_value)
3137
+ // : %ResolvePromise(.promise, .async_return_value);
3138
+ Expression* resolve_or_reject_promise =
3139
+ factory ()->NewConditional (factory ()->NewVariableProxy (is_rejection_var),
3140
+ BuildRejectPromise (AsyncReturnVariable ()),
3141
+ BuildResolvePromise (), kNoSourcePosition );
3142
+ finally_block->statements ()->Add (
3143
+ factory ()->NewExpressionStatement (resolve_or_reject_promise,
3144
+ kNoSourcePosition ),
3145
+ zone ());
3146
+ // %AsyncFunctionPromiseRelease(.promise);
3048
3147
ZoneList<Expression*>* args = new (zone ()) ZoneList<Expression*>(1 , zone ());
3049
3148
args->Add (factory ()->NewVariableProxy (PromiseVariable ()), zone ());
3050
3149
Expression* call_promise_release = factory ()->NewCallRuntime (
3051
3150
Context::ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, args, kNoSourcePosition );
3052
3151
Statement* promise_release = factory ()->NewExpressionStatement (
3053
3152
call_promise_release, kNoSourcePosition );
3054
3153
finally_block->statements ()->Add (promise_release, zone ());
3154
+
3155
+ // return .promise;
3156
+ Statement* return_promise = factory ()->NewReturnStatement (
3157
+ factory ()->NewVariableProxy (PromiseVariable ()), kNoSourcePosition );
3158
+ finally_block->statements ()->Add (return_promise, zone ());
3055
3159
}
3056
3160
3057
3161
Statement* try_finally_statement = factory ()->NewTryFinallyStatement (
3058
3162
outer_try_block, finally_block, kNoSourcePosition );
3059
-
3060
3163
result->statements ()->Add (try_finally_statement, zone ());
3061
3164
return result;
3062
3165
}
@@ -3072,31 +3175,25 @@ Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
3072
3175
pos);
3073
3176
}
3074
3177
3075
- Expression* Parser::BuildResolvePromise (Expression* value, int pos ) {
3076
- // %ResolvePromise(.promise, value ), .promise
3178
+ Expression* Parser::BuildResolvePromise () {
3179
+ // %ResolvePromise(.promise, .async_return_variable ), .promise
3077
3180
ZoneList<Expression*>* args = new (zone ()) ZoneList<Expression*>(2 , zone ());
3078
3181
args->Add (factory ()->NewVariableProxy (PromiseVariable ()), zone ());
3079
- args->Add (value, zone ());
3080
- Expression* call_runtime =
3081
- factory ()->NewCallRuntime (Context::PROMISE_RESOLVE_INDEX, args, pos);
3082
- return factory ()->NewBinaryOperation (
3083
- Token::COMMA, call_runtime,
3084
- factory ()->NewVariableProxy (PromiseVariable ()), pos);
3182
+ args->Add (factory ()->NewVariableProxy (AsyncReturnVariable ()), zone ());
3183
+ return factory ()->NewCallRuntime (Context::PROMISE_RESOLVE_INDEX, args,
3184
+ kNoSourcePosition );
3085
3185
}
3086
3186
3087
- Expression* Parser::BuildRejectPromise (Expression * value, int pos ) {
3088
- // %RejectPromiseNoDebugEvent(.promise, value, true), .promise
3187
+ Expression* Parser::BuildRejectPromise (Variable * value) {
3188
+ // %RejectPromiseNoDebugEvent(.promise, . value, true)
3089
3189
// The NoDebugEvent variant disables the additional debug event for the
3090
3190
// rejection since a debug event already happened for the exception that got
3091
3191
// us here.
3092
3192
ZoneList<Expression*>* args = new (zone ()) ZoneList<Expression*>(2 , zone ());
3093
3193
args->Add (factory ()->NewVariableProxy (PromiseVariable ()), zone ());
3094
- args->Add (value, zone ());
3095
- Expression* call_runtime = factory ()->NewCallRuntime (
3096
- Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, pos);
3097
- return factory ()->NewBinaryOperation (
3098
- Token::COMMA, call_runtime,
3099
- factory ()->NewVariableProxy (PromiseVariable ()), pos);
3194
+ args->Add (factory ()->NewVariableProxy (value), zone ());
3195
+ return factory ()->NewCallRuntime (
3196
+ Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, kNoSourcePosition );
3100
3197
}
3101
3198
3102
3199
Variable* Parser::PromiseVariable () {
@@ -3111,6 +3208,19 @@ Variable* Parser::PromiseVariable() {
3111
3208
return promise;
3112
3209
}
3113
3210
3211
+ Variable* Parser::AsyncReturnVariable () {
3212
+ // Based on the various compilation paths, there are many different
3213
+ // code paths which may be the first to access the return value
3214
+ // temporary. Whichever comes first should create it and stash it in
3215
+ // the FunctionState.
3216
+ Variable* async_return = function_state_->async_return_variable ();
3217
+ if (async_return == nullptr ) {
3218
+ async_return = scope ()->NewTemporary (ast_value_factory ()->empty_string ());
3219
+ function_state_->set_async_return_variable (async_return);
3220
+ }
3221
+ return async_return;
3222
+ }
3223
+
3114
3224
Expression* Parser::BuildInitialYield (int pos, FunctionKind kind) {
3115
3225
Expression* allocation = BuildCreateJSGeneratorObject (pos, kind);
3116
3226
VariableProxy* init_proxy =
@@ -3235,7 +3345,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3235
3345
3236
3346
// TODO(littledan): Merge the two rejection blocks into one
3237
3347
if (IsAsyncFunction (kind)) {
3238
- init_block = BuildRejectPromiseOnException (init_block, CHECK_OK );
3348
+ init_block = BuildRejectPromiseOnExceptionForParameters (init_block);
3239
3349
}
3240
3350
3241
3351
DCHECK_NOT_NULL (init_block);
@@ -4176,14 +4286,16 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
4176
4286
// .generator_object = %CreateGeneratorObject();
4177
4287
// BuildRejectPromiseOnException({
4178
4288
// ... block ...
4179
- // return %ResolvePromise(.promise, expr), .promise ;
4289
+ // .async_return_var = expr ;
4180
4290
// })
4181
4291
// }
4182
4292
4183
- return_value = BuildResolvePromise (return_value, return_value->position ());
4184
- block->statements ()->Add (
4185
- factory ()->NewReturnStatement (return_value, return_value->position ()),
4186
- zone ());
4293
+ Assignment* set_async_return_var = factory ()->NewAssignment (
4294
+ Token::ASSIGN, factory ()->NewVariableProxy (AsyncReturnVariable ()),
4295
+ return_value, kNoSourcePosition );
4296
+ block->statements ()->Add (factory ()->NewExpressionStatement (
4297
+ set_async_return_var, kNoSourcePosition ),
4298
+ zone ());
4187
4299
block = BuildRejectPromiseOnException (block, CHECK_OK_VOID);
4188
4300
body->Add (block, zone ());
4189
4301
}
0 commit comments