1 #ifndef SRC_NODE_REALM_INL_H_
2 #define SRC_NODE_REALM_INL_H_
3
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6 #include "cleanup_queue-inl.h"
7 #include "node_realm.h"
8
9 namespace node {
10
GetCurrent(v8::Isolate * isolate)11 inline Realm* Realm::GetCurrent(v8::Isolate* isolate) {
12 if (UNLIKELY(!isolate->InContext())) return nullptr;
13 v8::HandleScope handle_scope(isolate);
14 return GetCurrent(isolate->GetCurrentContext());
15 }
16
GetCurrent(v8::Local<v8::Context> context)17 inline Realm* Realm::GetCurrent(v8::Local<v8::Context> context) {
18 if (UNLIKELY(!ContextEmbedderTag::IsNodeContext(context))) return nullptr;
19 return static_cast<Realm*>(
20 context->GetAlignedPointerFromEmbedderData(ContextEmbedderIndex::kRealm));
21 }
22
GetCurrent(const v8::FunctionCallbackInfo<v8::Value> & info)23 inline Realm* Realm::GetCurrent(
24 const v8::FunctionCallbackInfo<v8::Value>& info) {
25 return GetCurrent(info.GetIsolate()->GetCurrentContext());
26 }
27
28 template <typename T>
GetCurrent(const v8::PropertyCallbackInfo<T> & info)29 inline Realm* Realm::GetCurrent(const v8::PropertyCallbackInfo<T>& info) {
30 return GetCurrent(info.GetIsolate()->GetCurrentContext());
31 }
32
isolate_data()33 inline IsolateData* Realm::isolate_data() const {
34 return env_->isolate_data();
35 }
36
env()37 inline Environment* Realm::env() const {
38 return env_;
39 }
40
isolate()41 inline v8::Isolate* Realm::isolate() const {
42 return isolate_;
43 }
44
has_run_bootstrapping_code()45 inline bool Realm::has_run_bootstrapping_code() const {
46 return has_run_bootstrapping_code_;
47 }
48
49 // static
50 template <typename T, typename U>
GetBindingData(const v8::PropertyCallbackInfo<U> & info)51 inline T* Realm::GetBindingData(const v8::PropertyCallbackInfo<U>& info) {
52 return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
53 }
54
55 // static
56 template <typename T>
GetBindingData(const v8::FunctionCallbackInfo<v8::Value> & info)57 inline T* Realm::GetBindingData(
58 const v8::FunctionCallbackInfo<v8::Value>& info) {
59 return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
60 }
61
62 // static
63 template <typename T>
GetBindingData(v8::Local<v8::Context> context)64 inline T* Realm::GetBindingData(v8::Local<v8::Context> context) {
65 BindingDataStore* map =
66 static_cast<BindingDataStore*>(context->GetAlignedPointerFromEmbedderData(
67 ContextEmbedderIndex::kBindingDataStoreIndex));
68 DCHECK_NOT_NULL(map);
69 constexpr size_t binding_index = static_cast<size_t>(T::binding_type_int);
70 static_assert(binding_index < std::tuple_size_v<BindingDataStore>);
71 auto ptr = (*map)[binding_index];
72 if (UNLIKELY(!ptr)) return nullptr;
73 T* result = static_cast<T*>(ptr.get());
74 DCHECK_NOT_NULL(result);
75 DCHECK_EQ(result->realm(), GetCurrent(context));
76 return result;
77 }
78
79 template <typename T>
AddBindingData(v8::Local<v8::Context> context,v8::Local<v8::Object> target)80 inline T* Realm::AddBindingData(v8::Local<v8::Context> context,
81 v8::Local<v8::Object> target) {
82 DCHECK_EQ(GetCurrent(context), this);
83 // This won't compile if T is not a BaseObject subclass.
84 BaseObjectPtr<T> item = MakeDetachedBaseObject<T>(this, target);
85 BindingDataStore* map =
86 static_cast<BindingDataStore*>(context->GetAlignedPointerFromEmbedderData(
87 ContextEmbedderIndex::kBindingDataStoreIndex));
88 DCHECK_NOT_NULL(map);
89 constexpr size_t binding_index = static_cast<size_t>(T::binding_type_int);
90 static_assert(binding_index < std::tuple_size_v<BindingDataStore>);
91 CHECK(!(*map)[binding_index]); // Should not insert the binding twice.
92 (*map)[binding_index] = item;
93 DCHECK_EQ(GetBindingData<T>(context), item.get());
94 return item.get();
95 }
96
binding_data_store()97 inline BindingDataStore* Realm::binding_data_store() {
98 return &binding_data_store_;
99 }
100
101 template <typename T>
ForEachBaseObject(T && iterator)102 void Realm::ForEachBaseObject(T&& iterator) const {
103 cleanup_queue_.ForEachBaseObject(std::forward<T>(iterator));
104 }
105
modify_base_object_count(int64_t delta)106 void Realm::modify_base_object_count(int64_t delta) {
107 base_object_count_ += delta;
108 }
109
base_object_created_after_bootstrap()110 int64_t Realm::base_object_created_after_bootstrap() const {
111 return base_object_count_ - base_object_created_by_bootstrap_;
112 }
113
base_object_count()114 int64_t Realm::base_object_count() const {
115 return base_object_count_;
116 }
117
118 #define V(PropertyName, TypeName) \
119 inline v8::Local<TypeName> Realm::PropertyName() const { \
120 return PersistentToLocal::Strong(PropertyName##_); \
121 } \
122 inline void Realm::set_##PropertyName(v8::Local<TypeName> value) { \
123 PropertyName##_.Reset(isolate(), value); \
124 }
PER_REALM_STRONG_PERSISTENT_VALUES(V)125 PER_REALM_STRONG_PERSISTENT_VALUES(V)
126 #undef V
127
128 v8::Local<v8::Context> Realm::context() const {
129 return PersistentToLocal::Strong(context_);
130 }
131
AddCleanupHook(CleanupQueue::Callback fn,void * arg)132 void Realm::AddCleanupHook(CleanupQueue::Callback fn, void* arg) {
133 cleanup_queue_.Add(fn, arg);
134 }
135
RemoveCleanupHook(CleanupQueue::Callback fn,void * arg)136 void Realm::RemoveCleanupHook(CleanupQueue::Callback fn, void* arg) {
137 cleanup_queue_.Remove(fn, arg);
138 }
139
HasCleanupHooks()140 bool Realm::HasCleanupHooks() const {
141 return !cleanup_queue_.empty();
142 }
143
144 } // namespace node
145
146 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
147
148 #endif // SRC_NODE_REALM_INL_H_
149