2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2021 ,  Andreas  Kling  < kling @ serenityos . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-07 15:17:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <AK/Debug.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 10:02:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <AK/TemporaryChange.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-15 12:36:57 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/AST.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Bytecode/BasicBlock.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-17 13:16:35 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Bytecode/Generator.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Bytecode/Instruction.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibJS/Bytecode/Interpreter.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 09:19:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Bytecode/Op.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-01 12:24:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/GlobalEnvironment.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 18:26:13 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/GlobalObject.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-11 20:27:36 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibJS/Runtime/Realm.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  JS : : Bytecode  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-10-24 13:34:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								bool  g_dump_bytecode  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:53:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 15:59:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								Interpreter : : Interpreter ( VM &  vm ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    :  m_vm ( vm ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:53:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Interpreter : : ~ Interpreter ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-02 12:53:10 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Interpreter : : visit_edges ( Cell : : Visitor &  visitor ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( auto &  frame  :  m_call_frames )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        frame . visit ( [ & ] ( auto &  value )  {  value - > visit_edges ( visitor ) ;  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-02 12:53:10 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-15 12:36:57 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								// 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								ThrowCompletionOr < Value >  Interpreter : : run ( Script &  script_record ,  JS : : GCPtr < Environment >  lexical_environment_override ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto &  vm  =  this - > vm ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 1. Let globalEnv be scriptRecord.[[Realm]].[[GlobalEnv]].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto &  global_environment  =  script_record . realm ( ) . global_environment ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 2. Let scriptContext be a new ECMAScript code execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ExecutionContext  script_context ( vm . heap ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 3. Set the Function of scriptContext to null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // NOTE: This was done during execution context construction.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 4. Set the Realm of scriptContext to scriptRecord.[[Realm]].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    script_context . realm  =  & script_record . realm ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 5. Set the ScriptOrModule of scriptContext to scriptRecord.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    script_context . script_or_module  =  NonnullGCPtr < Script > ( script_record ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 6. Set the VariableEnvironment of scriptContext to globalEnv.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    script_context . variable_environment  =  & global_environment ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 7. Set the LexicalEnvironment of scriptContext to globalEnv.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    script_context . lexical_environment  =  & global_environment ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Non-standard: Override the lexical environment if requested.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( lexical_environment_override ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        script_context . lexical_environment  =  lexical_environment_override ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 8. Set the PrivateEnvironment of scriptContext to null.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // NOTE: This isn't in the spec, but we require it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    script_context . is_strict_mode  =  script_record . parse_node ( ) . is_strict_mode ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: 9. Suspend the currently running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 10. Push scriptContext onto the execution context stack; scriptContext is now the running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TRY ( vm . push_execution_context ( script_context ,  { } ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 11. Let script be scriptRecord.[[ECMAScriptCode]].
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto &  script  =  script_record . parse_node ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 12. Let result be Completion(GlobalDeclarationInstantiation(script, globalEnv)).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  instantiation_result  =  script . global_declaration_instantiation ( vm ,  global_environment ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Completion  result  =  instantiation_result . is_throw_completion ( )  ?  instantiation_result . throw_completion ( )  :  normal_completion ( { } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 13. If result.[[Type]] is normal, then
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( result . type ( )  = =  Completion : : Type : : Normal )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  executable_result  =  JS : : Bytecode : : Generator : : generate ( script ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( executable_result . is_error ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( auto  error_string  =  executable_result . error ( ) . to_string ( ) ;  error_string . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  vm . template  throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else  if  ( error_string  =  String : : formatted ( " TODO({}) " , error_string.value()) ;  error_string . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  vm . template  throw_completion < JS : : InternalError > ( vm . error_message ( JS : : VM : : ErrorMessage : : OutOfMemory ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  JS : : throw_completion ( JS : : InternalError : : create ( realm ( ) ,  error_string . release_value ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto  executable  =  executable_result . release_value ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( g_dump_bytecode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                executable - > dump ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // a. Set result to the result of evaluating script.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-21 09:26:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto  result_or_error  =  run_and_return_frame ( * executable ,  nullptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-15 12:36:57 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( result_or_error . value . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  result_or_error . value . release_error ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                result  =  result_or_error . frame - > registers [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 14. If result.[[Type]] is normal and result.[[Value]] is empty, then
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( result . type ( )  = =  Completion : : Type : : Normal  & &  ! result . value ( ) . has_value ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // a. Set result to NormalCompletion(undefined).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        result  =  normal_completion ( js_undefined ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: 15. Suspend scriptContext and remove it from the execution context stack.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm . pop_execution_context ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 16. Assert: The execution context stack is not empty.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    VERIFY ( ! vm . execution_context_stack ( ) . is_empty ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: 17. Resume the context that is now on the top of the execution context stack as the running execution context.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // At this point we may have already run any queued promise jobs via on_call_stack_emptied,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // in which case this is a no-op.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: These three should be moved out of Interpreter::run and give the host an option to run these, as it's up to the host when these get run.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        https://tc39.es/ecma262/#sec-jobs for jobs and https://tc39.es/ecma262/#_ref_3508 for ClearKeptObjects
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        finish_execution_generation is particularly an issue for LibWeb, as the HTML spec wants to run it specifically after performing a microtask checkpoint.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        The promise and registry cleanup queues don't cause LibWeb an issue, as LibWeb overrides the hooks that push onto these queues.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm . run_queued_promise_jobs ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm . run_queued_finalization_registry_cleanup_jobs ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm . finish_execution_generation ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // 18. Return ? result.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( result . is_abrupt ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        VERIFY ( result . type ( )  = =  Completion : : Type : : Throw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  result . release_error ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    VERIFY ( result . value ( ) . has_value ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  * result . value ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								ThrowCompletionOr < Value >  Interpreter : : run ( SourceTextModule &  module ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // FIXME: This is not a entry point as defined in the spec, but is convenient.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        To avoid work we use link_and_eval_module however that can already be
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    //        dangerous if the vm loaded other modules.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto &  vm  =  this - > vm ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    TRY ( vm . link_and_eval_module ( Badge < Bytecode : : Interpreter >  { } ,  module ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm . run_queued_promise_jobs ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm . run_queued_finalization_registry_cleanup_jobs ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  js_undefined ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-21 09:26:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								Interpreter : : ValueAndFrame  Interpreter : : run_and_return_frame ( Executable &  executable ,  BasicBlock  const *  entry_point ,  CallFrame *  in_frame ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 09:11:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    dbgln_if ( JS_BYTECODE_DEBUG ,  " Bytecode::Interpreter will run unit {:p} " ,  & executable ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 10:02:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TemporaryChange  restore_executable  {  m_current_executable ,  & executable  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 16:15:34 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TemporaryChange  restore_saved_jump  {  m_scheduled_jump ,  static_cast < BasicBlock  const * > ( nullptr )  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 10:02:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-01 16:53:55 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    VERIFY ( ! vm ( ) . execution_context_stack ( ) . is_empty ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:11:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-06 17:16:25 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TemporaryChange  restore_current_block  {  m_current_block ,  entry_point  ? :  executable . basic_blocks . first ( )  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-08 19:38:57 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-15 20:20:51 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( in_frame ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        push_call_frame ( in_frame ,  executable . number_of_registers ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-15 20:20:51 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        push_call_frame ( make < CallFrame > ( ) ,  executable . number_of_registers ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-11 00:34:44 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-01 16:53:55 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        auto  pc  =  InstructionStreamIterator  {  m_current_block - > instruction_stream ( ) ,  m_current_executable  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        TemporaryChange  temp_change  {  m_pc ,  Optional < InstructionStreamIterator & > ( pc )  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-30 11:58:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 20:45:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // FIXME: This is getting kinda spaghetti-y
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        bool  will_jump  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bool  will_return  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 20:45:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        bool  will_yield  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        while  ( ! pc . at_end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            auto &  instruction  =  * pc ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-07 14:36:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto  ran_or_error  =  instruction . execute ( * this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ran_or_error . is_error ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                reg ( Register : : exception ( ) )  =  * ran_or_error . throw_completion ( ) . value ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 23:15:44 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( unwind_contexts ( ) . is_empty ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 23:15:44 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                auto &  unwind_context  =  unwind_contexts ( ) . last ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-25 12:30:54 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( unwind_context . executable  ! =  m_current_executable ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-14 15:50:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( unwind_context . handler  & &  ! unwind_context . handler_called )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-13 18:53:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    vm ( ) . running_execution_context ( ) . lexical_environment  =  unwind_context . lexical_environment ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-30 11:58:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    m_current_block  =  unwind_context . handler ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-14 15:50:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    unwind_context . handler_called  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-14 02:20:50 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    accumulator ( )  =  reg ( Register : : exception ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    reg ( Register : : exception ( ) )  =  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    will_jump  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-24 23:52:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( unwind_context . finalizer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-30 11:58:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    m_current_block  =  unwind_context . finalizer ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-14 15:50:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    // If an exception was thrown inside the corresponding `catch` block, we need to rethrow it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    // from the `finally` block. But if the exception is from the `try` block, and has already been
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    // handled by `catch`, we swallow it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( ! unwind_context . handler_called ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        reg ( Register : : exception ( ) )  =  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    will_jump  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-10-24 23:52:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-14 02:20:50 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // An unwind context with no handler or finalizer? We have nowhere to jump, and continuing on will make us crash on the next `Call` to a non-native function if there's an exception! So let's crash here instead.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // If you run into this, you probably forgot to remove the current unwind_context somewhere.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                VERIFY_NOT_REACHED ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( m_pending_jump . has_value ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-30 11:58:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                m_current_block  =  m_pending_jump . release_value ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                will_jump  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 15:32:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! reg ( Register : : return_value ( ) ) . is_empty ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                will_return  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 20:45:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // Note: A `yield` statement will not go through a finally statement,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                //       hence we need to set a flag to not do so,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                //       but we generate a Yield Operation in the case of returns in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                //       generators as well, so we need to check if it will actually
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                //       continue or is a `return` in disguise
 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-15 09:59:19 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                will_yield  =  ( instruction . type ( )  = =  Instruction : : Type : : Yield  & &  static_cast < Op : : Yield  const & > ( instruction ) . continuation ( ) . has_value ( ) )  | |  instruction . type ( )  = =  Instruction : : Type : : Await ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            + + pc ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 12:07:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-13 20:56:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( will_jump ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-06 20:45:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! unwind_contexts ( ) . is_empty ( )  & &  ! will_yield )  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-13 20:56:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto &  unwind_context  =  unwind_contexts ( ) . last ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( unwind_context . executable  = =  m_current_executable  & &  unwind_context . finalizer )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 15:32:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                reg ( Register : : saved_return_value ( ) )  =  reg ( Register : : return_value ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                reg ( Register : : return_value ( ) )  =  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-13 20:56:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                m_current_block  =  unwind_context . finalizer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // the unwind_context will be pop'ed when entering the finally block
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 06:49:58 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-13 20:56:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( pc . at_end ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:53:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 18:19:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! reg ( Register : : exception ( ) ) . is_empty ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 18:19:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-13 20:56:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( will_return ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-04 12:07:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-09 09:11:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    dbgln_if ( JS_BYTECODE_DEBUG ,  " Bytecode::Interpreter did run unit {:p} " ,  & executable ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-07 15:17:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  constexpr  ( JS_BYTECODE_DEBUG )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( size_t  i  =  0 ;  i  <  registers ( ) . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-12 21:54:02 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            String  value_string ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-07 15:17:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( registers ( ) [ i ] . is_empty ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-07 11:12:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                value_string  =  " (empty) " _string ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-07 15:17:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-09 08:49:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                value_string  =  registers ( ) [ i ] . to_string_without_side_effects ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-07 15:17:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            dbgln ( " [{:3}] {} " ,  i ,  value_string ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:53:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 15:32:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  return_value  =  js_undefined ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! reg ( Register : : return_value ( ) ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return_value  =  reg ( Register : : return_value ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else  if  ( ! reg ( Register : : saved_return_value ( ) ) . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return_value  =  reg ( Register : : saved_return_value ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  exception  =  reg ( Register : : exception ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-21 17:30:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  frame  =  pop_call_frame ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:53:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // NOTE: The return value from a called function is put into $0 in the caller context.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! m_call_frames . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        call_frame ( ) . registers [ 0 ]  =  return_value ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-05 15:53:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-11 00:44:56 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    // At this point we may have already run any queued promise jobs via on_call_stack_emptied,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // in which case this is a no-op.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    vm ( ) . run_queued_promise_jobs ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-12 17:32:54 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    vm ( ) . finish_execution_generation ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! exception . is_empty ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( auto *  call_frame  =  frame . get_pointer < NonnullOwnPtr < CallFrame > > ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  {  throw_completion ( exception ) ,  move ( * call_frame )  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  {  throw_completion ( exception ) ,  nullptr  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-07 14:36:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-11 04:11:56 +03:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( auto *  call_frame  =  frame . get_pointer < NonnullOwnPtr < CallFrame > > ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  {  return_value ,  move ( * call_frame )  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-15 20:20:51 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  {  return_value ,  nullptr  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Interpreter : : enter_unwind_context ( Optional < Label >  handler_target ,  Optional < Label >  finalizer_target ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-13 18:53:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    unwind_contexts ( ) . empend ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m_current_executable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        handler_target . has_value ( )  ?  & handler_target - > block ( )  :  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        finalizer_target . has_value ( )  ?  & finalizer_target - > block ( )  :  nullptr , 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-02 15:05:17 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        vm ( ) . running_execution_context ( ) . lexical_environment ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  Interpreter : : leave_unwind_context ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 23:15:44 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    unwind_contexts ( ) . take_last ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-07 14:36:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ThrowCompletionOr < void >  Interpreter : : continue_pending_unwind ( Label  const &  resume_label ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 11:57:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( auto  exception  =  reg ( Register : : exception ( ) ) ;  ! exception . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  throw_completion ( exception ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-07 14:36:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-21 17:30:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! saved_return_value ( ) . is_empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        do_return ( saved_return_value ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-13 20:56:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 16:15:34 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( m_scheduled_jump )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // FIXME: If we `break` or `continue` in the finally, we need to clear
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //        this field
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        jump ( Label  {  * m_scheduled_jump  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m_scheduled_jump  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        jump ( resume_label ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-07 14:36:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-10 15:04:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-13 20:40:20 +04:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 15:59:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ThrowCompletionOr < NonnullOwnPtr < Bytecode : : Executable > >  compile ( VM &  vm ,  ASTNode  const &  node ,  FunctionKind  kind ,  DeprecatedFlyString  const &  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  executable_result  =  Bytecode : : Generator : : generate ( node ,  kind ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( executable_result . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  vm . throw_completion < InternalError > ( ErrorType : : NotImplemented ,  TRY_OR_THROW_OOM ( vm ,  executable_result . error ( ) . to_string ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  bytecode_executable  =  executable_result . release_value ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bytecode_executable - > name  =  name ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-26 20:10:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-06-22 15:59:18 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( Bytecode : : g_dump_bytecode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bytecode_executable - > dump ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  bytecode_executable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								Realm &  Interpreter : : realm ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  * m_vm . current_realm ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  Interpreter : : push_call_frame ( Variant < NonnullOwnPtr < CallFrame > ,  CallFrame * >  frame ,  size_t  register_count ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-01 13:56:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    m_call_frames . append ( move ( frame ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    this - > call_frame ( ) . registers . resize ( register_count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m_current_call_frame  =  this - > call_frame ( ) . registers ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-26 15:32:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    reg ( Register : : return_value ( ) )  =  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-01 13:56:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								Variant < NonnullOwnPtr < CallFrame > ,  CallFrame * >  Interpreter : : pop_call_frame ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-01 13:56:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-20 10:46:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  frame  =  m_call_frames . take_last ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m_current_call_frame  =  m_call_frames . is_empty ( )  ?  Span < Value >  { }  :  this - > call_frame ( ) . registers ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  frame ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-01 13:56:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-03 10:46:30 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								}