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: 823 948 86.8 %
Date: 2020-02-27 22:14:15 Branches: 477 705 67.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.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::Global;
33
using v8::HandleScope;
34
using v8::Integer;
35
using v8::IntegrityLevel;
36
using v8::Isolate;
37
using v8::Just;
38
using v8::Local;
39
using v8::Maybe;
40
using v8::MaybeLocal;
41
using v8::Module;
42
using v8::Nothing;
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::ScriptOrModule;
50
using v8::String;
51
using v8::UnboundModuleScript;
52
using v8::Undefined;
53
using v8::Value;
54
55
static const char* const EXTENSIONS[] = {
56
  ".js",
57
  ".json",
58
  ".node",
59
  ".mjs"
60
};
61
62
29672
ModuleWrap::ModuleWrap(Environment* env,
63
                       Local<Object> object,
64
                       Local<Module> module,
65
29672
                       Local<String> url) :
66
  BaseObject(env, object),
67
148364
  id_(env->get_next_module_id()) {
68
29673
  module_.Reset(env->isolate(), module);
69
29673
  url_.Reset(env->isolate(), url);
70
29674
  env->id_to_module_map.emplace(id_, this);
71
29673
}
72
73
195077
ModuleWrap::~ModuleWrap() {
74
55734
  HandleScope scope(env()->isolate());
75
55737
  Local<Module> module = module_.Get(env()->isolate());
76
27868
  env()->id_to_module_map.erase(id_);
77
27869
  auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash());
78
27867
  for (auto it = range.first; it != range.second; ++it) {
79
27869
    if (it->second == this) {
80
27869
      env()->hash_to_module_map.erase(it);
81
27869
      break;
82
    }
83
  }
84
55735
}
85
86
29723
ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
87
                                      Local<Module> module) {
88
29723
  auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
89
29724
  for (auto it = range.first; it != range.second; ++it) {
90
59446
    if (it->second->module_ == module) {
91
29723
      return it->second;
92
    }
93
  }
94
  return nullptr;
95
}
96
97
49
ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) {
98
49
  auto module_wrap_it = env->id_to_module_map.find(id);
99
49
  if (module_wrap_it == env->id_to_module_map.end()) {
100
    return nullptr;
101
  }
102
49
  return module_wrap_it->second;
103
}
104
105
// new ModuleWrap(url, context, source, lineOffset, columnOffset)
106
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
107
29680
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
108
29680
  CHECK(args.IsConstructCall());
109
29680
  CHECK_GE(args.Length(), 3);
110
111
29680
  Environment* env = Environment::GetCurrent(args);
112
29681
  Isolate* isolate = env->isolate();
113
114
29681
  Local<Object> that = args.This();
115
116
89043
  CHECK(args[0]->IsString());
117
59362
  Local<String> url = args[0].As<String>();
118
119
  Local<Context> context;
120
89043
  if (args[1]->IsUndefined()) {
121
29673
    context = that->CreationContext();
122
  } else {
123
16
    CHECK(args[1]->IsObject());
124
    ContextifyContext* sandbox =
125
8
        ContextifyContext::ContextFromContextifiedSandbox(
126
24
            env, args[1].As<Object>());
127
8
    CHECK_NOT_NULL(sandbox);
128
8
    context = sandbox->context();
129
  }
130
131
  Local<Integer> line_offset;
132
  Local<Integer> column_offset;
133
134
59360
  bool synthetic = args[2]->IsArray();
135
29681
  if (synthetic) {
136
    // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
137
58798
    CHECK(args[3]->IsFunction());
138
  } else {
139
    // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
140
846
    CHECK(args[2]->IsString());
141
564
    CHECK(args[3]->IsNumber());
142
564
    line_offset = args[3].As<Integer>();
143
564
    CHECK(args[4]->IsNumber());
144
564
    column_offset = args[4].As<Integer>();
145
  }
146
147
  Local<PrimitiveArray> host_defined_options =
148
29681
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
149
89041
  host_defined_options->Set(isolate, HostDefinedOptions::kType,
150
29680
                            Number::New(isolate, ScriptType::kModule));
151
152
59354
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
153
59353
  TryCatchScope try_catch(env);
154
155
  Local<Module> module;
156
157
  {
158
29673
    Context::Scope context_scope(context);
159
29681
    if (synthetic) {
160
58798
      CHECK(args[2]->IsArray());
161
58798
      Local<Array> export_names_arr = args[2].As<Array>();
162
163
29399
      uint32_t len = export_names_arr->Length();
164
58798
      std::vector<Local<String>> export_names(len);
165
825853
      for (uint32_t i = 0; i < len; i++) {
166
        Local<Value> export_name_val =
167
1592908
            export_names_arr->Get(context, i).ToLocalChecked();
168
1592908
        CHECK(export_name_val->IsString());
169
1592908
        export_names[i] = export_name_val.As<String>();
170
      }
171
172
      module = Module::CreateSyntheticModule(isolate, url, export_names,
173
29399
        SyntheticModuleEvaluationStepsCallback);
174
    } else {
175
282
      ScriptCompiler::CachedData* cached_data = nullptr;
176
846
      if (!args[5]->IsUndefined()) {
177
4
        CHECK(args[5]->IsArrayBufferView());
178
4
        Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
179
        uint8_t* data = static_cast<uint8_t*>(
180
4
            cached_data_buf->Buffer()->GetBackingStore()->Data());
181
2
        cached_data =
182
2
            new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
183
2
                                           cached_data_buf->ByteLength());
184
      }
185
186
564
      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
282
                          host_defined_options);
197
274
      ScriptCompiler::Source source(source_text, origin, cached_data);
198
      ScriptCompiler::CompileOptions options;
199
282
      if (source.GetCachedData() == nullptr) {
200
280
        options = ScriptCompiler::kNoCompileOptions;
201
      } else {
202
2
        options = ScriptCompiler::kConsumeCodeCache;
203
      }
204
564
      if (!ScriptCompiler::CompileModule(isolate, &source, options)
205
282
               .ToLocal(&module)) {
206

7
        if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
207
14
          CHECK(!try_catch.Message().IsEmpty());
208
14
          CHECK(!try_catch.Exception().IsEmpty());
209
7
          AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
210
7
                              ErrorHandlingMode::MODULE_ERROR);
211
7
          try_catch.ReThrow();
212
        }
213
7
        return;
214
      }
215

277
      if (options == ScriptCompiler::kConsumeCodeCache &&
216
2
          source.GetCachedData()->rejected) {
217
        THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED(
218
1
            env, "cachedData buffer was rejected");
219
1
        try_catch.ReThrow();
220
1
        return;
221
      }
222
    }
223
  }
224
225
118691
  if (!that->Set(context, env->url_string(), url).FromMaybe(false)) {
226
    return;
227
  }
228
229
29672
  ModuleWrap* obj = new ModuleWrap(env, that, module, url);
230
231
29673
  if (synthetic) {
232
29398
    obj->synthetic_ = true;
233
29398
    obj->synthetic_evaluation_steps_.Reset(
234
88194
        env->isolate(), args[3].As<Function>());
235
  }
236
237
29673
  obj->context_.Reset(isolate, context);
238
239
29673
  env->hash_to_module_map.emplace(module->GetIdentityHash(), obj);
240
241
89018
  host_defined_options->Set(isolate, HostDefinedOptions::kID,
242
59346
                            Number::New(isolate, obj->id()));
243
244
29673
  that->SetIntegrityLevel(context, IntegrityLevel::kFrozen);
245
59346
  args.GetReturnValue().Set(that);
246
}
247
248
416
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
249
416
  Environment* env = Environment::GetCurrent(args);
250
416
  Isolate* isolate = args.GetIsolate();
251
252
416
  CHECK_EQ(args.Length(), 1);
253
832
  CHECK(args[0]->IsFunction());
254
255
416
  Local<Object> that = args.This();
256
257
  ModuleWrap* obj;
258
419
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
259
260
416
  if (obj->linked_)
261
3
    return;
262
413
  obj->linked_ = true;
263
264
826
  Local<Function> resolver_arg = args[0].As<Function>();
265
266
826
  Local<Context> mod_context = obj->context_.Get(isolate);
267
826
  Local<Module> module = obj->module_.Get(isolate);
268
269
413
  const int module_requests_length = module->GetModuleRequestsLength();
270
826
  MaybeStackBuffer<Local<Value>, 16> promises(module_requests_length);
271
272
  // call the dependency resolve callbacks
273
706
  for (int i = 0; i < module_requests_length; i++) {
274
293
    Local<String> specifier = module->GetModuleRequest(i);
275
586
    Utf8Value specifier_utf8(env->isolate(), specifier);
276
586
    std::string specifier_std(*specifier_utf8, specifier_utf8.length());
277
278
    Local<Value> argv[] = {
279
      specifier
280
586
    };
281
282
    MaybeLocal<Value> maybe_resolve_return_value =
283
293
        resolver_arg->Call(mod_context, that, 1, argv);
284
293
    if (maybe_resolve_return_value.IsEmpty()) {
285
      return;
286
    }
287
    Local<Value> resolve_return_value =
288
293
        maybe_resolve_return_value.ToLocalChecked();
289
293
    if (!resolve_return_value->IsPromise()) {
290
      env->ThrowError("linking error, expected resolver to return a promise");
291
    }
292
293
    Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
293
293
    obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
294
295
586
    promises[i] = resolve_promise;
296
  }
