@@ -102,9 +102,17 @@ ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
102102 return nullptr ;
103103}
104104
105- // new ModuleWrap(url, context, source, lineOffset, columnOffset, cachedData)
105+ Local<PrimitiveArray> ModuleWrap::GetHostDefinedOptions (
106+ Isolate* isolate, Local<Symbol> id_symbol) {
107+ Local<PrimitiveArray> host_defined_options =
108+ PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
109+ host_defined_options->Set (isolate, HostDefinedOptions::kID , id_symbol);
110+ return host_defined_options;
111+ }
112+
113+ // new ModuleWrap(url, context, source, lineOffset, columnOffset[, cachedData]);
106114// new ModuleWrap(url, context, source, lineOffset, columOffset,
107- // hostDefinedOption)
115+ // idSymbol);
108116// new ModuleWrap(url, context, exportNames, evaluationCallback[, cjsModule])
109117void ModuleWrap::New (const FunctionCallbackInfo<Value>& args) {
110118 CHECK (args.IsConstructCall ());
@@ -143,9 +151,10 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
143151 // cjsModule])
144152 CHECK (args[3 ]->IsFunction ());
145153 } else {
146- // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
154+ // new ModuleWrap(url, context, source, lineOffset, columOffset[,
155+ // cachedData]);
147156 // new ModuleWrap(url, context, source, lineOffset, columOffset,
148- // hostDefinedOption)
157+ // idSymbol);
149158 CHECK (args[2 ]->IsString ());
150159 CHECK (args[3 ]->IsNumber ());
151160 line_offset = args[3 ].As <Int32>()->Value ();
@@ -159,7 +168,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
159168 } else {
160169 id_symbol = Symbol::New (isolate, url);
161170 }
162- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
171+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
163172
164173 if (that->SetPrivate (context,
165174 realm->isolate_data ()->host_defined_option_symbol (),
@@ -192,50 +201,34 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
192201 module = Module::CreateSyntheticModule (isolate, url, export_names,
193202 SyntheticModuleEvaluationStepsCallback);
194203 } else {
195- ScriptCompiler::CachedData* cached_data = nullptr ;
196- bool used_cache_from_user = false ;
204+ // When we are compiling for the default loader, this will be
205+ // std::nullopt, and CompileSourceTextModule() should use
206+ // on-disk cache.
207+ std::optional<v8::ScriptCompiler::CachedData*> user_cached_data;
208+ if (id_symbol !=
209+ realm->isolate_data ()->source_text_module_default_hdo ()) {
210+ user_cached_data = nullptr ;
211+ }
197212 if (args[5 ]->IsArrayBufferView ()) {
198- DCHECK (!can_use_builtin_cache); // We don't use this option internally.
199- used_cache_from_user = true ;
213+ CHECK (!can_use_builtin_cache); // We don't use this option internally.
200214 Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
201215 uint8_t * data =
202216 static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
203- cached_data =
217+ user_cached_data =
204218 new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
205219 cached_data_buf->ByteLength ());
206220 }
207-
208221 Local<String> source_text = args[2 ].As <String>();
209- ScriptOrigin origin (isolate,
210- url,
211- line_offset,
212- column_offset,
213- true , // is cross origin
214- -1 , // script id
215- Local<Value>(), // source map URL
216- false , // is opaque (?)
217- false , // is WASM
218- true , // is ES Module
219- host_defined_options);
220-
221- CompileCacheEntry* cache_entry = nullptr ;
222- if (can_use_builtin_cache && realm->env ()->use_compile_cache ()) {
223- cache_entry = realm->env ()->compile_cache_handler ()->GetOrInsert (
224- source_text, url, CachedCodeType::kESM );
225- }
226- if (cache_entry != nullptr && cache_entry->cache != nullptr ) {
227- // source will take ownership of cached_data.
228- cached_data = cache_entry->CopyCache ();
229- }
230222
231- ScriptCompiler::Source source (source_text, origin, cached_data);
232- ScriptCompiler::CompileOptions options;
233- if (source.GetCachedData () == nullptr ) {
234- options = ScriptCompiler::kNoCompileOptions ;
235- } else {
236- options = ScriptCompiler::kConsumeCodeCache ;
237- }
238- if (!ScriptCompiler::CompileModule (isolate, &source, options)
223+ bool cache_rejected = false ;
224+ if (!CompileSourceTextModule (realm,
225+ source_text,
226+ url,
227+ line_offset,
228+ column_offset,
229+ host_defined_options,
230+ user_cached_data,
231+ &cache_rejected)
239232 .ToLocal (&module )) {
240233 if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
241234 CHECK (!try_catch.Message ().IsEmpty ());
@@ -249,18 +242,8 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
249242 return ;
250243 }
251244
252- bool cache_rejected = false ;
253- if (options == ScriptCompiler::kConsumeCodeCache ) {
254- cache_rejected = source.GetCachedData ()->rejected ;
255- }
256-
257- if (cache_entry != nullptr ) {
258- realm->env ()->compile_cache_handler ()->MaybeSave (
259- cache_entry, module , cache_rejected);
260- }
261-
262- // If the cache comes from builtin compile cache, fail silently.
263- if (cache_rejected && used_cache_from_user) {
245+ if (user_cached_data.has_value () && user_cached_data.value () != nullptr &&
246+ cache_rejected) {
264247 THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
265248 realm, " cachedData buffer was rejected" );
266249 try_catch.ReThrow ();
@@ -303,6 +286,71 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
303286 args.GetReturnValue ().Set (that);
304287}
305288
289+ MaybeLocal<Module> ModuleWrap::CompileSourceTextModule (
290+ Realm* realm,
291+ Local<String> source_text,
292+ Local<String> url,
293+ int line_offset,
294+ int column_offset,
295+ Local<PrimitiveArray> host_defined_options,
296+ std::optional<ScriptCompiler::CachedData*> user_cached_data,
297+ bool * cache_rejected) {
298+ Isolate* isolate = realm->isolate ();
299+ EscapableHandleScope scope (isolate);
300+ ScriptOrigin origin (isolate,
301+ url,
302+ line_offset,
303+ column_offset,
304+ true , // is cross origin
305+ -1 , // script id
306+ Local<Value>(), // source map URL
307+ false , // is opaque (?)
308+ false , // is WASM
309+ true , // is ES Module
310+ host_defined_options);
311+ ScriptCompiler::CachedData* cached_data = nullptr ;
312+ CompileCacheEntry* cache_entry = 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+ } else if (realm->env ()->use_compile_cache ()) {
319+ cache_entry = realm->env ()->compile_cache_handler ()->GetOrInsert (
320+ source_text, url, CachedCodeType::kESM );
321+ }
322+
323+ if (cache_entry != nullptr && cache_entry->cache != nullptr ) {
324+ // source will take ownership of cached_data.
325+ cached_data = cache_entry->CopyCache ();
326+ }
327+
328+ ScriptCompiler::Source source (source_text, origin, cached_data);
329+ ScriptCompiler::CompileOptions options;
330+ if (cached_data == nullptr ) {
331+ options = ScriptCompiler::kNoCompileOptions ;
332+ } else {
333+ options = ScriptCompiler::kConsumeCodeCache ;
334+ }
335+
336+ Local<Module> module ;
337+ if (!ScriptCompiler::CompileModule (isolate, &source, options)
338+ .ToLocal (&module )) {
339+ return scope.EscapeMaybe (MaybeLocal<Module>());
340+ }
341+
342+ if (options == ScriptCompiler::kConsumeCodeCache ) {
343+ *cache_rejected = source.GetCachedData ()->rejected ;
344+ }
345+
346+ if (cache_entry != nullptr ) {
347+ realm->env ()->compile_cache_handler ()->MaybeSave (
348+ cache_entry, module , *cache_rejected);
349+ }
350+
351+ return scope.Escape (module );
352+ }
353+
306354static Local<Object> createImportAttributesContainer (
307355 Realm* realm,
308356 Isolate* isolate,
0 commit comments