Coverage Report

Created: 2025-08-03 10:06

/src/node/src/module_wrap.cc
Line
Count
Source (jump to first uncovered line)
1
#include "module_wrap.h"
2
3
#include "env.h"
4
#include "memory_tracker-inl.h"
5
#include "node_contextify.h"
6
#include "node_errors.h"
7
#include "node_external_reference.h"
8
#include "node_internals.h"
9
#include "node_process-inl.h"
10
#include "node_watchdog.h"
11
#include "util-inl.h"
12
13
#include <sys/stat.h>  // S_IFDIR
14
15
#include <algorithm>
16
17
namespace node {
18
namespace loader {
19
20
using errors::TryCatchScope;
21
22
using node::contextify::ContextifyContext;
23
using v8::Array;
24
using v8::ArrayBufferView;
25
using v8::Context;
26
using v8::EscapableHandleScope;
27
using v8::FixedArray;
28
using v8::Function;
29
using v8::FunctionCallbackInfo;
30
using v8::FunctionTemplate;
31
using v8::HandleScope;
32
using v8::Int32;
33
using v8::Integer;
34
using v8::IntegrityLevel;
35
using v8::Isolate;
36
using v8::Local;
37
using v8::MaybeLocal;
38
using v8::MemorySpan;
39
using v8::MicrotaskQueue;
40
using v8::Module;
41
using v8::ModuleRequest;
42
using v8::Object;
43
using v8::ObjectTemplate;
44
using v8::PrimitiveArray;
45
using v8::Promise;
46
using v8::ScriptCompiler;
47
using v8::ScriptOrigin;
48
using v8::String;
49
using v8::Symbol;
50
using v8::UnboundModuleScript;
51
using v8::Undefined;
52
using v8::Value;
53
54
ModuleWrap::ModuleWrap(Realm* realm,
55
                       Local<Object> object,
56
                       Local<Module> module,
57
                       Local<String> url,
58
                       Local<Object> context_object,
59
                       Local<Value> synthetic_evaluation_step)
60
0
    : BaseObject(realm, object),
61
0
      module_(realm->isolate(), module),
62
0
      module_hash_(module->GetIdentityHash()) {
63
0
  realm->env()->hash_to_module_map.emplace(module_hash_, this);
64
65
0
  object->SetInternalField(kModuleSlot, module);
66
0
  object->SetInternalField(kURLSlot, url);
67
0
  object->SetInternalField(kSyntheticEvaluationStepsSlot,
68
0
                           synthetic_evaluation_step);
69
0
  object->SetInternalField(kContextObjectSlot, context_object);
70
71
0
  if (!synthetic_evaluation_step->IsUndefined()) {
72
0
    synthetic_ = true;
73
0
  }
74
0
  MakeWeak();
75
0
  module_.SetWeak();
76
0
}
77
78
0
ModuleWrap::~ModuleWrap() {
79
0
  auto range = env()->hash_to_module_map.equal_range(module_hash_);
80
0
  for (auto it = range.first; it != range.second; ++it) {
81
0
    if (it->second == this) {
82
0
      env()->hash_to_module_map.erase(it);
83
0
      break;
84
0
    }
85
0
  }
86
0
}
87
88
0
Local<Context> ModuleWrap::context() const {
89
0
  Local<Value> obj = object()->GetInternalField(kContextObjectSlot).As<Value>();
90
  // If this fails, there is likely a bug e.g. ModuleWrap::context() is accessed
91
  // before the ModuleWrap constructor completes.
92
0
  CHECK(obj->IsObject());
93
0
  return obj.As<Object>()->GetCreationContextChecked();
94
0
}
95
96
ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
97
0
                                      Local<Module> module) {
98
0
  auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
99
0
  for (auto it = range.first; it != range.second; ++it) {
100
0
    if (it->second->module_ == module) {
101
0
      return it->second;
102
0
    }
103
0
  }
104
0
  return nullptr;
105
0
}
106
107
0
v8::Maybe<bool> ModuleWrap::CheckUnsettledTopLevelAwait() {
108
0
  Isolate* isolate = env()->isolate();
109
0
  Local<Context> context = env()->context();
110
111
  // This must be invoked when the environment is shutting down, and the module
112
  // is kept alive by the module wrap via an internal field.
113
0
  CHECK(env()->exiting());
114
0
  CHECK(!module_.IsEmpty());
115
116
0
  Local<Module> module = module_.Get(isolate);
117
  // It's a synthetic module, likely a facade wrapping CJS.
118
0
  if (!module->IsSourceTextModule()) {
119
0
    return v8::Just(true);
120
0
  }
121
122
0
  if (!module->IsGraphAsync()) {  // There is no TLA, no need to check.
123
0
    return v8::Just(true);
124
0
  }
125
126
0
  auto stalled_messages =
127
0
      std::get<1>(module->GetStalledTopLevelAwaitMessages(isolate));
128
0
  if (stalled_messages.size() == 0) {
129
0
    return v8::Just(true);
130
0
  }
131
132
0
  if (env()->options()->warnings) {
133
0
    for (auto& message : stalled_messages) {
134
0
      std::string reason = "Warning: Detected unsettled top-level await at ";
135
0
      std::string info =
136
0
          FormatErrorMessage(isolate, context, "", message, true);
137
0
      reason += info;
138
0
      FPrintF(stderr, "%s\n", reason);
139
0
    }
140
0
  }
141
142
0
  return v8::Just(false);
143
0
}
144
145
// new ModuleWrap(url, context, source, lineOffset, columnOffset, cachedData)
146
// new ModuleWrap(url, context, source, lineOffset, columOffset,
147
// hostDefinedOption) new ModuleWrap(url, context, exportNames,
148
// syntheticExecutionFunction)
149
0
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
150
0
  CHECK(args.IsConstructCall());
151
0
  CHECK_GE(args.Length(), 3);
152
153
0
  Realm* realm = Realm::GetCurrent(args);
154
0
  Isolate* isolate = realm->isolate();
155
156
0
  Local<Object> that = args.This();
157
158
0
  CHECK(args[0]->IsString());
159
0
  Local<String> url = args[0].As<String>();
160
161
0
  Local<Context> context;
162
0
  ContextifyContext* contextify_context = nullptr;
163
0
  if (args[1]->IsUndefined()) {
164
0
    context = that->GetCreationContextChecked();
165
0
  } else {
166
0
    CHECK(args[1]->IsObject());
167
0
    contextify_context = ContextifyContext::ContextFromContextifiedSandbox(
168
0
        realm->env(), args[1].As<Object>());
169
0
    CHECK_NOT_NULL(contextify_context);
170
0
    context = contextify_context->context();
171
0
  }
172
173
0
  int line_offset = 0;
174
0
  int column_offset = 0;
175
176
0
  bool synthetic = args[2]->IsArray();
177
178
0
  Local<PrimitiveArray> host_defined_options =
179
0
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
180
0
  Local<Symbol> id_symbol;
181
0
  if (synthetic) {
182
    // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
183
0
    CHECK(args[3]->IsFunction());
184
0
  } else {
185
    // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
186
    // new ModuleWrap(url, context, source, lineOffset, columOffset,
187
    // hostDefinedOption)
188
0
    CHECK(args[2]->IsString());
189
0
    CHECK(args[3]->IsNumber());
190
0
    line_offset = args[3].As<Int32>()->Value();
191
0
    CHECK(args[4]->IsNumber());
192
0
    column_offset = args[4].As<Int32>()->Value();
193
0
    if (args[5]->IsSymbol()) {
194
0
      id_symbol = args[5].As<Symbol>();
195
0
    } else {
196
0
      id_symbol = Symbol::New(isolate, url);
197
0
    }
198
0
    host_defined_options->Set(isolate, HostDefinedOptions::kID, id_symbol);
199
200
0
    if (that->SetPrivate(context,
201
0
                         realm->isolate_data()->host_defined_option_symbol(),
202
0
                         id_symbol)
203
0
            .IsNothing()) {
204
0
      return;
205
0
    }
206
0
  }
207
208
0
  ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
209
0
  TryCatchScope try_catch(realm->env());
210
211
0
  Local<Module> module;
212
213
0
  {
214
0
    Context::Scope context_scope(context);
215
0
    if (synthetic) {
216
0
      CHECK(args[2]->IsArray());
217
0
      Local<Array> export_names_arr = args[2].As<Array>();
218
219
0
      uint32_t len = export_names_arr->Length();
220
0
      std::vector<Local<String>> export_names(len);
221
0
      for (uint32_t i = 0; i < len; i++) {
222
0
        Local<Value> export_name_val =
223
0
            export_names_arr->Get(context, i).ToLocalChecked();
224
0
        CHECK(export_name_val->IsString());
225
0
        export_names[i] = export_name_val.As<String>();
226
0
      }
227
228
0
      const MemorySpan<const Local<String>> span(export_names.begin(),
229
0
                                                 export_names.size());
230
0
      module = Module::CreateSyntheticModule(
231
0
          isolate, url, span, SyntheticModuleEvaluationStepsCallback);
232
0
    } else {
233
0
      ScriptCompiler::CachedData* cached_data = nullptr;
234
0
      if (args[5]->IsArrayBufferView()) {
235
0
        Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
236
0
        uint8_t* data =
237
0
            static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
238
0
        cached_data =
239
0
            new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
240
0
                                           cached_data_buf->ByteLength());
241
0
      }
242
243
0
      Local<String> source_text = args[2].As<String>();
244
0
      ScriptOrigin origin(isolate,
245
0
                          url,
246
0
                          line_offset,
247
0
                          column_offset,
248
0
                          true,                             // is cross origin
249
0
                          -1,                               // script id
250
0
                          Local<Value>(),                   // source map URL
251
0
                          false,                            // is opaque (?)
252
0
                          false,                            // is WASM
253
0
                          true,                             // is ES Module
254
0
                          host_defined_options);
255
0
      ScriptCompiler::Source source(source_text, origin, cached_data);
256
0
      ScriptCompiler::CompileOptions options;
257
0
      if (source.GetCachedData() == nullptr) {
258
0
        options = ScriptCompiler::kNoCompileOptions;
259
0
      } else {
260
0
        options = ScriptCompiler::kConsumeCodeCache;
261
0
      }
262
0
      if (!ScriptCompiler::CompileModule(isolate, &source, options)
263
0
               .ToLocal(&module)) {
264
0
        if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
265
0
          CHECK(!try_catch.Message().IsEmpty());
266
0
          CHECK(!try_catch.Exception().IsEmpty());
267
0
          AppendExceptionLine(realm->env(),
268
0
                              try_catch.Exception(),
269
0
                              try_catch.Message(),
270
0
                              ErrorHandlingMode::MODULE_ERROR);
271
0
          try_catch.ReThrow();
272
0
        }
273
0
        return;
274
0
      }
275
0
      if (options == ScriptCompiler::kConsumeCodeCache &&
276
0
          source.GetCachedData()->rejected) {
277
0
        THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED(
278
0
            realm, "cachedData buffer was rejected");
279
0
        try_catch.ReThrow();
280
0
        return;
281
0
      }
282
283
0
      if (that->Set(context,
284
0
                    realm->env()->source_map_url_string(),
285
0
                    module->GetUnboundModuleScript()->GetSourceMappingURL())
286
0
              .IsNothing()) {
287
0
        return;
288
0
      }
289
0
    }