297
298
1239
  args.GetReturnValue().Set(
299
      Array::New(isolate, promises.out(), promises.length()));
300
}
301
302
29501
void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
303
29501
  Environment* env = Environment::GetCurrent(args);
304
29502
  Isolate* isolate = args.GetIsolate();
305
  ModuleWrap* obj;
306
29505
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
307
59004
  Local<Context> context = obj->context_.Get(isolate);
308
59004
  Local<Module> module = obj->module_.Get(isolate);
309
59000
  TryCatchScope try_catch(env);
310
29502
  USE(module->InstantiateModule(context, ResolveCallback));
311
312
  // clear resolve cache on instantiate
313
29501
  obj->resolve_cache_.clear();
314
315

29502
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
316
6
    CHECK(!try_catch.Message().IsEmpty());
317
6
    CHECK(!try_catch.Exception().IsEmpty());
318
3
    AppendExceptionLine(env, try_catch.Exception(), try_catch.Message(),
319
3
                        ErrorHandlingMode::MODULE_ERROR);
320
3
    try_catch.ReThrow();
321
3
    return;
322
  }
323
}
324
325
29498
void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
326
29498
  Environment* env = Environment::GetCurrent(args);
327
29498
  Isolate* isolate = env->isolate();
328
  ModuleWrap* obj;
329
29505
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
330
58996
  Local<Context> context = obj->context_.Get(isolate);
331
58996
  Local<Module> module = obj->module_.Get(isolate);
332
333
  // module.evaluate(timeout, breakOnSigint)
334
29498
  CHECK_EQ(args.Length(), 2);
335
336
58996
  CHECK(args[0]->IsNumber());
337
117994
  int64_t timeout = args[0]->IntegerValue(env->context()).FromJust();
338
339
58996
  CHECK(args[1]->IsBoolean());
340
58998
  bool break_on_sigint = args[1]->IsTrue();
341
342
58989
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
343
58989
  TryCatchScope try_catch(env);
344
345
29498
  bool timed_out = false;
346
29498
  bool received_signal = false;
347
  MaybeLocal<Value> result;
348

29498
  if (break_on_sigint && timeout != -1) {
349
    Watchdog wd(isolate, timeout, &timed_out);
350
    SigintWatchdog swd(isolate, &received_signal);
351
    result = module->Evaluate(context);
352
29498
  } else if (break_on_sigint) {
353
    SigintWatchdog swd(isolate, &received_signal);
354
    result = module->Evaluate(context);
355
29498
  } else if (timeout != -1) {
356
2
    Watchdog wd(isolate, timeout, &timed_out);
357
1
    result = module->Evaluate(context);
358
  } else {
359
29497
    result = module->Evaluate(context);
360
  }
361
362
29497
  if (result.IsEmpty()) {
363
7
    CHECK(try_catch.HasCaught());
364
  }
365
366
  // Convert the termination exception into a regular exception.
367

29497
  if (timed_out || received_signal) {
368

1
    if (!env->is_main_thread() && env->is_stopping())
369
      return;
370
1
    env->isolate()->CancelTerminateExecution();
371
    // It is possible that execution was terminated by another timeout in
372
    // which this timeout is nested, so check whether one of the watchdogs
373
    // from this invocation is responsible for termination.
374
1
    if (timed_out) {
375
1
      THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout);
376
    } else if (received_signal) {
377
      THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env);
378
    }
379
  }
380
381
29497
  if (try_catch.HasCaught()) {
382
7
    if (!try_catch.HasTerminated())
383
6
      try_catch.ReThrow();
384
7
    return;
385
  }
386
387
58980
  args.GetReturnValue().Set(result.ToLocalChecked());
388
}
389
390
135
void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
391
135
  Environment* env = Environment::GetCurrent(args);
392
135
  Isolate* isolate = args.GetIsolate();
393
  ModuleWrap* obj;
394
135
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
395
396
270
  Local<Module> module = obj->module_.Get(isolate);
397
398
135
  switch (module->GetStatus()) {
399
    default:
400
      return env->ThrowError(
401
          "cannot get namespace, Module has not been instantiated");
402
    case v8::Module::Status::kInstantiated:
403
    case v8::Module::Status::kEvaluating:
404
    case v8::Module::Status::kEvaluated:
405
135
      break;
406
  }
407
408
135
  Local<Value> result = module->GetModuleNamespace();
409
270
  args.GetReturnValue().Set(result);
410
}
411
412
191
void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
413
191
  Isolate* isolate = args.GetIsolate();
414
  ModuleWrap* obj;
415
191
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
416
417
382
  Local<Module> module = obj->module_.Get(isolate);
418
419
573
  args.GetReturnValue().Set(module->GetStatus());
420
}
421
422
2
void ModuleWrap::GetStaticDependencySpecifiers(
423
    const FunctionCallbackInfo<Value>& args) {
424
2
  Environment* env = Environment::GetCurrent(args);
425
  ModuleWrap* obj;
426
2
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
427
428
4
  Local<Module> module = obj->module_.Get(env->isolate());
429
430
2
  int count = module->GetModuleRequestsLength();
431
432
4
  MaybeStackBuffer<Local<Value>, 16> specifiers(count);
433
434
3
  for (int i = 0; i < count; i++)
435
3
    specifiers[i] = module->GetModuleRequest(i);
436
437
6
  args.GetReturnValue().Set(
438
      Array::New(env->isolate(), specifiers.out(), count));
439
}
440
441
1
void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
442
1
  Isolate* isolate = args.GetIsolate();
443
  ModuleWrap* obj;
444
1
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
445
446
2
  Local<Module> module = obj->module_.Get(isolate);
447
3
  args.GetReturnValue().Set(module->GetException());
