GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/module_wrap.cc Lines: 251 418 60.0 %
Date: 2021-02-19 04:08:54 Branches: 83 265 31.3 %

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.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::Function;
30
using v8::FunctionCallbackInfo;
31
using v8::FunctionTemplate;
32
using v8::HandleScope;
33
using v8::Integer;
34
using v8::IntegrityLevel;
35
using v8::Isolate;
36
using v8::Local;
37
using v8::MaybeLocal;
38
using v8::MicrotaskQueue;
39
using v8::Module;
40
using v8::Number;
41
using v8::Object;
42
using v8::PrimitiveArray;
43
using v8::Promise;
44
using v8::ScriptCompiler;
45
using v8::ScriptOrigin;
46
using v8::ScriptOrModule;
47
using v8::String;
48
using v8::UnboundModuleScript;
49
using v8::Undefined;
50
using v8::Value;
51
52
1072
ModuleWrap::ModuleWrap(Environment* env,
53
                       Local<Object> object,
54
                       Local<Module> module,
55
1072
                       Local<String> url)
56
  : BaseObject(env, object),
57
    module_(env->isolate(), module),
58
2144
    id_(env->get_next_module_id()) {
59
1072
  env->id_to_module_map.emplace(id_, this);
60
61
1072
  Local<Value> undefined = Undefined(env->isolate());
62
1072
  object->SetInternalField(kURLSlot, url);
63
1072
  object->SetInternalField(kSyntheticEvaluationStepsSlot, undefined);
64
1072
  object->SetInternalField(kContextObjectSlot, undefined);
65
1072
}
66
67
4136
ModuleWrap::~ModuleWrap() {
68
2068
  HandleScope scope(env()->isolate());
69
2068
  Local<Module> module = module_.Get(env()->isolate());
70
1034
  env()->id_to_module_map.erase(id_);
71
1034
  auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash());
72
1034
  for (auto it = range.first; it != range.second; ++it) {
73
1034
    if (it->second == this) {
74
1034
      env()->hash_to_module_map.erase(it);
75
1034
      break;
76
    }
77
  }
78
2068
}
79
80
2146
Local<Context> ModuleWrap::context() const {
81
6438
  Local<Value> obj = object()->GetInternalField(kContextObjectSlot);
82
2146
  if (obj.IsEmpty()) return {};
83
4292
  return obj.As<Object>()->CreationContext();
84
}
85
86
1069
ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
87
                                      Local<Module> module) {
88
1069
  auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
89
1069
  for (auto it = range.first; it != range.second; ++it) {
90
2138
    if (it->second->module_ == module) {
91
1069
      return it->second;
92
    }
93
  }
94
  return nullptr;
95
}
96
97
1
ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) {
98
1
  auto module_wrap_it = env->id_to_module_map.find(id);
99
1
  if (module_wrap_it == env->id_to_module_map.end()) {
100
    return nullptr;
101
  }
102
1
  return module_wrap_it->second;
103
}
104
105
// new ModuleWrap(url, context, source, lineOffset, columnOffset)
106
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
107
1072
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
108
1072
  CHECK(args.IsConstructCall());
109
1072
  CHECK_GE(args.Length(), 3);
110
111
1072
  Environment* env = Environment::GetCurrent(args);
112
1072
  Isolate* isolate = env->isolate();
113
114
1072
  Local<Object> that = args.This();
115
116
3216
  CHECK(args[0]->IsString());
117
2144
  Local<String> url = args[0].As<String>();
118
119
  Local<Context> context;
120
1072
  ContextifyContext* contextify_context = nullptr;
121
3216
  if (args[1]->IsUndefined()) {
122
1072
    context = that->CreationContext();
123
  } else {
124
    CHECK(args[1]->IsObject());
125
    contextify_context = ContextifyContext::ContextFromContextifiedSandbox(
126
        env, args[1].As<Object>());
127
    CHECK_NOT_NULL(contextify_context);
128
    context = contextify_context->context();
129
  }
130
131
  Local<Integer> line_offset;
132
  Local<Integer> column_offset;
133
134
2144
  bool synthetic = args[2]->IsArray();