290
0
  }
291
292
0
  if (!that->Set(context, realm->isolate_data()->url_string(), url)
293
0
           .FromMaybe(false)) {
294
0
    return;
295
0
  }
296
297
  // Use the extras object as an object whose GetCreationContext() will be the
298
  // original `context`, since the `Context` itself strictly speaking cannot
299
  // be stored in an internal field.
300
0
  Local<Object> context_object = context->GetExtrasBindingObject();
301
0
  Local<Value> synthetic_evaluation_step =
302
0
      synthetic ? args[3] : Undefined(realm->isolate()).As<v8::Value>();
303
304
0
  ModuleWrap* obj = new ModuleWrap(
305
0
      realm, that, module, url, context_object, synthetic_evaluation_step);
306
307
0
  obj->contextify_context_ = contextify_context;
308
309
0
  that->SetIntegrityLevel(context, IntegrityLevel::kFrozen);
310
0
  args.GetReturnValue().Set(that);
311
0
}
312
313
static Local<Object> createImportAttributesContainer(
314
    Realm* realm,
315
    Isolate* isolate,
316
    Local<FixedArray> raw_attributes,
317
0
    const int elements_per_attribute) {
318
0
  CHECK_EQ(raw_attributes->Length() % elements_per_attribute, 0);
319
0
  Local<Object> attributes =
320
0
      Object::New(isolate, v8::Null(isolate), nullptr, nullptr, 0);
321
0
  for (int i = 0; i < raw_attributes->Length(); i += elements_per_attribute) {
322
0
    attributes
323
0
        ->Set(realm->context(),
324
0
              raw_attributes->Get(realm->context(), i).As<String>(),
325
0
              raw_attributes->Get(realm->context(), i + 1).As<Value>())
326
0
        .ToChecked();
327
0
  }
328
329
0
  return attributes;
330
0
}
331
332
void ModuleWrap::GetModuleRequestsSync(
333
0
    const FunctionCallbackInfo<Value>& args) {
334
0
  Realm* realm = Realm::GetCurrent(args);
335
0
  Isolate* isolate = args.GetIsolate();
336
337
0
  Local<Object> that = args.This();
338
339
0
  ModuleWrap* obj;
340
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
341
342
0
  CHECK(!obj->linked_);
343
344
0
  Local<Module> module = obj->module_.Get(isolate);
345
0
  Local<FixedArray> module_requests = module->GetModuleRequests();
346
0
  const int module_requests_length = module_requests->Length();
347
348
0
  std::vector<Local<Value>> requests;
349
0
  requests.reserve(module_requests_length);
350
  // call the dependency resolve callbacks
351
0
  for (int i = 0; i < module_requests_length; i++) {
352
0
    Local<ModuleRequest> module_request =
353
0
        module_requests->Get(realm->context(), i).As<ModuleRequest>();
354
0
    Local<FixedArray> raw_attributes = module_request->GetImportAssertions();
355
0
    std::vector<Local<Value>> request = {
356
0
        module_request->GetSpecifier(),
357
0
        createImportAttributesContainer(realm, isolate, raw_attributes, 3),
358
0
    };
359
0
    requests.push_back(Array::New(isolate, request.data(), request.size()));
360
0
  }
361
362
0
  args.GetReturnValue().Set(
363
0
      Array::New(isolate, requests.data(), requests.size()));
364
0
}
365
366
void ModuleWrap::CacheResolvedWrapsSync(
367
0
    const FunctionCallbackInfo<Value>& args) {
368
0
  Isolate* isolate = args.GetIsolate();
369
370
0
  CHECK_EQ(args.Length(), 3);
371
0
  CHECK(args[0]->IsString());
372
0
  CHECK(args[1]->IsPromise());
373
0
  CHECK(args[2]->IsBoolean());
374
375
0
  ModuleWrap* dependent;
376
0
  ASSIGN_OR_RETURN_UNWRAP(&dependent, args.This());
377
378
0
  Utf8Value specifier(isolate, args[0]);
379
0
  dependent->resolve_cache_[specifier.ToString()].Reset(isolate,
380
0
                                                        args[1].As<Promise>());
381
382
0
  if (args[2].As<v8::Boolean>()->Value()) {
383
0
    dependent->linked_ = true;
384
0
  }
385
0
}
386
387
0
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
388
0
  Realm* realm = Realm::GetCurrent(args);