448
}
449
450
276
MaybeLocal<Module> ModuleWrap::ResolveCallback(Local<Context> context,
451
                                               Local<String> specifier,
452
                                               Local<Module> referrer) {
453
276
  Environment* env = Environment::GetCurrent(context);
454
276
  CHECK_NOT_NULL(env);  // TODO(addaleax): Handle nullptr here.
455
276
  Isolate* isolate = env->isolate();
456
457
276
  ModuleWrap* dependent = GetFromModule(env, referrer);
458
276
  if (dependent == nullptr) {
459
    env->ThrowError("linking error, null dep");
460
    return MaybeLocal<Module>();
461
  }
462
463
552
  Utf8Value specifier_utf8(isolate, specifier);
464
552
  std::string specifier_std(*specifier_utf8, specifier_utf8.length());
465
466
276
  if (dependent->resolve_cache_.count(specifier_std) != 1) {
467
    env->ThrowError("linking error, not in local cache");
468
    return MaybeLocal<Module>();
469
  }
470
471
  Local<Promise> resolve_promise =
472
552
      dependent->resolve_cache_[specifier_std].Get(isolate);
473
474
276
  if (resolve_promise->State() != Promise::kFulfilled) {
475
    env->ThrowError("linking error, dependency promises must be resolved on "
476
                    "instantiate");
477
    return MaybeLocal<Module>();
478
  }
479
480
552
  Local<Object> module_object = resolve_promise->Result().As<Object>();
481

552
  if (module_object.IsEmpty() || !module_object->IsObject()) {
482
    env->ThrowError("linking error, expected a valid module object from "
483
                    "resolver");
484
    return MaybeLocal<Module>();
485
  }
486
487
  ModuleWrap* module;
488
276
  ASSIGN_OR_RETURN_UNWRAP(&module, module_object, MaybeLocal<Module>());
489
552
  return module->module_.Get(isolate);
490
}
491
492
namespace {
493
494
// Tests whether a path starts with /, ./ or ../
495
// In WhatWG terminology, the alternative case is called a "bare" specifier
496
// (e.g. in `import "jquery"`).
497
327
inline bool ShouldBeTreatedAsRelativeOrAbsolutePath(
498
    const std::string& specifier) {
499
327
  size_t len = specifier.length();
500
327
  if (len == 0)
501
    return false;
502
327
  if (specifier[0] == '/') {
503
    return true;
504
327
  } else if (specifier[0] == '.') {
505

170
    if (len == 1 || specifier[1] == '/')
506
63
      return true;
507
107
    if (specifier[1] == '.') {
508

107
      if (len == 2 || specifier[2] == '/')
509
107
        return true;
510
    }
511
  }
512
157
  return false;
513
}
514
515
36
std::string ReadFile(uv_file file) {
516
36
  std::string contents;
517
  uv_fs_t req;
518
  char buffer_memory[4096];
519
36
  uv_buf_t buf = uv_buf_init(buffer_memory, sizeof(buffer_memory));
520
521
  do {
522
72
    const int r = uv_fs_read(nullptr,
523
                             &req,
524
                             file,
525
                             &buf,
526
                             1,
527
72
                             contents.length(),  // offset
528
72
                             nullptr);
529
72
    uv_fs_req_cleanup(&req);
530
531
72
    if (r <= 0)
532
36
      break;
533
36
    contents.append(buf.base, r);
534
  } while (true);
535
36
  return contents;
536
}
537
538
enum DescriptorType {
539
  FILE,
540
  DIRECTORY,
541
  NONE
542
};
543
544
// When DescriptorType cache is added, this can also return
545
// Nothing for the "null" cache entries.
546
930
inline Maybe<uv_file> OpenDescriptor(const std::string& path) {
547
  uv_fs_t fs_req;
548
#ifdef _WIN32
549
  std::string pth = "\\\\.\\" + path;
550
  uv_file fd = uv_fs_open(nullptr, &fs_req, pth.c_str(), O_RDONLY, 0, nullptr);
551
#else
552
930
  uv_file fd = uv_fs_open(nullptr, &fs_req, path.c_str(), O_RDONLY, 0, nullptr);
553
#endif
554
930
  uv_fs_req_cleanup(&fs_req);
555
930
  if (fd < 0) return Nothing<uv_file>();
556
397
  return Just(fd);
557
}
558
559
397
inline void CloseDescriptor(uv_file fd) {
560
  uv_fs_t fs_req;
561
397
  CHECK_EQ(0, uv_fs_close(nullptr, &fs_req, fd, nullptr));
562
397
  uv_fs_req_cleanup(&fs_req);
563
397
}
564
565
397
inline DescriptorType CheckDescriptorAtFile(uv_file fd) {
566
  uv_fs_t fs_req;
567
397
  int rc = uv_fs_fstat(nullptr, &fs_req, fd, nullptr);
568
397
  if (rc == 0) {
569
397
    uint64_t is_directory = fs_req.statbuf.st_mode & S_IFDIR;
570
397
    uv_fs_req_cleanup(&fs_req);
571
397
    return is_directory ? DIRECTORY : FILE;
572
  }
573
  uv_fs_req_cleanup(&fs_req);
574
  return NONE;
575
}
576
577
// TODO(@guybedford): Add a DescriptorType cache layer here.
578
// Should be directory based -> if path/to/dir doesn't exist
579
// then the cache should early-fail any path/to/dir/file check.
580
493
DescriptorType CheckDescriptorAtPath(const std::string& path) {
581
493
  Maybe<uv_file> fd = OpenDescriptor(path);
582
493
  if (fd.IsNothing()) return NONE;
583
361
  DescriptorType type = CheckDescriptorAtFile(fd.FromJust());
584
361
  CloseDescriptor(fd.FromJust());
585
361
  return type;
586
}
587
588
437
Maybe<std::string> ReadIfFile(const std::string& path) {
589
437
  Maybe<uv_file> fd = OpenDescriptor(path);
590
437
  if (fd.IsNothing()) return Nothing<std::string>();
591
36
  DescriptorType type = CheckDescriptorAtFile(fd.FromJust());
592
36
  if (type != FILE) return Nothing<std::string>();
593
72
  std::string source = ReadFile(fd.FromJust());
594
36
  CloseDescriptor(fd.FromJust());
595
36
  return Just(source);
596
}
597
598
using Exists = PackageConfig::Exists;
599
using IsValid = PackageConfig::IsValid;
600
using HasMain = PackageConfig::HasMain;
601
using HasName = PackageConfig::HasName;
602
using PackageType = PackageConfig::PackageType;
603
604
809
Maybe<const PackageConfig*> GetPackageConfig(Environment* env,
605
                                             const std::string& path,
606
                                             const URL& base) {
607
809
  auto existing = env->package_json_cache.find(path);
608
809
  if (existing != env->package_json_cache.end()) {
609
372
    const PackageConfig* pcfg = &existing->second;
610
372
    if (pcfg->is_valid == IsValid::No) {
611
      std::string msg = "Invalid JSON in " + path +
612
        " imported from " + base.ToFilePath();
613
      node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str());
614
      return Nothing<const PackageConfig*>();
615
    }
616
372
    return Just(pcfg);
617
  }
618
619
874
  Maybe<std::string> source = ReadIfFile(path);
620
621
437
  if (source.IsNothing()) {
622
    auto entry = env->package_json_cache.emplace(path,
623
802
        PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "",
624
                        HasName::No, "",
625
401
                        PackageType::None, Global<Value>() });
626
401
    return Just(&entry.first->second);
627
  }
628
629
36
  std::string pkg_src = source.FromJust();
630
631
36
  Isolate* isolate = env->isolate();
632
72
  HandleScope handle_scope(isolate);
633
634
  Local<Object> pkg_json;
635
  {
636
    Local<Value> src;
637
    Local<Value> pkg_json_v;
638
36
    Local<Context> context = env->context();
639
640

180
    if (!ToV8Value(context, pkg_src).ToLocal(&src) ||
641

180
        !v8::JSON::Parse(context, src.As<String>()).ToLocal(&pkg_json_v) ||
642
108
        !pkg_json_v->ToObject(context).ToLocal(&pkg_json)) {
643
      env->package_json_cache.emplace(path,
644
          PackageConfig { Exists::Yes, IsValid::No, HasMain::No, "",
645
                          HasName::No, "",
646
                          PackageType::None, Global<Value>() });
647
      std::string msg = "Invalid JSON in " + path +
648
          " imported from " + base.ToFilePath();
649
      node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str());
650
      return Nothing<const PackageConfig*>();
651
    }
652
  }
653
654
  Local<Value> pkg_main;
655
36
  HasMain has_main = HasMain::No;
656
72
  std::string main_std;
657
144
  if (pkg_json->Get(env->context(), env->main_string()).ToLocal(&pkg_main)) {
658
72
    if (pkg_main->IsString()) {
659
17
      has_main = HasMain::Yes;
660
    }
661
72
    Utf8Value main_utf8(isolate, pkg_main);
662
36
    main_std.assign(std::string(*main_utf8, main_utf8.length()));
663
  }
664
665
  Local<Value> pkg_name;
666
36
  HasName has_name = HasName::No;
667
72
  std::string name_std;
668
144
  if (pkg_json->Get(env->context(), env->name_string()).ToLocal(&pkg_name)) {
669
72
    if (pkg_name->IsString()) {
670
3
      has_name = HasName::Yes;
671
672
6
      Utf8Value name_utf8(isolate, pkg_name);
673
3
      name_std.assign(std::string(*name_utf8, name_utf8.length()));
674
    }
675
  }
676
677
36
  PackageType pkg_type = PackageType::None;
678
  Local<Value> type_v;
679
144
  if (pkg_json->Get(env->context(), env->type_string()).ToLocal(&type_v)) {
680
72
    if (type_v->StrictEquals(env->module_string())) {
681
10
      pkg_type = PackageType::Module;
682
52
    } else if (type_v->StrictEquals(env->commonjs_string())) {
683
5
      pkg_type = PackageType::CommonJS;
684
    }
685
    // ignore unknown types for forwards compatibility
686
  }
687
688
  Local<Value> exports_v;
689
108
  if (pkg_json->Get(env->context(),
690

216
      env->exports_string()).ToLocal(&exports_v) &&
691
72
      !exports_v->IsNullOrUndefined()) {
692
    Global<Value> exports;
693
7
    exports.Reset(env->isolate(), exports_v);
694
695
    auto entry = env->package_json_cache.emplace(path,
696
14
        PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std,
697
                        has_name, name_std,
698
14
                        pkg_type, std::move(exports) });
699
7
    return Just(&entry.first->second);
700
  }
701
702
  auto entry = env->package_json_cache.emplace(path,
703
58
      PackageConfig { Exists::Yes, IsValid::Yes, has_main, main_std,
704
                      has_name, name_std,
705
29
                      pkg_type, Global<Value>() });
706
29
  return Just(&entry.first->second);
707
}
708
709
128
Maybe<const PackageConfig*> GetPackageScopeConfig(Environment* env,
710
                                                  const URL& resolved,
711
                                                  const URL& base) {
712
256
  URL pjson_url("./package.json", &resolved);
713
  while (true) {
714
1396
    std::string pjson_url_path = pjson_url.path();
715

2640
    if (pjson_url_path.length() > 25 &&
716
1878
        pjson_url_path.substr(pjson_url_path.length() - 25, 25) ==
717
        "node_modules/package.json") {
718
2
      break;
719
    }
720
    Maybe<const PackageConfig*> pkg_cfg =
721
760
        GetPackageConfig(env, pjson_url.ToFilePath(), base);
722
760
    if (pkg_cfg.IsNothing()) return pkg_cfg;
723
760
    if (pkg_cfg.FromJust()->exists == Exists::Yes) return pkg_cfg;
724
725
1336
    URL last_pjson_url = pjson_url;
726
702
    pjson_url = URL("../package.json", pjson_url);
727
728
    // Terminates at root where ../package.json equals ../../package.json
729
    // (can't just check "/package.json" for Windows support).
730

702
    if (pjson_url.path() == last_pjson_url.path()) break;
731
634
  }
732
140
  auto entry = env->package_json_cache.emplace(pjson_url.ToFilePath(),
733
140
  PackageConfig { Exists::No, IsValid::Yes, HasMain::No, "",
734
                  HasName::No, "",
735
70
                  PackageType::None, Global<Value>() });
736
70
  const PackageConfig* pcfg = &entry.first->second;
737
70
  return Just(pcfg);
738
}
739
740
/*
741
 * Legacy CommonJS main resolution:
742
 * 1. let M = pkg_url + (json main field)
743
 * 2. TRY(M, M.js, M.json, M.node)
744
 * 3. TRY(M/index.js, M/index.json, M/index.node)
745
 * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node)
746
 * 5. NOT_FOUND
747
 */