135
1072
  if (synthetic) {
136
    // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
137
2138
    CHECK(args[3]->IsFunction());
138
  } else {
139
    // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
140
9
    CHECK(args[2]->IsString());
141
6
    CHECK(args[3]->IsNumber());
142
6
    line_offset = args[3].As<Integer>();
143
6
    CHECK(args[4]->IsNumber());
144
6
    column_offset = args[4].As<Integer>();
145
  }
146
147
  Local<PrimitiveArray> host_defined_options =
148
1072
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
149
3216
  host_defined_options->Set(isolate, HostDefinedOptions::kType,
150
1072
                            Number::New(isolate, ScriptType::kModule));
151
152
2144
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
153
2144
  TryCatchScope try_catch(env);
154
155
  Local<Module> module;
156
157
  {
158
1072
    Context::Scope context_scope(context);
159
1072
    if (synthetic) {
160
2138
      CHECK(args[2]->IsArray());
161
2138
      Local<Array> export_names_arr = args[2].As<Array>();
162
163
1069
      uint32_t len = export_names_arr->Length();
164
2138
      std::vector<Local<String>> export_names(len);
165
49384
      for (uint32_t i = 0; i < len; i++) {
166
        Local<Value> export_name_val =
167
96630
            export_names_arr->Get(context, i).ToLocalChecked();
168
96630
        CHECK(export_name_val->IsString());
169
96630
        export_names[i] = export_name_val.As<String>();
170
      }
171
172
      module = Module::CreateSyntheticModule(isolate, url, export_names,
173
1069
        SyntheticModuleEvaluationStepsCallback);
174
    } else {
175
3
      ScriptCompiler::CachedData* cached_data = nullptr;
176
9
      if (!args[5]->IsUndefined()) {
177
        CHECK(args[5]->IsArrayBufferView());
178
        Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
179
        uint8_t* data = static_cast<uint8_t*>(
180
            cached_data_buf->Buffer()->GetBackingStore()->Data());
181
        cached_data =
182
            new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
183
                                           cached_data_buf->ByteLength());
184
      }
185
186
6
      Local<String> source_text = args[2].As<String>();
187
      ScriptOrigin origin(url,
188
                          line_offset,                      // line offset
189
                          column_offset,                    // column offset
190
                          True(isolate),                    // is cross origin
191
                          Local<Integer>(),                 // script id
192
                          Local<Value>(),                   // source map URL
193
                          False(isolate),                   // is opaque (?)
194
                          False(isolate),                   // is WASM
195
                          True(isolate),                    // is ES Module
196
3
                          host_defined_options);
197
3
      ScriptCompiler::Source source(source_text, origin, cached_data);
198
      ScriptCompiler::CompileOptions options;
199
3
      if (source.GetCachedData() == nullptr) {
200
3
        options = ScriptCompiler::kNoCompileOptions;
201
      } else {
202
        options = ScriptCompiler::kConsumeCodeCache;
203
      }
204
6
      if (!ScriptCompiler::CompileModule(isolate, &source, options)
205
3
               .ToLocal(&module)) {
206
        if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
207
          CHECK(!try_catch.Message().IsEmpty());
208
          CHECK(!try_catch.Exception().IsEmpty());
209
          AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
210
                              ErrorHandlingMode::MODULE_ERROR);
211
          try_catch.ReThrow();
212
        }
213
        return;
214
      }
215

3
      if (options == ScriptCompiler::kConsumeCodeCache &&
216
          source.GetCachedData()->rejected) {
217
        THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED(
218
            env, "cachedData buffer was rejected");
219
        try_catch.ReThrow();
220
        return;
221
      }
222
    }
223
  }
224
225
4288
  if (!that->Set(context, env->url_string(), url).FromMaybe(false)) {
226
    return;
227
  }
228
229
1072
  ModuleWrap* obj = new ModuleWrap(env, that, module, url);
230
231
1072
  if (synthetic) {
232
1069
    obj->synthetic_ = true;
233
2138
    obj->object()->SetInternalField(kSyntheticEvaluationStepsSlot, args[3]);
234
  }
235
236
  // Use the extras object as an object whose CreationContext() will be the
237
  // original `context`, since the `Context` itself strictly speaking cannot
238
  // be stored in an internal field.
239
4288
  obj->object()->SetInternalField(kContextObjectSlot,
240
1072
      context->GetExtrasBindingObject());
