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