748
130
inline bool FileExists(const URL& url) {
749
130
  return CheckDescriptorAtPath(url.ToFilePath()) == FILE;
750
}
751
Maybe<URL> LegacyMainResolve(const URL& pjson_url,
752
                             const PackageConfig& pcfg) {
753
  URL guess;
754
  if (pcfg.has_main == HasMain::Yes) {
755
    // Note: fs check redundances will be handled by Descriptor cache here.
756
    if (FileExists(guess = URL("./" + pcfg.main, pjson_url))) {
757
      return Just(guess);
758
    }
759
    if (FileExists(guess = URL("./" + pcfg.main + ".js", pjson_url))) {
760
      return Just(guess);
761
    }
762
    if (FileExists(guess = URL("./" + pcfg.main + ".json", pjson_url))) {
763
      return Just(guess);
764
    }
765
    if (FileExists(guess = URL("./" + pcfg.main + ".node", pjson_url))) {
766
      return Just(guess);
767
    }
768
    if (FileExists(guess = URL("./" + pcfg.main + "/index.js", pjson_url))) {
769
      return Just(guess);
770
    }
771
    // Such stat.
772
    if (FileExists(guess = URL("./" + pcfg.main + "/index.json", pjson_url))) {
773
      return Just(guess);
774
    }
775
    if (FileExists(guess = URL("./" + pcfg.main + "/index.node", pjson_url))) {
776
      return Just(guess);
777
    }
778
    // Fallthrough.
779
  }
780
  if (FileExists(guess = URL("./index.js", pjson_url))) {
781
    return Just(guess);
782
  }
783
  // So fs.
784
  if (FileExists(guess = URL("./index.json", pjson_url))) {
785
    return Just(guess);
786
  }
787
  if (FileExists(guess = URL("./index.node", pjson_url))) {
788
    return Just(guess);
789
  }
790
  // Not found.
791
  return Nothing<URL>();
792
}
793
794
enum ResolveExtensionsOptions {
795
  TRY_EXACT_NAME,
796
  ONLY_VIA_EXTENSIONS
797
};
798
799
template <ResolveExtensionsOptions options>
800
57
Maybe<URL> ResolveExtensions(const URL& search) {
801
  if (options == TRY_EXACT_NAME) {
802
48
    if (FileExists(search)) {
803
29
      return Just(search);
804
    }
805
  }
806
807

92
  for (const char* extension : EXTENSIONS) {
808
146
    URL guess(search.path() + extension, &search);
809

82
    if (FileExists(guess)) {
810

18
      return Just(guess);
811
    }
812
  }
813
814
10
  return Nothing<URL>();
815
}
816
817
9
inline Maybe<URL> ResolveIndex(const URL& search) {
818
9
  return ResolveExtensions<ONLY_VIA_EXTENSIONS>(URL("index", search));
819
}
820
821
307
Maybe<URL> FinalizeResolution(Environment* env,
822
                              const URL& resolved,
823
                              const URL& base) {
824
307
  if (env->options()->experimental_specifier_resolution == "node") {
825
96
    Maybe<URL> file = ResolveExtensions<TRY_EXACT_NAME>(resolved);
826
48
    if (!file.IsNothing()) {
827
39
      return file;
828
    }
829
9
    if (resolved.path().back() != '/') {
830
7
      file = ResolveIndex(URL(resolved.path() + "/", &base));
831
    } else {
832
2
      file = ResolveIndex(resolved);
833
    }
834
9
    if (!file.IsNothing()) {
835
8
      return file;
836
    }
837
2
    std::string msg = "Cannot find module " + resolved.path() +
838
4
        " imported from " + base.ToFilePath();
839
1
    node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
840
1
    return Nothing<URL>();
841
  }
842
843
259
  if (resolved.path().back() == '/') {
844
1
    return Just(resolved);
845
  }
846
847
516
  const std::string& path = resolved.ToFilePath();
848
258
  if (CheckDescriptorAtPath(path) != FILE) {
849
14
    std::string msg = "Cannot find module " +
850
28
        (path.length() != 0 ? path : resolved.path()) +
851
28
        " imported from " + base.ToFilePath();
852
7
    node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
853
7
    return Nothing<URL>();
854
  }
855
856
251
  return Just(resolved);
857
}
858
859
10
void ThrowExportsNotFound(Environment* env,
860
                          const std::string& subpath,
861
                          const URL& pjson_url,
862
                          const URL& base) {
863
20
  const std::string msg = "Package subpath '" + subpath + "' is not defined" +
864
40
      " by \"exports\" in " + pjson_url.ToFilePath() + " imported from " +
865
40
      base.ToFilePath();
866
10
  node::THROW_ERR_PACKAGE_PATH_NOT_EXPORTED(env, msg.c_str());
867
10
}
868
869
1
void ThrowSubpathInvalid(Environment* env,
870
                         const std::string& subpath,
871
                         const URL& pjson_url,
872
                         const URL& base) {
873
2
  const std::string msg = "Package subpath '" + subpath + "' is not a valid " +
874
2
      "module request for the \"exports\" resolution of " +
875
4
      pjson_url.ToFilePath() + " imported from " + base.ToFilePath();
876
1
  node::THROW_ERR_INVALID_MODULE_SPECIFIER(env, msg.c_str());
877
1
}
878
879
19
void ThrowExportsInvalid(Environment* env,
880
                         const std::string& subpath,
881
                         const std::string& target,
882
                         const URL& pjson_url,
883
                         const URL& base) {
884
19
  if (subpath.length()) {
885
38
    const std::string msg = "Invalid \"exports\" target \"" + target +
886
38
        "\" defined for '" + subpath + "' in the package config " +
887
76
        pjson_url.ToFilePath() + " imported from " + base.ToFilePath();
888
19
    node::THROW_ERR_INVALID_PACKAGE_TARGET(env, msg.c_str());
889
  } else {
890
    const std::string msg = "Invalid \"exports\" main target " + target +
891
        " defined in the package config " + pjson_url.ToFilePath() +
892
        " imported from " + base.ToFilePath();
893
    node::THROW_ERR_INVALID_PACKAGE_TARGET(env, msg.c_str());
894
  }
895
19
}
896
897
9
void ThrowExportsInvalid(Environment* env,
898
                         const std::string& subpath,
899
                         Local<Value> target,
900
                         const URL& pjson_url,
901
                         const URL& base) {
902
  Local<String> target_string;
903
9
  if (target->IsObject()) {
904
9
    if (!v8::JSON::Stringify(env->context(), target.As<Object>(),
905
12
            v8::String::Empty(env->isolate())).ToLocal(&target_string))
906
      return;
907
  } else {
908
18
    if (!target->ToString(env->context()).ToLocal(&target_string))
909
      return;
910
  }
911
18
  Utf8Value target_utf8(env->isolate(), target_string);
912
18
  std::string target_str(*target_utf8, target_utf8.length());
913
9
  if (target->IsArray()) {
914
3
    target_str = '[' + target_str + ']';
915
  }
916
9
  ThrowExportsInvalid(env, subpath, target_str, pjson_url, base);
917
}
918
919
27
Maybe<URL> ResolveExportsTargetString(Environment* env,
920
                                      const std::string& target,
921
                                      const std::string& subpath,
922
                                      const std::string& match,
923
                                      const URL& pjson_url,
924
                                      const URL& base) {
925
27
  if (target.substr(0, 2) != "./") {
926
8
    ThrowExportsInvalid(env, match, target, pjson_url, base);
927
8
    return Nothing<URL>();
928
  }
929

19
  if (subpath.length() > 0 && target.back() != '/') {
930
1
    ThrowExportsInvalid(env, match, target, pjson_url, base);
931
1
    return Nothing<URL>();
932
  }
933
36
  URL resolved(target, pjson_url);
934
36
  std::string resolved_path = resolved.path();
935
36
  std::string pkg_path = URL(".", pjson_url).path();
936

36
  if (resolved_path.find(pkg_path) != 0 ||
937
18
      resolved_path.find("/node_modules/", pkg_path.length() - 1) !=
938
      std::string::npos) {
939
1
    ThrowExportsInvalid(env, match, target, pjson_url, base);
940
1
    return Nothing<URL>();
941
  }
942
17
  if (subpath.length() == 0) return Just(resolved);
943
10
  URL subpath_resolved(subpath, resolved);
944
10
  std::string subpath_resolved_path = subpath_resolved.path();
945

9
  if (subpath_resolved_path.find(resolved_path) != 0 ||
946
4
      subpath_resolved_path.find("/node_modules/", pkg_path.length() - 1)
947
      != std::string::npos) {
948
1
    ThrowSubpathInvalid(env, match + subpath, pjson_url, base);
949
1
    return Nothing<URL>();
950
  }
951
4
  return Just(subpath_resolved);
952
}
953
954
12
bool IsArrayIndex(Environment* env, Local<Value> p) {
955
12
  Local<Context> context = env->context();
956
24
  Local<String> p_str = p->ToString(context).ToLocalChecked();
957
24
  double n_dbl = static_cast<double>(p_str->NumberValue(context).FromJust());
958
12
  Local<Number> n = Number::New(env->isolate(), n_dbl);
959
24
  Local<String> cmp_str = n->ToString(context).ToLocalChecked();
960
24
  if (!p_str->Equals(context, cmp_str).FromJust()) {
961
11
    return false;
962
  }
963

1
  if (n_dbl == 0 && std::signbit(n_dbl) == false) {
964
1
    return true;
965
  }
966
  Local<Integer> cmp_integer;
967
  if (!n->ToInteger(context).ToLocal(&cmp_integer)) {
968
    return false;
969
  }
970
  return n_dbl > 0 && n_dbl < (1LL << 32) - 1;
971
}
972
973
51
Maybe<URL> ResolveExportsTarget(Environment* env,
974
                                const URL& pjson_url,
975
                                Local<Value> target,
976
                                const std::string& subpath,
977
                                const std::string& pkg_subpath,
978
                                const URL& base) {
979
51
  Isolate* isolate = env->isolate();
980
51
  Local<Context> context = env->context();
981
102
  if (target->IsString()) {
982
54
    Utf8Value target_utf8(isolate, target.As<String>());
983
54
    std::string target_str(*target_utf8, target_utf8.length());
984
    Maybe<URL> resolved = ResolveExportsTargetString(env, target_str, subpath,
985
54
        pkg_subpath, pjson_url, base);
986
27
    if (resolved.IsNothing()) {
987
11
      return Nothing<URL>();
988
    }
989
16
    return FinalizeResolution(env, resolved.FromJust(), base);
990
24
  } else if (target->IsArray()) {
991
7
      Local<Array> target_arr = target.As<Array>();
992
7
      const uint32_t length = target_arr->Length();
993
7
      if (length == 0) {
994
3
        ThrowExportsInvalid(env, pkg_subpath, target, pjson_url, base);
995
3
        return Nothing<URL>();
996
      }
997
16
      for (uint32_t i = 0; i < length; i++) {
998
30
        auto target_item = target_arr->Get(context, i).ToLocalChecked();
999
        {
1000
15
          TryCatchScope try_catch(env);
1001
          Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
1002
15
              target_item, subpath, pkg_subpath, base);
1003
15
          if (resolved.IsNothing()) {
1004
12
            CHECK(try_catch.HasCaught());
1005
24
            if (try_catch.Exception().IsEmpty()) return Nothing<URL>();
1006
            Local<Object> e;
1007
36
            if (!try_catch.Exception()->ToObject(context).ToLocal(&e))
1008
              return Nothing<URL>();
1009
            Local<Value> code;
1010
36
            if (!e->Get(context, env->code_string()).ToLocal(&code))
1011
              return Nothing<URL>();
1012
            Local<String> code_string;
1013
24
            if (!code->ToString(context).ToLocal(&code_string))
1014
              return Nothing<URL>();
1015
12
            Utf8Value code_utf8(env->isolate(), code_string);
1016

21
            if (strcmp(*code_utf8, "ERR_PACKAGE_PATH_NOT_EXPORTED") == 0 ||
1017
9
                strcmp(*code_utf8, "ERR_INVALID_PACKAGE_TARGET") == 0) {
1018
12
              continue;
1019
            }
1020
            try_catch.ReThrow();
1021
            return Nothing<URL>();
1022
          }
1023
3
          CHECK(!try_catch.HasCaught());
1024

3
          return FinalizeResolution(env, resolved.FromJust(), base);
1025
        }
1026
      }
1027
3
      auto invalid = target_arr->Get(context, length - 1).ToLocalChecked();
1028
      Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url, invalid,
1029
2
          subpath, pkg_subpath, base);