241
1072
  obj->contextify_context_ = contextify_context;
242
243
1072
  env->hash_to_module_map.emplace(module->GetIdentityHash(), obj);
244
245
3216
  host_defined_options->Set(isolate, HostDefinedOptions::kID,
246
2144
                            Number::New(isolate, obj->id()));
247
248
1072
  that->SetIntegrityLevel(context, IntegrityLevel::kFrozen);
249
2144
  args.GetReturnValue().Set(that);
250
}
251
252
3
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
253
3
  Environment* env = Environment::GetCurrent(args);
254
3
  Isolate* isolate = args.GetIsolate();
255
256
3
  CHECK_EQ(args.Length(), 1);
257
6
  CHECK(args[0]->IsFunction());
258
259
3
  Local<Object> that = args.This();
260
261
  ModuleWrap* obj;
262
3
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
263
264
3
  if (obj->linked_)
265
    return;
266
3
  obj->linked_ = true;
267
268
6
  Local<Function> resolver_arg = args[0].As<Function>();
269
270
3
  Local<Context> mod_context = obj->context();
271
6
  Local<Module> module = obj->module_.Get(isolate);
272
273
3
  const int module_requests_length = module->GetModuleRequestsLength();
274
6
  MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
275
276
  // call the dependency resolve callbacks
277
3
  for (int i = 0; i < module_requests_length; i++) {
278
    Local<String> specifier = module->GetModuleRequest(i);
279
    Utf8Value specifier_utf8(env->isolate(), specifier);
280
    std::string specifier_std(*specifier_utf8, specifier_utf8.length());
281
282
    Local<Value> argv[] = {
283
      specifier
284
    };
285
286
    MaybeLocal<Value> maybe_resolve_return_value =
287
        resolver_arg->Call(mod_context, that, arraysize(argv), argv);
288
    if (maybe_resolve_return_value.IsEmpty()) {
289
      return;
290
    }
291
    Local<Value> resolve_return_value =
292
        maybe_resolve_return_value.ToLocalChecked();
293
    if (!resolve_return_value->IsPromise()) {
294
      env->ThrowError("linking error, expected resolver to return a promise");
295
    }
296
    Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
297
    obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
298
299
    promises[i] = resolve_promise;
300
  }
301
302
9
  args.GetReturnValue().Set(
303
      Array::New(isolate, promises.out(), promises.length()));
304
}
305
306
1072
void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
307
1072
  Environment* env = Environment::GetCurrent(args);
308
1072
  Isolate* isolate = args.GetIsolate();
309
  ModuleWrap* obj;
310
1072
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
311
1072
  Local<Context> context = obj->context();
312
2144
  Local<Module> module = obj->module_.Get(isolate);
313
2144
  TryCatchScope try_catch(env);
314
1072
  USE(module->InstantiateModule(context, ResolveCallback));
315
316
  // clear resolve cache on instantiate
317
1072
  obj->resolve_cache_.clear();
318
319

1072
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
320
    CHECK(!try_catch.Message().IsEmpty());
321
    CHECK(!try_catch.Exception().IsEmpty());
322
    AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
323
                        ErrorHandlingMode::MODULE_ERROR);
324
    try_catch.ReThrow();
325
    return;
326
  }
327
}
328
329
1071
void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
330
1071
  Environment* env = Environment::GetCurrent(args);
331
1071
  Isolate* isolate = env->isolate();
332
  ModuleWrap* obj;
333
1071
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
334
1071
  Local<Context> context = obj->context();
335
2142
  Local<Module> module = obj->module_.Get(isolate);
336
337
1071
  ContextifyContext* contextify_context = obj->contextify_context_;
338
2142
  std::shared_ptr<MicrotaskQueue> microtask_queue;
339
1071
  if (contextify_context != nullptr)
340
      microtask_queue = contextify_context->microtask_queue();
341
342
  // module.evaluate(timeout, breakOnSigint)
343
1071
  CHECK_EQ(args.Length(), 2);
344
345
2142
  CHECK(args[0]->IsNumber());
346
4284
  int64_t timeout = args[0]->IntegerValue(env->context()).FromJust();
347
348
2142
  CHECK(args[1]->IsBoolean());
