GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: module_wrap.cc Lines: 390 433 90.1 %
Date: 2022-09-07 04:19:57 Branches: 172 293 58.7 %

Line Branch Exec Source
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_internals.h"
8
#include "node_process-inl.h"
9
#include "node_url.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 node::url::URL;
24
using node::url::URL_FLAGS_FAILED;
25
using v8::Array;
26
using v8::ArrayBufferView;
27
using v8::Context;
28
using v8::EscapableHandleScope;
29
using v8::FixedArray;
30
using v8::Function;
31
using v8::FunctionCallbackInfo;
32
using v8::FunctionTemplate;
33
using v8::HandleScope;
34
using v8::Int32;
35
using v8::Integer;
36
using v8::IntegrityLevel;
37
using v8::Isolate;
38
using v8::Local;
39
using v8::MaybeLocal;
40
using v8::MicrotaskQueue;
41
using v8::Module;
42
using v8::ModuleRequest;
43
using v8::Number;
44
using v8::Object;
45
using v8::PrimitiveArray;
46
using v8::Promise;
47
using v8::ScriptCompiler;
48
using v8::ScriptOrigin;
49
using v8::String;
50
using v8::UnboundModuleScript;
51
using v8::Undefined;
52
using v8::Value;
53
54
51680
ModuleWrap::ModuleWrap(Environment* env,
55
                       Local<Object> object,
56
                       Local<Module> module,
57
51680
                       Local<String> url)
58
  : BaseObject(env, object),
59
    module_(env->isolate(), module),
60
103360
    id_(env->get_next_module_id()) {
61
51680
  env->id_to_module_map.emplace(id_, this);
62
63
103360
  Local<Value> undefined = Undefined(env->isolate());
64
51680
  object->SetInternalField(kURLSlot, url);
65
51680
  object->SetInternalField(kSyntheticEvaluationStepsSlot, undefined);
66
51680
  object->SetInternalField(kContextObjectSlot, undefined);
67
51680
}
68
69
292482
ModuleWrap::~ModuleWrap() {
70
194988
  HandleScope scope(env()->isolate());
71
97494
  Local<Module> module = module_.Get(env()->isolate());
72
97494
  env()->id_to_module_map.erase(id_);
73
97494
  auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash());
74
97494
  for (auto it = range.first; it != range.second; ++it) {
75
97494
    if (it->second == this) {
76
97494
      env()->hash_to_module_map.erase(it);
77
97494
      break;
78
    }
79
  }
80
194988
}
81
82
103760
Local<Context> ModuleWrap::context() const {
83
311280
  Local<Value> obj = object()->GetInternalField(kContextObjectSlot);
84
103760
  if (obj.IsEmpty()) return {};
85
207520
  return obj.As<Object>()->GetCreationContext().ToLocalChecked();
86
}
87
88
52037
ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
89
                                      Local<Module> module) {
90
52037
  auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
91
52037
  for (auto it = range.first; it != range.second; ++it) {
92

104074
    if (it->second->module_ == module) {
93
52037
      return it->second;
94
    }
95
  }
96
  return nullptr;
97
}
98
99
256
ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) {
100
256
  auto module_wrap_it = env->id_to_module_map.find(id);
101
256
  if (module_wrap_it == env->id_to_module_map.end()) {
102
    return nullptr;
103
  }
104
256
  return module_wrap_it->second;
105
}
106
107
// new ModuleWrap(url, context, source, lineOffset, columnOffset)
108
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
109
51687
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
110
51687
  CHECK(args.IsConstructCall());
111
51687
  CHECK_GE(args.Length(), 3);
112
113
51687
  Environment* env = Environment::GetCurrent(args);
114
51687
  Isolate* isolate = env->isolate();
115
116
51687
  Local<Object> that = args.This();
117
118
103374
  CHECK(args[0]->IsString());
119
103374
  Local<String> url = args[0].As<String>();
120
121
  Local<Context> context;
122
51687
  ContextifyContext* contextify_context = nullptr;