1030
1
      CHECK(resolved.IsNothing());
1031
1
      return Nothing<URL>();
1032
17
  } else if (target->IsObject()) {
1033
11
    Local<Object> target_obj = target.As<Object>();
1034
    Local<Array> target_obj_keys =
1035
22
        target_obj->GetOwnPropertyNames(context).ToLocalChecked();
1036
    Local<Value> conditionalTarget;
1037
44
    for (uint32_t i = 0; i < target_obj_keys->Length(); ++i) {
1038
      Local<Value> key =
1039
24
          target_obj_keys->Get(context, i).ToLocalChecked();
1040
12
      if (IsArrayIndex(env, key)) {
1041
2
        const std::string msg = "Invalid package config " +
1042
4
            pjson_url.ToFilePath() + " imported from " + base.ToFilePath() +
1043
2
            ". \"exports\" cannot contain numeric property keys.";
1044
1
        node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str());
1045
1
        return Nothing<URL>();
1046
      }
1047
    }
1048
32
    for (uint32_t i = 0; i < target_obj_keys->Length(); ++i) {
1049
20
      Local<Value> key = target_obj_keys->Get(context, i).ToLocalChecked();
1050
      Utf8Value key_utf8(env->isolate(),
1051
25
                         key->ToString(context).ToLocalChecked());
1052
15
      std::string key_str(*key_utf8, key_utf8.length());
1053

10
      if (key_str == "node" || key_str == "import") {
1054
8
        conditionalTarget = target_obj->Get(context, key).ToLocalChecked();
1055
        {
1056
4
          TryCatchScope try_catch(env);
1057
          Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
1058
4
              conditionalTarget, subpath, pkg_subpath, base);
1059
4
          if (resolved.IsNothing()) {
1060
1
            CHECK(try_catch.HasCaught());
1061
2
            if (try_catch.Exception().IsEmpty()) return Nothing<URL>();
1062
            Local<Object> e;
1063
3
            if (!try_catch.Exception()->ToObject(context).ToLocal(&e))
1064
              return Nothing<URL>();
1065
            Local<Value> code;
1066
3
            if (!e->Get(context, env->code_string()).ToLocal(&code))
1067
              return Nothing<URL>();
1068
            Local<String> code_string;
1069
2
            if (!code->ToString(context).ToLocal(&code_string))
1070
              return Nothing<URL>();
1071
1
            Utf8Value code_utf8(env->isolate(), code_string);
1072
1
            if (strcmp(*code_utf8, "ERR_PACKAGE_PATH_NOT_EXPORTED") == 0)
1073
1
              continue;
1074
            try_catch.ReThrow();
1075
            return Nothing<URL>();
1076
          }
1077
3
          CHECK(!try_catch.HasCaught());
1078

3
          return resolved;
1079
        }
1080
6
      } else if (key_str == "default") {
1081
2
        conditionalTarget = target_obj->Get(context, key).ToLocalChecked();
1082
        {
1083
1
          TryCatchScope try_catch(env);
1084
          Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
1085
1
              conditionalTarget, subpath, pkg_subpath, base);
1086
1
          if (resolved.IsNothing()) {
1087
            CHECK(try_catch.HasCaught() && !try_catch.Exception().IsEmpty());
1088
            auto e = try_catch.Exception()->ToObject(context).ToLocalChecked();
1089
            auto code = e->Get(context, env->code_string()).ToLocalChecked();
1090
            Utf8Value code_utf8(env->isolate(),
1091
                                code->ToString(context).ToLocalChecked());
1092
            std::string code_str(*code_utf8, code_utf8.length());
1093
            if (code_str == "ERR_PACKAGE_PATH_NOT_EXPORTED") continue;
1094
            try_catch.ReThrow();
1095
            return Nothing<URL>();
1096
          }
1097
1
          CHECK(!try_catch.HasCaught());
1098

1
          return resolved;
1099
        }
1100
      }
1101
    }
1102
6
    ThrowExportsNotFound(env, pkg_subpath, pjson_url, base);
1103
6
    return Nothing<URL>();
1104
  }
1105
6
  ThrowExportsInvalid(env, pkg_subpath, target, pjson_url, base);
1106
6
  return Nothing<URL>();