349
2142
  bool break_on_sigint = args[1]->IsTrue();
350
351
2142
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
352
2142
  TryCatchScope try_catch(env);
353
2142
  Isolate::SafeForTerminationScope safe_for_termination(env->isolate());
354
355
1071
  bool timed_out = false;
356
1071
  bool received_signal = false;
357
  MaybeLocal<Value> result;
358
1071
  auto run = [&]() {
359
2142
    MaybeLocal<Value> result = module->Evaluate(context);
360

1071
    if (!result.IsEmpty() && microtask_queue)
361
      microtask_queue->PerformCheckpoint(isolate);
362
1071
    return result;
363
1071
  };
364

1071
  if (break_on_sigint && timeout != -1) {
365
    Watchdog wd(isolate, timeout, &timed_out);
366
    SigintWatchdog swd(isolate, &received_signal);
367
    result = run();
368
1071
  } else if (break_on_sigint) {
369
    SigintWatchdog swd(isolate, &received_signal);
370
    result = run();
371
1071
  } else if (timeout != -1) {
372
    Watchdog wd(isolate, timeout, &timed_out);
373
    result = run();
374
  } else {
375
1071
    result = run();
376
  }
377
378
1071
  if (result.IsEmpty()) {
379
    CHECK(try_catch.HasCaught());
380
  }
381
382
  // Convert the termination exception into a regular exception.
383

1071
  if (timed_out || received_signal) {
384
    if (!env->is_main_thread() && env->is_stopping())
385
      return;
386
    env->isolate()->CancelTerminateExecution();
387
    // It is possible that execution was terminated by another timeout in
388
    // which this timeout is nested, so check whether one of the watchdogs
389
    // from this invocation is responsible for termination.
390
    if (timed_out) {
391
      THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
392
    } else if (received_signal) {
393
      THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
394
    }
395
  }
396
397
1071
  if (try_catch.HasCaught()) {
398
    if (!try_catch.HasTerminated())
399
      try_catch.ReThrow();
400
    return;
401
  }
402
403
  // If TLA is enabled, `result` is the evaluation's promise.
404
  // Otherwise, `result` is the last evaluated value of the module,
405
  // which could be a promise, which would result in it being incorrectly
406
  // unwrapped when the higher level code awaits the evaluation.
407
1071
  if (env->isolate_data()->options()->experimental_top_level_await) {
408
2142
    args.GetReturnValue().Set(result.ToLocalChecked());
409
  }
410
}
411
412
void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
413
  Environment* env = Environment::GetCurrent(args);
414
  Isolate* isolate = args.GetIsolate();
415
  ModuleWrap* obj;
416
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
417
418
  Local<Module> module = obj->module_.Get(isolate);
419
420
  switch (module->GetStatus()) {
421
    case v8::Module::Status::kUninstantiated:
422
    case v8::Module::Status::kInstantiating:
423
      return env->ThrowError(
424
          "cannot get namespace, module has not been instantiated");
425
    case v8::Module::Status::kInstantiated:
426
    case v8::Module::Status::kEvaluating:
427
    case v8::Module::Status::kEvaluated:
428
    case v8::Module::Status::kErrored:
429
      break;
430
    default:
431
      UNREACHABLE();
432
  }
433
434
  Local<Value> result = module->GetModuleNamespace();
435
  args.GetReturnValue().Set(result);
436
}
437
438
8
void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
439
8
  Isolate* isolate = args.GetIsolate();
440
  ModuleWrap* obj;
441
8
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
442
443
16
  Local<Module> module = obj->module_.Get(isolate);
444
445
24
  args.GetReturnValue().Set(module->GetStatus());
446
}
447
448
void ModuleWrap::GetStaticDependencySpecifiers(
449
    const FunctionCallbackInfo<Value>& args) {
450
  Environment* env = Environment::GetCurrent(args);
451
  ModuleWrap* obj;
452
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
453
454
  Local<Module> module = obj->module_.Get(env->isolate());
455
456
  int count = module->GetModuleRequestsLength();
457
458
  MaybeStackBuffer<Local<Value>, 16> specifiers(count);
459
460
  for (int i = 0; i < count; i++)
461
    specifiers[i] = module->GetModuleRequest(i);
462
463
  args.GetReturnValue().Set(
464
      Array::New(env->isolate(), specifiers.out(), count));
465
}
466
467
void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
468
  Isolate* isolate = args.GetIsolate();
