See More

#ifndef SRC_MODULE_WRAP_H_ #define SRC_MODULE_WRAP_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include #include #include #include #include "base_object.h" #include "v8-script.h" namespace node { class IsolateData; class Environment; class ExternalReferenceRegistry; namespace contextify { class ContextifyContext; } namespace loader { enum ScriptType : int { kScript, kModule, kFunction, }; enum HostDefinedOptions : int { kID = 8, kLength = 9, }; enum ModulePhase : int { kSourcePhase = 1, kEvaluationPhase = 2, }; /** * ModuleCacheKey is used to uniquely identify a module request * in the module cache. It is a composition of the module specifier * and the import attributes. ModuleImportPhase is not included * in the key. */ struct ModuleCacheKey : public MemoryRetainer { using ImportAttributeVector = std::vector<:pair std::string>>; std::string specifier; ImportAttributeVector import_attributes; // A hash of the specifier, and import attributes. // This does not guarantee uniqueness, but is used to reduce // the number of comparisons needed when checking for equality. std::size_t hash; SET_MEMORY_INFO_NAME(ModuleCacheKey) SET_SELF_SIZE(ModuleCacheKey) void MemoryInfo(MemoryTracker* tracker) const override; // Returns a string representation of the ModuleCacheKey. std::string ToString() const; template static ModuleCacheKey From(v8::Local<:string> specifier, v8::Local<:fixedarray> import_attributes); static ModuleCacheKey From(v8::Local<:modulerequest> v8_request); struct Hash { std::size_t operator()(const ModuleCacheKey& request) const { return request.hash; } }; // Equality operator for ModuleCacheKey. bool operator==(const ModuleCacheKey& other) const { // Hash does not provide uniqueness guarantee, so ignore it. return specifier == other.specifier && import_attributes == other.import_attributes; } private: // Use public ModuleCacheKey::From to create instances. ModuleCacheKey(std::string specifier, ImportAttributeVector import_attributes, std::size_t hash) : specifier(specifier), import_attributes(import_attributes), hash(hash) {} }; class ModuleWrap : public BaseObject { public: enum InternalFields { kModuleSlot = BaseObject::kInternalFieldCount, kModuleSourceObjectSlot, kSyntheticEvaluationStepsSlot, kContextObjectSlot, // Object whose creation context is the target Context kLinkedRequestsSlot, // Array of linked requests, each is a ModuleWrap JS // wrapper object. kInternalFieldCount }; static void CreatePerIsolateProperties(IsolateData* isolate_data, v8::Local<:objecttemplate> target); static void CreatePerContextProperties(v8::Local<:object> target, v8::Local<:value> unused, v8::Local<:context> context, void* priv); static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static void HostInitializeImportMetaObjectCallback( v8::Local<:context> context, v8::Local<:module> module, v8::Local<:object> meta); v8::Local<:context> context() const; v8::Maybe CheckUnsettledTopLevelAwait(); bool HasAsyncGraph(); SET_MEMORY_INFO_NAME(ModuleWrap) SET_SELF_SIZE(ModuleWrap) SET_NO_MEMORY_INFO() bool IsNotIndicativeOfMemoryLeakAtExit() const override { // XXX: The garbage collection rules for ModuleWrap are *super* unclear. // Do these objects ever get GC'd? Are we just okay with leaking them? return true; } bool IsLinked() const { return linked_; } static v8::Local<:primitivearray> GetHostDefinedOptions( v8::Isolate* isolate, v8::Local<:symbol> symbol); // When user_cached_data is not std::nullopt, use the code cache if it's not // nullptr, otherwise don't use code cache. // TODO(joyeecheung): when it is std::nullopt, use on-disk cache // See: https://github.com/nodejs/node/issues/47472 static v8::MaybeLocal<:module> CompileSourceTextModule( Realm* realm, v8::Local<:string> source_text, v8::Local<:string> url, int line_offset, int column_offset, v8::Local<:primitivearray> host_defined_options, std::optional<:scriptcompiler::cacheddata> user_cached_data, bool* cache_rejected); static void CreateRequiredModuleFacade( const v8::FunctionCallbackInfo<:value>& args); private: ModuleWrap(Realm* realm, v8::Local<:object> object, v8::Local<:module> module, v8::Local<:string> url, v8::Local<:object> context_object, v8::Local<:value> synthetic_evaluation_step); ~ModuleWrap() override; static void New(const v8::FunctionCallbackInfo<:value>& args); static void GetModuleRequests( const v8::FunctionCallbackInfo<:value>& args); static void SetModuleSourceObject( const v8::FunctionCallbackInfo<:value>& args); static void GetModuleSourceObject( const v8::FunctionCallbackInfo<:value>& args); static void Link(const v8::FunctionCallbackInfo<:value>& args); static void Instantiate(const v8::FunctionCallbackInfo<:value>& args); static void Evaluate(const v8::FunctionCallbackInfo<:value>& args); static void EvaluateSync(const v8::FunctionCallbackInfo<:value>& args); static void GetNamespace(const v8::FunctionCallbackInfo<:value>& args); static void GetStatus(const v8::FunctionCallbackInfo<:value>& args); static void GetError(const v8::FunctionCallbackInfo<:value>& args); static void HasAsyncGraph(v8::Local<:name> property, const v8::PropertyCallbackInfo<:value>& args); static void SetImportModuleDynamicallyCallback( const v8::FunctionCallbackInfo<:value>& args); static void SetImportMetaResolveInitializer( const v8::FunctionCallbackInfo<:value>& args); static void SetInitializeImportMetaObjectCallback( const v8::FunctionCallbackInfo<:value>& args); static v8::MaybeLocal<:value> SyntheticModuleEvaluationStepsCallback( v8::Local<:context> context, v8::Local<:module> module); static void SetSyntheticExport( const v8::FunctionCallbackInfo<:value>& args); static void CreateCachedData(const v8::FunctionCallbackInfo<:value>& args); static v8::MaybeLocal<:module> ResolveModuleCallback( v8::Local<:context> context, size_t module_request_index, v8::Local<:module> referrer); static v8::MaybeLocal<:object> ResolveSourceCallback( v8::Local<:context> context, size_t module_request_index, v8::Local<:module> referrer); static ModuleWrap* GetFromModule(node::Environment*, v8::Local<:module>); // This method may throw a JavaScript exception, so the return type is // wrapped in a Maybe. static v8::Maybe ResolveModule(v8::Local<:context> context, size_t module_request_index, v8::Local<:module> referrer); std::string url_; v8::Global<:module> module_; contextify::ContextifyContext* contextify_context_ = nullptr; bool synthetic_ = false; bool linked_ = false; // This depends on the module to be instantiated so it begins with a // nullopt value. std::optional has_async_graph_ = std::nullopt; int module_hash_; // Corresponds to the ModuleWrap* of the wrappers in kLinkedRequestsSlot. // These are populated during Link(), and are only valid after that as // convenient shortcuts, but do not hold the ModuleWraps alive. The actual // strong references come from the array in kLinkedRequestsSlot. std::vector linked_module_wraps_; }; } // namespace loader } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_MODULE_WRAP_H_