@@ -142,10 +142,18 @@ 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) new ModuleWrap(url, context, exportNames,
148- // syntheticExecutionFunction)
155+ // idSymbol);
156+ // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
149157void ModuleWrap::New (const FunctionCallbackInfo<Value>& args) {
150158 CHECK (args.IsConstructCall ());
151159 CHECK_GE (args.Length (), 3 );
@@ -174,17 +182,16 @@ 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, syntheticExecutionFunction)
183189 CHECK (args[3 ]->IsFunction ());
184190 } else {
185- // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
191+ // new ModuleWrap(url, context, source, lineOffset, columOffset[,
192+ // cachedData]);
186193 // new ModuleWrap(url, context, source, lineOffset, columOffset,
187- // hostDefinedOption)
194+ // idSymbol);
188195 CHECK (args[2 ]->IsString ());
189196 CHECK (args[3 ]->IsNumber ());
190197 line_offset = args[3 ].As <Int32>()->Value ();
@@ -195,7 +202,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
195202 } else {
196203 id_symbol = Symbol::New (isolate, url);
197204 }
198- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
205+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
199206
200207 if (that->SetPrivate (context,
201208 realm->isolate_data ()->host_defined_option_symbol (),
@@ -230,36 +237,32 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
230237 module = Module::CreateSyntheticModule (
231238 isolate, url, span, SyntheticModuleEvaluationStepsCallback);
232239 } else {
233- ScriptCompiler::CachedData* cached_data = nullptr ;
240+ std::optional<v8::ScriptCompiler::CachedData*> user_cached_data;
241+ if (id_symbol !=
242+ realm->isolate_data ()->source_text_module_default_hdo ()) {
243+ // TODO(joyeecheung): when we are compiling for the default loader, this
244+ // will be std::nullopt, and CompileSourceTextModule() should use
245+ // on-disk cache. See: https://github.com/nodejs/node/issues/47472
246+ user_cached_data = nullptr ;
247+ }
234248 if (args[5 ]->IsArrayBufferView ()) {
235249 Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
236250 uint8_t * data =
237251 static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
238- cached_data =
252+ user_cached_data =
239253 new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
240254 cached_data_buf->ByteLength ());
241255 }
242-
243256 Local<String> source_text = args[2 ].As <String>();
244- ScriptOrigin origin (isolate,
245- url,
246- line_offset,
247- column_offset,
248- true , // is cross origin
249- -1 , // script id
250- Local<Value>(), // source map URL
251- false , // is opaque (?)
252- false , // is WASM
253- true , // is ES Module
254- host_defined_options);
255- ScriptCompiler::Source source (source_text, origin, cached_data);
256- ScriptCompiler::CompileOptions options;
257- if (source.GetCachedData () == nullptr ) {
258- options = ScriptCompiler::kNoCompileOptions ;
259- } else {
260- options = ScriptCompiler::kConsumeCodeCache ;
261- }
262- if (!ScriptCompiler::CompileModule (isolate, &source, options)
257+ bool cache_rejected = false ;
258+ if (!CompileSourceTextModule (realm,
259+ source_text,
260+ url,
261+ line_offset,
262+ column_offset,
263+ host_defined_options,
264+ user_cached_data,
265+ &cache_rejected)
263266 .ToLocal (&module )) {
264267 if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
265268 CHECK (!try_catch.Message ().IsEmpty ());
@@ -272,8 +275,9 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
272275 }
273276 return ;
274277 }
275- if (options == ScriptCompiler::kConsumeCodeCache &&
276- source.GetCachedData ()->rejected ) {
278+
279+ if (user_cached_data.has_value () && user_cached_data.value () != nullptr &&
280+ cache_rejected) {
277281 THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
278282 realm, " cachedData buffer was rejected" );
279283 try_catch.ReThrow ();
@@ -310,6 +314,51 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
310314 args.GetReturnValue ().Set (that);
311315}
312316
317+ MaybeLocal<Module> ModuleWrap::CompileSourceTextModule (
318+ Realm* realm,
319+ Local<String> source_text,
320+ Local<String> url,
321+ int line_offset,
322+ int column_offset,
323+ Local<PrimitiveArray> host_defined_options,
324+ std::optional<ScriptCompiler::CachedData*> user_cached_data,
325+ bool * cache_rejected) {
326+ Isolate* isolate = realm->isolate ();
327+ EscapableHandleScope scope (isolate);
328+ ScriptOrigin origin (isolate,
329+ url,
330+ line_offset,
331+ column_offset,
332+ true , // is cross origin
333+ -1 , // script id
334+ Local<Value>(), // source map URL
335+ false , // is opaque (?)
336+ false , // is WASM
337+ true , // is ES Module
338+ host_defined_options);
339+ ScriptCompiler::CachedData* cached_data = nullptr ;
340+ if (user_cached_data.has_value ()) {
341+ cached_data = user_cached_data.value ();
342+ }
343+ ScriptCompiler::Source source (source_text, origin, cached_data);
344+ ScriptCompiler::CompileOptions options;
345+ if (cached_data == nullptr ) {
346+ options = ScriptCompiler::kNoCompileOptions ;
347+ } else {
348+ options = ScriptCompiler::kConsumeCodeCache ;
349+ }
350+ Local<Module> module ;
351+ if (!ScriptCompiler::CompileModule (isolate, &source, options)
352+ .ToLocal (&module )) {
353+ return scope.EscapeMaybe (MaybeLocal<Module>());
354+ }
355+ if (cached_data != nullptr ) {
356+ *cache_rejected = source.GetCachedData ()->rejected ;
357+ }
358+
359+ return scope.Escape (module );
360+ }
361+
313362static Local<Object> createImportAttributesContainer (
314363 Realm* realm,
315364 Isolate* isolate,
0 commit comments