2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2021 ,  Idan  Horowitz  < idan . horowitz @ serenityos . org > 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-02 20:54:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2021 - 2022 ,  Linus  Groh  < linusg @ serenityos . org > 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <AK/TypeCasts.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/Completion.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/NativeFunction.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-02 10:59:22 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/Promise.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/PromiseCapability.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/PromiseConstructor.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/VM.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/Value.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  JS  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-14 00:48:15 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								Completion : : Completion ( ThrowCompletionOr < Value >  const &  throw_completion_or_value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( throw_completion_or_value . is_throw_completion ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m_type  =  Type : : Throw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m_value  =  throw_completion_or_value . throw_completion ( ) . value ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m_type  =  Type : : Normal ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m_value  =  throw_completion_or_value . value ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								// 6.2.3.1 Await, https://tc39.es/ecma262/#await
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-21 20:38:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ThrowCompletionOr < Value >  await ( VM &  vm ,  Value  value ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-21 20:38:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto &  realm  =  * vm . current_realm ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. Let asyncContext be the running execution context.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // NOTE: This is not needed, as we don't suspend anything.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. Let promise be ? PromiseResolve(%Promise%, value).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-27 00:54:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto *  promise_object  =  TRY ( promise_resolve ( vm ,  * realm . intrinsics ( ) . promise_constructor ( ) ,  value ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    Optional < bool >  success ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    Value  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 3. Let fulfilledClosure be a new Abstract Closure with parameters (value) that captures asyncContext and performs the following steps when called:
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-22 11:48:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  fulfilled_closure  =  [ & success ,  & result ] ( VM &  vm )  - >  ThrowCompletionOr < Value >  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        // a. Let prevContext be the running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // b. Suspend prevContext.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: We don't have this concept yet.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // NOTE: Since we don't support context suspension, we exfiltrate the result to await()'s scope instead
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        success  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        result  =  vm . argument ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // NOTE: This is not done, because we're not suspending anything (see above).
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // d. Resume the suspended evaluation of asyncContext using NormalCompletion(value) as the result of the operation that suspended it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // e. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: We don't have this concept yet.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // f. Return undefined.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  js_undefined ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-02 20:54:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 4. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-16 00:20:49 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto *  on_fulfilled  =  NativeFunction : : create ( realm ,  move ( fulfilled_closure ) ,  1 ,  " " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 5. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures asyncContext and performs the following steps when called:
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-22 11:48:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  rejected_closure  =  [ & success ,  & result ] ( VM &  vm )  - >  ThrowCompletionOr < Value >  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        // a. Let prevContext be the running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // b. Suspend prevContext.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: We don't have this concept yet.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // NOTE: Since we don't support context suspension, we exfiltrate the result to await()'s scope instead
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        success  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        result  =  vm . argument ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // c. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // NOTE: This is not done, because we're not suspending anything (see above).
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // d. Resume the suspended evaluation of asyncContext using ThrowCompletion(reason) as the result of the operation that suspended it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // e. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: We don't have this concept yet.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // f. Return undefined.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  js_undefined ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-02 20:54:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 6. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-16 00:20:49 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto *  on_rejected  =  NativeFunction : : create ( realm ,  move ( rejected_closure ) ,  1 ,  " " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-02 20:54:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 7. Perform PerformPromiseThen(promise, onFulfilled, onRejected).
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto *  promise  =  verify_cast < Promise > ( promise_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    promise - > perform_then ( on_fulfilled ,  on_rejected ,  { } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: Since we don't support context suspension, we attempt to "wait" for the promise to resolve
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        by letting the event loop spin until our promise is no longer pending, and then synchronously
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        running all queued promise jobs.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Note: This is not used by LibJS itself, and is performed for the embedder (i.e. LibWeb).
 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-08 00:13:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( auto *  custom_data  =  vm . custom_data ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        custom_data - > spin_event_loop_until ( [ & ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  success . has_value ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 8. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // NOTE: Since we don't push any EC, this step is not performed.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-02 20:54:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // 9. Set the code evaluation state of asyncContext such that when evaluation is resumed with a Completion Record completion, the following steps of the algorithm that invoked Await will be performed, with completion available.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 10. Return NormalCompletion(unused).
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    // 11. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of asyncContext.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    vm . run_queued_promise_jobs ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // Make sure that the promise _actually_ resolved.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Note that this is checked down the chain (result.is_empty()) anyway, but let's make the source of the issue more clear.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    VERIFY ( success . has_value ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( success . value ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        return  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 02:41:18 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  throw_completion ( result ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 15:22:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 6.2.3.3 ThrowCompletion ( value ), https://tc39.es/ecma262/#sec-throwcompletion
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Completion  throw_completion ( Value  value ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  {  Completion : : Type : : Throw ,  value ,  { }  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-09 22:52:21 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								}