389
0
  Isolate* isolate = args.GetIsolate();
390
391
0
  CHECK_EQ(args.Length(), 1);
392
0
  CHECK(args[0]->IsFunction());
393
394
0
  Local<Object> that = args.This();
395
396
0
  ModuleWrap* obj;
397
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
398
399
0
  if (obj->linked_)
400
0
    return;
401
0
  obj->linked_ = true;
402
403
0
  Local<Function> resolver_arg = args[0].As<Function>();
404
405
0
  Local<Context> mod_context = obj->context();
406
0
  Local<Module> module = obj->module_.Get(isolate);
407
408
0
  Local<FixedArray> module_requests = module->GetModuleRequests();
409
0
  const int module_requests_length = module_requests->Length();
410
0
  MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
411
412
  // call the dependency resolve callbacks
413
0
  for (int i = 0; i < module_requests_length; i++) {
414
0
    Local<ModuleRequest> module_request =
415
0
        module_requests->Get(realm->context(), i).As<ModuleRequest>();
416
0
    Local<String> specifier = module_request->GetSpecifier();
417
0
    Utf8Value specifier_utf8(realm->isolate(), specifier);
418
0
    std::string specifier_std(*specifier_utf8, specifier_utf8.length());
419
420
0
    Local<FixedArray> raw_attributes = module_request->GetImportAssertions();
421
0
    Local<Object> attributes =
422
0
        createImportAttributesContainer(realm, isolate, raw_attributes, 3);
423
424
0
    Local<Value> argv[] = {
425
0
        specifier,
426
0
        attributes,
427
0
    };
428
429
0
    MaybeLocal<Value> maybe_resolve_return_value =
430
0
        resolver_arg->Call(mod_context, that, arraysize(argv), argv);
431
0
    if (maybe_resolve_return_value.IsEmpty()) {
432
0
      return;
433
0
    }
434
0
    Local<Value> resolve_return_value =
435
0
        maybe_resolve_return_value.ToLocalChecked();
436
0
    if (!resolve_return_value->IsPromise()) {
437
0
      THROW_ERR_VM_MODULE_LINK_FAILURE(
438
0
          realm, "request for '%s' did not return promise", specifier_std);
439
0
      return;
440
0
    }
441
0
    Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
442
0
    obj->resolve_cache_[specifier_std].Reset(isolate, resolve_promise);
443
444
0
    promises[i] = resolve_promise;
445
0
  }