123
103374
  if (args[1]->IsUndefined()) {
124
103330
    context = that->GetCreationContext().ToLocalChecked();
125
  } else {
126
22
    CHECK(args[1]->IsObject());
127
44
    contextify_context = ContextifyContext::ContextFromContextifiedSandbox(
128
44
        env, args[1].As<Object>());
129
22
    CHECK_NOT_NULL(contextify_context);
130
22
    context = contextify_context->context();
131
  }
132
133
51687
  int line_offset = 0;
134
51687
  int column_offset = 0;
135
136
51687
  bool synthetic = args[2]->IsArray();
137
51687
  if (synthetic) {
138
    // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
139
50763
    CHECK(args[3]->IsFunction());
140
  } else {
141
    // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
142
1848
    CHECK(args[2]->IsString());
143
924
    CHECK(args[3]->IsNumber());
144
1848
    line_offset = args[3].As<Int32>()->Value();
145
924
    CHECK(args[4]->IsNumber());
146
1848
    column_offset = args[4].As<Int32>()->Value();
147
  }
148
149
  Local<PrimitiveArray> host_defined_options =
150
51687
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
151
103374
  host_defined_options->Set(isolate, HostDefinedOptions::kType,
152
                            Number::New(isolate, ScriptType::kModule));
153
154
51687
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
155
51687
  TryCatchScope try_catch(env);
156
157
  Local<Module> module;
158
159
  {
160
51687
    Context::Scope context_scope(context);
161
51687
    if (synthetic) {
162
50763
      CHECK(args[2]->IsArray());
163
101526
      Local<Array> export_names_arr = args[2].As<Array>();
164
165
50763
      uint32_t len = export_names_arr->Length();
166
101526
      std::vector<Local<String>> export_names(len);
167
1653037
      for (uint32_t i = 0; i < len; i++) {
168
        Local<Value> export_name_val =
169
3204548
            export_names_arr->Get(context, i).ToLocalChecked();
170
3204548
        CHECK(export_name_val->IsString());
171
1602274
        export_names[i] = export_name_val.As<String>();
172
      }
173
174
      module = Module::CreateSyntheticModule(isolate, url, export_names,
175
50763
        SyntheticModuleEvaluationStepsCallback);
176
    } else {
177
924
      ScriptCompiler::CachedData* cached_data = nullptr;
178
2772
      if (!args[5]->IsUndefined()) {
179
2
        CHECK(args[5]->IsArrayBufferView());
180
6
        Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
181
        uint8_t* data =
182
4
            static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
183
2
        cached_data =
184
2
            new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
185
2
                                           cached_data_buf->ByteLength());
186
      }
187
188
1848
      Local<String> source_text = args[2].As<String>();
189
      ScriptOrigin origin(isolate,
190
                          url,
191
                          line_offset,
192
                          column_offset,
193
                          true,                             // is cross origin
194
                          -1,                               // script id
195
                          Local<Value>(),                   // source map URL
196
                          false,                            // is opaque (?)
197
                          false,                            // is WASM
198
                          true,                             // is ES Module
199
1848
                          host_defined_options);
200
924
      ScriptCompiler::Source source(source_text, origin, cached_data);
201
      ScriptCompiler::CompileOptions options;
202
924
      if (source.GetCachedData() == nullptr) {
203
922
        options = ScriptCompiler::kNoCompileOptions;
204
      } else {
205
2
        options = ScriptCompiler::kConsumeCodeCache;
206
      }
207
924
      if (!ScriptCompiler::CompileModule(isolate, &source, options)
208
924
               .ToLocal(&module)) {
209

6
        if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
210
12
          CHECK(!try_catch.Message().IsEmpty());
211
12
          CHECK(!try_catch.Exception().IsEmpty());
212
6
          AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
213
                              ErrorHandlingMode::MODULE_ERROR);
214
6
          try_catch.ReThrow();
215
        }
216
6
        return;
217
      }
218

920
      if (options == ScriptCompiler::kConsumeCodeCache &&
219
2
          source.GetCachedData()->rejected) {
220
1
        THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED(
221
            env, "cachedData buffer was rejected");
222
1
        try_catch.ReThrow();
223
1
        return;
224
      }