469
  ModuleWrap* obj;
470
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
471
472
  Local<Module> module = obj->module_.Get(isolate);
473
  args.GetReturnValue().Set(module->GetException());
474
}
475
476
MaybeLocal<Module> ModuleWrap::ResolveCallback(Local<Context> context,
477
                                               Local<String> specifier,
478
                                               Local<Module> referrer) {
479
  Environment* env = Environment::GetCurrent(context);
480
  if (env == nullptr) {
481
    Isolate* isolate = context->GetIsolate();
482
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
483
    return MaybeLocal<Module>();
484
  }
485
486
  Isolate* isolate = env->isolate();
487
488
  ModuleWrap* dependent = GetFromModule(env, referrer);
489
  if (dependent == nullptr) {
490
    env->ThrowError("linking error, null dep");
491
    return MaybeLocal<Module>();
492
  }
493
494
  Utf8Value specifier_utf8(isolate, specifier);
495
  std::string specifier_std(*specifier_utf8, specifier_utf8.length());
496
497
  if (dependent->resolve_cache_.count(specifier_std) != 1) {
498
    env->ThrowError("linking error, not in local cache");
499
    return MaybeLocal<Module>();
500
  }
501
502
  Local<Promise> resolve_promise =
503
      dependent->resolve_cache_[specifier_std].Get(isolate);
504
505
  if (resolve_promise->State() != Promise::kFulfilled) {
506
    env->ThrowError("linking error, dependency promises must be resolved on "
507
                    "instantiate");
508
    return MaybeLocal<Module>();
509
  }
510
511
  Local<Object> module_object = resolve_promise->Result().As<Object>();
512
  if (module_object.IsEmpty() || !module_object->IsObject()) {
513
    env->ThrowError("linking error, expected a valid module object from "
514
                    "resolver");
515
    return MaybeLocal<Module>();
516
  }
517
518
  ModuleWrap* module;
519
  ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
520
  return module->module_.Get(isolate);
521
}
522
523
1
static MaybeLocal<Promise> ImportModuleDynamically(
524
    Local<Context> context,
525
    Local<ScriptOrModule> referrer,
526
    Local<String> specifier) {
527
1
  Isolate* iso = context->GetIsolate();
528
1
  Environment* env = Environment::GetCurrent(context);
529
1
  if (env == nullptr) {
530
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(iso);
531
    return MaybeLocal<Promise>();
532
  }
533
534
1
  EscapableHandleScope handle_scope(iso);
535
536
  Local<Function> import_callback =
537
1
    env->host_import_module_dynamically_callback();
538
539
1
  Local<PrimitiveArray> options = referrer->GetHostDefinedOptions();
540
1
  if (options->Length() != HostDefinedOptions::kLength) {
541
    Local<Promise::Resolver> resolver;
542
    if (!Promise::Resolver::New(context).ToLocal(&resolver)) return {};
543
    resolver
544
        ->Reject(context,
545
                 v8::Exception::TypeError(FIXED_ONE_BYTE_STRING(
546
                     context->GetIsolate(), "Invalid host defined options")))
547
        .ToChecked();
548
    return handle_scope.Escape(resolver->GetPromise());
549
  }
550
551
  Local<Value> object;
552
553
2
  int type = options->Get(iso, HostDefinedOptions::kType)
554
2
                 .As<Number>()
555
2
                 ->Int32Value(context)
556
1
                 .ToChecked();
557
2
  uint32_t id = options->Get(iso, HostDefinedOptions::kID)
558
2
                    .As<Number>()
559
2
                    ->Uint32Value(context)
560
1
                    .ToChecked();
561
1
  if (type == ScriptType::kScript) {
562
    contextify::ContextifyScript* wrap = env->id_to_script_map.find(id)->second;
563
    object = wrap->object();
564
1
  } else if (type == ScriptType::kModule) {
565
1
    ModuleWrap* wrap = ModuleWrap::GetFromID(env, id);
566
2
    object = wrap->object();
567
  } else if (type == ScriptType::kFunction) {
568
    auto it = env->id_to_function_map.find(id);
569
    CHECK_NE(it, env->id_to_function_map.end());
570
    object = it->second->object();
571
  } else {
572
    UNREACHABLE();
573
  }
574
575
  Local<Value> import_args[] = {
576
    object,
577
    Local<Value>(specifier),
578
2
  };
579
580
  Local<Value> result;
581
3
  if (import_callback->Call(
582
        context,
583
        Undefined(iso),
584
1
        arraysize(import_args),
585
3
        import_args).ToLocal(&result)) {
586
1
    CHECK(result->IsPromise());
587
1
    return handle_scope.Escape(result.As<Promise>());
588
  }
589
590
  return MaybeLocal<Promise>();
591
}
592
593
119
void ModuleWrap::SetImportModuleDynamicallyCallback(
594
    const FunctionCallbackInfo<Value>& args) {
595
119
  Isolate* iso = args.GetIsolate();
596
119
  Environment* env = Environment::GetCurrent(args);
597
238
  HandleScope handle_scope(iso);
598
599
119
  CHECK_EQ(args.Length(), 1);
600
238
  CHECK(args[0]->IsFunction());
601
238
  Local<Function> import_callback = args[0].As<Function>();
602
119
  env->set_host_import_module_dynamically_callback(import_callback);
603
604
119
  iso->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
605
119
}
606
607
void ModuleWrap::HostInitializeImportMetaObjectCallback(
608
    Local<Context> context, Local<Module> module, Local<Object> meta) {
609
  Environment* env = Environment::GetCurrent(context);
610
  if (env == nullptr)
611
    return;
612
  ModuleWrap* module_wrap = GetFromModule(env, module);
613
614
  if (module_wrap == nullptr) {
615
    return;
616
  }
617
618
  Local<Object> wrap = module_wrap->object();
619
  Local<Function> callback =
620
      env->host_initialize_import_meta_object_callback();
621
  Local<Value> args[] = { wrap, meta };
622
  TryCatchScope try_catch(env);
623
  USE(callback->Call(
624
        context, Undefined(env->isolate()), arraysize(args), args));
625
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
626
    try_catch.ReThrow();
627
  }