446
447
0
  args.GetReturnValue().Set(
448
0
      Array::New(isolate, promises.out(), promises.length()));
449
0
}
450
451
0
void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
452
0
  Realm* realm = Realm::GetCurrent(args);
453
0
  Isolate* isolate = args.GetIsolate();
454
0
  ModuleWrap* obj;
455
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
456
0
  Local<Context> context = obj->context();
457
0
  Local<Module> module = obj->module_.Get(isolate);
458
0
  TryCatchScope try_catch(realm->env());
459
0
  USE(module->InstantiateModule(context, ResolveModuleCallback));
460
461
  // clear resolve cache on instantiate
462
0
  obj->resolve_cache_.clear();
463
464
0
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
465
0
    CHECK(!try_catch.Message().IsEmpty());
466
0
    CHECK(!try_catch.Exception().IsEmpty());
467
0
    AppendExceptionLine(realm->env(),
468
0
                        try_catch.Exception(),
469
0
                        try_catch.Message(),
470
0
                        ErrorHandlingMode::MODULE_ERROR);
471
0
    try_catch.ReThrow();
472
0
    return;
473
0
  }
474
0
}
475
476
0
void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
477
0
  Realm* realm = Realm::GetCurrent(args);
478
0
  Isolate* isolate = realm->isolate();
479
0
  ModuleWrap* obj;
480
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
481
0
  Local<Context> context = obj->context();
482
0
  Local<Module> module = obj->module_.Get(isolate);
483
484
0
  ContextifyContext* contextify_context = obj->contextify_context_;
485
0
  MicrotaskQueue* microtask_queue = nullptr;
486
0
  if (contextify_context != nullptr)
487
0
      microtask_queue = contextify_context->microtask_queue();
488
489
  // module.evaluate(timeout, breakOnSigint)
490
0
  CHECK_EQ(args.Length(), 2);
491
492
0
  CHECK(args[0]->IsNumber());
493
0
  int64_t timeout = args[0]->IntegerValue(realm->context()).FromJust();
494
495
0
  CHECK(args[1]->IsBoolean());
496
0
  bool break_on_sigint = args[1]->IsTrue();
497
498
0
  ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
499
0
  TryCatchScope try_catch(realm->env());
500
0
  Isolate::SafeForTerminationScope safe_for_termination(isolate);
501
502
0
  bool timed_out = false;
503
0
  bool received_signal = false;
504
0
  MaybeLocal<Value> result;
505
0
  auto run = [&]() {
506
0
    MaybeLocal<Value> result = module->Evaluate(context);
507
0
    if (!result.IsEmpty() && microtask_queue)
508
0
      microtask_queue->PerformCheckpoint(isolate);
509
0
    return result;
510
0
  };
511
0
  if (break_on_sigint && timeout != -1) {
512
0
    Watchdog wd(isolate, timeout, &timed_out);
513
0
    SigintWatchdog swd(isolate, &received_signal);
514
0
    result = run();
515
0
  } else if (break_on_sigint) {
516
0
    SigintWatchdog swd(isolate, &received_signal);
517
0
    result = run();
518
0
  } else if (timeout != -1) {
519
0
    Watchdog wd(isolate, timeout, &timed_out);
520
0
    result = run();
521
0
  } else {
522
0
    result = run();
523
0
  }
524
525
0
  if (result.IsEmpty()) {
526
0
    CHECK(try_catch.HasCaught());
527
0
  }
528
529
  // Convert the termination exception into a regular exception.
530
0
  if (timed_out || received_signal) {
531
0
    if (!realm->env()->is_main_thread() && realm->env()->is_stopping()) return;
532
0
    isolate->CancelTerminateExecution();
533
    // It is possible that execution was terminated by another timeout in
534
    // which this timeout is nested, so check whether one of the watchdogs
535
    // from this invocation is responsible for termination.
536
0
    if (timed_out) {
537
0
      THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(realm->env(), timeout);
538
0
    } else if (received_signal) {
539
0
      THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(realm->env());
540
0
    }
541
0
  }
542
543
0
  if (try_catch.HasCaught()) {
544
0
    if (!try_catch.HasTerminated())
545
0
      try_catch.ReThrow();
546
0
    return;
547
0
  }
548
549
0
  args.GetReturnValue().Set(result.ToLocalChecked());