225
    }
226
  }
227
228

155040
  if (!that->Set(context, env->url_string(), url).FromMaybe(false)) {
229
    return;
230
  }
231
232
51680
  ModuleWrap* obj = new ModuleWrap(env, that, module, url);
233
234
51680
  if (synthetic) {
235
50763
    obj->synthetic_ = true;
236
152289
    obj->object()->SetInternalField(kSyntheticEvaluationStepsSlot, args[3]);
237
  }
238
239
  // Use the extras object as an object whose GetCreationContext() will be the
240
  // original `context`, since the `Context` itself strictly speaking cannot
241
  // be stored in an internal field.
242
155040
  obj->object()->SetInternalField(kContextObjectSlot,
243
      context->GetExtrasBindingObject());
244
51680
  obj->contextify_context_ = contextify_context;
245
246
51680
  env->hash_to_module_map.emplace(module->GetIdentityHash(), obj);
247
248
103360
  host_defined_options->Set(isolate, HostDefinedOptions::kID,
249
51680
                            Number::New(isolate, obj->id()));
250
251
51680
  that->SetIntegrityLevel(context, IntegrityLevel::kFrozen);
252
103360
  args.GetReturnValue().Set(that);
253
}
254
255
1531
static Local<Object> createImportAssertionContainer(Environment* env,
256
  Isolate* isolate, Local<FixedArray> raw_assertions) {
257
  Local<Object> assertions =
258
3062
        Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0);
259
3106
  for (int i = 0; i < raw_assertions->Length(); i += 3) {
260
      assertions
261
44
          ->Set(env->context(),
262
44
                raw_assertions->Get(env->context(), i).As<String>(),
263
132
                raw_assertions->Get(env->context(), i + 1).As<Value>())
264
          .ToChecked();
265
  }
266
267
1531
  return assertions;
268
}
269
270
1512
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
271
1512
  Environment* env = Environment::GetCurrent(args);
272
1512
  Isolate* isolate = args.GetIsolate();
273
274
1512
  CHECK_EQ(args.Length(), 1);
275
1512
  CHECK(args[0]->IsFunction());
276
277
1512
  Local<Object> that = args.This();
278
279
  ModuleWrap* obj;
280
1515
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
281
282
1512
  if (obj->linked_)
283
3
    return;
284
1509
  obj->linked_ = true;
285
286
1509
  Local<Function> resolver_arg = args[0].As<Function>();
287
288
1509
  Local<Context> mod_context = obj->context();
289
3018
  Local<Module> module = obj->module_.Get(isolate);
290
291
1509
  Local<FixedArray> module_requests = module->GetModuleRequests();
292
1509
  const int module_requests_length = module_requests->Length();
293
1509
  MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
294
295
  // call the dependency resolve callbacks
296
2672
  for (int i = 0; i < module_requests_length; i++) {
297
    Local<ModuleRequest> module_request =
298
2326
      module_requests->Get(env->context(), i).As<ModuleRequest>();
299
1163
    Local<String> specifier = module_request->GetSpecifier();
300
1163
    Utf8Value specifier_utf8(env->isolate(), specifier);
301
2326
    std::string specifier_std(*specifier_utf8, specifier_utf8.length());
302
303
1163
    Local<FixedArray> raw_assertions = module_request->GetImportAssertions();
304
    Local<Object> assertions =
305
1163
      createImportAssertionContainer(env, isolate, raw_assertions);
306
307
    Local<Value> argv[] = {
308
        specifier,
309
        assertions,
310
1163
    };
311
312
    MaybeLocal<Value> maybe_resolve_return_value =
313
1163
        resolver_arg->Call(mod_context, that, arraysize(argv), argv);
314
1163
    if (maybe_resolve_return_value.IsEmpty()) {
315
      return;
316
    }
317
    Local<Value> resolve_return_value =
318
1163
        maybe_resolve_return_value.ToLocalChecked();
319
1163
    if (!resolve_return_value->IsPromise()) {
320
      THROW_ERR_VM_MODULE_LINK_FAILURE(
321
          env, "request for '%s' did not return promise", specifier_std);
322
      return;
323
    }
324
1163
    Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
325
1163
    obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
326
327
1163
    promises[i] = resolve_promise;
328
  }
