xref: /third_party/node/src/node_realm.h (revision 1cb0ef41)
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
13namespace node {
14
15struct 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
24using 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 */
44class 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