• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef SRC_NODE_REALM_H_
2 #define SRC_NODE_REALM_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 #include <v8.h>
7 #include <unordered_map>
8 #include "cleanup_queue.h"
9 #include "env_properties.h"
10 #include "memory_tracker.h"
11 #include "node_snapshotable.h"
12 
13 namespace node {
14 
15 struct RealmSerializeInfo {
16   std::vector<PropInfo> persistent_values;
17   std::vector<PropInfo> native_objects;
18 
19   SnapshotIndex context;
20   friend std::ostream& operator<<(std::ostream& o, const RealmSerializeInfo& i);
21 };
22 
23 using BindingDataStore = std::unordered_map<FastStringKey,
24                                             BaseObjectPtr<BaseObject>,
25                                             FastStringKey::Hash>;
26 
27 /**
28  * node::Realm is a container for a set of JavaScript objects and functions
29  * that associated with a particular global environment.
30  *
31  * An ECMAScript realm (https://tc39.es/ecma262/#sec-code-realms) representing
32  * a global environment in which script is run. Each ECMAScript realm comes
33  * with a global object and a set of intrinsic objects. An ECMAScript realm has
34  * a [[HostDefined]] field, which contains the node::Realm object.
35  *
36  * Realm can be a principal realm or a synthetic realm. A principal realm is
37  * created with an Environment as its principal global environment to evaluate
38  * scripts. A synthetic realm is created with JS APIs like ShadowRealm.
39  *
40  * Native bindings and builtin modules can be evaluated in either a principal
41  * realm or a synthetic realm.
42  */
43 class Realm : public MemoryRetainer {
44  public:
45   static inline Realm* GetCurrent(v8::Isolate* isolate);
46   static inline Realm* GetCurrent(v8::Local<v8::Context> context);
47   static inline Realm* GetCurrent(
48       const v8::FunctionCallbackInfo<v8::Value>& info);
49   template <typename T>
50   static inline Realm* GetCurrent(const v8::PropertyCallbackInfo<T>& info);
51 
52   Realm(Environment* env,
53         v8::Local<v8::Context> context,
54         const RealmSerializeInfo* realm_info);
55   ~Realm();
56 
57   Realm(const Realm&) = delete;
58   Realm& operator=(const Realm&) = delete;
59   Realm(Realm&&) = delete;
60   Realm& operator=(Realm&&) = delete;
61 
62   SET_MEMORY_INFO_NAME(Realm)
63   SET_SELF_SIZE(Realm)
64   void MemoryInfo(MemoryTracker* tracker) const override;
65 
66   void CreateProperties();
67   RealmSerializeInfo Serialize(v8::SnapshotCreator* creator);
68   void DeserializeProperties(const RealmSerializeInfo* info);
69 
70   v8::MaybeLocal<v8::Value> ExecuteBootstrapper(
71       const char* id, std::vector<v8::Local<v8::Value>>* arguments);
72   v8::MaybeLocal<v8::Value> BootstrapInternalLoaders();
73   v8::MaybeLocal<v8::Value> BootstrapNode();
74   v8::MaybeLocal<v8::Value> RunBootstrapping();
75 
76   inline void AddCleanupHook(CleanupQueue::Callback cb, void* arg);
77   inline void RemoveCleanupHook(CleanupQueue::Callback cb, void* arg);
78   inline bool HasCleanupHooks() const;
79   void RunCleanup();
80 
81   template <typename T>
82   void ForEachBaseObject(T&& iterator) const;
83 
84   void PrintInfoForSnapshot();
85   void VerifyNoStrongBaseObjects();
86 
87   inline IsolateData* isolate_data() const;
88   inline Environment* env() const;
89   inline v8::Isolate* isolate() const;
90   inline v8::Local<v8::Context> context() const;
91   inline bool has_run_bootstrapping_code() const;
92 
93   // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside
94   // this scope can access the created T* object using
95   // GetBindingData<T>(args) later.
96   template <typename T>
97   T* AddBindingData(v8::Local<v8::Context> context,
98                     v8::Local<v8::Object> target);
99   template <typename T, typename U>
100   static inline T* GetBindingData(const v8::PropertyCallbackInfo<U>& info);
101   template <typename T>
102   static inline T* GetBindingData(
103       const v8::FunctionCallbackInfo<v8::Value>& info);
104   template <typename T>
105   static inline T* GetBindingData(v8::Local<v8::Context> context);
106   inline BindingDataStore* binding_data_store();
107 
108   // The BaseObject count is a debugging helper that makes sure that there are
109   // no memory leaks caused by BaseObjects staying alive longer than expected
110   // (in particular, no circular BaseObjectPtr references).
111   inline void modify_base_object_count(int64_t delta);
112   inline int64_t base_object_count() const;
113 
114   // Base object count created after the bootstrap of the realm.
115   inline int64_t base_object_created_after_bootstrap() const;
116 
117 #define V(PropertyName, TypeName)                                              \
118   inline v8::Local<TypeName> PropertyName() const;                             \
119   inline void set_##PropertyName(v8::Local<TypeName> value);
120   PER_REALM_STRONG_PERSISTENT_VALUES(V)
121 #undef V
122 
123  private:
124   void InitializeContext(v8::Local<v8::Context> context,
125                          const RealmSerializeInfo* realm_info);
126   void DoneBootstrapping();
127 
128   Environment* env_;
129   // Shorthand for isolate pointer.
130   v8::Isolate* isolate_;
131   v8::Global<v8::Context> context_;
132   bool has_run_bootstrapping_code_ = false;
133 
134   int64_t base_object_count_ = 0;
135   int64_t base_object_created_by_bootstrap_ = 0;
136 
137   BindingDataStore binding_data_store_;
138 
139   CleanupQueue cleanup_queue_;
140 
141 #define V(PropertyName, TypeName) v8::Global<TypeName> PropertyName##_;
142   PER_REALM_STRONG_PERSISTENT_VALUES(V)
143 #undef V
144 };
145 
146 }  // namespace node
147 
148 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
149 
150 #endif  // SRC_NODE_REALM_H_
151