550
0
}
551
552
0
void ModuleWrap::InstantiateSync(const FunctionCallbackInfo<Value>& args) {
553
0
  Realm* realm = Realm::GetCurrent(args);
554
0
  Isolate* isolate = args.GetIsolate();
555
0
  ModuleWrap* obj;
556
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
557
0
  Local<Context> context = obj->context();
558
0
  Local<Module> module = obj->module_.Get(isolate);
559
0
  Environment* env = realm->env();
560
561
0
  {
562
0
    TryCatchScope try_catch(env);
563
0
    USE(module->InstantiateModule(context, ResolveModuleCallback));
564
565
    // clear resolve cache on instantiate
566
0
    obj->resolve_cache_.clear();
567
568
0
    if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
569
0
      CHECK(!try_catch.Message().IsEmpty());
570
0
      CHECK(!try_catch.Exception().IsEmpty());
571
0
      AppendExceptionLine(env,
572
0
                          try_catch.Exception(),
573
0
                          try_catch.Message(),
574
0
                          ErrorHandlingMode::MODULE_ERROR);
575
0
      try_catch.ReThrow();
576
0
      return;
577
0
    }
578
0
  }
579
580
  // If --experimental-print-required-tla is true, proceeds to evaluation even
581
  // if it's async because we want to search for the TLA and help users locate
582
  // them.
583
0
  if (module->IsGraphAsync() && !env->options()->print_required_tla) {
584
0
    THROW_ERR_REQUIRE_ASYNC_MODULE(env);
585
0
    return;
586
0
  }
587
0
}
588
589
0
void ModuleWrap::EvaluateSync(const FunctionCallbackInfo<Value>& args) {
590
0
  Realm* realm = Realm::GetCurrent(args);
591
0
  Isolate* isolate = args.GetIsolate();
592
0
  ModuleWrap* obj;
593
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
594
0
  Local<Context> context = obj->context();
595
0
  Local<Module> module = obj->module_.Get(isolate);
596
0
  Environment* env = realm->env();
597
598
0
  Local<Value> result;
599
0
  {
600
0
    TryCatchScope try_catch(env);
601
0
    if (!module->Evaluate(context).ToLocal(&result)) {
602
0
      if (try_catch.HasCaught()) {
603
0
        if (!try_catch.HasTerminated()) {
604
0
          try_catch.ReThrow();
605
0
        }
606
0
        return;
607
0
      }
608
0
    }
609
0
  }
610
611
0
  CHECK(result->IsPromise());
612
0
  Local<Promise> promise = result.As<Promise>();
613
0
  if (promise->State() == Promise::PromiseState::kRejected) {
614
0
    Local<Value> exception = promise->Result();
615
0
    Local<v8::Message> message =
616
0
        v8::Exception::CreateMessage(isolate, exception);
617
0
    AppendExceptionLine(
618
0
        env, exception, message, ErrorHandlingMode::MODULE_ERROR);
619
0
    isolate->ThrowException(exception);
620
0
    return;
621
0
  }
622
623
0
  if (module->IsGraphAsync()) {
624
0
    CHECK(env->options()->print_required_tla);
625
0
    auto stalled_messages =
626
0
        std::get<1>(module->GetStalledTopLevelAwaitMessages(isolate));
627
0
    if (stalled_messages.size() != 0) {
628
0
      for (auto& message : stalled_messages) {
629
0
        std::string reason = "Error: unexpected top-level await at ";
630
0
        std::string info =
631
0
            FormatErrorMessage(isolate, context, "", message, true);
632
0
        reason += info;
633
0
        FPrintF(stderr, "%s\n", reason);
634
0
      }
635
0
    }
636
0
    THROW_ERR_REQUIRE_ASYNC_MODULE(env);
637
0
    return;
638
0
  }
639
640
0
  CHECK_EQ(promise->State(), Promise::PromiseState::kFulfilled);
641
642
0
  args.GetReturnValue().Set(module->GetModuleNamespace());
643
0
}
644
645
0
void ModuleWrap::GetNamespaceSync(const FunctionCallbackInfo<Value>& args) {
646
0
  Realm* realm = Realm::GetCurrent(args);
647
0
  Isolate* isolate = args.GetIsolate();
648
0
  ModuleWrap* obj;
649
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
650
0
  Local<Module> module = obj->module_.Get(isolate);
651
652
0
  switch (module->GetStatus()) {
653
0
    case v8::Module::Status::kUninstantiated:
654
0
    case v8::Module::Status::kInstantiating:
655
0
      return realm->env()->ThrowError(
656
0
          "cannot get namespace, module has not been instantiated");
657
0
    case v8::Module::Status::kEvaluating:
658
0
      return THROW_ERR_REQUIRE_ASYNC_MODULE(realm->env());
659
0
    case v8::Module::Status::kInstantiated:
660
0
    case v8::Module::Status::kEvaluated:
661
0
    case v8::Module::Status::kErrored:
662
0
      break;
663
0
    default:
664
0
      UNREACHABLE();
665
0
  }
666
667
0
  if (module->IsGraphAsync()) {
668
0
    return THROW_ERR_REQUIRE_ASYNC_MODULE(realm->env());
669
0
  }
670
0
  Local<Value> result = module->GetModuleNamespace();
671
0
  args.GetReturnValue().Set(result);
672
0
}
673
674
0
void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
675
0
  Realm* realm = Realm::GetCurrent(args);
676
0
  Isolate* isolate = args.GetIsolate();
677
0
  ModuleWrap* obj;
678
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
679
680
0
  Local<Module> module = obj->module_.Get(isolate);
681
682
0
  switch (module->GetStatus()) {
683
0
    case v8::Module::Status::kUninstantiated:
684
0
    case v8::Module::Status::kInstantiating:
685
0
      return realm->env()->ThrowError(
686
0
          "cannot get namespace, module has not been instantiated");
687
0
    case v8::Module::Status::kInstantiated:
688
0
    case v8::Module::Status::kEvaluating:
689
0
    case v8::Module::Status::kEvaluated:
690
0
    case v8::Module::Status::kErrored:
691
0
      break;
692
0
    default:
693
0
      UNREACHABLE();
694
0
  }
