#ifndef SRC_NODE_REALM_H_ #define SRC_NODE_REALM_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include #include #include "cleanup_queue.h" #include "env_properties.h" #include "memory_tracker.h" #include "node_snapshotable.h" namespace node { struct RealmSerializeInfo { std::vector builtins; std::vector persistent_values; std::vector native_objects; SnapshotIndex context; friend std::ostream& operator<<(std::ostream& o, const RealmSerializeInfo& i); }; using BindingDataStore = std::array, static_cast( BindingDataType::kBindingDataTypeCount)>; /** * node::Realm is a container for a set of JavaScript objects and functions * that associated with a particular global environment. * * An ECMAScript realm (https://tc39.es/ecma262/#sec-code-realms) representing * a global environment in which script is run. Each ECMAScript realm comes * with a global object and a set of intrinsic objects. An ECMAScript realm has * a [[HostDefined]] field, which contains the node::Realm object. * * Realm can be a principal realm or a synthetic realm. A principal realm is * created with an Environment as its principal global environment to evaluate * scripts. A synthetic realm is created with JS APIs like ShadowRealm. * * Native bindings and builtin modules can be evaluated in either a principal * realm or a synthetic realm. */ class Realm : public MemoryRetainer { public: enum Kind { kPrincipal, kShadowRealm, }; static inline Realm* GetCurrent(v8::Isolate* isolate); static inline Realm* GetCurrent(v8::Local context); static inline Realm* GetCurrent( const v8::FunctionCallbackInfo& info); template static inline Realm* GetCurrent(const v8::PropertyCallbackInfo& info); Realm(Environment* env, v8::Local context, Kind kind); Realm(const Realm&) = delete; Realm& operator=(const Realm&) = delete; Realm(Realm&&) = delete; Realm& operator=(Realm&&) = delete; void MemoryInfo(MemoryTracker* tracker) const override; void CreateProperties(); RealmSerializeInfo Serialize(v8::SnapshotCreator* creator); void DeserializeProperties(const RealmSerializeInfo* info); v8::MaybeLocal ExecuteBootstrapper(const char* id); v8::MaybeLocal RunBootstrapping(); inline void AddCleanupHook(CleanupQueue::Callback cb, void* arg); inline void RemoveCleanupHook(CleanupQueue::Callback cb, void* arg); inline bool HasCleanupHooks() const; void RunCleanup(); template void ForEachBaseObject(T&& iterator) const; void PrintInfoForSnapshot(); void VerifyNoStrongBaseObjects(); inline IsolateData* isolate_data() const; inline Environment* env() const; inline v8::Isolate* isolate() const; inline Kind kind() const; virtual v8::Local context() const; inline bool has_run_bootstrapping_code() const; // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside // this scope can access the created T* object using // GetBindingData(args) later. template T* AddBindingData(v8::Local context, v8::Local target, Args&&... args); template static inline T* GetBindingData(const v8::PropertyCallbackInfo& info); template static inline T* GetBindingData( const v8::FunctionCallbackInfo& info); template static inline T* GetBindingData(v8::Local context); inline BindingDataStore* binding_data_store(); // The BaseObject count is a debugging helper that makes sure that there are // no memory leaks caused by BaseObjects staying alive longer than expected // (in particular, no circular BaseObjectPtr references). inline void modify_base_object_count(int64_t delta); inline int64_t base_object_count() const; // Base object count created after the bootstrap of the realm. inline int64_t base_object_created_after_bootstrap() const; #define V(PropertyName, TypeName) \ virtual v8::Local PropertyName() const = 0; \ virtual void set_##PropertyName(v8::Local value) = 0; PER_REALM_STRONG_PERSISTENT_VALUES(V) #undef V std::set internal_bindings; std::set builtins_with_cache; std::set builtins_without_cache; // This is only filled during deserialization. We use a vector since // it's only used for tests. std::vector builtins_in_snapshot; protected: ~Realm(); virtual v8::MaybeLocal BootstrapRealm() = 0; Environment* env_; // Shorthand for isolate pointer. v8::Isolate* isolate_; v8::Global context_; #define V(PropertyName, TypeName) v8::Global PropertyName##_; PER_REALM_STRONG_PERSISTENT_VALUES(V) #undef V private: void InitializeContext(v8::Local context, const RealmSerializeInfo* realm_info); void DoneBootstrapping(); Kind kind_; bool has_run_bootstrapping_code_ = false; int64_t base_object_count_ = 0; int64_t base_object_created_by_bootstrap_ = 0; BindingDataStore binding_data_store_; CleanupQueue cleanup_queue_; }; class PrincipalRealm : public Realm { public: PrincipalRealm(Environment* env, v8::Local context, const RealmSerializeInfo* realm_info); ~PrincipalRealm() = default; SET_MEMORY_INFO_NAME(PrincipalRealm) SET_SELF_SIZE(PrincipalRealm) #define V(PropertyName, TypeName) \ v8::Local PropertyName() const override; \ void set_##PropertyName(v8::Local value) override; PER_REALM_STRONG_PERSISTENT_VALUES(V) #undef V protected: v8::MaybeLocal BootstrapRealm() override; }; } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_REALM_H_