1107
}
1108
1109
35
Maybe<bool> IsConditionalExportsMainSugar(Environment* env,
1110
                                          Local<Value> exports,
1111
                                          const URL& pjson_url,
1112
                                          const URL& base) {
1113

101
  if (exports->IsString() || exports->IsArray()) return Just(true);
1114
31
  if (!exports->IsObject()) return Just(false);
1115
30
  Local<Context> context = env->context();
1116
30
  Local<Object> exports_obj = exports.As<Object>();
1117
  Local<Array> keys =
1118
60
      exports_obj->GetOwnPropertyNames(context).ToLocalChecked();
1119
30
  bool isConditionalSugar = false;
1120
1112
  for (uint32_t i = 0; i < keys->Length(); ++i) {
1121
1054
    Local<Value> key = keys->Get(context, i).ToLocalChecked();
1122
1580
    Utf8Value key_utf8(env->isolate(), key->ToString(context).ToLocalChecked());
1123

527
    bool curIsConditionalSugar = key_utf8.length() == 0 || key_utf8[0] != '.';
1124
527
    if (i == 0) {
1125
30
      isConditionalSugar = curIsConditionalSugar;
1126
497
    } else if (isConditionalSugar != curIsConditionalSugar) {
1127
2
      const std::string msg = "Invalid package config " + pjson_url.ToFilePath()
1128
4
        + " imported from " + base.ToFilePath() + ". " +
1129
2
        "\"exports\" cannot contain some keys starting with '.' and some not." +
1130
        " The exports object must either be an object of package subpath keys" +
1131
2
        " or an object of main entry condition name keys only.";
1132
1
      node::THROW_ERR_INVALID_PACKAGE_CONFIG(env, msg.c_str());
1133
1
      return Nothing<bool>();
1134
    }
1135
  }
1136
29
  return Just(isConditionalSugar);
1137
}
1138
1139
20
Maybe<URL> PackageMainResolve(Environment* env,
1140
                              const URL& pjson_url,
1141
                              const PackageConfig& pcfg,
1142
                              const URL& base) {
1143
20
  if (pcfg.exists == Exists::Yes) {
1144
20
    Isolate* isolate = env->isolate();
1145
1146
40
    if (!pcfg.exports.IsEmpty()) {
1147
12
      Local<Value> exports = pcfg.exports.Get(isolate);
1148
      Maybe<bool> isConditionalExportsMainSugar =
1149
6
          IsConditionalExportsMainSugar(env, exports, pjson_url, base);
1150
6
      if (isConditionalExportsMainSugar.IsNothing())
1151
7
        return Nothing<URL>();
1152
5
      if (isConditionalExportsMainSugar.FromJust()) {
1153
5
        return ResolveExportsTarget(env, pjson_url, exports, "", "", base);
1154
      } else if (exports->IsObject()) {
1155
        Local<Object> exports_obj = exports.As<Object>();
1156
        if (exports_obj->HasOwnProperty(env->context(), env->dot_string())
1157
            .FromJust()) {
1158
          Local<Value> target =
1159
              exports_obj->Get(env->context(), env->dot_string())
1160
              .ToLocalChecked();
1161
          return ResolveExportsTarget(env, pjson_url, target, "", "", base);
1162
        }
1163
      }
1164
      std::string msg = "No \"exports\" main resolved in " +
1165
          pjson_url.ToFilePath();
1166
      node::THROW_ERR_PACKAGE_PATH_NOT_EXPORTED(env, msg.c_str());
1167
    }
1168
14
    if (pcfg.has_main == HasMain::Yes) {
1169
23
      URL resolved(pcfg.main, pjson_url);
1170
23
      const std::string& path = resolved.ToFilePath();
1171
14
      if (CheckDescriptorAtPath(path) == FILE) {
1172
5
        return Just(resolved);
1173
      }
1174
    }
1175
9
    if (env->options()->experimental_specifier_resolution == "node") {
1176
9
      if (pcfg.has_main == HasMain::Yes) {
1177
9
        return FinalizeResolution(env, URL(pcfg.main, pjson_url), base);
1178
      } else {
1179
        return FinalizeResolution(env, URL("index", pjson_url), base);
1180
      }
1181
    }
1182
    if (pcfg.type != PackageType::Module) {
1183
      Maybe<URL> resolved = LegacyMainResolve(pjson_url, pcfg);
1184
      if (!resolved.IsNothing()) {
1185
        return resolved;
1186
      }
1187
    }
1188
  }
1189
  std::string msg = "Cannot find main entry point for " +
1190
      URL(".", pjson_url).ToFilePath() + " imported from " +
1191
      base.ToFilePath();
1192
  node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
1193
  return Nothing<URL>();
1194
}
1195
1196
29
Maybe<URL> PackageExportsResolve(Environment* env,
1197
                                 const URL& pjson_url,
1198
                                 const std::string& pkg_subpath,
1199
                                 const PackageConfig& pcfg,
1200
                                 const URL& base) {
1201
29
  Isolate* isolate = env->isolate();
1202
29
  Local<Context> context = env->context();
1203
58
  Local<Value> exports = pcfg.exports.Get(isolate);
1204
  Maybe<bool> isConditionalExportsMainSugar =
1205
29
      IsConditionalExportsMainSugar(env, exports, pjson_url, base);
1206
29
  if (isConditionalExportsMainSugar.IsNothing())
1207
    return Nothing<URL>();
1208

56
  if (!exports->IsObject() || isConditionalExportsMainSugar.FromJust()) {
1209
3
    ThrowExportsNotFound(env, pkg_subpath, pjson_url, base);
1210
3
    return Nothing<URL>();
1211
  }
1212
26
  Local<Object> exports_obj = exports.As<Object>();
1213
52
  Local<String> subpath = String::NewFromUtf8(isolate,
1214
52
      pkg_subpath.c_str(), v8::NewStringType::kNormal).ToLocalChecked();
1215
1216
52
  if (exports_obj->HasOwnProperty(context, subpath).FromJust()) {
1217
36
    Local<Value> target = exports_obj->Get(context, subpath).ToLocalChecked();
1218
    Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url, target, "",
1219
36
                                               pkg_subpath, base);
1220
18
    if (resolved.IsNothing()) {
1221
10
      return Nothing<URL>();
1222
    }
1223
8
    return FinalizeResolution(env, resolved.FromJust(), base);
1224
  }
1225
1226
  Local<String> best_match;
1227
16
  std::string best_match_str = "";
1228
  Local<Array> keys =
1229
16
      exports_obj->GetOwnPropertyNames(context).ToLocalChecked();
1230
336
  for (uint32_t i = 0; i < keys->Length(); ++i) {
1231
320
    Local<Value> key = keys->Get(context, i).ToLocalChecked();
1232
352
    Utf8Value key_utf8(isolate, key->ToString(context).ToLocalChecked());
1233
192
    std::string key_str(*key_utf8, key_utf8.length());
1234
160
    if (key_str.back() != '/') continue;
1235


39
    if (pkg_subpath.substr(0, key_str.length()) == key_str &&
1236
7
        key_str.length() > best_match_str.length()) {
1237
14
      best_match = key->ToString(context).ToLocalChecked();
1238
7
      best_match_str = key_str;
1239
    }
1240
  }
1241
1242
8
  if (best_match_str.length() > 0) {
1243
14
    auto target = exports_obj->Get(context, best_match).ToLocalChecked();
1244
14
    std::string subpath = pkg_subpath.substr(best_match_str.length());
1245
1246
    Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url, target, subpath,
1247
14
                                               pkg_subpath, base);
1248
7
    if (resolved.IsNothing()) {
1249
5
      return Nothing<URL>();
1250
    }
1251
2
    return FinalizeResolution(env, resolved.FromJust(), base);
1252
  }
1253
1254
1
  ThrowExportsNotFound(env, pkg_subpath, pjson_url, base);
1255
1
  return Nothing<URL>();