628
}
629
630
119
void ModuleWrap::SetInitializeImportMetaObjectCallback(
631
    const FunctionCallbackInfo<Value>& args) {
632
119
  Environment* env = Environment::GetCurrent(args);
633
119
  Isolate* isolate = env->isolate();
634
635
119
  CHECK_EQ(args.Length(), 1);
636
238
  CHECK(args[0]->IsFunction());
637
238
  Local<Function> import_meta_callback = args[0].As<Function>();
638
119
  env->set_host_initialize_import_meta_object_callback(import_meta_callback);
639
640
  isolate->SetHostInitializeImportMetaObjectCallback(
641
119
      HostInitializeImportMetaObjectCallback);
642
119
}
643
644
1069
MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
645
    Local<Context> context, Local<Module> module) {
646
1069
  Environment* env = Environment::GetCurrent(context);
647
1069
  Isolate* isolate = env->isolate();
648
649
1069
  ModuleWrap* obj = GetFromModule(env, module);
650
651
2138
  TryCatchScope try_catch(env);
652
  Local<Function> synthetic_evaluation_steps =
653
4276
      obj->object()->GetInternalField(kSyntheticEvaluationStepsSlot)
654
1069
          .As<Function>();
655
3207
  obj->object()->SetInternalField(
656
1069
      kSyntheticEvaluationStepsSlot, Undefined(isolate));
657
  MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
658
2138
      obj->object(), 0, nullptr);
659
1069
  if (ret.IsEmpty()) {
660
    CHECK(try_catch.HasCaught());
661
  }
662

1069
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
663
    CHECK(!try_catch.Message().IsEmpty());
664
    CHECK(!try_catch.Exception().IsEmpty());
665
    try_catch.ReThrow();
666
    return MaybeLocal<Value>();
667
  }
668
669
  Local<Promise::Resolver> resolver;
670
2138
  if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
671
    return MaybeLocal<Value>();
672
  }
673
674
2138
  resolver->Resolve(context, Undefined(isolate)).ToChecked();
