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: 826 951 86.9 %
Date: 2020-02-19 22:14:06 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::Function;
29
using v8::FunctionCallbackInfo;
30
using v8::FunctionTemplate;
31
using v8::Global;
32
using v8::HandleScope;
33
using v8::Integer;
34
using v8::IntegrityLevel;
35
using v8::Isolate;
36
using v8::Just;
37
using v8::Local;
38
using v8::Maybe;
39
using v8::MaybeLocal;
40
using v8::Module;
41
using v8::Nothing;
42
using v8::Number;
43
using v8::Object;
44
using v8::PrimitiveArray;
45
using v8::Promise;
46
using v8::ScriptCompiler;
47
using v8::ScriptOrigin;
48
using v8::String;
49
using v8::UnboundModuleScript;
50
using v8::Undefined;
51
using v8::Value;
52
53
static const char* const EXTENSIONS[] = {
54
  ".js",
55
  ".json",
56
  ".node",
57
  ".mjs"
58
};
59
60
29551
ModuleWrap::ModuleWrap(Environment* env,
61
                       Local<Object> object,
62
                       Local<Module> module,
63
29551
                       Local<String> url) :
64
  BaseObject(env, object),
65
147755
  id_(env->get_next_module_id()) {
66
29551
  module_.Reset(env->isolate(), module);
67
29551
  url_.Reset(env->isolate(), url);
68
29551
  env->id_to_module_map.emplace(id_, this);
69
29551
}
70
71
194224
ModuleWrap::~ModuleWrap() {
72
55493
  HandleScope scope(env()->isolate());
73
55494
  Local<Module> module = module_.Get(env()->isolate());
74
27747
  env()->id_to_module_map.erase(id_);
75
27747
  auto range = env()->hash_to_module_map.equal_range(module->GetIdentityHash());
76
27747
  for (auto it = range.first; it != range.second; ++it) {
77
27747
    if (it->second == this) {
78
27747
      env()->hash_to_module_map.erase(it);
79
27747
      break;
80
    }
81
  }
82
55493
}
83
84
29597
ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
85
                                      Local<Module> module) {
86
29597
  auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
87
29597
  for (auto it = range.first; it != range.second; ++it) {
88
59194
    if (it->second->module_ == module) {
89
29597
      return it->second;
90
    }
91
  }
92
  return nullptr;
93
}
94
95
49
ModuleWrap* ModuleWrap::GetFromID(Environment* env, uint32_t id) {
96
49
  auto module_wrap_it = env->id_to_module_map.find(id);
97
49
  if (module_wrap_it == env->id_to_module_map.end()) {
98
    return nullptr;
99
  }
100
49
  return module_wrap_it->second;
101
}
102
103
// new ModuleWrap(url, context, source, lineOffset, columnOffset)
104
// new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
105
29559
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
106
29559
  CHECK(args.IsConstructCall());
107
29559
  CHECK_GE(args.Length(), 3);
108
109
29559
  Environment* env = Environment::GetCurrent(args);
110
29559
  Isolate* isolate = env->isolate();
111
112
29559
  Local<Object> that = args.This();
113
114
88677
  CHECK(args[0]->IsString());
115
59118
  Local<String> url = args[0].As<String>();
116
117
  Local<Context> context;
118
88677
  if (args[1]->IsUndefined()) {
119
29551
    context = that->CreationContext();
120
  } else {
121
16
    CHECK(args[1]->IsObject());
122
    ContextifyContext* sandbox =
123
8
        ContextifyContext::ContextFromContextifiedSandbox(
124
24
            env, args[1].As<Object>());
125
8
    CHECK_NOT_NULL(sandbox);
126
8
    context = sandbox->context();
127
  }
128
129
  Local<Integer> line_offset;
130
  Local<Integer> column_offset;
131
132
59118
  bool synthetic = args[2]->IsArray();
133
29559
  if (synthetic) {
134
    // new ModuleWrap(url, context, exportNames, syntheticExecutionFunction)
135
58562
    CHECK(args[3]->IsFunction());
136
  } else {
137
    // new ModuleWrap(url, context, source, lineOffset, columOffset, cachedData)
138
834
    CHECK(args[2]->IsString());
139
556
    CHECK(args[3]->IsNumber());
140
556
    line_offset = args[3].As<Integer>();
141
556
    CHECK(args[4]->IsNumber());
142
556
    column_offset = args[4].As<Integer>();
143
  }
144
145
  Local<PrimitiveArray> host_defined_options =
146
29559
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
147
88677
  host_defined_options->Set(isolate, HostDefinedOptions::kType,
148
29559
                            Number::New(isolate, ScriptType::kModule));
149
150
59110
  ShouldNotAbortOnUncaughtScope no_abort_scope(env);
151
59110
  TryCatchScope try_catch(env);
152
153
  Local<Module> module;