1256
}
1257
1258
60
Maybe<URL> PackageResolve(Environment* env,
1259
                          const std::string& specifier,
1260
                          const URL& base) {
1261
60
  size_t sep_index = specifier.find('/');
1262
60
  bool valid_package_name = true;
1263
60
  bool scope = false;
1264
60
  if (specifier[0] == '@') {
1265
2
    scope = true;
1266

2
    if (sep_index == std::string::npos || specifier.length() == 0) {
1267
1
      valid_package_name = false;
1268
    } else {
1269
1
      sep_index = specifier.find('/', sep_index + 1);
1270
    }
1271
58
  } else if (specifier[0] == '.') {
1272
    valid_package_name = false;
1273
  }
1274
  std::string pkg_name = specifier.substr(0,
1275
120
      sep_index == std::string::npos ? std::string::npos : sep_index);
1276
  // Package name cannot have leading . and cannot have percent-encoding or
1277
  // separators.
1278
758
  for (size_t i = 0; i < pkg_name.length(); i++) {
1279
701
    char c = pkg_name[i];
1280

701
    if (c == '%' || c == '\\') {
1281
3
      valid_package_name = false;
1282
3
      break;
1283
    }
1284
  }
1285
60
  if (!valid_package_name) {
1286
8
    std::string msg = "Invalid package name '" + specifier +
1287
16
      "' imported from " + base.ToFilePath();
1288
4
    node::THROW_ERR_INVALID_MODULE_SPECIFIER(env, msg.c_str());
1289
4
    return Nothing<URL>();
1290
  }
1291
112
  std::string pkg_subpath;
1292
56
  if (sep_index == std::string::npos) {
1293
24
    pkg_subpath = "";
1294
  } else {
1295
32
    pkg_subpath = "." + specifier.substr(sep_index);
1296
  }
1297
1298
  // ResolveSelf
1299
  const PackageConfig* pcfg;
1300

168
  if (GetPackageScopeConfig(env, base, base).To(&pcfg) &&
1301
56
      pcfg->exists == Exists::Yes) {
1302
    // TODO(jkrems): Find a way to forward the pair/iterator already generated
1303
    // while executing GetPackageScopeConfig
1304
35
    URL pjson_url("");
1305
19
    bool found_pjson = false;
1306
117
    for (const auto& it : env->package_json_cache) {
1307
98
      if (&it.second == pcfg) {
1308
19
        pjson_url = URL::FromFilePath(it.first);
1309
19
        found_pjson = true;
1310
      }
1311
    }
1312


22
    if (found_pjson && pcfg->name == pkg_name && !pcfg->exports.IsEmpty()) {
1313
3
      if (pkg_subpath == "./") {
1314
        return Just(URL("./", pjson_url));
1315
3
      } else if (!pkg_subpath.length()) {
1316
1
        return PackageMainResolve(env, pjson_url, *pcfg, base);
1317
      } else {
1318
2
        return PackageExportsResolve(env, pjson_url, pkg_subpath, *pcfg, base);
1319
      }
1320
    }
1321
  }
1322
1323
106
  URL pjson_url("./node_modules/" + pkg_name + "/package.json", &base);
1324
106
  std::string pjson_path = pjson_url.ToFilePath();
1325
106
  std::string last_path;
1326
80
  do {
1327
    DescriptorType check =
1328
91
        CheckDescriptorAtPath(pjson_path.substr(0, pjson_path.length() - 13));
1329
91
    if (check != DIRECTORY) {
1330
42
      last_path = pjson_path;
1331
84
      pjson_url = URL((scope ?
1332
84
          "../../../../node_modules/" : "../../../node_modules/") +
1333
126
          pkg_name + "/package.json", &pjson_url);
1334
42
      pjson_path = pjson_url.ToFilePath();
1335
42
      continue;
1336
    }
1337
1338
    // Package match.
1339
49
    Maybe<const PackageConfig*> pcfg = GetPackageConfig(env, pjson_path, base);
1340
    // Invalid package configuration error.
1341
98
    if (pcfg.IsNothing()) return Nothing<URL>();
1342
49
    if (pkg_subpath == "./") {
1343
1
      return Just(URL("./", pjson_url));
1344
48
    } else if (!pkg_subpath.length()) {
1345
19
      return PackageMainResolve(env, pjson_url, *pcfg.FromJust(), base);
1346
    } else {
1347
58
      if (!pcfg.FromJust()->exports.IsEmpty()) {
1348
        return PackageExportsResolve(env, pjson_url, pkg_subpath,
1349
27
                                     *pcfg.FromJust(), base);
1350
      } else {
1351
2
        return FinalizeResolution(env, URL(pkg_subpath, pjson_url), base);
1352
      }
1353
    }
1354
    CHECK(false);
1355
    // Cross-platform root check.
1356
42
  } while (pjson_path.length() != last_path.length());
1357
1358
8
  std::string msg = "Cannot find package '" + pkg_name +
1359
16
      "' imported from " + base.ToFilePath();
1360
4
  node::THROW_ERR_MODULE_NOT_FOUND(env, msg.c_str());
1361
4
  return Nothing<URL>();
1362
}
1363
1364
}  // anonymous namespace
1365
1366
327
Maybe<URL> Resolve(Environment* env,
1367
                   const std::string& specifier,
1368
                   const URL& base) {
1369
  // Order swapped from spec for minor perf gain.
1370
  // Ok since relative URLs cannot parse as URLs.
1371
654
  URL resolved;
1372
327
  if (ShouldBeTreatedAsRelativeOrAbsolutePath(specifier)) {
1373
170
    resolved = URL(specifier, base);
1374
  } else {
1375
254
    URL pure_url(specifier);
1376
157
    if (!(pure_url.flags() & URL_FLAGS_FAILED)) {
1377
97
      resolved = pure_url;
1378
    } else {
1379
60
      return PackageResolve(env, specifier, base);
1380
    }
1381
  }
1382
267
  return FinalizeResolution(env, resolved, base);
1383
}
1384
1385
327
void ModuleWrap::Resolve(const FunctionCallbackInfo<Value>& args) {
1386
327
  Environment* env = Environment::GetCurrent(args);
1387
1388
  // module.resolve(specifier, url)
1389
327
  CHECK_EQ(args.Length(), 2);
1390
1391
981
  CHECK(args[0]->IsString());
1392
619
  Utf8Value specifier_utf8(env->isolate(), args[0]);
1393
619
  std::string specifier_std(*specifier_utf8, specifier_utf8.length());
1394
1395
981
  CHECK(args[1]->IsString());
1396
619
  Utf8Value url_utf8(env->isolate(), args[1]);
1397
619
  URL url(*url_utf8, url_utf8.length());
1398
1399
327
  if (url.flags() & URL_FLAGS_FAILED) {
1400
    return node::THROW_ERR_INVALID_ARG_TYPE(
1401
        env, "second argument is not a URL string");
1402
  }
1403
1404
  Maybe<URL> result =
1405
      node::loader::Resolve(env,
1406
                            specifier_std,
1407
619
                            url);
1408
327
  if (result.IsNothing()) {
1409
35
    return;
1410
  }
1411
1412
292
  URL resolution = result.FromJust();
1413
292
  CHECK(!(resolution.flags() & URL_FLAGS_FAILED));
1414
1415
  Local<Value> resolution_obj;
1416
584
  if (resolution.ToObject(env).ToLocal(&resolution_obj))
1417
584
    args.GetReturnValue().Set(resolution_obj);
1418
}
1419
1420
72
void ModuleWrap::GetPackageType(const FunctionCallbackInfo<Value>& args) {
1421
72
  Environment* env = Environment::GetCurrent(args);
1422
1423
  // module.getPackageType(url)
1424
72
  CHECK_EQ(args.Length(), 1);
1425
1426
216
  CHECK(args[0]->IsString());
1427
144
  Utf8Value url_utf8(env->isolate(), args[0]);
1428
144
  URL url(*url_utf8, url_utf8.length());
1429
1430
72
  PackageType pkg_type = PackageType::None;
1431
  Maybe<const PackageConfig*> pcfg =
1432
72
      GetPackageScopeConfig(env, url, url);
1433
72
  if (!pcfg.IsNothing()) {
1434
72
    pkg_type = pcfg.FromJust()->type;
1435
  }
1436
1437
216
  args.GetReturnValue().Set(Integer::New(env->isolate(), pkg_type));
1438
72
}
1439
1440
86
static MaybeLocal<Promise> ImportModuleDynamically(
1441
    Local<Context> context,
1442
    Local<ScriptOrModule> referrer,
1443
    Local<String> specifier) {
1444
86
  Isolate* iso = context->GetIsolate();
1445
86
  Environment* env = Environment::GetCurrent(context);
1446
86
  CHECK_NOT_NULL(env);  // TODO(addaleax): Handle nullptr here.
1447
86
  EscapableHandleScope handle_scope(iso);
1448
1449
  Local<Function> import_callback =
1450
86
    env->host_import_module_dynamically_callback();
1451
1452
86
  Local<PrimitiveArray> options = referrer->GetHostDefinedOptions();
1453
86
  if (options->Length() != HostDefinedOptions::kLength) {
1454
    Local<Promise::Resolver> resolver =
1455
        Promise::Resolver::New(context).ToLocalChecked();
1456
    resolver
1457
        ->Reject(context,
1458
                 v8::Exception::TypeError(FIXED_ONE_BYTE_STRING(
1459
                     context->GetIsolate(), "Invalid host defined options")))
1460
        .ToChecked();
1461
    return handle_scope.Escape(resolver->GetPromise());
1462
  }
1463
1464
  Local<Value> object;
1465
1466
172
  int type = options->Get(iso, HostDefinedOptions::kType)
1467
172
                 .As<Number>()
1468
172
                 ->Int32Value(context)
1469
86
                 .ToChecked();
1470
172
  uint32_t id = options->Get(iso, HostDefinedOptions::kID)
1471
172
                    .As<Number>()
1472
172
                    ->Uint32Value(context)
1473
86
                    .ToChecked();
1474
86
  if (type == ScriptType::kScript) {
1475
5
    contextify::ContextifyScript* wrap = env->id_to_script_map.find(id)->second;
1476
10
    object = wrap->object();
1477
81
  } else if (type == ScriptType::kModule) {
1478
49
    ModuleWrap* wrap = ModuleWrap::GetFromID(env, id);
1479
98
    object = wrap->object();
1480
32
  } else if (type == ScriptType::kFunction) {
1481
32
    auto it = env->id_to_function_map.find(id);
1482
32
    CHECK_NE(it, env->id_to_function_map.end());
1483
64
    object = it->second->object();
1484
  } else {
1485
    UNREACHABLE();
1486
  }
1487
1488
  Local<Value> import_args[] = {
1489
    object,
1490
    Local<Value>(specifier),
1491
172
  };
1492
1493
  Local<Value> result;
1494
258
  if (import_callback->Call(
1495
        context,
1496
        Undefined(iso),
1497
86
        arraysize(import_args),
1498
258
        import_args).ToLocal(&result)) {
1499
86
    CHECK(result->IsPromise());
1500
86
    return handle_scope.Escape(result.As<Promise>());
1501
  }
1502
1503
  return MaybeLocal<Promise>();
1504
}
1505
1506
4358
void ModuleWrap::SetImportModuleDynamicallyCallback(
1507
    const FunctionCallbackInfo<Value>& args) {
1508
4358
  Isolate* iso = args.GetIsolate();
1509
4358
  Environment* env = Environment::GetCurrent(args);
1510
8716
  HandleScope handle_scope(iso);
1511
1512
4358
  CHECK_EQ(args.Length(), 1);
1513
8716
  CHECK(args[0]->IsFunction());
1514
8716
  Local<Function> import_callback = args[0].As<Function>();
1515
4358
  env->set_host_import_module_dynamically_callback(import_callback);
1516
1517
4358
  iso->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
1518
4358
}
1519
1520
59
void ModuleWrap::HostInitializeImportMetaObjectCallback(
1521
    Local<Context> context, Local<Module> module, Local<Object> meta) {
1522
59
  Environment* env = Environment::GetCurrent(context);
1523
59
  CHECK_NOT_NULL(env);  // TODO(addaleax): Handle nullptr here.
1524
59
  ModuleWrap* module_wrap = GetFromModule(env, module);
1525
1526
59
  if (module_wrap == nullptr) {
1527
    return;
1528
  }
1529
1530
59
  Local<Object> wrap = module_wrap->object();
1531
  Local<Function> callback =
1532
59
      env->host_initialize_import_meta_object_callback();
1533
177
  Local<Value> args[] = { wrap, meta };
1534
118
  TryCatchScope try_catch(env);
1535
118
  USE(callback->Call(
1536
236
        context, Undefined(env->isolate()), arraysize(args), args));
1537

59
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
1538
    try_catch.ReThrow();
1539
  }