675
2138
  return resolver->GetPromise();
676
}
677
678
286246
void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
679
286246
  Isolate* isolate = args.GetIsolate();
680
286246
  Local<Object> that = args.This();
681
682
  ModuleWrap* obj;
683
286246
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
684
685
286246
  CHECK(obj->synthetic_);
686
687
286246
  CHECK_EQ(args.Length(), 2);
688
689
858738
  CHECK(args[0]->IsString());
690
572492
  Local<String> export_name = args[0].As<String>();
691
692
286246
  Local<Value> export_value = args[1];
693
694
572492
  Local<Module> module = obj->module_.Get(isolate);
695
286246
  USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
696
}
697
698
void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
699
  Isolate* isolate = args.GetIsolate();
700
  Local<Object> that = args.This();
701
702
  ModuleWrap* obj;
703
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
704
705
  CHECK(!obj->synthetic_);
706
707
  Local<Module> module = obj->module_.Get(isolate);
708
709
  CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
710
711
  Local<UnboundModuleScript> unbound_module_script =
712
      module->GetUnboundModuleScript();
713
  std::unique_ptr<ScriptCompiler::CachedData> cached_data(
714
      ScriptCompiler::CreateCodeCache(unbound_module_script));
715
  Environment* env = Environment::GetCurrent(args);
716
  if (!cached_data) {
717
    args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
718
  } else {
719
    MaybeLocal<Object> buf =
720
        Buffer::Copy(env,
721
                     reinterpret_cast<const char*>(cached_data->data),
722
                     cached_data->length);
723
    args.GetReturnValue().Set(buf.ToLocalChecked());
724
  }
725
}
726
727
120
void ModuleWrap::Initialize(Local<Object> target,
728
                            Local<Value> unused,
729
                            Local<Context> context,
730
                            void* priv) {
731
120
  Environment* env = Environment::GetCurrent(context);
732
733
120
  Local<FunctionTemplate> tpl = env->NewFunctionTemplate(New);
734
360
  tpl->InstanceTemplate()->SetInternalFieldCount(
735
120
      ModuleWrap::kInternalFieldCount);
736
240
  tpl->Inherit(BaseObject::GetConstructorTemplate(env));
737
738
120
  env->SetProtoMethod(tpl, "link", Link);
739
120
  env->SetProtoMethod(tpl, "instantiate", Instantiate);
740
120
  env->SetProtoMethod(tpl, "evaluate", Evaluate);
741
120
  env->SetProtoMethod(tpl, "setExport", SetSyntheticExport);
742
120
  env->SetProtoMethodNoSideEffect(tpl, "createCachedData", CreateCachedData);
743
120
  env->SetProtoMethodNoSideEffect(tpl, "getNamespace", GetNamespace);
744
120
  env->SetProtoMethodNoSideEffect(tpl, "getStatus", GetStatus);
745
120
  env->SetProtoMethodNoSideEffect(tpl, "getError", GetError);
746
  env->SetProtoMethodNoSideEffect(tpl, "getStaticDependencySpecifiers",
747
120
                                  GetStaticDependencySpecifiers);
748
749
120
  env->SetConstructorFunction(target, "ModuleWrap", tpl);
750
751
  env->SetMethod(target,
752
                 "setImportModuleDynamicallyCallback",
753
120
                 SetImportModuleDynamicallyCallback);
754
  env->SetMethod(target,
755
                 "setInitializeImportMetaObjectCallback",
756
120
                 SetInitializeImportMetaObjectCallback);
757
758
#define V(name)                                                                \
759
    target->Set(context,                                                       \
760
      FIXED_ONE_BYTE_STRING(env->isolate(), #name),                            \
761
      Integer::New(env->isolate(), Module::Status::name))                      \
762
        .FromJust()
763
480
    V(kUninstantiated);
764
480
    V(kInstantiating);
765
480
    V(kInstantiated);
766
480
    V(kEvaluating);
767
480
    V(kEvaluated);
768
480
    V(kErrored);
769
#undef V
770
120
}
771
772
}  // namespace loader
773
}  // namespace node
774
775

481
NODE_MODULE_CONTEXT_AWARE_INTERNAL(module_wrap,
776
                                   node::loader::ModuleWrap::Initialize)