154
155
  {
156
29551
    Context::Scope context_scope(context);
157
29559
    if (synthetic) {
158
58562
      CHECK(args[2]->IsArray());
159
58562
      Local<Array> export_names_arr = args[2].As<Array>();
160
161
29281
      uint32_t len = export_names_arr->Length();
162
58562
      std::vector<Local<String>> export_names(len);
163
822029
      for (uint32_t i = 0; i < len; i++) {
164
        Local<Value> export_name_val =
165
1585496
            export_names_arr->Get(context, i).ToLocalChecked();
166
1585496
        CHECK(export_name_val->IsString());
167
1585496
        export_names[i] = export_name_val.As<String>();
168
      }
169
170
      module = Module::CreateSyntheticModule(isolate, url, export_names,
171
29281
        SyntheticModuleEvaluationStepsCallback);
172
    } else {
173
278
      ScriptCompiler::CachedData* cached_data = nullptr;
174
834
      if (!args[5]->IsUndefined()) {
175
4
        CHECK(args[5]->IsArrayBufferView());
176
4
        Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
177
        uint8_t* data = static_cast<uint8_t*>(
178
4
            cached_data_buf->Buffer()->GetBackingStore()->Data());
179
2
        cached_data =
180
2
            new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
181
2
                                           cached_data_buf->ByteLength());
182
      }
183
184
556
      Local<String> source_text = args[2].As<String>();
185
      ScriptOrigin origin(url,
186
                          line_offset,                      // line offset
187
                          column_offset,                    // column offset
188
                          True(isolate),                    // is cross origin
189
                          Local<Integer>(),                 // script id
190
                          Local<Value>(),                   // source map URL
191
                          False(isolate),                   // is opaque (?)
192
                          False(isolate),                   // is WASM
193
                          True(isolate),                    // is ES Module
194
278
                          host_defined_options);
195
270
      ScriptCompiler::Source source(source_text, origin, cached_data);
196
      ScriptCompiler::CompileOptions options;
197
278
      if (source.GetCachedData() == nullptr) {
198
276
        options = ScriptCompiler::kNoCompileOptions;
199
      } else {
200
2
        options = ScriptCompiler::kConsumeCodeCache;
201
      }
202
556
      if (!ScriptCompiler::CompileModule(isolate, &source, options)
203
278
               .ToLocal(&module)) {
204

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

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

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

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

29379
  if (timed_out || received_signal) {
366

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

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

167
    if (len == 1 || specifier[1] == '/')
504
62
      return true;
505
105
    if (specifier[1] == '.') {
506

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

175
    if (!ToV8Value(context, pkg_src).ToLocal(&src) ||
639

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

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

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

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

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

82
    if (FileExists(guess)) {
808

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

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

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

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

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

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

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

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

3
          return resolved;
1078
        }
1079
6
      } else if (key_str == "default") {
1080
2
        conditionalTarget = target_obj->Get(context, key).ToLocalChecked();
1081
        {
1082
1
          TryCatchScope try_catch(env);
1083
          Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
1084
1
              conditionalTarget, subpath, pkg_subpath, base);
1085
1
          if (resolved.IsNothing()) {
1086
            CHECK(try_catch.HasCaught() && !try_catch.Exception().IsEmpty());
1087
            auto e = try_catch.Exception()->ToObject(context).ToLocalChecked();
1088
            auto code = e->Get(context, env->code_string()).ToLocalChecked();
1089
            Utf8Value code_utf8(env->isolate(),
1090
                                code->ToString(context).ToLocalChecked());
1091
            std::string code_str(*code_utf8, code_utf8.length());
1092
            if (code_str == "ERR_PACKAGE_PATH_NOT_EXPORTED") continue;
1093
            try_catch.ReThrow();
1094
            return Nothing<URL>();
1095
          }
1096
1
          CHECK(!try_catch.HasCaught());
1097
1
          ProcessEmitExperimentalWarning(env, "Conditional exports");
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
34
Maybe<bool> IsConditionalExportsMainSugar(Environment* env,
1110
                                          Local<Value> exports,
1111
                                          const URL& pjson_url,
1112
                                          const URL& base) {
1113

99
  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
19
Maybe<URL> PackageMainResolve(Environment* env,
1140
                              const URL& pjson_url,
1141
                              const PackageConfig& pcfg,
1142
                              const URL& base) {
1143
19
  if (pcfg.exists == Exists::Yes) {
1144
19
    Isolate* isolate = env->isolate();
1145
1146
38
    if (!pcfg.exports.IsEmpty()) {
1147
10
      Local<Value> exports = pcfg.exports.Get(isolate);
1148
      Maybe<bool> isConditionalExportsMainSugar =
1149
5
          IsConditionalExportsMainSugar(env, exports, pjson_url, base);
1150
5
      if (isConditionalExportsMainSugar.IsNothing())
1151
6
        return Nothing<URL>();
1152
4
      if (isConditionalExportsMainSugar.FromJust()) {
1153
4
        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
59
Maybe<URL> PackageResolve(Environment* env,
1259
                          const std::string& specifier,
1260
                          const URL& base) {
1261
59
  size_t sep_index = specifier.find('/');
1262
59
  bool valid_package_name = true;
1263
59
  bool scope = false;
1264
59
  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
57
  } else if (specifier[0] == '.') {
1272
    valid_package_name = false;
1273
  }
1274
  std::string pkg_name = specifier.substr(0,
1275
118
      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
741
  for (size_t i = 0; i < pkg_name.length(); i++) {
1279
685
    char c = pkg_name[i];
1280

685
    if (c == '%' || c == '\\') {
1281
3
      valid_package_name = false;
1282
3
      break;
1283
    }
1284
  }
1285
59
  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
110
  std::string pkg_subpath;
1292
55
  if (sep_index == std::string::npos) {
1293
23
    pkg_subpath = "";
1294
  } else {
1295
32
    pkg_subpath = "." + specifier.substr(sep_index);
1296
  }
1297
1298
  // ResolveSelf
1299
  const PackageConfig* pcfg;
1300

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

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

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