329
330
3018
  args.GetReturnValue().Set(
331
      Array::New(isolate, promises.out(), promises.length()));
332
}
333
334
51119
void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
335
51119
  Environment* env = Environment::GetCurrent(args);
336
51119
  Isolate* isolate = args.GetIsolate();
337
  ModuleWrap* obj;
338
51134
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
339
51119
  Local<Context> context = obj->context();
340
51119
  Local<Module> module = obj->module_.Get(isolate);
341
51119
  TryCatchScope try_catch(env);
342
51119
  USE(module->InstantiateModule(context, ResolveModuleCallback));
343
344
  // clear resolve cache on instantiate
345
51119
  obj->resolve_cache_.clear();
346
347

51119
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
348
30
    CHECK(!try_catch.Message().IsEmpty());
349
30
    CHECK(!try_catch.Exception().IsEmpty());
350
15
    AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
351
                        ErrorHandlingMode::MODULE_ERROR);
352
15
    try_catch.ReThrow();
353
15
    return;
354
  }
355
}
356
357
51132
void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
358
51132
  Environment* env = Environment::GetCurrent(args);
359
51132
  Isolate* isolate = env->isolate();
360
  ModuleWrap* obj;
361
51142
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
362
51132
  Local<Context> context = obj->context();
363
51132
  Local<Module> module = obj->module_.Get(isolate);
364
365
51132
  ContextifyContext* contextify_context = obj->contextify_context_;
366
51132
  std::shared_ptr<MicrotaskQueue> microtask_queue;
367
51132
  if (contextify_context != nullptr)
368
4
      microtask_queue = contextify_context->microtask_queue();
369
370
  // module.evaluate(timeout, breakOnSigint)
371
51132
  CHECK_EQ(args.Length(), 2);
372
373
51132
  CHECK(args[0]->IsNumber());
374
102264
  int64_t timeout = args[0]->IntegerValue(env->context()).FromJust();
375
376
51132
  CHECK(args[1]->IsBoolean());
377
51132
  bool break_on_sigint = args[1]->IsTrue();
378
379
51132
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
380
51132
  TryCatchScope try_catch(env);
381
51132
  Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
382
383
51132
  bool timed_out = false;
384
51132
  bool received_signal = false;
385
  MaybeLocal<Value> result;
386
51132
  auto run = [&]() {
387
51132
    MaybeLocal<Value> result = module->Evaluate(context);
388

51129
    if (!result.IsEmpty() && microtask_queue)
389
1
      microtask_queue->PerformCheckpoint(isolate);
390
51129
    return result;
391
51132
  };
392

51132
  if (break_on_sigint && timeout != -1) {
393
    Watchdog wd(isolate, timeout, &timed_out);
394
    SigintWatchdog swd(isolate, &received_signal);
395
    result = run();
396
51132
  } else if (break_on_sigint) {
397
    SigintWatchdog swd(isolate, &received_signal);
398
    result = run();
399
51132
  } else if (timeout != -1) {
400
6
    Watchdog wd(isolate, timeout, &timed_out);
401
3
    result = run();
402
  } else {
403
51129
    result = run();
404
  }
405
406
51129
  if (result.IsEmpty()) {
407
4
    CHECK(try_catch.HasCaught());
408
  }
409
410
  // Convert the termination exception into a regular exception.
411

51129
  if (timed_out || received_signal) {
412

3
    if (!env->is_main_thread() && env->is_stopping())
413
      return;
414
3
    env->isolate()->CancelTerminateExecution();
415
    // It is possible that execution was terminated by another timeout in
416
    // which this timeout is nested, so check whether one of the watchdogs
417
    // from this invocation is responsible for termination.
418
3
    if (timed_out) {
419
3
      THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
420
    } else if (received_signal) {
421
      THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
422
    }
423
  }