695
696
0
  Local<Value> result = module->GetModuleNamespace();
697
0
  args.GetReturnValue().Set(result);
698
0
}
699
700
0
void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
701
0
  Isolate* isolate = args.GetIsolate();
702
0
  ModuleWrap* obj;
703
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
704
705
0
  Local<Module> module = obj->module_.Get(isolate);
706
707
0
  args.GetReturnValue().Set(module->GetStatus());
708
0
}
709
710
void ModuleWrap::GetStaticDependencySpecifiers(
711
0
    const FunctionCallbackInfo<Value>& args) {
712
0
  Realm* realm = Realm::GetCurrent(args);
713
0
  ModuleWrap* obj;
714
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
715
716
0
  Local<Module> module = obj->module_.Get(realm->isolate());
717
718
0
  Local<FixedArray> module_requests = module->GetModuleRequests();
719
0
  int count = module_requests->Length();
720
721
0
  MaybeStackBuffer<Local<Value>, 16> specifiers(count);
722
723
0
  for (int i = 0; i < count; i++) {
724
0
    Local<ModuleRequest> module_request =
725
0
        module_requests->Get(realm->context(), i).As<ModuleRequest>();
726
0
    specifiers[i] = module_request->GetSpecifier();
727
0
  }
728
729
0
  args.GetReturnValue().Set(
730
0
      Array::New(realm->isolate(), specifiers.out(), count));
731
0
}
732
733
0
void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
734
0
  Isolate* isolate = args.GetIsolate();
735
0
  ModuleWrap* obj;
736
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
737
738
0
  Local<Module> module = obj->module_.Get(isolate);
739
0
  args.GetReturnValue().Set(module->GetException());
740
0
}
741
742
MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
743
    Local<Context> context,
744
    Local<String> specifier,
745
    Local<FixedArray> import_attributes,
746
0
    Local<Module> referrer) {
747
0
  Isolate* isolate = context->GetIsolate();
748
0
  Environment* env = Environment::GetCurrent(context);
749
0
  if (env == nullptr) {
750
0
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
751
0
    return MaybeLocal<Module>();
752
0
  }
753
754
0
  Utf8Value specifier_utf8(isolate, specifier);
755
0
  std::string specifier_std(*specifier_utf8, specifier_utf8.length());
756
757
0
  ModuleWrap* dependent = GetFromModule(env, referrer);
758
0
  if (dependent == nullptr) {
759
0
    THROW_ERR_VM_MODULE_LINK_FAILURE(
760
0
        env, "request for '%s' is from invalid module", specifier_std);
761
0
    return MaybeLocal<Module>();
762
0
  }
763
764
0
  if (dependent->resolve_cache_.count(specifier_std) != 1) {
765
0
    THROW_ERR_VM_MODULE_LINK_FAILURE(
766
0
        env, "request for '%s' is not in cache", specifier_std);
767
0
    return MaybeLocal<Module>();
768
0
  }
769
770
0
  Local<Promise> resolve_promise =
771
0
      dependent->resolve_cache_[specifier_std].Get(isolate);
772
773
0
  if (resolve_promise->State() != Promise::kFulfilled) {
774
0
    THROW_ERR_VM_MODULE_LINK_FAILURE(
775
0
        env, "request for '%s' is not yet fulfilled", specifier_std);
776
0
    return MaybeLocal<Module>();
777
0
  }
778
779
0
  Local<Object> module_object = resolve_promise->Result().As<Object>();
780
0
  if (module_object.IsEmpty() || !module_object->IsObject()) {
781
0
    THROW_ERR_VM_MODULE_LINK_FAILURE(
782
0
        env, "request for '%s' did not return an object", specifier_std);
783
0
    return MaybeLocal<Module>();
784
0
  }
785
786
0
  ModuleWrap* module;
787
0
  ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
788
0
  return module->module_.Get(isolate);
789
0
}
790
791
static MaybeLocal<Promise> ImportModuleDynamically(
792
    Local<Context> context,
793
    Local<v8::Data> host_defined_options,
794
    Local<Value> resource_name,
795
    Local<String> specifier,
796
0
    Local<FixedArray> import_attributes) {
797
0
  Isolate* isolate = context->GetIsolate();
798
0
  Environment* env = Environment::GetCurrent(context);
799
0
  if (env == nullptr) {
800
0
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
801
0
    return MaybeLocal<Promise>();
802
0
  }
803
0
  Realm* realm = Realm::GetCurrent(context);
804
0
  if (realm == nullptr) {
805
    // Fallback to the principal realm if it's in a vm context.
806
0
    realm = env->principal_realm();
807
0
  }
808
809
0
  EscapableHandleScope handle_scope(isolate);
810
811
0
  Local<Function> import_callback =
812
0
      realm->host_import_module_dynamically_callback();
813
0
  Local<Value> id;
814
815
0
  Local<FixedArray> options = host_defined_options.As<FixedArray>();
816
  // Get referrer id symbol from the host-defined options.
817
  // If the host-defined options are empty, get the referrer id symbol
818
  // from the realm global object.
819
0
  if (options->Length() == HostDefinedOptions::kLength) {
820
0
    id = options->Get(context, HostDefinedOptions::kID).As<Symbol>();
821
0
  } else {
822
0
    id = context->Global()
823
0
             ->GetPrivate(context, env->host_defined_option_symbol())
824
0
             .ToLocalChecked();
825
0
  }
826
827
0
  Local<Object> attributes =
828
0
      createImportAttributesContainer(realm, isolate, import_attributes, 2);
829
830
0
  Local<Value> import_args[] = {
831
0
      id,
832
0
      Local<Value>(specifier),
833
0
      attributes,
834
0
      resource_name,
835
0
  };
836
837
0
  Local<Value> result;
838
0
  if (import_callback->Call(
839
0
        context,
840
0
        Undefined(isolate),
841
0
        arraysize(import_args),
842
0
        import_args).ToLocal(&result)) {
843
0
    CHECK(result->IsPromise());
844
0
    return handle_scope.Escape(result.As<Promise>());
845
0
  }
846
847
0
  return MaybeLocal<Promise>();
848
0
}
849
850
void ModuleWrap::SetImportModuleDynamicallyCallback(
851
126k
    const FunctionCallbackInfo<Value>& args) {
852
126k
  Isolate* isolate = args.GetIsolate();
853
126k
  Realm* realm = Realm::GetCurrent(args);
854
126k
  HandleScope handle_scope(isolate);
855
856
126k
  CHECK_EQ(args.Length(), 1);
857
126k
  CHECK(args[0]->IsFunction());
858
126k
  Local<Function> import_callback = args[0].As<Function>();
859
126k
  realm->set_host_import_module_dynamically_callback(import_callback);
860
861
126k
  isolate->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
862
126k
}
863
864
void ModuleWrap::HostInitializeImportMetaObjectCallback(
865
0
    Local<Context> context, Local<Module> module, Local<Object> meta) {
866
0
  Environment* env = Environment::GetCurrent(context);
867
0
  if (env == nullptr)
868
0
    return;
869
0
  ModuleWrap* module_wrap = GetFromModule(env, module);
870
871
0
  if (module_wrap == nullptr) {
872
0
    return;
873
0
  }
874
0
  Realm* realm = Realm::GetCurrent(context);
875
0
  if (realm == nullptr) {
876
    // Fallback to the principal realm if it's in a vm context.
877
0
    realm = env->principal_realm();
878
0
  }
879
880
0
  Local<Object> wrap = module_wrap->object();
881
0
  Local<Function> callback =
882
0
      realm->host_initialize_import_meta_object_callback();
883
0
  Local<Value> id;
884
0
  if (!wrap->GetPrivate(context, env->host_defined_option_symbol())
885
0
           .ToLocal(&id)) {
886
0
    return;
887
0
  }
888
0
  DCHECK(id->IsSymbol());
889
0
  Local<Value> args[] = {id, meta, wrap};
890
0
  TryCatchScope try_catch(env);
891
0
  USE(callback->Call(
892
0
      context, Undefined(realm->isolate()), arraysize(args), args));
893
0
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
894
0
    try_catch.ReThrow();
895
0
  }