1540
}
1541
1542
4358
void ModuleWrap::SetInitializeImportMetaObjectCallback(
1543
    const FunctionCallbackInfo<Value>& args) {
1544
4358
  Environment* env = Environment::GetCurrent(args);
1545
4358
  Isolate* isolate = env->isolate();
1546
1547
4358
  CHECK_EQ(args.Length(), 1);
1548
8716
  CHECK(args[0]->IsFunction());
1549
8716
  Local<Function> import_meta_callback = args[0].As<Function>();
1550
4358
  env->set_host_initialize_import_meta_object_callback(import_meta_callback);
1551
1552
  isolate->SetHostInitializeImportMetaObjectCallback(
1553
4358
      HostInitializeImportMetaObjectCallback);
1554
4358
}
1555
1556
29388
MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
1557
    Local<Context> context, Local<Module> module) {
1558
29388
  Environment* env = Environment::GetCurrent(context);
1559
29389
  Isolate* isolate = env->isolate();
1560
1561
29389
  ModuleWrap* obj = GetFromModule(env, module);
1562
1563
58778
  TryCatchScope try_catch(env);
1564
  Local<Function> synthetic_evaluation_steps =
1565
58778
      obj->synthetic_evaluation_steps_.Get(isolate);
1566
  MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
1567
58778
      obj->object(), 0, nullptr);
1568
29388
  if (ret.IsEmpty()) {
1569
    CHECK(try_catch.HasCaught());
1570
  }
1571
29388
  obj->synthetic_evaluation_steps_.Reset();
1572

29389
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
1573
    CHECK(!try_catch.Message().IsEmpty());
1574
    CHECK(!try_catch.Exception().IsEmpty());
1575
    try_catch.ReThrow();
1576
    return MaybeLocal<Value>();
1577
  }
1578
29389
  return ret;
1579
}
1580
1581
2426541
void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
1582
2426541
  Isolate* isolate = args.GetIsolate();
1583
2426541
  Local<Object> that = args.This();
1584
1585
  ModuleWrap* obj;
1586
2426541
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
1587
1588
2426550
  CHECK(obj->synthetic_);
1589
1590
2426550
  CHECK_EQ(args.Length(), 2);
1591
1592
7279650
  CHECK(args[0]->IsString());
1593
4853100
  Local<String> export_name = args[0].As<String>();
1594
1595
2426550
  Local<Value> export_value = args[1];
1596
1597
4853101
  Local<Module> module = obj->module_.Get(isolate);
1598
2426551
  USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
1599
}
1600
1601
1
void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
1602
1
  Isolate* isolate = args.GetIsolate();
1603
1
  Local<Object> that = args.This();
1604
1605
  ModuleWrap* obj;
1606
1
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);
1607
1608
1
  CHECK(!obj->synthetic_);
1609
1610
2
  Local<Module> module = obj->module_.Get(isolate);
1611
1612
1
  CHECK_LT(module->GetStatus(), v8::Module::Status::kEvaluating);
1613
1614
  Local<UnboundModuleScript> unbound_module_script =
1615
1
      module->GetUnboundModuleScript();
1616
  std::unique_ptr<ScriptCompiler::CachedData> cached_data(
1617
2
      ScriptCompiler::CreateCodeCache(unbound_module_script));
1618
1
  Environment* env = Environment::GetCurrent(args);
1619
1
  if (!cached_data) {
1620
    args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
1621
  } else {
1622
    MaybeLocal<Object> buf =
1623
        Buffer::Copy(env,
1624
1
                     reinterpret_cast<const char*>(cached_data->data),
1625
2
                     cached_data->length);
1626
2
    args.GetReturnValue().Set(buf.ToLocalChecked());
1627
  }
1628
}
1629
1630
4358
void ModuleWrap::Initialize(Local<Object> target,
1631
                            Local<Value> unused,
1632
                            Local<Context> context,
1633
                            void* priv) {
1634
4358
  Environment* env = Environment::GetCurrent(context);
1635
4358
  Isolate* isolate = env->isolate();
1636
1637
4358
  Local<FunctionTemplate> tpl = env->NewFunctionTemplate(New);
1638
8716
  tpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"));
1639
8716
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
1640
1641
4358
  env->SetProtoMethod(tpl, "link", Link);
1642
4358
  env->SetProtoMethod(tpl, "instantiate", Instantiate);
1643
4358
  env->SetProtoMethod(tpl, "evaluate", Evaluate);
1644
4358
  env->SetProtoMethod(tpl, "setExport", SetSyntheticExport);
1645
4358
  env->SetProtoMethodNoSideEffect(tpl, "createCachedData", CreateCachedData);
1646
4358
  env->SetProtoMethodNoSideEffect(tpl, "getNamespace", GetNamespace);
1647
4358
  env->SetProtoMethodNoSideEffect(tpl, "getStatus", GetStatus);
1648
4358
  env->SetProtoMethodNoSideEffect(tpl, "getError", GetError);
1649
  env->SetProtoMethodNoSideEffect(tpl, "getStaticDependencySpecifiers",
1650
4358
                                  GetStaticDependencySpecifiers);
1651
1652
8716
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"),
1653
21790
              tpl->GetFunction(context).ToLocalChecked()).Check();
1654
4358
  env->SetMethod(target, "resolve", Resolve);
1655
4358
  env->SetMethod(target, "getPackageType", GetPackageType);
1656
  env->SetMethod(target,
1657
                 "setImportModuleDynamicallyCallback",
1658
4358
                 SetImportModuleDynamicallyCallback);
1659
  env->SetMethod(target,
1660
                 "setInitializeImportMetaObjectCallback",
1661
4358
                 SetInitializeImportMetaObjectCallback);
1662
1663
#define V(name)                                                                \
1664
    target->Set(context,                                                       \
1665
      FIXED_ONE_BYTE_STRING(env->isolate(), #name),                            \
1666
      Integer::New(env->isolate(), Module::Status::name))                      \
1667
        .FromJust()
1668
17432
    V(kUninstantiated);
1669
17432
    V(kInstantiating);
1670
17432
    V(kInstantiated);
1671
17432
    V(kEvaluating);
1672
17432
    V(kEvaluated);
1673
17432
    V(kErrored);
1674
#undef V
1675
4358
}
1676
1677
}  // namespace loader
1678
}  // namespace node
1679
1680
4200
NODE_MODULE_CONTEXT_AWARE_INTERNAL(module_wrap,
1681
                                   node::loader::ModuleWrap::Initialize)