@@ -142,9 +142,17 @@ v8::Maybe<bool> ModuleWrap::CheckUnsettledTopLevelAwait() {
142142 return v8::Just (false );
143143}
144144
145- // new ModuleWrap(url, context, source, lineOffset, columnOffset, cachedData)
145+ Local<PrimitiveArray> ModuleWrap::GetHostDefinedOptions (
146+ Isolate* isolate, Local<Symbol> id_symbol) {
147+ Local<PrimitiveArray> host_defined_options =
148+ PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
149+ host_defined_options->Set (isolate, HostDefinedOptions::kID , id_symbol);
150+ return host_defined_options;
151+ }
152+
153+ // new ModuleWrap(url, context, source, lineOffset, columnOffset[, cachedData]);
146154// new ModuleWrap(url, context, source, lineOffset, columOffset,
147- // hostDefinedOption)
155+ // idSymbol);
148156// new ModuleWrap(url, context, exportNames, evaluationCallback[, cjsModule])
149157void ModuleWrap::New (const FunctionCallbackInfo<Value>& args) {
150158 CHECK (args.IsConstructCall ());
@@ -174,18 +182,17 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
174182 int column_offset = 0 ;
175183
176184 bool synthetic = args[2 ]->IsArray ();
177-
178- Local<PrimitiveArray> host_defined_options =
179- PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
185+ Local<PrimitiveArray> host_defined_options;
180186 Local<Symbol> id_symbol;
181187 if (synthetic) {
182188 // new ModuleWrap(url, context, exportNames, evaluationCallback[,
183189 // cjsModule])
184190 CHECK (args[3 ]->IsFunction ());
185191 } else {
186- // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
192+ // new ModuleWrap(url, context, source, lineOffset, columOffset[,
193+ // cachedData]);
187194 // new ModuleWrap(url, context, source, lineOffset, columOffset,
188- // hostDefinedOption)
195+ // idSymbol);
189196 CHECK (args[2 ]->IsString ());
190197 CHECK (args[3 ]->IsNumber ());
191198 line_offset = args[3 ].As <Int32>()->Value ();
@@ -196,7 +203,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
196203 } else {
197204 id_symbol = Symbol::New (isolate, url);
198205 }
199- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
206+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
200207
201208 if (that->SetPrivate (context,
202209 realm->isolate_data ()->host_defined_option_symbol (),
@@ -231,36 +238,32 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
231238 module = Module::CreateSyntheticModule (
232239 isolate, url, span, SyntheticModuleEvaluationStepsCallback);
233240 } else {
234- ScriptCompiler::CachedData* cached_data = nullptr ;
241+ std::optional<v8::ScriptCompiler::CachedData*> user_cached_data;
242+ if (id_symbol !=
243+ realm->isolate_data ()->source_text_module_default_hdo ()) {
244+ // TODO(joyeecheung): when we are compiling for the default loader, this
245+ // will be std::nullopt, and CompileSourceTextModule() should use
246+ // on-disk cache. See: https://github.com/nodejs/node/issues/47472
247+ user_cached_data = nullptr ;
248+ }
235249 if (args[5 ]->IsArrayBufferView ()) {
236250 Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
237251 uint8_t * data =
238252 static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
239- cached_data =
253+ user_cached_data =
240254 new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
241255 cached_data_buf->ByteLength ());
242256 }
243-
244257 Local<String> source_text = args[2 ].As <String>();
245- ScriptOrigin origin (isolate,
246- url,
247- line_offset,
248- column_offset,
249- true , // is cross origin
250- -1 , // script id
251- Local<Value>(), // source map URL
252- false , // is opaque (?)
253- false , // is WASM
254- true , // is ES Module
255- host_defined_options);
256- ScriptCompiler::Source source (source_text, origin, cached_data);
257- ScriptCompiler::CompileOptions options;
258- if (source.GetCachedData () == nullptr ) {
259- options = ScriptCompiler::kNoCompileOptions ;
260- } else {
261- options = ScriptCompiler::kConsumeCodeCache ;
262- }
263- if (!ScriptCompiler::CompileModule (isolate, &source, options)
258+ bool cache_rejected = false ;
259+ if (!CompileSourceTextModule (realm,
260+ source_text,
261+ url,
262+ line_offset,
263+ column_offset,
264+ host_defined_options,
265+ user_cached_data,
266+ &cache_rejected)
264267 .ToLocal (&module )) {
265268 if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
266269 CHECK (!try_catch.Message ().IsEmpty ());
@@ -273,8 +276,9 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
273276 }
274277 return ;
275278 }
276- if (options == ScriptCompiler::kConsumeCodeCache &&
277- source.GetCachedData ()->rejected ) {
279+
280+ if (user_cached_data.has_value () && user_cached_data.value () != nullptr &&
281+ cache_rejected) {
278282 THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
279283 realm, " cachedData buffer was rejected" );
280284 try_catch.ReThrow ();
@@ -317,6 +321,51 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
317321 args.GetReturnValue ().Set (that);
318322}
319323
324+ MaybeLocal<Module> ModuleWrap::CompileSourceTextModule (
325+ Realm* realm,
326+ Local<String> source_text,
327+ Local<String> url,
328+ int line_offset,
329+ int column_offset,
330+ Local<PrimitiveArray> host_defined_options,
331+ std::optional<ScriptCompiler::CachedData*> user_cached_data,
332+ bool * cache_rejected) {
333+ Isolate* isolate = realm->isolate ();
334+ EscapableHandleScope scope (isolate);
335+ ScriptOrigin origin (isolate,
336+ url,
337+ line_offset,
338+ column_offset,
339+ true , // is cross origin
340+ -1 , // script id
341+ Local<Value>(), // source map URL
342+ false , // is opaque (?)
343+ false , // is WASM
344+ true , // is ES Module
345+ host_defined_options);
346+ ScriptCompiler::CachedData* cached_data = nullptr ;
347+ if (user_cached_data.has_value ()) {
348+ cached_data = user_cached_data.value ();
349+ }
350+ ScriptCompiler::Source source (source_text, origin, cached_data);
351+ ScriptCompiler::CompileOptions options;
352+ if (cached_data == nullptr ) {
353+ options = ScriptCompiler::kNoCompileOptions ;
354+ } else {
355+ options = ScriptCompiler::kConsumeCodeCache ;
356+ }
357+ Local<Module> module ;
358+ if (!ScriptCompiler::CompileModule (isolate, &source, options)
359+ .ToLocal (&module )) {
360+ return scope.EscapeMaybe (MaybeLocal<Module>());
361+ }
362+ if (cached_data != nullptr ) {
363+ *cache_rejected = source.GetCachedData ()->rejected ;
364+ }
365+
366+ return scope.Escape (module );
367+ }
368+
320369static Local<Object> createImportAttributesContainer (
321370 Realm* realm,
322371 Isolate* isolate,
0 commit comments