896
0
}
897
898
void ModuleWrap::SetInitializeImportMetaObjectCallback(
899
126k
    const FunctionCallbackInfo<Value>& args) {
900
126k
  Realm* realm = Realm::GetCurrent(args);
901
126k
  Isolate* isolate = realm->isolate();
902
903
126k
  CHECK_EQ(args.Length(), 1);
904
126k
  CHECK(args[0]->IsFunction());
905
126k
  Local<Function> import_meta_callback = args[0].As<Function>();
906
126k
  realm->set_host_initialize_import_meta_object_callback(import_meta_callback);
907
908
126k
  isolate->SetHostInitializeImportMetaObjectCallback(
909
126k
      HostInitializeImportMetaObjectCallback);
910
126k
}
911
912
MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
913
0
    Local<Context> context, Local<Module> module) {
914
0
  Environment* env = Environment::GetCurrent(context);
915
0
  Isolate* isolate = env->isolate();
916
917
0
  ModuleWrap* obj = GetFromModule(env, module);
918
919
0
  TryCatchScope try_catch(env);
920
0
  Local<Function> synthetic_evaluation_steps =
921
0
      obj->object()
922
0
          ->GetInternalField(kSyntheticEvaluationStepsSlot)
923
0
          .As<Value>()
924
0
          .As<Function>();
925
0
  obj->object()->SetInternalField(
926
0
      kSyntheticEvaluationStepsSlot, Undefined(isolate));
927
0
  MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
928
0
      obj->object(), 0, nullptr);
929
0
  if (ret.IsEmpty()) {
930
0
    CHECK(try_catch.HasCaught());
931
0
  }
932
0
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
933
0
    CHECK(!try_catch.Message().IsEmpty());
934
0
    CHECK(!try_catch.Exception().IsEmpty());
935
0
    try_catch.ReThrow();
936
0
    return MaybeLocal<Value>();
937
0
  }
938
939
0
  Local<Promise::Resolver> resolver;
940
0
  if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
941
0
    return MaybeLocal<Value>();
942
0
  }
943
944
0
  resolver->Resolve(context, Undefined(isolate)).ToChecked();
945
0
  return resolver->GetPromise();
946
0
}
947
948
0
void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
949
0
  Isolate* isolate = args.GetIsolate();
950
0
  Local<Object> that = args.This();
951
952
0
  ModuleWrap* obj;
953
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
954
955
0
  CHECK(obj->synthetic_);
956
957
0
  CHECK_EQ(args.Length(), 2);
958
959
0
  CHECK(args[0]->IsString());
960
0
  Local<String> export_name = args[0].As<String>();
961
962
0
  Local<Value> export_value = args[1];
963
964
0
  Local<Module> module = obj->module_.Get(isolate);
965
0
  USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
966
0
}
967
968
0
void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
969
0
  Isolate* isolate = args.GetIsolate();
970
0
  Local<Object> that = args.This();
971
972
0
  ModuleWrap* obj;
973
0
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
974
975
0
  CHECK(!obj->synthetic_);
976
977
0
  Local<Module> module = obj->module_.Get(isolate);
978
979
0
  CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
980
981
0
  Local<UnboundModuleScript> unbound_module_script =
982
0
      module->GetUnboundModuleScript();
