@@ -102,9 +102,18 @@ ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
102102 return nullptr ;
103103}
104104
105- // new ModuleWrap(url, context, source, lineOffset, columnOffset, cachedData)
105+
106+ Local<PrimitiveArray> ModuleWrap::GetHostDefinedOptions (
107+ Isolate* isolate, Local<Symbol> id_symbol) {
108+ Local<PrimitiveArray> host_defined_options =
109+ PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
110+ host_defined_options->Set (isolate, HostDefinedOptions::kID , id_symbol);
111+ return host_defined_options;
112+ }
113+
114+ // new ModuleWrap(url, context, source, lineOffset, columnOffset[, cachedData]);
106115// new ModuleWrap(url, context, source, lineOffset, columOffset,
107- // hostDefinedOption)
116+ // idSymbol);
108117// new ModuleWrap(url, context, exportNames, evaluationCallback[, cjsModule])
109118void ModuleWrap::New (const FunctionCallbackInfo<Value>& args) {
110119 CHECK (args.IsConstructCall ());
@@ -134,7 +143,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
134143 int column_offset = 0 ;
135144
136145 bool synthetic = args[2 ]->IsArray ();
137-
146+ bool can_use_builtin_cache = false ;
138147 Local<PrimitiveArray> host_defined_options =
139148 PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
140149 Local<Symbol> id_symbol;
@@ -143,20 +152,24 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
143152 // cjsModule])
144153 CHECK (args[3 ]->IsFunction ());
145154 } else {
146- // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
155+ // new ModuleWrap(url, context, source, lineOffset, columOffset[,
156+ // cachedData]);
147157 // new ModuleWrap(url, context, source, lineOffset, columOffset,
148- // hostDefinedOption)
158+ // idSymbol);
149159 CHECK (args[2 ]->IsString ());
150160 CHECK (args[3 ]->IsNumber ());
151161 line_offset = args[3 ].As <Int32>()->Value ();
152162 CHECK (args[4 ]->IsNumber ());
153163 column_offset = args[4 ].As <Int32>()->Value ();
154164 if (args[5 ]->IsSymbol ()) {
155165 id_symbol = args[5 ].As <Symbol>();
166+ can_use_builtin_cache =
167+ (id_symbol ==
168+ realm->isolate_data ()->source_text_module_default_hdo ());
156169 } else {
157170 id_symbol = Symbol::New (isolate, url);
158171 }
159- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
172+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
160173
161174 if (that->SetPrivate (context,
162175 realm->isolate_data ()->host_defined_option_symbol (),
@@ -189,36 +202,34 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
189202 module = Module::CreateSyntheticModule (isolate, url, export_names,
190203 SyntheticModuleEvaluationStepsCallback);
191204 } else {
192- ScriptCompiler::CachedData* cached_data = nullptr ;
205+ // When we are compiling for the default loader, this will be
206+ // std::nullopt, and CompileSourceTextModule() should use
207+ // on-disk cache (not present on v20.x).
208+ std::optional<v8::ScriptCompiler::CachedData*> user_cached_data;
209+ if (id_symbol !=
210+ realm->isolate_data ()->source_text_module_default_hdo ()) {
211+ user_cached_data = nullptr ;
212+ }
193213 if (args[5 ]->IsArrayBufferView ()) {
214+ CHECK (!can_use_builtin_cache); // We don't use this option internally.
194215 Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
195216 uint8_t * data =
196217 static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
197- cached_data =
218+ user_cached_data =
198219 new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
199220 cached_data_buf->ByteLength ());
200221 }
201-
202222 Local<String> source_text = args[2 ].As <String>();
203- ScriptOrigin origin (isolate,
204- url,
205- line_offset,
206- column_offset,
207- true , // is cross origin
208- -1 , // script id
209- Local<Value>(), // source map URL
210- false , // is opaque (?)
211- false , // is WASM
212- true , // is ES Module
213- host_defined_options);
214- ScriptCompiler::Source source (source_text, origin, cached_data);
215- ScriptCompiler::CompileOptions options;
216- if (source.GetCachedData () == nullptr ) {
217- options = ScriptCompiler::kNoCompileOptions ;
218- } else {
219- options = ScriptCompiler::kConsumeCodeCache ;
220- }
221- if (!ScriptCompiler::CompileModule (isolate, &source, options)
223+
224+ bool cache_rejected = false ;
225+ if (!CompileSourceTextModule (realm,
226+ source_text,
227+ url,
228+ line_offset,
229+ column_offset,
230+ host_defined_options,
231+ user_cached_data,
232+ &cache_rejected)
222233 .ToLocal (&module )) {
223234 if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
224235 CHECK (!try_catch.Message ().IsEmpty ());
@@ -231,8 +242,9 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
231242 }
232243 return ;
233244 }
234- if (options == ScriptCompiler::kConsumeCodeCache &&
235- source.GetCachedData ()->rejected ) {
245+
246+ if (user_cached_data.has_value () && user_cached_data.value () != nullptr &&
247+ cache_rejected) {
236248 THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
237249 realm, " cachedData buffer was rejected" );
238250 try_catch.ReThrow ();
@@ -275,6 +287,57 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
275287 args.GetReturnValue ().Set (that);
276288}
277289
290+ MaybeLocal<Module> ModuleWrap::CompileSourceTextModule (
291+ Realm* realm,
292+ Local<String> source_text,
293+ Local<String> url,
294+ int line_offset,
295+ int column_offset,
296+ Local<PrimitiveArray> host_defined_options,
297+ std::optional<ScriptCompiler::CachedData*> user_cached_data,
298+ bool * cache_rejected) {
299+ Isolate* isolate = realm->isolate ();
300+ EscapableHandleScope scope (isolate);
301+ ScriptOrigin origin (isolate,
302+ url,
303+ line_offset,
304+ column_offset,
305+ true , // is cross origin
306+ -1 , // script id
307+ Local<Value>(), // source map URL
308+ false , // is opaque (?)
309+ false , // is WASM
310+ true , // is ES Module
311+ host_defined_options);
312+ ScriptCompiler::CachedData* cached_data = nullptr ;
313+ // When compiling for the default loader, user_cached_data is std::nullptr.
314+ // When compiling for vm.Module, it's either nullptr or a pointer to the
315+ // cached data.
316+ if (user_cached_data.has_value ()) {
317+ cached_data = user_cached_data.value ();
318+ }
319+
320+ ScriptCompiler::Source source (source_text, origin, cached_data);
321+ ScriptCompiler::CompileOptions options;
322+ if (cached_data == nullptr ) {
323+ options = ScriptCompiler::kNoCompileOptions ;
324+ } else {
325+ options = ScriptCompiler::kConsumeCodeCache ;
326+ }
327+
328+ Local<Module> module ;
329+ if (!ScriptCompiler::CompileModule (isolate, &source, options)
330+ .ToLocal (&module )) {
331+ return scope.EscapeMaybe (MaybeLocal<Module>());
332+ }
333+
334+ if (options == ScriptCompiler::kConsumeCodeCache ) {
335+ *cache_rejected = source.GetCachedData ()->rejected ;
336+ }
337+
338+ return scope.Escape (module );
339+ }
340+
278341static Local<Object> createImportAttributesContainer (
279342 Realm* realm,
280343 Isolate* isolate,
0 commit comments