@@ -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 ());
@@ -134,7 +142,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
134142 int column_offset = 0 ;
135143
136144 bool synthetic = args[2 ]->IsArray ();
137-
145+ bool can_use_builtin_cache = false ;
138146 Local<PrimitiveArray> host_defined_options =
139147 PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
140148 Local<Symbol> id_symbol;
@@ -143,20 +151,24 @@ 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 ();
152161 CHECK (args[4 ]->IsNumber ());
153162 column_offset = args[4 ].As <Int32>()->Value ();
154163 if (args[5 ]->IsSymbol ()) {
155164 id_symbol = args[5 ].As <Symbol>();
165+ can_use_builtin_cache =
166+ (id_symbol ==
167+ realm->isolate_data ()->source_text_module_default_hdo ());
156168 } else {
157169 id_symbol = Symbol::New (isolate, url);
158170 }
159- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
171+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
160172
161173 if (that->SetPrivate (context,
162174 realm->isolate_data ()->host_defined_option_symbol (),
@@ -189,36 +201,34 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
189201 module = Module::CreateSyntheticModule (isolate, url, export_names,
190202 SyntheticModuleEvaluationStepsCallback);
191203 } else {
192- ScriptCompiler::CachedData* cached_data = nullptr ;
204+ // When we are compiling for the default loader, this will be
205+ // std::nullopt, and CompileSourceTextModule() should use
206+ // on-disk cache (not present on v20.x).
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+ }
193212 if (args[5 ]->IsArrayBufferView ()) {
213+ CHECK (!can_use_builtin_cache); // We don't use this option internally.
194214 Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
195215 uint8_t * data =
196216 static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
197- cached_data =
217+ user_cached_data =
198218 new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
199219 cached_data_buf->ByteLength ());
200220 }
201-
202221 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)
222+
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)
222232 .ToLocal (&module )) {
223233 if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
224234 CHECK (!try_catch.Message ().IsEmpty ());
@@ -231,8 +241,9 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
231241 }
232242 return ;
233243 }
234- if (options == ScriptCompiler::kConsumeCodeCache &&
235- source.GetCachedData ()->rejected ) {
244+
245+ if (user_cached_data.has_value () && user_cached_data.value () != nullptr &&
246+ cache_rejected) {
236247 THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
237248 realm, " cachedData buffer was rejected" );
238249 try_catch.ReThrow ();
@@ -275,6 +286,57 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
275286 args.GetReturnValue ().Set (that);
276287}
277288
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+ // When compiling for the default loader, user_cached_data is std::nullptr.
313+ // When compiling for vm.Module, it's either nullptr or a pointer to the
314+ // cached data.
315+ if (user_cached_data.has_value ()) {
316+ cached_data = user_cached_data.value ();
317+ }
318+
319+ ScriptCompiler::Source source (source_text, origin, cached_data);
320+ ScriptCompiler::CompileOptions options;
321+ if (cached_data == nullptr ) {
322+ options = ScriptCompiler::kNoCompileOptions ;
323+ } else {
324+ options = ScriptCompiler::kConsumeCodeCache ;
325+ }
326+
327+ Local<Module> module ;
328+ if (!ScriptCompiler::CompileModule (isolate, &source, options)
329+ .ToLocal (&module )) {
330+ return scope.EscapeMaybe (MaybeLocal<Module>());
331+ }
332+
333+ if (options == ScriptCompiler::kConsumeCodeCache ) {
334+ *cache_rejected = source.GetCachedData ()->rejected ;
335+ }
336+
337+ return scope.Escape (module );
338+ }
339+
278340static Local<Object> createImportAttributesContainer (
279341 Realm* realm,
280342 Isolate* isolate,
0 commit comments