2020-03-07 21:42:11 +03:00
/*
* Copyright ( c ) 2020 , Andreas Kling < kling @ serenityos . org >
2022-01-16 15:16:04 +03:00
* Copyright ( c ) 2022 , Luke Wilde < lukew @ serenityos . org >
2020-03-07 21:42:11 +03:00
*
2021-04-22 11:24:48 +03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-03-07 21:42:11 +03:00
*/
# pragma once
2020-03-25 00:03:50 +03:00
# include <AK/FlyString.h>
2020-03-09 23:13:55 +03:00
# include <AK/HashMap.h>
2020-03-12 21:53:31 +03:00
# include <AK/String.h>
2020-05-23 19:53:09 +03:00
# include <AK/Weakable.h>
2020-05-28 08:22:08 +03:00
# include <LibJS/AST.h>
2020-03-07 21:42:11 +03:00
# include <LibJS/Forward.h>
2020-09-20 20:24:44 +03:00
# include <LibJS/Heap/DeferGC.h>
2020-03-16 16:20:30 +03:00
# include <LibJS/Heap/Heap.h>
2022-01-08 23:28:27 +03:00
# include <LibJS/Runtime/Completion.h>
2021-07-01 13:24:46 +03:00
# include <LibJS/Runtime/DeclarativeEnvironment.h>
2020-06-10 08:48:01 +03:00
# include <LibJS/Runtime/ErrorTypes.h>
2022-01-16 15:16:04 +03:00
# include <LibJS/Runtime/GlobalEnvironment.h>
2021-09-11 21:36:25 +03:00
# include <LibJS/Runtime/GlobalObject.h>
2020-04-19 18:24:56 +03:00
# include <LibJS/Runtime/MarkedValueList.h>
2021-09-11 21:36:25 +03:00
# include <LibJS/Runtime/Realm.h>
2020-09-20 20:24:44 +03:00
# include <LibJS/Runtime/VM.h>
2020-03-16 16:20:30 +03:00
# include <LibJS/Runtime/Value.h>
2022-01-16 15:16:04 +03:00
# include <LibJS/Script.h>
# include <LibJS/SourceTextModule.h>
2020-03-07 21:42:11 +03:00
namespace JS {
2021-03-21 19:38:42 +03:00
struct ExecutingASTNodeChain {
ExecutingASTNodeChain * previous { nullptr } ;
const ASTNode & node ;
} ;
2020-05-23 19:53:09 +03:00
class Interpreter : public Weakable < Interpreter > {
2020-03-07 21:42:11 +03:00
public :
2022-01-16 15:16:04 +03:00
// 9.6 InitializeHostDefinedRealm ( ), https://tc39.es/ecma262/#sec-initializehostdefinedrealm
template < typename GlobalObjectType , typename GlobalThisObjectType , typename . . . Args >
static NonnullOwnPtr < Interpreter > create ( VM & vm , Args & & . . . args ) requires ( IsBaseOf < GlobalObject , GlobalObjectType > & & IsBaseOf < Object , GlobalThisObjectType > )
2020-04-01 19:53:28 +03:00
{
2020-09-20 20:24:44 +03:00
DeferGC defer_gc ( vm . heap ( ) ) ;
auto interpreter = adopt_own ( * new Interpreter ( vm ) ) ;
2020-09-21 14:36:32 +03:00
VM : : InterpreterExecutionScope scope ( * interpreter ) ;
2022-01-16 15:16:04 +03:00
// 1. Let realm be CreateRealm().
2021-09-11 21:36:25 +03:00
auto * realm = Realm : : create ( vm ) ;
2022-01-16 15:16:04 +03:00
// 2. Let newContext be a new execution context. (This was done in the Interpreter constructor)
// 3. Set the Function of newContext to null. (This is done for us when the execution context is constructed)
// 4. Set the Realm of newContext to realm.
interpreter - > m_global_execution_context . realm = realm ;
// 5. Set the ScriptOrModule of newContext to null. (This was done during execution context construction)
// 7. If the host requires use of an exotic object to serve as realm's global object, let global be such an object created in a host-defined manner.
// Otherwise, let global be undefined, indicating that an ordinary object should be created as the global object.
auto * global_object = static_cast < GlobalObject * > ( interpreter - > heap ( ) . allocate_without_global_object < GlobalObjectType > ( forward < Args > ( args ) . . . ) ) ;
// 6. Push newContext onto the execution context stack; newContext is now the running execution context.
// NOTE: This is out of order from the spec, but it shouldn't matter here.
vm . push_execution_context ( interpreter - > m_global_execution_context , * global_object ) ;
// 8. If the host requires that the this binding in realm's global scope return an object other than the global object, let thisValue be such an object created
// in a host-defined manner. Otherwise, let thisValue be undefined, indicating that realm's global this binding should be the global object.
if constexpr ( IsSame < GlobalObjectType , GlobalThisObjectType > ) {
// 9. Perform SetRealmGlobalObject(realm, global, thisValue).
realm - > set_global_object ( * global_object , global_object ) ;
} else {
// FIXME: Should we pass args in here? Let's er on the side of caution and say yes.
auto * global_this_value = static_cast < Object * > ( interpreter - > heap ( ) . allocate_without_global_object < GlobalThisObjectType > ( forward < Args > ( args ) . . . ) ) ;
// 9. Perform SetRealmGlobalObject(realm, global, thisValue).
realm - > set_global_object ( * global_object , global_this_value ) ;
}
// NOTE: These are not in the spec.
static FlyString global_execution_context_name = " (global execution context) " ;
interpreter - > m_global_execution_context . function_name = global_execution_context_name ;
2021-09-11 21:36:25 +03:00
interpreter - > m_global_object = make_handle ( global_object ) ;
interpreter - > m_realm = make_handle ( realm ) ;
2022-01-16 15:16:04 +03:00
// 10. Let globalObj be ? SetDefaultGlobalBindings(realm).
// 11. Create any host-defined global object properties on globalObj.
2021-09-11 21:36:25 +03:00
static_cast < GlobalObjectType * > ( global_object ) - > initialize_global_object ( ) ;
2022-01-16 15:16:04 +03:00
// 12. Return NormalCompletion(empty).
2020-04-01 22:04:51 +03:00
return interpreter ;
2020-04-01 19:53:28 +03:00
}
2022-01-16 15:16:04 +03:00
template < typename GlobalObjectType , typename . . . Args >
static NonnullOwnPtr < Interpreter > create ( VM & vm , Args & & . . . args ) requires IsBaseOf < GlobalObject , GlobalObjectType >
{
// NOTE: This function is here to facilitate step 8 of InitializeHostDefinedRealm. (Callers don't have to specify the same type twice if not necessary)
return create < GlobalObjectType , GlobalObjectType > ( vm , args . . . ) ;
}
2021-09-12 14:33:54 +03:00
static NonnullOwnPtr < Interpreter > create_with_existing_realm ( Realm & ) ;
2020-09-27 18:24:14 +03:00
2020-04-01 22:04:51 +03:00
~ Interpreter ( ) ;
2022-01-16 15:16:04 +03:00
ThrowCompletionOr < Value > run ( Script & ) ;
ThrowCompletionOr < Value > run ( SourceTextModule & ) ;
2020-09-12 00:47:43 +03:00
2020-04-08 12:05:38 +03:00
GlobalObject & global_object ( ) ;
const GlobalObject & global_object ( ) const ;
2020-03-07 21:42:11 +03:00
2021-09-11 21:36:25 +03:00
Realm & realm ( ) ;
Realm const & realm ( ) const ;
2021-03-21 19:39:43 +03:00
ALWAYS_INLINE VM & vm ( ) { return * m_vm ; }
ALWAYS_INLINE const VM & vm ( ) const { return * m_vm ; }
ALWAYS_INLINE Heap & heap ( ) { return vm ( ) . heap ( ) ; }
2020-03-08 21:23:58 +03:00
2021-07-01 13:24:46 +03:00
Environment * lexical_environment ( ) { return vm ( ) . lexical_environment ( ) ; }
2021-06-22 00:47:44 +03:00
2021-03-21 19:38:42 +03:00
void push_ast_node ( ExecutingASTNodeChain & chain_node )
{
chain_node . previous = m_ast_node_chain ;
m_ast_node_chain = & chain_node ;
}
2020-12-28 20:15:22 +03:00
2021-03-21 19:38:42 +03:00
void pop_ast_node ( )
{
VERIFY ( m_ast_node_chain ) ;
m_ast_node_chain = m_ast_node_chain - > previous ;
}
2021-03-21 14:18:56 +03:00
2021-03-21 19:38:42 +03:00
const ASTNode * current_node ( ) const { return m_ast_node_chain ? & m_ast_node_chain - > node : nullptr ; }
2020-09-27 17:56:58 +03:00
2020-03-14 14:56:49 +03:00
private :
2020-09-20 20:24:44 +03:00
explicit Interpreter ( VM & ) ;
2020-04-01 22:04:51 +03:00
2021-03-21 19:38:42 +03:00
ExecutingASTNodeChain * m_ast_node_chain { nullptr } ;
2020-10-04 03:02:43 +03:00
2020-09-20 20:24:44 +03:00
NonnullRefPtr < VM > m_vm ;
2020-03-08 21:23:58 +03:00
2021-09-11 21:36:25 +03:00
Handle < GlobalObject > m_global_object ;
Handle < Realm > m_realm ;
2022-01-16 15:16:04 +03:00
// This is here to keep the global execution context alive for the entire lifespan of the Interpreter.
ExecutionContext m_global_execution_context ;
2020-03-07 21:42:11 +03:00
} ;
}