424
425
51129
  if (try_catch.HasCaught()) {
426
10
    if (!try_catch.HasTerminated())
427
8
      try_catch.ReThrow();
428
10
    return;
429
  }
430
431
102238
  args.GetReturnValue().Set(result.ToLocalChecked());
432
}
433
434
482
void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
435
482
  Environment* env = Environment::GetCurrent(args);
436
482
  Isolate* isolate = args.GetIsolate();
437
  ModuleWrap* obj;
438
482
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
439
440
964
  Local<Module> module = obj->module_.Get(isolate);
441
442
482
  switch (module->GetStatus()) {
443
    case v8::Module::Status::kUninstantiated:
444
    case v8::Module::Status::kInstantiating:
445
      return env->ThrowError(
446
          "cannot get namespace, module has not been instantiated");
447
482
    case v8::Module::Status::kInstantiated:
448
    case v8::Module::Status::kEvaluating:
449
    case v8::Module::Status::kEvaluated:
450
    case v8::Module::Status::kErrored:
451
482
      break;
452
    default:
453
      UNREACHABLE();
454
  }
455
456
482
  Local<Value> result = module->GetModuleNamespace();
457
964
  args.GetReturnValue().Set(result);
458
}
459
460
219
void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
461
219
  Isolate* isolate = args.GetIsolate();
462
  ModuleWrap* obj;
463
219
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
464
465
438
  Local<Module> module = obj->module_.Get(isolate);
466
467
438
  args.GetReturnValue().Set(module->GetStatus());
468
}
469
470
2
void ModuleWrap::GetStaticDependencySpecifiers(
471
    const FunctionCallbackInfo<Value>& args) {
472
2
  Environment* env = Environment::GetCurrent(args);
473
  ModuleWrap* obj;
474
2
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
475
476
4
  Local<Module> module = obj->module_.Get(env->isolate());
477
478
2
  Local<FixedArray> module_requests = module->GetModuleRequests();
479
2
  int count = module_requests->Length();
480
481
2
  MaybeStackBuffer<Local<Value>, 16> specifiers(count);
482
483
3
  for (int i = 0; i < count; i++) {
484
    Local<ModuleRequest> module_request =
485
2
      module_requests->Get(env->context(), i).As<ModuleRequest>();
486
2
    specifiers[i] = module_request->GetSpecifier();
487
  }
488
489
4
  args.GetReturnValue().Set(
490
      Array::New(env->isolate(), specifiers.out(), count));
491
}
492
493
2
void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
494
2
  Isolate* isolate = args.GetIsolate();
495
  ModuleWrap* obj;
496
2
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
497
498
4
  Local<Module> module = obj->module_.Get(isolate);
499
4
  args.GetReturnValue().Set(module->GetException());
500
}
501
502
1116
MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
503
    Local<Context> context,
504
    Local<String> specifier,
505
    Local<FixedArray> import_assertions,
