1 #ifndef SRC_NODE_BUILTINS_H_ 2 #define SRC_NODE_BUILTINS_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include <list> 7 #include <map> 8 #include <memory> 9 #include <optional> 10 #include <set> 11 #include <string> 12 #include <vector> 13 #include "node_mutex.h" 14 #include "node_threadsafe_cow.h" 15 #include "node_union_bytes.h" 16 #include "v8.h" 17 18 // Forward declare test fixture for `friend` declaration. 19 class PerProcessTest; 20 21 namespace node { 22 class SnapshotBuilder; 23 class ExternalReferenceRegistry; 24 class Realm; 25 26 namespace builtins { 27 28 using BuiltinSourceMap = std::map<std::string, UnionBytes>; 29 using BuiltinCodeCacheMap = 30 std::unordered_map<std::string, 31 std::unique_ptr<v8::ScriptCompiler::CachedData>>; 32 33 struct CodeCacheInfo { 34 std::string id; 35 std::vector<uint8_t> data; 36 }; 37 38 // Handles compilation and caching of built-in JavaScript modules and 39 // bootstrap scripts, whose source are bundled into the binary as static data. 40 class NODE_EXTERN_PRIVATE BuiltinLoader { 41 public: 42 BuiltinLoader(); 43 BuiltinLoader(const BuiltinLoader&) = delete; 44 BuiltinLoader& operator=(const BuiltinLoader&) = delete; 45 46 static void RegisterExternalReferences(ExternalReferenceRegistry* registry); 47 static void CreatePerIsolateProperties( 48 IsolateData* isolate_data, v8::Local<v8::FunctionTemplate> target); 49 static void CreatePerContextProperties(v8::Local<v8::Object> target, 50 v8::Local<v8::Value> unused, 51 v8::Local<v8::Context> context, 52 void* priv); 53 54 // The parameters used to compile the scripts are detected based on 55 // the pattern of the id. 56 v8::MaybeLocal<v8::Function> LookupAndCompile(v8::Local<v8::Context> context, 57 const char* id, 58 Realm* optional_realm); 59 60 v8::MaybeLocal<v8::Value> CompileAndCall(v8::Local<v8::Context> context, 61 const char* id, 62 int argc, 63 v8::Local<v8::Value> argv[], 64 Realm* optional_realm); 65 66 v8::MaybeLocal<v8::Value> CompileAndCall(v8::Local<v8::Context> context, 67 const char* id, 68 Realm* realm); 69 70 v8::Local<v8::Object> GetSourceObject(v8::Local<v8::Context> context); 71 // Returns config.gypi as a JSON string 72 v8::Local<v8::String> GetConfigString(v8::Isolate* isolate); 73 bool Exists(const char* id); 74 bool Add(const char* id, const UnionBytes& source); 75 bool Add(const char* id, std::string_view utf8source); 76 77 bool CompileAllBuiltins(v8::Local<v8::Context> context); 78 void RefreshCodeCache(const std::vector<CodeCacheInfo>& in); 79 void CopyCodeCache(std::vector<CodeCacheInfo>* out) const; 80 81 void CopySourceAndCodeCacheReferenceFrom(const BuiltinLoader* other); 82 83 private: 84 // Only allow access from friends. 85 friend class CodeCacheBuilder; 86 87 // Generated by tools/js2c.py as node_javascript.cc 88 void LoadJavaScriptSource(); // Loads data into source_ 89 UnionBytes GetConfig(); // Return data for config.gypi 90 91 std::vector<std::string> GetBuiltinIds() const; 92 93 struct BuiltinCategories { 94 std::set<std::string> can_be_required; 95 std::set<std::string> cannot_be_required; 96 }; 97 // This method builds `BuiltinCategories` from scratch every time, 98 // and is therefore somewhat expensive, but also currently only being 99 // used for testing, so that should not be an issue. 100 BuiltinCategories GetBuiltinCategories() const; 101 102 const v8::ScriptCompiler::CachedData* GetCodeCache(const char* id) const; 103 enum class Result { kWithCache, kWithoutCache }; 104 v8::MaybeLocal<v8::String> LoadBuiltinSource(v8::Isolate* isolate, 105 const char* id) const; 106 // If an exception is encountered (e.g. source code contains 107 // syntax error), the returned value is empty. 108 v8::MaybeLocal<v8::Function> LookupAndCompileInternal( 109 v8::Local<v8::Context> context, 110 const char* id, 111 std::vector<v8::Local<v8::String>>* parameters, 112 Result* result); 113 114 static void RecordResult(const char* id, 115 BuiltinLoader::Result result, 116 Realm* realm); 117 static void GetBuiltinCategories( 118 v8::Local<v8::Name> property, 119 const v8::PropertyCallbackInfo<v8::Value>& info); 120 static void GetCacheUsage(const v8::FunctionCallbackInfo<v8::Value>& args); 121 // Passing ids of built-in source code into JS land as 122 // internalBinding('builtins').builtinIds 123 static void BuiltinIdsGetter(v8::Local<v8::Name> property, 124 const v8::PropertyCallbackInfo<v8::Value>& info); 125 // Passing config.gypi into JS land as internalBinding('builtins').config 126 static void ConfigStringGetter( 127 v8::Local<v8::Name> property, 128 const v8::PropertyCallbackInfo<v8::Value>& info); 129 // Compile a specific built-in as a function 130 static void CompileFunction(const v8::FunctionCallbackInfo<v8::Value>& args); 131 static void HasCachedBuiltins( 132 const v8::FunctionCallbackInfo<v8::Value>& args); 133 134 void AddExternalizedBuiltin(const char* id, const char* filename); 135 136 ThreadsafeCopyOnWrite<BuiltinSourceMap> source_; 137 138 const UnionBytes config_; 139 140 struct BuiltinCodeCache { 141 RwLock mutex; 142 BuiltinCodeCacheMap map; 143 bool has_code_cache = false; 144 }; 145 std::shared_ptr<BuiltinCodeCache> code_cache_; 146 147 friend class ::PerProcessTest; 148 }; 149 } // namespace builtins 150 151 } // namespace node 152 153 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 154 155 #endif // SRC_NODE_BUILTINS_H_ 156