/src/serenity/Userland/Libraries/LibJS/Runtime/Realm.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org> |
3 | | * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <AK/TypeCasts.h> |
9 | | #include <LibJS/Heap/DeferGC.h> |
10 | | #include <LibJS/Runtime/GlobalEnvironment.h> |
11 | | #include <LibJS/Runtime/GlobalObject.h> |
12 | | #include <LibJS/Runtime/Realm.h> |
13 | | #include <LibJS/Runtime/VM.h> |
14 | | |
15 | | namespace JS { |
16 | | |
17 | | JS_DEFINE_ALLOCATOR(Realm); |
18 | | |
19 | | // 9.3.1 InitializeHostDefinedRealm ( ), https://tc39.es/ecma262/#sec-initializehostdefinedrealm |
20 | | ThrowCompletionOr<NonnullOwnPtr<ExecutionContext>> Realm::initialize_host_defined_realm(VM& vm, Function<Object*(Realm&)> create_global_object, Function<Object*(Realm&)> create_global_this_value) |
21 | 0 | { |
22 | 0 | DeferGC defer_gc(vm.heap()); |
23 | | |
24 | | // 1. Let realm be a new Realm Record |
25 | 0 | auto realm = vm.heap().allocate_without_realm<Realm>(); |
26 | | |
27 | | // 2. Perform CreateIntrinsics(realm). |
28 | 0 | MUST(Intrinsics::create(*realm)); |
29 | | |
30 | | // FIXME: 3. Set realm.[[AgentSignifier]] to AgentSignifier(). |
31 | | |
32 | | // NOTE: Done on step 1. |
33 | | // 4. Set realm.[[GlobalObject]] to undefined. |
34 | | // 5. Set realm.[[GlobalEnv]] to undefined. |
35 | | |
36 | | // FIXME: 6. Set realm.[[TemplateMap]] to a new empty List. |
37 | | |
38 | | // 7. Let newContext be a new execution context. |
39 | 0 | auto new_context = ExecutionContext::create(); |
40 | | |
41 | | // 8. Set the Function of newContext to null. |
42 | 0 | new_context->function = nullptr; |
43 | | |
44 | | // 9. Set the Realm of newContext to realm. |
45 | 0 | new_context->realm = realm; |
46 | | |
47 | | // 10. Set the ScriptOrModule of newContext to null. |
48 | 0 | new_context->script_or_module = {}; |
49 | | |
50 | | // 11. Push newContext onto the execution context stack; newContext is now the running execution context. |
51 | 0 | vm.push_execution_context(*new_context); |
52 | | |
53 | | // 12. If the host requires use of an exotic object to serve as realm's global object, then |
54 | 0 | Object* global = nullptr; |
55 | 0 | if (create_global_object) { |
56 | | // a. Let global be such an object created in a host-defined manner. |
57 | 0 | global = create_global_object(*realm); |
58 | 0 | } |
59 | | // 13. Else, |
60 | 0 | else { |
61 | | // a. Let global be OrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]]). |
62 | | // NOTE: We allocate a proper GlobalObject directly as this plain object is |
63 | | // turned into one via SetDefaultGlobalBindings in the spec. |
64 | 0 | global = vm.heap().allocate_without_realm<GlobalObject>(realm); |
65 | 0 | } |
66 | | |
67 | | // 14. If the host requires that the this binding in realm's global scope return an object other than the global object, then |
68 | 0 | Object* this_value = nullptr; |
69 | 0 | if (create_global_this_value) { |
70 | | // a. Let thisValue be such an object created in a host-defined manner. |
71 | 0 | this_value = create_global_this_value(*realm); |
72 | 0 | } |
73 | | // 15. Else, |
74 | 0 | else { |
75 | | // a. Let thisValue be global. |
76 | 0 | this_value = global; |
77 | 0 | } |
78 | | |
79 | | // 16. Set realm.[[GlobalObject]] to global. |
80 | 0 | realm->m_global_object = global; |
81 | | |
82 | | // 17. Set realm.[[GlobalEnv]] to NewGlobalEnvironment(global, thisValue). |
83 | 0 | realm->m_global_environment = vm.heap().allocate_without_realm<GlobalEnvironment>(*global, *this_value); |
84 | | |
85 | | // 18. Perform ? SetDefaultGlobalBindings(realm). |
86 | 0 | set_default_global_bindings(*realm); |
87 | | |
88 | | // 19. Create any host-defined global object properties on global. |
89 | 0 | global->initialize(*realm); |
90 | | |
91 | | // 20. Return unused. |
92 | 0 | return new_context; |
93 | 0 | } |
94 | | |
95 | | void Realm::visit_edges(Visitor& visitor) |
96 | 0 | { |
97 | 0 | Base::visit_edges(visitor); |
98 | 0 | visitor.visit(m_intrinsics); |
99 | 0 | visitor.visit(m_global_object); |
100 | 0 | visitor.visit(m_global_environment); |
101 | 0 | if (m_host_defined) |
102 | 0 | m_host_defined->visit_edges(visitor); |
103 | 0 | } |
104 | | |
105 | | } |