506
    Local<Module> referrer) {
507
1116
  Environment* env = Environment::GetCurrent(context);
508
1116
  if (env == nullptr) {
509
    Isolate* isolate = context->GetIsolate();
510
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
511
    return MaybeLocal<Module>();
512
  }
513
514
1116
  Isolate* isolate = env->isolate();
515
516
2232
  Utf8Value specifier_utf8(isolate, specifier);
517
2232
  std::string specifier_std(*specifier_utf8, specifier_utf8.length());
518
519
1116
  ModuleWrap* dependent = GetFromModule(env, referrer);
520
1116
  if (dependent == nullptr) {
521
    THROW_ERR_VM_MODULE_LINK_FAILURE(
522
        env, "request for '%s' is from invalid module", specifier_std);
523
    return MaybeLocal<Module>();
524
  }
525
526
1116
  if (dependent->resolve_cache_.count(specifier_std) != 1) {
527
    THROW_ERR_VM_MODULE_LINK_FAILURE(
528
        env, "request for '%s' is not in cache", specifier_std);
529
    return MaybeLocal<Module>();
530
  }
531
532
  Local<Promise> resolve_promise =
533
2232
      dependent->resolve_cache_[specifier_std].Get(isolate);
534
535
1116
  if (resolve_promise->State() != Promise::kFulfilled) {
536
    THROW_ERR_VM_MODULE_LINK_FAILURE(
537
        env, "request for '%s' is not yet fulfilled", specifier_std);
538
    return MaybeLocal<Module>();
539
  }
540
541
2232
  Local<Object> module_object = resolve_promise->Result().As<Object>();
542

2232
  if (module_object.IsEmpty() || !module_object->IsObject()) {
543
    THROW_ERR_VM_MODULE_LINK_FAILURE(
544
        env, "request for '%s' did not return an object", specifier_std);
545
    return MaybeLocal<Module>();
546
  }
547
548
  ModuleWrap* module;
549
1116
  ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
550
2232
  return module->module_.Get(isolate);
551
}
552
553
368
static MaybeLocal<Promise> ImportModuleDynamically(
554
    Local<Context> context,
555
    Local<v8::Data> host_defined_options,
556
    Local<Value> resource_name,
557
    Local<String> specifier,
558
    Local<FixedArray> import_assertions) {
559
368
  Isolate* isolate = context->GetIsolate();
560
368
  Environment* env = Environment::GetCurrent(context);
561
368
  if (env == nullptr) {
562
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
563
    return MaybeLocal<Promise>();
564
  }
565
566
368
  EscapableHandleScope handle_scope(isolate);
567
568
  Local<Function> import_callback =
569
368
    env->host_import_module_dynamically_callback();
570
571
368
  Local<FixedArray> options = host_defined_options.As<FixedArray>();
572
368
  if (options->Length() != HostDefinedOptions::kLength) {
573
    Local<Promise::Resolver> resolver;
574
    if (!Promise::Resolver::New(context).ToLocal(&resolver)) return {};
575
    resolver
576
        ->Reject(context,
577
                 v8::Exception::TypeError(FIXED_ONE_BYTE_STRING(
578
                     context->GetIsolate(), "Invalid host defined options")))
579
        .ToChecked();
580
    return handle_scope.Escape(resolver->GetPromise());
581
  }
582
583
  Local<Value> object;
584
585
368
  int type = options->Get(context, HostDefinedOptions::kType)
586
368
                 .As<Number>()
587
368
                 ->Int32Value(context)
588
368
                 .ToChecked();
589
368
  uint32_t id = options->Get(context, HostDefinedOptions::kID)
590
368
                    .As<Number>()
591
368
                    ->Uint32Value(context)
592
368
                    .ToChecked();
593
368
  if (type == ScriptType::kScript) {
594
10
    contextify::ContextifyScript* wrap = env->id_to_script_map.find(id)->second;
595
20
    object = wrap->object();
596
358
  } else if (type == ScriptType::kModule) {
597
256
    ModuleWrap* wrap = ModuleWrap::GetFromID(env, id);
598
512
    object = wrap->object();
599
102
  } else if (type == ScriptType::kFunction) {
600
102
    auto it = env->id_to_function_map.find(id);
601
102
    CHECK_NE(it, env->id_to_function_map.end());
602
204
    object = it->second->object();
603
  } else {
604
    UNREACHABLE();
605
  }
606
607
  Local<Object> assertions =
608
368
    createImportAssertionContainer(env, isolate, import_assertions);
609
610
  Local<Value> import_args[] = {
611
    object,
612
    Local<Value>(specifier),
613
    assertions,
614
368
  };
615
616
  Local<Value> result;
617
736
  if (import_callback->Call(
618
        context,
619
        Undefined(isolate),
620
368
        arraysize(import_args),
621
1104
        import_args).ToLocal(&result)) {
622
368
    CHECK(result->IsPromise());
623
368
    return handle_scope.Escape(result.As<Promise>());
624
  }
625
626
  return MaybeLocal<Promise>();
627
}
628
629
6198
void ModuleWrap::SetImportModuleDynamicallyCallback(
630
    const FunctionCallbackInfo<Value>& args) {
631
6198
  Isolate* isolate = args.GetIsolate();
632
6198
  Environment* env = Environment::GetCurrent(args);
633
12396
  HandleScope handle_scope(isolate);
634
635
6198
  CHECK_EQ(args.Length(), 1);
636
6198
  CHECK(args[0]->IsFunction());
637
6198
  Local<Function> import_callback = args[0].As<Function>();
638
6198
  env->set_host_import_module_dynamically_callback(import_callback);
639
640
6198
  isolate->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
641
6198
}
642
643
175
void ModuleWrap::HostInitializeImportMetaObjectCallback(
644
    Local<Context> context, Local<Module> module, Local<Object> meta) {
645
175
  Environment* env = Environment::GetCurrent(context);
646
175
  if (env == nullptr)
647
    return;
648
175
  ModuleWrap* module_wrap = GetFromModule(env, module);
649
650
175
  if (module_wrap == nullptr) {
651
    return;
652
  }
653
654
175
  Local<Object> wrap = module_wrap->object();
655
  Local<Function> callback =
656
175
      env->host_initialize_import_meta_object_callback();
657
175
  Local<Value> args[] = { wrap, meta };
658
350
  TryCatchScope try_catch(env);
659
175
  USE(callback->Call(
660
350
        context, Undefined(env->isolate()), arraysize(args), args));
661

175
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
662
    try_catch.ReThrow();
663
  }
