@@ -142,10 +142,18 @@ v8::Maybe<bool> ModuleWrap::CheckUnsettledTopLevelAwait() {
142
142
return v8::Just (false );
143
143
}
144
144
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]);
146
154
// 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)
149
157
void ModuleWrap::New (const FunctionCallbackInfo<Value>& args) {
150
158
CHECK (args.IsConstructCall ());
151
159
CHECK_GE (args.Length (), 3 );
@@ -174,17 +182,16 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
174
182
int column_offset = 0 ;
175
183
176
184
bool synthetic = args[2 ]->IsArray ();
177
-
178
- Local<PrimitiveArray> host_defined_options =
179
- PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
185
+ Local<PrimitiveArray> host_defined_options;
180
186
Local<Symbol> id_symbol;
181
187
if (synthetic) {
182
188
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
183
189
CHECK (args[3 ]->IsFunction ());
184
190
} else {
185
- // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
191
+ // new ModuleWrap(url, context, source, lineOffset, columOffset[,
192
+ // cachedData]);
186
193
// new ModuleWrap(url, context, source, lineOffset, columOffset,
187
- // hostDefinedOption)
194
+ // idSymbol);
188
195
CHECK (args[2 ]->IsString ());
189
196
CHECK (args[3 ]->IsNumber ());
190
197
line_offset = args[3 ].As <Int32>()->Value ();
@@ -195,7 +202,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
195
202
} else {
196
203
id_symbol = Symbol::New (isolate, url);
197
204
}
198
- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
205
+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
199
206
200
207
if (that->SetPrivate (context,
201
208
realm->isolate_data ()->host_defined_option_symbol (),
@@ -230,36 +237,32 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
230
237
module = Module::CreateSyntheticModule (
231
238
isolate, url, span, SyntheticModuleEvaluationStepsCallback);
232
239
} 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
+ }
234
248
if (args[5 ]->IsArrayBufferView ()) {
235
249
Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
236
250
uint8_t * data =
237
251
static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
238
- cached_data =
252
+ user_cached_data =
239
253
new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
240
254
cached_data_buf->ByteLength ());
241
255
}
242
-
243
256
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)
263
266
.ToLocal (&module)) {
264
267
if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
265
268
CHECK (!try_catch.Message ().IsEmpty ());
@@ -272,8 +275,9 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
272
275
}
273
276
return ;
274
277
}
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) {
277
281
THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
278
282
realm, " cachedData buffer was rejected" );
279
283
try_catch.ReThrow ();
@@ -310,6 +314,51 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
310
314
args.GetReturnValue ().Set (that);
311
315
}
312
316
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
+
313
362
static Local<Object> createImportAttributesContainer (
314
363
Realm* realm,
315
364
Isolate* isolate,
0 commit comments