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