@@ -102,9 +102,18 @@ ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
102
102
return nullptr ;
103
103
}
104
104
105
- // new ModuleWrap(url, context, source, lineOffset, columnOffset, cachedData)
105
+
106
+ Local<PrimitiveArray> ModuleWrap::GetHostDefinedOptions (
107
+ Isolate* isolate, Local<Symbol> id_symbol) {
108
+ Local<PrimitiveArray> host_defined_options =
109
+ PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
110
+ host_defined_options->Set (isolate, HostDefinedOptions::kID , id_symbol);
111
+ return host_defined_options;
112
+ }
113
+
114
+ // new ModuleWrap(url, context, source, lineOffset, columnOffset[, cachedData]);
106
115
// new ModuleWrap(url, context, source, lineOffset, columOffset,
107
- // hostDefinedOption)
116
+ // idSymbol);
108
117
// new ModuleWrap(url, context, exportNames, evaluationCallback[, cjsModule])
109
118
void ModuleWrap::New (const FunctionCallbackInfo<Value>& args) {
110
119
CHECK (args.IsConstructCall ());
@@ -134,7 +143,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
134
143
int column_offset = 0 ;
135
144
136
145
bool synthetic = args[2 ]->IsArray ();
137
-
146
+ bool can_use_builtin_cache = false ;
138
147
Local<PrimitiveArray> host_defined_options =
139
148
PrimitiveArray::New (isolate, HostDefinedOptions::kLength );
140
149
Local<Symbol> id_symbol;
@@ -143,20 +152,24 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
143
152
// cjsModule])
144
153
CHECK (args[3 ]->IsFunction ());
145
154
} else {
146
- // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
155
+ // new ModuleWrap(url, context, source, lineOffset, columOffset[,
156
+ // cachedData]);
147
157
// new ModuleWrap(url, context, source, lineOffset, columOffset,
148
- // hostDefinedOption)
158
+ // idSymbol);
149
159
CHECK (args[2 ]->IsString ());
150
160
CHECK (args[3 ]->IsNumber ());
151
161
line_offset = args[3 ].As <Int32>()->Value ();
152
162
CHECK (args[4 ]->IsNumber ());
153
163
column_offset = args[4 ].As <Int32>()->Value ();
154
164
if (args[5 ]->IsSymbol ()) {
155
165
id_symbol = args[5 ].As <Symbol>();
166
+ can_use_builtin_cache =
167
+ (id_symbol ==
168
+ realm->isolate_data ()->source_text_module_default_hdo ());
156
169
} else {
157
170
id_symbol = Symbol::New (isolate, url);
158
171
}
159
- host_defined_options-> Set (isolate, HostDefinedOptions:: kID , id_symbol);
172
+ host_defined_options = GetHostDefinedOptions (isolate, id_symbol);
160
173
161
174
if (that->SetPrivate (context,
162
175
realm->isolate_data ()->host_defined_option_symbol (),
@@ -189,36 +202,34 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
189
202
module = Module::CreateSyntheticModule (isolate, url, export_names,
190
203
SyntheticModuleEvaluationStepsCallback);
191
204
} else {
192
- ScriptCompiler::CachedData* cached_data = nullptr ;
205
+ // When we are compiling for the default loader, this will be
206
+ // std::nullopt, and CompileSourceTextModule() should use
207
+ // on-disk cache (not present on v20.x).
208
+ std::optional<v8::ScriptCompiler::CachedData*> user_cached_data;
209
+ if (id_symbol !=
210
+ realm->isolate_data ()->source_text_module_default_hdo ()) {
211
+ user_cached_data = nullptr ;
212
+ }
193
213
if (args[5 ]->IsArrayBufferView ()) {
214
+ CHECK (!can_use_builtin_cache); // We don't use this option internally.
194
215
Local<ArrayBufferView> cached_data_buf = args[5 ].As <ArrayBufferView>();
195
216
uint8_t * data =
196
217
static_cast <uint8_t *>(cached_data_buf->Buffer ()->Data ());
197
- cached_data =
218
+ user_cached_data =
198
219
new ScriptCompiler::CachedData (data + cached_data_buf->ByteOffset (),
199
220
cached_data_buf->ByteLength ());
200
221
}
201
-
202
222
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)
223
+
224
+ bool cache_rejected = false ;
225
+ if (!CompileSourceTextModule (realm,
226
+ source_text,
227
+ url,
228
+ line_offset,
229
+ column_offset,
230
+ host_defined_options,
231
+ user_cached_data,
232
+ &cache_rejected)
222
233
.ToLocal (&module)) {
223
234
if (try_catch.HasCaught () && !try_catch.HasTerminated ()) {
224
235
CHECK (!try_catch.Message ().IsEmpty ());
@@ -231,8 +242,9 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
231
242
}
232
243
return ;
233
244
}
234
- if (options == ScriptCompiler::kConsumeCodeCache &&
235
- source.GetCachedData ()->rejected ) {
245
+
246
+ if (user_cached_data.has_value () && user_cached_data.value () != nullptr &&
247
+ cache_rejected) {
236
248
THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED (
237
249
realm, " cachedData buffer was rejected" );
238
250
try_catch.ReThrow ();
@@ -275,6 +287,57 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
275
287
args.GetReturnValue ().Set (that);
276
288
}
277
289
290
+ MaybeLocal<Module> ModuleWrap::CompileSourceTextModule (
291
+ Realm* realm,
292
+ Local<String> source_text,
293
+ Local<String> url,
294
+ int line_offset,
295
+ int column_offset,
296
+ Local<PrimitiveArray> host_defined_options,
297
+ std::optional<ScriptCompiler::CachedData*> user_cached_data,
298
+ bool * cache_rejected) {
299
+ Isolate* isolate = realm->isolate ();
300
+ EscapableHandleScope scope (isolate);
301
+ ScriptOrigin origin (isolate,
302
+ url,
303
+ line_offset,
304
+ column_offset,
305
+ true , // is cross origin
306
+ -1 , // script id
307
+ Local<Value>(), // source map URL
308
+ false , // is opaque (?)
309
+ false , // is WASM
310
+ true , // is ES Module
311
+ host_defined_options);
312
+ ScriptCompiler::CachedData* cached_data = 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
+ }
319
+
320
+ ScriptCompiler::Source source (source_text, origin, cached_data);
321
+ ScriptCompiler::CompileOptions options;
322
+ if (cached_data == nullptr ) {
323
+ options = ScriptCompiler::kNoCompileOptions ;
324
+ } else {
325
+ options = ScriptCompiler::kConsumeCodeCache ;
326
+ }
327
+
328
+ Local<Module> module;
329
+ if (!ScriptCompiler::CompileModule (isolate, &source, options)
330
+ .ToLocal (&module)) {
331
+ return scope.EscapeMaybe (MaybeLocal<Module>());
332
+ }
333
+
334
+ if (options == ScriptCompiler::kConsumeCodeCache ) {
335
+ *cache_rejected = source.GetCachedData ()->rejected ;
336
+ }
337
+
338
+ return scope.Escape (module);
339
+ }
340
+
278
341
static Local<Object> createImportAttributesContainer (
279
342
Realm* realm,
280
343
Isolate* isolate,
0 commit comments