983
0
  std::unique_ptr<ScriptCompiler::CachedData> cached_data(
984
0
      ScriptCompiler::CreateCodeCache(unbound_module_script));
985
0
  Environment* env = Environment::GetCurrent(args);
986
0
  if (!cached_data) {
987
0
    args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
988
0
  } else {
989
0
    MaybeLocal<Object> buf =
990
0
        Buffer::Copy(env,
991
0
                     reinterpret_cast<const char*>(cached_data->data),
992
0
                     cached_data->length);
993
0
    args.GetReturnValue().Set(buf.ToLocalChecked());
994
0
  }
995
0
}
996
997
void ModuleWrap::CreatePerIsolateProperties(IsolateData* isolate_data,
998
126k
                                            Local<ObjectTemplate> target) {
999
126k
  Isolate* isolate = isolate_data->isolate();
1000
1001
126k
  Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New);
1002
126k
  tpl->InstanceTemplate()->SetInternalFieldCount(
1003
126k
      ModuleWrap::kInternalFieldCount);
1004
1005
126k
  SetProtoMethod(isolate, tpl, "link", Link);
1006
126k
  SetProtoMethod(isolate, tpl, "getModuleRequestsSync", GetModuleRequestsSync);
1007
126k
  SetProtoMethod(
1008
126k
      isolate, tpl, "cacheResolvedWrapsSync", CacheResolvedWrapsSync);
1009
126k
  SetProtoMethod(isolate, tpl, "instantiateSync", InstantiateSync);
1010
126k
  SetProtoMethod(isolate, tpl, "evaluateSync", EvaluateSync);
1011
126k
  SetProtoMethod(isolate, tpl, "getNamespaceSync", GetNamespaceSync);
1012
126k
  SetProtoMethod(isolate, tpl, "instantiate", Instantiate);
1013
126k
  SetProtoMethod(isolate, tpl, "evaluate", Evaluate);
1014
126k
  SetProtoMethod(isolate, tpl, "setExport", SetSyntheticExport);
1015
126k
  SetProtoMethodNoSideEffect(
1016
126k
      isolate, tpl, "createCachedData", CreateCachedData);
1017
126k
  SetProtoMethodNoSideEffect(isolate, tpl, "getNamespace", GetNamespace);
1018
126k
  SetProtoMethodNoSideEffect(isolate, tpl, "getStatus", GetStatus);
1019
126k
  SetProtoMethodNoSideEffect(isolate, tpl, "getError", GetError);
1020
126k
  SetProtoMethodNoSideEffect(isolate,
1021
126k
                             tpl,
1022
126k
                             "getStaticDependencySpecifiers",
1023
126k
                             GetStaticDependencySpecifiers);
1024
1025
126k
  SetConstructorFunction(isolate, target, "ModuleWrap", tpl);
1026
1027
126k
  SetMethod(isolate,
1028
126k
            target,
1029
126k
            "setImportModuleDynamicallyCallback",
1030
126k
            SetImportModuleDynamicallyCallback);
1031
126k
  SetMethod(isolate,
1032
126k
            target,
1033
126k
            "setInitializeImportMetaObjectCallback",
1034
126k
            SetInitializeImportMetaObjectCallback);
1035
126k
}
1036
1037
void ModuleWrap::CreatePerContextProperties(Local<Object> target,
1038
                                            Local<Value> unused,
1039
                                            Local<Context> context,
1040
126k
                                            void* priv) {
1041
126k
  Realm* realm = Realm::GetCurrent(context);
1042
126k
  Isolate* isolate = realm->isolate();
1043
126k
#define V(name)                                                                \
1044
761k
  target                                                                       \
1045
761k
      ->Set(context,                                                           \
1046
761k
            FIXED_ONE_BYTE_STRING(isolate, #name),                             \
1047
761k
            Integer::New(isolate, Module::Status::name))                       \
1048
761k
      .FromJust()
1049
126k
  V(kUninstantiated);
1050
126k
  V(kInstantiating);
1051
126k
  V(kInstantiated);
1052
126k
  V(kEvaluating);
1053
126k
  V(kEvaluated);
1054
126k
  V(kErrored);
1055
126k
#undef V
1056
126k
}
1057
1058
void ModuleWrap::RegisterExternalReferences(
1059
0
    ExternalReferenceRegistry* registry) {
1060
0
  registry->Register(New);
1061
1062
0
  registry->Register(Link);
1063
0
  registry->Register(GetModuleRequestsSync);
1064
0
  registry->Register(CacheResolvedWrapsSync);
1065
0
  registry->Register(InstantiateSync);
1066
0
  registry->Register(EvaluateSync);
1067
0
  registry->Register(GetNamespaceSync);
1068
0
  registry->Register(Instantiate);
1069
0
  registry->Register(Evaluate);
1070
0
  registry->Register(SetSyntheticExport);
1071
0
  registry->Register(CreateCachedData);
1072
0
  registry->Register(GetNamespace);
1073
0
  registry->Register(GetStatus);
1074
0
  registry->Register(GetError);
1075
0
  registry->Register(GetStaticDependencySpecifiers);
1076
1077
0
  registry->Register(SetImportModuleDynamicallyCallback);
1078
0
  registry->Register(SetInitializeImportMetaObjectCallback);
1079
0
}
1080
}  // namespace loader
1081
}  // namespace node
1082
1083
NODE_BINDING_CONTEXT_AWARE_INTERNAL(
1084
    module_wrap, node::loader::ModuleWrap::CreatePerContextProperties)
1085
NODE_BINDING_PER_ISOLATE_INIT(
1086
    module_wrap, node::loader::ModuleWrap::CreatePerIsolateProperties)
1087
NODE_BINDING_EXTERNAL_REFERENCE(
1088
    module_wrap, node::loader::ModuleWrap::RegisterExternalReferences)