664
}
665
666
6198
void ModuleWrap::SetInitializeImportMetaObjectCallback(
667
    const FunctionCallbackInfo<Value>& args) {
668
6198
  Environment* env = Environment::GetCurrent(args);
669
6198
  Isolate* isolate = env->isolate();
670
671
6198
  CHECK_EQ(args.Length(), 1);
672
6198
  CHECK(args[0]->IsFunction());
673
6198
  Local<Function> import_meta_callback = args[0].As<Function>();
674
6198
  env->set_host_initialize_import_meta_object_callback(import_meta_callback);
675
676
6198
  isolate->SetHostInitializeImportMetaObjectCallback(
677
      HostInitializeImportMetaObjectCallback);
678
6198
}
679
680
50746
MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
681
    Local<Context> context, Local<Module> module) {
682
50746
  Environment* env = Environment::GetCurrent(context);
683
50746
  Isolate* isolate = env->isolate();
684
685
50746
  ModuleWrap* obj = GetFromModule(env, module);
686
687
101492
  TryCatchScope try_catch(env);
688
  Local<Function> synthetic_evaluation_steps =
689
152238
      obj->object()->GetInternalField(kSyntheticEvaluationStepsSlot)
690
50746
          .As<Function>();
691
152238
  obj->object()->SetInternalField(
692
      kSyntheticEvaluationStepsSlot, Undefined(isolate));
693
  MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
694
101492
      obj->object(), 0, nullptr);
695
50746
  if (ret.IsEmpty()) {
696
5
    CHECK(try_catch.HasCaught());
697
  }
698

50746
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
699
10
    CHECK(!try_catch.Message().IsEmpty());
700
10
    CHECK(!try_catch.Exception().IsEmpty());
701
5
    try_catch.ReThrow();
702
5
    return MaybeLocal<Value>();
703
  }
704
705
  Local<Promise::Resolver> resolver;
706
101482
  if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
707
    return MaybeLocal<Value>();
708
  }
709
710
152223
  resolver->Resolve(context, Undefined(isolate)).ToChecked();
711
101482
  return resolver->GetPromise();
712
}
713
714
4459465
void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
715
4459465
  Isolate* isolate = args.GetIsolate();
716
4459465
  Local<Object> that = args.This();
717
718
  ModuleWrap* obj;
719
4459465
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
720
721
4459465
  CHECK(obj->synthetic_);
722
723
4459465
  CHECK_EQ(args.Length(), 2);
724
725
8918930
  CHECK(args[0]->IsString());
726
8918930
  Local<String> export_name = args[0].As<String>();
727
728
4459465
  Local<Value> export_value = args[1];
729
730
8918930
  Local<Module> module = obj->module_.Get(isolate);
731
4459465
  USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
732
}
733
734
1
void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
735
1
  Isolate* isolate = args.GetIsolate();
736
1
  Local<Object> that = args.This();
737
738
  ModuleWrap* obj;
739
1
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
740
741
1
  CHECK(!obj->synthetic_);
742
743
2
  Local<Module> module = obj->module_.Get(isolate);
744
745
1
  CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
746
747
  Local<UnboundModuleScript> unbound_module_script =
748
1
      module->GetUnboundModuleScript();
749
  std::unique_ptr<ScriptCompiler::CachedData> cached_data(
750
2
      ScriptCompiler::CreateCodeCache(unbound_module_script));
751
1
  Environment* env = Environment::GetCurrent(args);
752
1
  if (!cached_data) {
753
    args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
754
  } else {
755
    MaybeLocal<Object> buf =
756
        Buffer::Copy(env,
757
2
                     reinterpret_cast<const char*>(cached_data->data),
758
1
                     cached_data->length);
759
2
    args.GetReturnValue().Set(buf.ToLocalChecked());
760
  }
761
}
762
763
6199
void ModuleWrap::Initialize(Local<Object> target,
764
                            Local<Value> unused,
765
                            Local<Context> context,
766
                            void* priv) {
767
6199
  Environment* env = Environment::GetCurrent(context);
768
6199
  Isolate* isolate = env->isolate();
769
770
6199
  Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New);
771
12398
  tpl->InstanceTemplate()->SetInternalFieldCount(
772
      ModuleWrap::kInternalFieldCount);
773
6199
  tpl->Inherit(BaseObject::GetConstructorTemplate(env));
774
775
6199
  SetProtoMethod(isolate, tpl, "link", Link);
776
6199
  SetProtoMethod(isolate, tpl, "instantiate", Instantiate);
777
6199
  SetProtoMethod(isolate, tpl, "evaluate", Evaluate);
778
6199
  SetProtoMethod(isolate, tpl, "setExport", SetSyntheticExport);
779
6199
  SetProtoMethodNoSideEffect(
780
      isolate, tpl, "createCachedData", CreateCachedData);
781
6199
  SetProtoMethodNoSideEffect(isolate, tpl, "getNamespace", GetNamespace);
782
6199
  SetProtoMethodNoSideEffect(isolate, tpl, "getStatus", GetStatus);
783
6199
  SetProtoMethodNoSideEffect(isolate, tpl, "getError", GetError);
784
6199
  SetProtoMethodNoSideEffect(isolate,
785
                             tpl,
786
                             "getStaticDependencySpecifiers",
787
                             GetStaticDependencySpecifiers);
788
789
6199
  SetConstructorFunction(context, target, "ModuleWrap", tpl);
790
791
6199
  SetMethod(context,
792
            target,
793
            "setImportModuleDynamicallyCallback",
794
            SetImportModuleDynamicallyCallback);
795
6199
  SetMethod(context,
796
            target,
797
            "setInitializeImportMetaObjectCallback",
798
            SetInitializeImportMetaObjectCallback);
799
800
#define V(name)                                                                \
801
    target->Set(context,                                                       \
802
      FIXED_ONE_BYTE_STRING(env->isolate(), #name),                            \
803
      Integer::New(env->isolate(), Module::Status::name))                      \
804
        .FromJust()
805
24796
    V(kUninstantiated);
806
24796
    V(kInstantiating);
807
24796
    V(kInstantiated);
808
24796
    V(kEvaluating);
809
24796
    V(kEvaluated);
810
18597
    V(kErrored);
811
#undef V
812
6199
}
813
814
}  // namespace loader
815
}  // namespace node
816
817
5545
NODE_MODULE_CONTEXT_AWARE_INTERNAL(module_wrap,
818
                                   node::loader::ModuleWrap::Initialize)