#include "module_wrap.h"

#include "env.h"
#include "memory_tracker-inl.h"
#include "node_contextify.h"
#include "node_errors.h"
#include "node_external_reference.h"
#include "node_internals.h"
#include "node_process-inl.h"
#include "node_url.h"
#include "node_watchdog.h"
#include "util-inl.h"

#include <sys/stat.h>  // S_IFDIR

#include <algorithm>

namespace node {
namespace loader {

using errors::TryCatchScope;

using node::contextify::ContextifyContext;
using v8::Array;
using v8::ArrayBufferView;
using v8::Boolean;
using v8::Context;
using v8::Data;
using v8::EscapableHandleScope;
using v8::Exception;
using v8::FixedArray;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Int32;
using v8::Integer;
using v8::Isolate;
using v8::Just;
using v8::JustVoid;
using v8::Local;
using v8::LocalVector;
using v8::Maybe;
using v8::MaybeLocal;
using v8::MemorySpan;
using v8::Message;
using v8::MicrotaskQueue;
using v8::Module;
using v8::ModuleImportPhase;
using v8::ModuleRequest;
using v8::Name;
using v8::Nothing;
using v8::Null;
using v8::Object;
using v8::ObjectTemplate;
using v8::PrimitiveArray;
using v8::Promise;
using v8::PromiseRejectEvent;
using v8::PropertyAttribute;
using v8::PropertyCallbackInfo;
using v8::ScriptCompiler;
using v8::ScriptOrigin;
using v8::String;
using v8::Symbol;
using v8::UnboundModuleScript;
using v8::Undefined;
using v8::Value;

inline bool DataIsString(Local<Data> data) {
  return data->IsValue() && data.As<Value>()->IsString();
}

void ModuleCacheKey::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackField("specifier", specifier);
  tracker->TrackField("import_attributes", import_attributes);
}

std::string ModuleCacheKey::ToString() const {
  std::string result = "ModuleCacheKey(\"" + specifier + "\"";
  if (!import_attributes.empty()) {
    result += ", {";
    bool first = true;
    for (const auto& attr : import_attributes) {
      if (first) {
        first = false;
      } else {
        result += ", ";
      }
      result += attr.first + ": " + attr.second;
    }
    result += "}";
  }
  result += ")";
  return result;
}

template <int elements_per_attribute>
ModuleCacheKey ModuleCacheKey::From(Local<Context> context,
                                    Local<String> specifier,
                                    Local<FixedArray> import_attributes) {
  CHECK_EQ(import_attributes->Length() % elements_per_attribute, 0);
  Isolate* isolate = Isolate::GetCurrent();
  std::size_t h1 = specifier->GetIdentityHash();
  size_t num_attributes = import_attributes->Length() / elements_per_attribute;
  ImportAttributeVector attributes;
  attributes.reserve(num_attributes);

  std::size_t h2 = 0;

  for (int i = 0; i < import_attributes->Length();
       i += elements_per_attribute) {
    DCHECK(DataIsString(import_attributes->Get(context, i)));
    DCHECK(DataIsString(import_attributes->Get(context, i + 1)));

    Local<String> v8_key = import_attributes->Get(i).As<String>();
    Local<String> v8_value = import_attributes->Get(i + 1).As<String>();
    Utf8Value key_utf8(isolate, v8_key);
    Utf8Value value_utf8(isolate, v8_value);

    attributes.emplace_back(key_utf8.ToString(), value_utf8.ToString());
    h2 ^= v8_key->GetIdentityHash();
    h2 ^= v8_value->GetIdentityHash();
  }

  // Combine the hashes using a simple XOR and bit shift to reduce
  // collisions. Note that the hash does not guarantee uniqueness.
  std::size_t hash = h1 ^ (h2 << 1);

  Utf8Value utf8_specifier(isolate, specifier);
  return ModuleCacheKey{utf8_specifier.ToString(), attributes, hash};
}

ModuleCacheKey ModuleCacheKey::From(Local<Context> context,
                                    Local<ModuleRequest> v8_request) {
  return From(
      context, v8_request->GetSpecifier(), v8_request->GetImportAttributes());
}

ModuleWrap::ModuleWrap(Realm* realm,
                       Local<Object> object,
                       Local<Module> module,
                       Local<String> url,
                       Local<Object> context_object,
                       Local<Value> synthetic_evaluation_step)
    : BaseObject(realm, object),
      url_(Utf8Value(realm->isolate(), url).ToString()),
      module_(realm->isolate(), module),
      module_hash_(module->GetIdentityHash()) {
  realm->env()->hash_to_module_map.emplace(module_hash_, this);

  object->SetInternalField(kModuleSlot, module);
  object->SetInternalField(kModuleSourceObjectSlot,
                           v8::Undefined(realm->isolate()));
  object->SetInternalField(kSyntheticEvaluationStepsSlot,
                           synthetic_evaluation_step);
  object->SetInternalField(kContextObjectSlot, context_object);
  object->SetInternalField(kLinkedRequestsSlot,
                           v8::Undefined(realm->isolate()));

  if (!synthetic_evaluation_step->IsUndefined()) {
    synthetic_ = true;
    // Synthetic modules have no dependencies.
    linked_ = true;
  }
  MakeWeak();
  module_.SetWeak();
}

ModuleWrap::~ModuleWrap() {
  auto range = env()->hash_to_module_map.equal_range(module_hash_);
  for (auto it = range.first; it != range.second; ++it) {
    if (it->second == this) {
      env()->hash_to_module_map.erase(it);
      break;
    }
  }
}

Local<Context> ModuleWrap::context() const {
  Local<Value> obj = object()->GetInternalField(kContextObjectSlot).As<Value>();
  // If this fails, there is likely a bug e.g. ModuleWrap::context() is accessed
  // before the ModuleWrap constructor completes.
  CHECK(obj->IsObject());
  return obj.As<Object>()->GetCreationContextChecked();
}

ModuleWrap* ModuleWrap::GetFromModule(Environment* env,
                                      Local<Module> module) {
  auto range = env->hash_to_module_map.equal_range(module->GetIdentityHash());
  for (auto it = range.first; it != range.second; ++it) {
    if (it->second->module_ == module) {
      return it->second;
    }
  }
  return nullptr;
}

Maybe<bool> ModuleWrap::CheckUnsettledTopLevelAwait() {
  Isolate* isolate = env()->isolate();
  Local<Context> context = env()->context();

  // This must be invoked when the environment is shutting down, and the module
  // is kept alive by the module wrap via an internal field.
  CHECK(env()->exiting());
  CHECK(!module_.IsEmpty());

  Local<Module> module = module_.Get(isolate);
  // It's a synthetic module, likely a facade wrapping CJS.
  if (!module->IsSourceTextModule()) {
    return Just(true);
  }

  if (!HasAsyncGraph()) {  // There is no TLA, no need to check.
    return Just(true);
  }

  auto stalled_messages =
      std::get<1>(module->GetStalledTopLevelAwaitMessages(isolate));
  if (stalled_messages.empty()) {
    return Just(true);
  }

  if (env()->options()->warnings) {
    for (auto& message : stalled_messages) {
      std::string reason = "Warning: Detected unsettled top-level await at ";
      std::string info =
          FormatErrorMessage(isolate, context, "", message, true);
      reason += info;
      FPrintF(stderr, "%s\n", reason);
    }
  }

  return Just(false);
}

bool ModuleWrap::HasAsyncGraph() {
  if (!has_async_graph_.has_value()) {
    Isolate* isolate = env()->isolate();
    HandleScope scope(isolate);

    has_async_graph_ = module_.Get(isolate)->IsGraphAsync();
  }
  return has_async_graph_.value();
}

Local<PrimitiveArray> ModuleWrap::GetHostDefinedOptions(
    Isolate* isolate, Local<Symbol> id_symbol) {
  Local<PrimitiveArray> host_defined_options =
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
  host_defined_options->Set(isolate, HostDefinedOptions::kID, id_symbol);
  return host_defined_options;
}

// new ModuleWrap(url, context, source, lineOffset, columnOffset[, cachedData]);
// new ModuleWrap(url, context, source, lineOffset, columnOffset,
//                idSymbol);
// new ModuleWrap(url, context, exportNames, evaluationCallback[, cjsModule])
void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) {
  CHECK(args.IsConstructCall());
  CHECK_GE(args.Length(), 3);

  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = realm->isolate();

  Local<Object> that = args.This();

  CHECK(args[0]->IsString());
  Local<String> url = args[0].As<String>();

  Local<Context> context;
  ContextifyContext* contextify_context = nullptr;
  if (args[1]->IsUndefined()) {
    context = that->GetCreationContextChecked();
  } else {
    CHECK(args[1]->IsObject());
    contextify_context = ContextifyContext::ContextFromContextifiedSandbox(
        realm->env(), args[1].As<Object>());
    CHECK_NOT_NULL(contextify_context);
    context = contextify_context->context();
  }

  int line_offset = 0;
  int column_offset = 0;

  bool synthetic = args[2]->IsArray();
  bool can_use_builtin_cache = false;
  Local<PrimitiveArray> host_defined_options =
      PrimitiveArray::New(isolate, HostDefinedOptions::kLength);
  Local<Symbol> id_symbol;
  if (synthetic) {
    // new ModuleWrap(url, context, exportNames, evaluationCallback[,
    // cjsModule])
    CHECK(args[3]->IsFunction());
  } else {
    // new ModuleWrap(url, context, source, lineOffset, columnOffset[,
    //                cachedData]);
    // new ModuleWrap(url, context, source, lineOffset, columnOffset,
    //                idSymbol);
    CHECK(args[2]->IsString());
    CHECK(args[3]->IsNumber());
    line_offset = args[3].As<Int32>()->Value();
    CHECK(args[4]->IsNumber());
    column_offset = args[4].As<Int32>()->Value();
    if (args[5]->IsSymbol()) {
      id_symbol = args[5].As<Symbol>();
      can_use_builtin_cache =
          (id_symbol ==
           realm->isolate_data()->source_text_module_default_hdo());
    } else {
      id_symbol = Symbol::New(isolate, url);
    }
    host_defined_options = GetHostDefinedOptions(isolate, id_symbol);

    if (that->SetPrivate(context,
                         realm->isolate_data()->host_defined_option_symbol(),
                         id_symbol)
            .IsNothing()) {
      return;
    }
  }

  ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
  TryCatchScope try_catch(realm->env());

  Local<Module> module;

  {
    Context::Scope context_scope(context);
    if (synthetic) {
      CHECK(args[2]->IsArray());
      Local<Array> export_names_arr = args[2].As<Array>();

      uint32_t len = export_names_arr->Length();
      LocalVector<String> export_names(realm->isolate(), len);
      for (uint32_t i = 0; i < len; i++) {
        Local<Value> export_name_val;
        if (!export_names_arr->Get(context, i).ToLocal(&export_name_val)) {
          return;
        }
        CHECK(export_name_val->IsString());
        export_names[i] = export_name_val.As<String>();
      }

      const MemorySpan<const Local<String>> span(export_names.begin(),
                                                 export_names.size());
      module = Module::CreateSyntheticModule(
          isolate, url, span, SyntheticModuleEvaluationStepsCallback);
    } else {
      // When we are compiling for the default loader, this will be
      // std::nullopt, and CompileSourceTextModule() should use
      // on-disk cache.
      std::optional<ScriptCompiler::CachedData*> user_cached_data;
      if (id_symbol !=
          realm->isolate_data()->source_text_module_default_hdo()) {
        user_cached_data = nullptr;
      }
      if (args[5]->IsArrayBufferView()) {
        CHECK(!can_use_builtin_cache);  // We don't use this option internally.
        Local<ArrayBufferView> cached_data_buf = args[5].As<ArrayBufferView>();
        uint8_t* data =
            static_cast<uint8_t*>(cached_data_buf->Buffer()->Data());
        user_cached_data =
            new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(),
                                           cached_data_buf->ByteLength());
      }
      Local<String> source_text = args[2].As<String>();

      bool cache_rejected = false;
      if (!CompileSourceTextModule(realm,
                                   source_text,
                                   url,
                                   line_offset,
                                   column_offset,
                                   host_defined_options,
                                   user_cached_data,
                                   &cache_rejected)
               .ToLocal(&module)) {
        if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
          CHECK(!try_catch.Message().IsEmpty());
          CHECK(!try_catch.Exception().IsEmpty());
          AppendExceptionLine(realm->env(),
                              try_catch.Exception(),
                              try_catch.Message(),
                              ErrorHandlingMode::MODULE_ERROR);
          try_catch.ReThrow();
        }
        return;
      }

      if (user_cached_data.has_value() && user_cached_data.value() != nullptr &&
          cache_rejected) {
        THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED(
            realm, "cachedData buffer was rejected");
        try_catch.ReThrow();
        return;
      }

      if (that->Set(context,
                    realm->env()->has_top_level_await_string(),
                    Boolean::New(isolate, module->HasTopLevelAwait()))
              .IsNothing()) {
        return;
      }

      if (that->Set(context,
                    realm->env()->source_url_string(),
                    module->GetUnboundModuleScript()->GetSourceURL())
              .IsNothing()) {
        return;
      }

      if (that->Set(context,
                    realm->env()->source_map_url_string(),
                    module->GetUnboundModuleScript()->GetSourceMappingURL())
              .IsNothing()) {
        return;
      }
    }
  }

  if (that->Set(context,
                realm->isolate_data()->synthetic_string(),
                Boolean::New(isolate, synthetic))
          .IsNothing()) {
    return;
  }

  if (!that->Set(context, realm->isolate_data()->url_string(), url)
           .FromMaybe(false)) {
    return;
  }

  if (synthetic && args[4]->IsObject() &&
      that->Set(context, realm->isolate_data()->imported_cjs_symbol(), args[4])
          .IsNothing()) {
    return;
  }

  // Initialize an empty slot for source map cache before the object is frozen.
  if (that->SetPrivate(context,
                       realm->isolate_data()->source_map_data_private_symbol(),
                       Undefined(isolate))
          .IsNothing()) {
    return;
  }

  // Use the extras object as an object whose GetCreationContext() will be the
  // original `context`, since the `Context` itself strictly speaking cannot
  // be stored in an internal field.
  Local<Object> context_object = context->GetExtrasBindingObject();
  Local<Value> synthetic_evaluation_step =
      synthetic ? args[3] : Undefined(realm->isolate()).As<Value>();

  ModuleWrap* obj = new ModuleWrap(
      realm, that, module, url, context_object, synthetic_evaluation_step);

  obj->contextify_context_ = contextify_context;

  args.GetReturnValue().Set(that);
}

MaybeLocal<Module> ModuleWrap::CompileSourceTextModule(
    Realm* realm,
    Local<String> source_text,
    Local<String> url,
    int line_offset,
    int column_offset,
    Local<PrimitiveArray> host_defined_options,
    std::optional<ScriptCompiler::CachedData*> user_cached_data,
    bool* cache_rejected) {
  Isolate* isolate = realm->isolate();
  EscapableHandleScope scope(isolate);
  ScriptOrigin origin(url,
                      line_offset,
                      column_offset,
                      true,            // is cross origin
                      -1,              // script id
                      Local<Value>(),  // source map URL
                      false,           // is opaque (?)
                      false,           // is WASM
                      true,            // is ES Module
                      host_defined_options);
  ScriptCompiler::CachedData* cached_data = nullptr;
  CompileCacheEntry* cache_entry = nullptr;
  // When compiling for the default loader, user_cached_data is std::nullptr.
  // When compiling for vm.Module, it's either nullptr or a pointer to the
  // cached data.
  if (user_cached_data.has_value()) {
    cached_data = user_cached_data.value();
  } else if (realm->env()->use_compile_cache()) {
    cache_entry = realm->env()->compile_cache_handler()->GetOrInsert(
        source_text, url, CachedCodeType::kESM);
  }

  if (cache_entry != nullptr && cache_entry->cache != nullptr) {
    // source will take ownership of cached_data.
    cached_data = cache_entry->CopyCache();
  }

  ScriptCompiler::Source source(source_text, origin, cached_data);
  ScriptCompiler::CompileOptions options;
  if (cached_data == nullptr) {
    options = ScriptCompiler::kNoCompileOptions;
  } else {
    options = ScriptCompiler::kConsumeCodeCache;
  }

  Local<Module> module;
  if (!ScriptCompiler::CompileModule(isolate, &source, options)
           .ToLocal(&module)) {
    return scope.EscapeMaybe(MaybeLocal<Module>());
  }

  if (options == ScriptCompiler::kConsumeCodeCache) {
    *cache_rejected = source.GetCachedData()->rejected;
  }

  if (cache_entry != nullptr) {
    realm->env()->compile_cache_handler()->MaybeSave(
        cache_entry, module, *cache_rejected);
  }

  return scope.Escape(module);
}

ModulePhase to_phase_constant(ModuleImportPhase phase) {
  switch (phase) {
    case ModuleImportPhase::kEvaluation:
      return kEvaluationPhase;
    case ModuleImportPhase::kSource:
      return kSourcePhase;
    default:
      UNREACHABLE();
  }
}

static Local<Object> createImportAttributesContainer(
    Realm* realm,
    Isolate* isolate,
    Local<FixedArray> raw_attributes,
    const int elements_per_attribute) {
  CHECK_EQ(raw_attributes->Length() % elements_per_attribute, 0);
  size_t num_attributes = raw_attributes->Length() / elements_per_attribute;
  LocalVector<Name> names(isolate, num_attributes);
  LocalVector<Value> values(isolate, num_attributes);

  for (int i = 0; i < raw_attributes->Length(); i += elements_per_attribute) {
    Local<Data> key = raw_attributes->Get(i);
    Local<Data> value = raw_attributes->Get(i + 1);
    DCHECK(DataIsString(key));
    DCHECK(DataIsString(value));

    int idx = i / elements_per_attribute;
    names[idx] = key.As<String>();
    values[idx] = value.As<String>();
  }

  Local<Object> attributes = Object::New(
      isolate, Null(isolate), names.data(), values.data(), num_attributes);
  attributes->SetIntegrityLevel(realm->context(), v8::IntegrityLevel::kFrozen)
      .Check();
  return attributes;
}

static Local<Array> createModuleRequestsContainer(
    Realm* realm, Isolate* isolate, Local<FixedArray> raw_requests) {
  EscapableHandleScope scope(isolate);
  Local<Context> context = realm->context();
  LocalVector<Value> requests(isolate, raw_requests->Length());

  for (int i = 0; i < raw_requests->Length(); i++) {
    DCHECK(raw_requests->Get(context, i)->IsModuleRequest());
    Local<ModuleRequest> module_request =
        raw_requests->Get(i).As<ModuleRequest>();

    Local<String> specifier = module_request->GetSpecifier();

    // Contains the import attributes for this request in the form:
    // [key1, value1, source_offset1, key2, value2, source_offset2, ...].
    Local<FixedArray> raw_attributes = module_request->GetImportAttributes();
    Local<Object> attributes =
        createImportAttributesContainer(realm, isolate, raw_attributes, 3);
    ModuleImportPhase phase = module_request->GetPhase();

    Local<Name> names[] = {
        realm->isolate_data()->specifier_string(),
        realm->isolate_data()->attributes_string(),
        realm->isolate_data()->phase_string(),
    };
    Local<Value> values[] = {
        specifier,
        attributes,
        Integer::New(isolate, to_phase_constant(phase)),
    };
    DCHECK_EQ(arraysize(names), arraysize(values));

    Local<Object> request =
        Object::New(isolate, Null(isolate), names, values, arraysize(names));
    request->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen).Check();

    requests[i] = request;
  }

  return scope.Escape(Array::New(isolate, requests.data(), requests.size()));
}

void ModuleWrap::GetModuleRequests(const FunctionCallbackInfo<Value>& args) {
  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = args.GetIsolate();
  Local<Object> that = args.This();

  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);

  Local<Module> module = obj->module_.Get(isolate);
  args.GetReturnValue().Set(createModuleRequestsContainer(
      realm, isolate, module->GetModuleRequests()));
}

// moduleWrap.link(moduleWraps)
void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  HandleScope handle_scope(isolate);
  Realm* realm = Realm::GetCurrent(args);
  Local<Context> context = realm->context();

  ModuleWrap* dependent;
  ASSIGN_OR_RETURN_UNWRAP(&dependent, args.This());

  CHECK_EQ(args.Length(), 1);

  Local<FixedArray> requests =
      dependent->module_.Get(isolate)->GetModuleRequests();
  Local<Array> modules = args[0].As<Array>();
  std::vector<Global<Value>> modules_vector;
  if (FromV8Array(context, modules, &modules_vector).IsEmpty()) {
    return;
  }
  size_t request_count = static_cast<size_t>(requests->Length());
  CHECK_EQ(modules_vector.size(), request_count);
  std::vector<ModuleWrap*> linked_module_wraps(request_count);

  // Track the duplicated module requests. For example if a modulelooks like
  // this:
  //
  // import { foo } from 'mod' with { type: 'json' };
  // import source ModSource from 'mod' with { type: 'json' };
  // import { baz } from 'mod2';
  //
  // The first two module requests are identical. The map would look like
  // { mod_key: 0, mod2_key: 2 } in this case, so that module request 0 and
  // module request 1 would be mapped to mod_key and both should resolve to the
  // module identified by module request 0 (the first one with this identity),
  // and module request 2 should resolve the module identified by index 2.
  std::unordered_map<ModuleCacheKey, size_t, ModuleCacheKey::Hash>
      module_request_map;

  for (size_t i = 0; i < request_count; i++) {
    // TODO(joyeecheung): merge this with the serializeKey() in module_map.js.
    // This currently doesn't sort the import attributes.
    Local<Value> module_value = modules_vector[i].Get(isolate);
    ModuleCacheKey module_cache_key =
        ModuleCacheKey::From(context, requests->Get(i).As<ModuleRequest>());
    auto it = module_request_map.find(module_cache_key);
    if (it == module_request_map.end()) {
      // This is the first request with this identity, record it - any mismatch
      // for this would only be found in subsequent requests, so no need to
      // check here.
      module_request_map[module_cache_key] = i;
    } else {  // This identity has been seen before, check for mismatch.
      size_t first_seen_index = it->second;
      // Check that the module is the same as the one resolved by the first
      // request with this identity.
      Local<Value> first_seen_value =
          modules_vector[first_seen_index].Get(isolate);
      if (!module_value->StrictEquals(first_seen_value)) {
        // If the module is different from the one of the same request, throw an
        // error.
        THROW_ERR_MODULE_LINK_MISMATCH(
            realm->env(),
            "Module request '%s' at index %d must be linked "
            "to the same module requested at index %d",
            module_cache_key.ToString(),
            i,
            first_seen_index);
        return;
      }
    }

    CHECK(module_value->IsObject());  // Guaranteed by link methods in JS land.
    ModuleWrap* resolved =
        BaseObject::Unwrap<ModuleWrap>(module_value.As<Object>());
    CHECK_NOT_NULL(resolved);  // Guaranteed by link methods in JS land.
    linked_module_wraps[i] = resolved;
  }

  args.This()->SetInternalField(kLinkedRequestsSlot, modules);
  std::swap(dependent->linked_module_wraps_, linked_module_wraps);
  dependent->linked_ = true;
}

void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) {
  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = args.GetIsolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
  Local<Context> context = obj->context();
  Local<Module> module = obj->module_.Get(isolate);
  Environment* env = realm->env();

  if (!obj->IsLinked()) {
    THROW_ERR_VM_MODULE_LINK_FAILURE(env, "module is not linked");
    return;
  }

  {
    TryCatchScope try_catch(env);
    USE(module->InstantiateModule(
        context, ResolveModuleCallback, ResolveSourceCallback));

    if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
      CHECK(!try_catch.Message().IsEmpty());
      CHECK(!try_catch.Exception().IsEmpty());
      AppendExceptionLine(env,
                          try_catch.Exception(),
                          try_catch.Message(),
                          ErrorHandlingMode::MODULE_ERROR);
      try_catch.ReThrow();
      return;
    }
  }
}

void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) {
  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = realm->isolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
  Local<Context> context = obj->context();
  Local<Module> module = obj->module_.Get(isolate);

  ContextifyContext* contextify_context = obj->contextify_context_;
  MicrotaskQueue* microtask_queue = nullptr;
  if (contextify_context != nullptr)
      microtask_queue = contextify_context->microtask_queue();

  // module.evaluate(timeout, breakOnSigint)
  CHECK_EQ(args.Length(), 2);

  CHECK(args[0]->IsNumber());
  int64_t timeout;
  if (!args[0]->IntegerValue(realm->context()).To(&timeout)) {
    return;
  }

  CHECK(args[1]->IsBoolean());
  bool break_on_sigint = args[1]->IsTrue();

  ShouldNotAbortOnUncaughtScope no_abort_scope(realm->env());
  TryCatchScope try_catch(realm->env());

  bool timed_out = false;
  bool received_signal = false;
  MaybeLocal<Value> result;
  {
    auto wd = timeout != -1
                  ? std::make_optional<Watchdog>(isolate, timeout, &timed_out)
                  : std::nullopt;
    auto swd = break_on_sigint ? std::make_optional<SigintWatchdog>(
                                     isolate, &received_signal)
                               : std::nullopt;

    result = module->Evaluate(context);

    Local<Value> res;
    if (result.ToLocal(&res) && microtask_queue) {
      DCHECK(res->IsPromise());

      // To address https://github.com/nodejs/node/issues/59541 when the
      // module has its own separate microtask queue in microtaskMode
      // "afterEvaluate", we avoid returning a promise built inside the
      // module's own context.
      //
      // Instead, we build a promise in the outer context, which we resolve
      // with {result}, then we checkpoint the module's own queue, and finally
      // we return the outer-context promise.
      //
      // If we simply returned the inner promise {result} directly, per
      // https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob, the outer
      // context, when resolving a promise coming from a different context,
      // would need to enqueue a task (known as a thenable job task) onto the
      // queue of that different context (the module's context). But this queue
      // will normally not be checkpointed after evaluate() returns.
      //
      // This means that the execution flow in the outer context would
      // silently fall through at the statement (in lib/internal/vm/module.js):
      //   await this[kWrap].evaluate(timeout, breakOnSigint)
      //
      // This is true for any promises created inside the module's context
      // and made available to the outer context, as the node:vm doc explains.
      //
      // We must handle this particular return value differently to make it
      // possible to await on the result of evaluate().
      Local<Context> outer_context = isolate->GetCurrentContext();
      Local<Promise::Resolver> resolver;
      if (!Promise::Resolver::New(outer_context).ToLocal(&resolver)) {
        result = {};
      }
      if (resolver->Resolve(outer_context, res).IsNothing()) {
        result = {};
      }
      result = resolver->GetPromise();

      microtask_queue->PerformCheckpoint(isolate);
    }
  }

  if (result.IsEmpty()) {
    CHECK(try_catch.HasCaught());
  }

  // Convert the termination exception into a regular exception.
  if (timed_out || received_signal) {
    if (!realm->env()->is_main_thread() && realm->env()->is_stopping()) return;
    isolate->CancelTerminateExecution();
    // It is possible that execution was terminated by another timeout in
    // which this timeout is nested, so check whether one of the watchdogs
    // from this invocation is responsible for termination.
    if (timed_out) {
      THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(realm->env(), timeout);
    } else if (received_signal) {
      THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(realm->env());
    }
  }

  if (try_catch.HasCaught()) {
    if (!try_catch.HasTerminated())
      try_catch.ReThrow();
    return;
  }

  Local<Value> res;
  if (result.ToLocal(&res)) {
    args.GetReturnValue().Set(res);
  }
}

Maybe<void> ThrowIfPromiseRejected(Realm* realm, Local<Promise> promise) {
  Isolate* isolate = realm->isolate();
  Local<Context> context = realm->context();
  if (promise->State() != Promise::PromiseState::kRejected) {
    return JustVoid();
  }
  // The rejected promise is created by V8, so we don't get a chance to mark
  // it as resolved before the rejection happens from evaluation. But we can
  // tell the promise rejection callback to treat it as a promise rejected
  // before handler was added which would remove it from the unhandled
  // rejection handling, since we are converting it into an error and throw
  // from here directly.
  Local<Value> type =
      Integer::New(isolate,
                   static_cast<int32_t>(
                       PromiseRejectEvent::kPromiseHandlerAddedAfterReject));
  Local<Value> args[] = {type, promise, Undefined(isolate)};
  if (realm->promise_reject_callback()
          ->Call(context, Undefined(isolate), arraysize(args), args)
          .IsEmpty()) {
    return Nothing<void>();
  }
  Local<Value> exception = promise->Result();
  Local<Message> message = Exception::CreateMessage(isolate, exception);
  AppendExceptionLine(
      realm->env(), exception, message, ErrorHandlingMode::MODULE_ERROR);
  isolate->ThrowException(exception);
  return Nothing<void>();
}

void ThrowIfPromiseRejected(const FunctionCallbackInfo<Value>& args) {
  if (!args[0]->IsPromise()) {
    return;
  }
  ThrowIfPromiseRejected(Realm::GetCurrent(args), args[0].As<Promise>());
}

void ModuleWrap::EvaluateSync(const FunctionCallbackInfo<Value>& args) {
  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = args.GetIsolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());
  Local<Context> context = obj->context();
  Local<Module> module = obj->module_.Get(isolate);
  Environment* env = realm->env();

  Local<Value> result;
  {
    TryCatchScope try_catch(env);
    if (!module->Evaluate(context).ToLocal(&result)) {
      if (try_catch.HasCaught()) {
        if (!try_catch.HasTerminated()) {
          try_catch.ReThrow();
        }
        return;
      }
    }
  }

  CHECK(result->IsPromise());
  Local<Promise> promise = result.As<Promise>();
  if (ThrowIfPromiseRejected(realm, promise).IsNothing()) {
    return;
  }

  if (obj->HasAsyncGraph()) {
    CHECK(env->options()->print_required_tla);
    auto stalled_messages =
        std::get<1>(module->GetStalledTopLevelAwaitMessages(isolate));
    if (stalled_messages.size() != 0) {
      for (auto& message : stalled_messages) {
        std::string reason = "Error: unexpected top-level await at ";
        std::string info =
            FormatErrorMessage(isolate, context, "", message, true);
        reason += info;
        FPrintF(stderr, "%s\n", reason);
      }
    }
    THROW_ERR_REQUIRE_ASYNC_MODULE(env, args[0], args[1]);
    return;
  }

  CHECK_EQ(promise->State(), Promise::PromiseState::kFulfilled);

  args.GetReturnValue().Set(module->GetModuleNamespace());
}

void ModuleWrap::GetNamespace(const FunctionCallbackInfo<Value>& args) {
  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = args.GetIsolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());

  Local<Module> module = obj->module_.Get(isolate);
  if (module->GetStatus() < Module::kInstantiated) {
    return THROW_ERR_MODULE_NOT_INSTANTIATED(realm->env());
  }

  Local<Value> result = module->GetModuleNamespace();
  args.GetReturnValue().Set(result);
}

void ModuleWrap::SetModuleSourceObject(
    const FunctionCallbackInfo<Value>& args) {
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());

  CHECK_EQ(args.Length(), 1);
  CHECK(args[0]->IsObject());
  CHECK(obj->object()
            ->GetInternalField(kModuleSourceObjectSlot)
            .As<Value>()
            ->IsUndefined());

  obj->object()->SetInternalField(kModuleSourceObjectSlot, args[0]);
}

void ModuleWrap::GetModuleSourceObject(
    const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());

  CHECK_EQ(args.Length(), 0);
  Local<Value> module_source_object =
      obj->object()->GetInternalField(kModuleSourceObjectSlot).As<Value>();

  if (module_source_object->IsUndefined()) {
    THROW_ERR_SOURCE_PHASE_NOT_DEFINED(isolate, obj->url_);
    return;
  }

  args.GetReturnValue().Set(module_source_object);
}

void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());

  Local<Module> module = obj->module_.Get(isolate);

  args.GetReturnValue().Set(module->GetStatus());
}

void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.This());

  Local<Module> module = obj->module_.Get(isolate);
  args.GetReturnValue().Set(module->GetException());
}

void ModuleWrap::HasAsyncGraph(Local<Name> property,
                               const PropertyCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Environment* env = Environment::GetCurrent(isolate);
  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, args.HolderV2());

  Local<Module> module = obj->module_.Get(isolate);
  if (module->GetStatus() < Module::kInstantiated) {
    return THROW_ERR_MODULE_NOT_INSTANTIATED(env);
  }

  args.GetReturnValue().Set(obj->HasAsyncGraph());
}

// static
MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
    Local<Context> context,
    size_t module_request_index,
    Local<Module> referrer) {
  ModuleWrap* resolved_module;
  if (!ResolveModule(context, module_request_index, referrer)
           .To(&resolved_module)) {
    return {};
  }
  DCHECK_NOT_NULL(resolved_module);
  return resolved_module->module_.Get(Isolate::GetCurrent());
}

// static
MaybeLocal<Object> ModuleWrap::ResolveSourceCallback(
    Local<Context> context,
    size_t module_request_index,
    Local<Module> referrer) {
  ModuleWrap* resolved_module;
  if (!ResolveModule(context, module_request_index, referrer)
           .To(&resolved_module)) {
    return {};
  }
  DCHECK_NOT_NULL(resolved_module);

  Local<Value> module_source_object =
      resolved_module->object()
          ->GetInternalField(ModuleWrap::kModuleSourceObjectSlot)
          .As<Value>();
  if (module_source_object->IsUndefined()) {
    THROW_ERR_SOURCE_PHASE_NOT_DEFINED(Isolate::GetCurrent(),
                                       resolved_module->url_);
    return {};
  }
  CHECK(module_source_object->IsObject());
  return module_source_object.As<Object>();
}

static std::string GetSpecifierFromModuleRequest(Local<Module> referrer,
                                                 size_t module_request_index) {
  Local<ModuleRequest> raw_request =
      referrer->GetModuleRequests()
          ->Get(static_cast<int>(module_request_index))
          .As<ModuleRequest>();
  Local<String> specifier = raw_request->GetSpecifier();
  Utf8Value specifier_utf8(Isolate::GetCurrent(), specifier);
  return specifier_utf8.ToString();
}

// static
Maybe<ModuleWrap*> ModuleWrap::ResolveModule(Local<Context> context,
                                             size_t module_request_index,
                                             Local<Module> referrer) {
  Isolate* isolate = Isolate::GetCurrent();
  Environment* env = Environment::GetCurrent(context);
  if (env == nullptr) {
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
    return Nothing<ModuleWrap*>();
  }
  // Check that the referrer is not yet been instantiated.
  DCHECK(referrer->GetStatus() <= Module::kInstantiated);

  ModuleWrap* dependent = ModuleWrap::GetFromModule(env, referrer);
  if (dependent == nullptr) {
    std::string specifier =
        GetSpecifierFromModuleRequest(referrer, module_request_index);
    THROW_ERR_VM_MODULE_LINK_FAILURE(
        env, "request for '%s' is from invalid module", specifier);
    return Nothing<ModuleWrap*>();
  }
  if (!dependent->IsLinked()) {
    std::string specifier =
        GetSpecifierFromModuleRequest(referrer, module_request_index);
    THROW_ERR_VM_MODULE_LINK_FAILURE(env,
                                     "request for '%s' can not be resolved on "
                                     "module '%s' that is not linked",
                                     specifier,
                                     dependent->url_);
    return Nothing<ModuleWrap*>();
  }

  size_t linked_module_count = dependent->linked_module_wraps_.size();
  if (linked_module_count > 0) {
    CHECK_LT(module_request_index, linked_module_count);
  } else {
    UNREACHABLE("Module resolution callback invoked for a module"
                " without linked requests");
  }

  return Just(dependent->linked_module_wraps_[module_request_index]);
}

static MaybeLocal<Promise> ImportModuleDynamicallyWithPhase(
    Local<Context> context,
    Local<Data> host_defined_options,
    Local<Value> resource_name,
    Local<String> specifier,
    ModuleImportPhase phase,
    Local<FixedArray> import_attributes) {
  Isolate* isolate = Isolate::GetCurrent();
  Environment* env = Environment::GetCurrent(context);
  if (env == nullptr) {
    THROW_ERR_EXECUTION_ENVIRONMENT_NOT_AVAILABLE(isolate);
    return MaybeLocal<Promise>();
  }
  Realm* realm = Realm::GetCurrent(context);
  if (realm == nullptr) {
    // Fallback to the principal realm if it's in a vm context.
    realm = env->principal_realm();
  }

  EscapableHandleScope handle_scope(isolate);

  Local<Function> import_callback =
      realm->host_import_module_dynamically_callback();
  Local<Value> id;

  Local<FixedArray> options = host_defined_options.As<FixedArray>();
  // Get referrer id symbol from the host-defined options.
  // If the host-defined options are empty, get the referrer id symbol
  // from the realm global object.
  if (options->Length() == HostDefinedOptions::kLength) {
    id = options->Get(HostDefinedOptions::kID).As<Symbol>();
  } else if (!context->Global()
                  ->GetPrivate(context, env->host_defined_option_symbol())
                  .ToLocal(&id)) {
    return MaybeLocal<Promise>();
  }

  Local<Object> attributes =
      createImportAttributesContainer(realm, isolate, import_attributes, 2);

  Local<Value> import_args[] = {
      id,
      Local<Value>(specifier),
      Integer::New(isolate, to_phase_constant(phase)),
      attributes,
      resource_name,
  };

  Local<Value> result;
  if (!import_callback
           ->Call(
               context, Undefined(isolate), arraysize(import_args), import_args)
           .ToLocal(&result)) {
    return {};
  }

  // Wrap the returned value in a promise created in the referrer context to
  // avoid dynamic scopes.
  Local<Promise::Resolver> resolver;
  if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
    return {};
  }
  if (resolver->Resolve(context, result).IsNothing()) {
    return {};
  }
  return handle_scope.Escape(resolver->GetPromise());
}

static MaybeLocal<Promise> ImportModuleDynamically(
    Local<Context> context,
    Local<Data> host_defined_options,
    Local<Value> resource_name,
    Local<String> specifier,
    Local<FixedArray> import_attributes) {
  return ImportModuleDynamicallyWithPhase(context,
                                          host_defined_options,
                                          resource_name,
                                          specifier,
                                          ModuleImportPhase::kEvaluation,
                                          import_attributes);
}

void ModuleWrap::SetImportModuleDynamicallyCallback(
    const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Realm* realm = Realm::GetCurrent(args);
  HandleScope handle_scope(isolate);

  CHECK_EQ(args.Length(), 1);
  CHECK(args[0]->IsFunction());
  Local<Function> import_callback = args[0].As<Function>();
  realm->set_host_import_module_dynamically_callback(import_callback);

  isolate->SetHostImportModuleDynamicallyCallback(ImportModuleDynamically);
  isolate->SetHostImportModuleWithPhaseDynamicallyCallback(
      ImportModuleDynamicallyWithPhase);
}

void ModuleWrap::SetImportMetaResolveInitializer(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Realm* realm = Realm::GetCurrent(args);
  HandleScope handle_scope(isolate);

  CHECK_EQ(args.Length(), 1);
  CHECK(args[0]->IsFunction());
  Local<Function> initializer = args[0].As<Function>();
  realm->set_host_import_meta_resolve_initializer(initializer);
}

static void ImportMetaResolveLazyGetter(
    Local<v8::Name> name, const PropertyCallbackInfo<Value>& info) {
  Isolate* isolate = info.GetIsolate();
  Local<Value> receiver_val = info.HolderV2();
  if (!receiver_val->IsObject()) {
    THROW_ERR_INVALID_INVOCATION(isolate);
    return;
  }
  Local<Object> receiver = receiver_val.As<Object>();
  Local<Context> context;
  if (!receiver->GetCreationContext().ToLocal(&context)) {
    THROW_ERR_INVALID_INVOCATION(isolate);
    return;
  }
  Realm* realm = Realm::GetCurrent(context);
  if (realm == nullptr) {
    THROW_ERR_INVALID_INVOCATION(isolate);
  }
  Local<Function> initializer = realm->host_import_meta_resolve_initializer();
  if (initializer.IsEmpty()) {
    THROW_ERR_INVALID_INVOCATION(isolate);
    return;
  }

  // This should be createImportMetaResolve(). The loader argument is already
  // bound at initialization time.
  Local<Value> args[] = {info.Data()};
  Local<Value> ret;
  if (!initializer
           ->Call(context, Undefined(realm->isolate()), arraysize(args), args)
           .ToLocal(&ret)) {
    return;
  }
  info.GetReturnValue().Set(ret);
}

static void PathHelpersLazyGetter(Local<v8::Name> name,
                                  const PropertyCallbackInfo<Value>& info) {
  Isolate* isolate = info.GetIsolate();
  // This getter has no JavaScript function representation and is not
  // invoked in the creation context.
  // When this getter is invoked in a vm context, the `Realm::GetCurrent(info)`
  // returns a nullptr and retrieve the creation context via `this` object and
  // get the creation Realm.
  Local<Value> receiver_val = info.HolderV2();
  if (!receiver_val->IsObject()) {
    THROW_ERR_INVALID_INVOCATION(isolate);
    return;
  }
  Local<Object> receiver = receiver_val.As<Object>();
  Local<Context> context;
  if (!receiver->GetCreationContext().ToLocal(&context)) {
    THROW_ERR_INVALID_INVOCATION(isolate);
    return;
  }
  Environment* env = Environment::GetCurrent(context);

  node::Utf8Value url(isolate, info.Data());
  auto file_url = ada::parse(url.ToStringView());
  CHECK(file_url);
  auto file_path = url::FileURLToPath(env, *file_url);
  CHECK(file_path.has_value());
  std::string_view ret_view = file_path.value();

  node::Utf8Value utf8name(isolate, name);
  auto plain_name = utf8name.ToStringView();
  if (plain_name == "dirname") {
#ifdef _WIN32
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
    auto index = ret_view.rfind(PATH_SEPARATOR);
    CHECK(index != std::string_view::npos);
    ret_view.remove_suffix(ret_view.size() - index);
#undef PATH_SEPARATOR
  }
  Local<Value> ret;
  if (!ToV8Value(context, ret_view, isolate).ToLocal(&ret)) {
    return;
  }
  info.GetReturnValue().Set(ret);
}

static Maybe<void> DefaultImportMetaObjectInitializer(Realm* realm,
                                                      Local<Object> wrap,
                                                      Local<Object> meta) {
  Local<Context> context = realm->context();
  Isolate* isolate = realm->isolate();
  Environment* env = realm->env();

  Local<Value> url;
  if (!wrap->Get(context, env->url_string()).ToLocal(&url)) {
    return Nothing<void>();
  }

  // N.B.: Order is important to keep keys in alphabetical order.

  Utf8Value url_utf8(isolate, url);
  if (url_utf8.ToStringView().starts_with("file:")) {
    // Set a lazy getter of import.meta.dirname
    if (meta->SetLazyDataProperty(
                context, env->dirname_string(), PathHelpersLazyGetter, url)
            .IsNothing()) {
      return Nothing<void>();
    }

    // Set a lazy getter of import.meta.filename
    if (meta->SetLazyDataProperty(
                context, env->filename_string(), PathHelpersLazyGetter, url)
            .IsNothing()) {
      return Nothing<void>();
    }
  }

  // Set import.meta.main = moduleWrap.isMain
  Local<Value> is_main;
  if (!wrap->Get(context, FIXED_ONE_BYTE_STRING(isolate, "isMain"))
           .ToLocal(&is_main)) {
    return Nothing<void>();
  }
  if (meta->Set(context,
                FIXED_ONE_BYTE_STRING(isolate, "main"),
                Boolean::New(isolate, is_main->IsTrue()))
          .IsEmpty()) {
    return Nothing<void>();
  }

  // Set a lazy getter of import.meta.resolve - only if the initializer is set,
  // which is only the case when run on a non-loader-hook thread.
  Local<Function> import_meta_resolve_initializer =
      realm->host_import_meta_resolve_initializer();
  if (!import_meta_resolve_initializer.IsEmpty() &&
      meta->SetLazyDataProperty(context,
                                FIXED_ONE_BYTE_STRING(isolate, "resolve"),
                                ImportMetaResolveLazyGetter,
                                url)
          .IsNothing()) {
    return Nothing<void>();
  }

  // Set import.meta.url = moduleWrap.url
  if (meta->Set(context, env->url_string(), url).IsEmpty()) {
    return Nothing<void>();
  }

  return JustVoid();
}

void ModuleWrap::HostInitializeImportMetaObjectCallback(
    Local<Context> context, Local<Module> module, Local<Object> meta) {
  Environment* env = Environment::GetCurrent(context);
  if (env == nullptr)
    return;
  ModuleWrap* module_wrap = GetFromModule(env, module);

  if (module_wrap == nullptr) {
    return;
  }
  Realm* realm = Realm::GetCurrent(context);
  if (realm == nullptr) {
    // Fallback to the principal realm if it's in a vm context.
    realm = env->principal_realm();
  }

  Local<Object> wrap = module_wrap->object();
  Local<Function> callback =
      realm->host_initialize_import_meta_object_callback();
  Local<Value> id;
  if (!wrap->GetPrivate(context, env->host_defined_option_symbol())
           .ToLocal(&id)) {
    return;
  }
  DCHECK(id->IsSymbol());

  // Use the default initializer for source text modules without custom
  // callbacks.
  if (id == env->source_text_module_default_hdo()) {
    USE(DefaultImportMetaObjectInitializer(realm, wrap, meta));
    return;
  }

  // For modules that have custom callbacks, call into JS land
  // to look up the callback from the registry.
  Local<Value> args[] = {id, meta, wrap};
  TryCatchScope try_catch(env);

  USE(callback->Call(
      context, Undefined(realm->isolate()), arraysize(args), args));
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
    try_catch.ReThrow();
  }
}

void ModuleWrap::SetInitializeImportMetaObjectCallback(
    const FunctionCallbackInfo<Value>& args) {
  Realm* realm = Realm::GetCurrent(args);
  Isolate* isolate = realm->isolate();

  CHECK_EQ(args.Length(), 1);
  CHECK(args[0]->IsFunction());
  Local<Function> import_meta_callback = args[0].As<Function>();
  realm->set_host_initialize_import_meta_object_callback(import_meta_callback);

  isolate->SetHostInitializeImportMetaObjectCallback(
      HostInitializeImportMetaObjectCallback);
}

MaybeLocal<Value> ModuleWrap::SyntheticModuleEvaluationStepsCallback(
    Local<Context> context, Local<Module> module) {
  Environment* env = Environment::GetCurrent(context);
  Isolate* isolate = env->isolate();

  ModuleWrap* obj = GetFromModule(env, module);

  TryCatchScope try_catch(env);
  Local<Function> synthetic_evaluation_steps =
      obj->object()
          ->GetInternalField(kSyntheticEvaluationStepsSlot)
          .As<Value>()
          .As<Function>();
  obj->object()->SetInternalField(
      kSyntheticEvaluationStepsSlot, Undefined(isolate));
  MaybeLocal<Value> ret = synthetic_evaluation_steps->Call(context,
      obj->object(), 0, nullptr);
  if (ret.IsEmpty()) {
    CHECK(try_catch.HasCaught());
  }
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
    CHECK(!try_catch.Message().IsEmpty());
    CHECK(!try_catch.Exception().IsEmpty());
    try_catch.ReThrow();
    return MaybeLocal<Value>();
  }

  Local<Promise::Resolver> resolver;
  if (!Promise::Resolver::New(context).ToLocal(&resolver)) {
    return MaybeLocal<Value>();
  }

  if (resolver->Resolve(context, Undefined(isolate)).IsNothing()) {
    return MaybeLocal<Value>();
  }
  return resolver->GetPromise();
}

void ModuleWrap::SetSyntheticExport(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Object> that = args.This();

  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);

  CHECK(obj->synthetic_);

  CHECK_EQ(args.Length(), 2);

  CHECK(args[0]->IsString());
  Local<String> export_name = args[0].As<String>();

  Local<Value> export_value = args[1];

  Local<Module> module = obj->module_.Get(isolate);
  USE(module->SetSyntheticModuleExport(isolate, export_name, export_value));
}

void ModuleWrap::CreateCachedData(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Object> that = args.This();

  ModuleWrap* obj;
  ASSIGN_OR_RETURN_UNWRAP(&obj, that);

  CHECK(!obj->synthetic_);

  Local<Module> module = obj->module_.Get(isolate);

  CHECK_LT(module->GetStatus(), Module::Status::kEvaluating);

  Local<UnboundModuleScript> unbound_module_script =
      module->GetUnboundModuleScript();
  std::unique_ptr<ScriptCompiler::CachedData> cached_data(
      ScriptCompiler::CreateCodeCache(unbound_module_script));
  Environment* env = Environment::GetCurrent(args);
  Local<Object> result;
  if (!cached_data) {
    if (!Buffer::New(env, 0).ToLocal(&result)) {
      return;
    }
  } else if (!Buffer::Copy(env,
                           reinterpret_cast<const char*>(cached_data->data),
                           cached_data->length)
                  .ToLocal(&result)) {
    return;
  }
  args.GetReturnValue().Set(result);
}

// This v8::Module::ResolveModuleCallback simply links `import 'original'`
// to the env->temporary_required_module_facade_original() which is stashed
// right before this callback is called and will be restored as soon as
// v8::Module::Instantiate() returns.
MaybeLocal<Module> LinkRequireFacadeWithOriginal(
    Local<Context> context,
    Local<String> specifier,
    Local<FixedArray> import_attributes,
    Local<Module> referrer) {
  Environment* env = Environment::GetCurrent(context);
  Isolate* isolate = Isolate::GetCurrent();
  CHECK(specifier->Equals(context, env->original_string()).ToChecked());
  CHECK(!env->temporary_required_module_facade_original.IsEmpty());
  return env->temporary_required_module_facade_original.Get(isolate);
}

// Wraps an existing source text module with a facade that adds
// .__esModule = true to the exports.
// See env->required_module_facade_source_string() for the source.
void ModuleWrap::CreateRequiredModuleFacade(
    const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Environment* env = Environment::GetCurrent(context);
  CHECK(args[0]->IsObject());  // original module
  Local<Object> wrap = args[0].As<Object>();
  ModuleWrap* original;
  ASSIGN_OR_RETURN_UNWRAP(&original, wrap);

  // Use the same facade source and URL to hit the compilation cache.
  ScriptOrigin origin(env->required_module_facade_url_string(),
                      0,               // line offset
                      0,               // column offset
                      true,            // is cross origin
                      -1,              // script id
                      Local<Value>(),  // source map URL
                      false,           // is opaque (?)
                      false,           // is WASM
                      true);           // is ES Module
  ScriptCompiler::Source source(env->required_module_facade_source_string(),
                                origin);

  // The module facade instantiation simply links `import 'original'` in the
  // facade with the original module and should never fail.
  Local<Module> facade;
  if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&facade)) {
    return;
  }
  // Stash the original module in temporary_required_module_facade_original
  // for the LinkRequireFacadeWithOriginal() callback to pick it up.
  CHECK(env->temporary_required_module_facade_original.IsEmpty());
  env->temporary_required_module_facade_original.Reset(
      isolate, original->module_.Get(isolate));
  CHECK(facade->InstantiateModule(context, LinkRequireFacadeWithOriginal)
            .IsJust());
  env->temporary_required_module_facade_original.Reset();

  // The evaluation of the facade is synchronous.
  Local<Value> evaluated;
  if (!facade->Evaluate(context).ToLocal(&evaluated)) {
    return;
  }
  CHECK(evaluated->IsPromise());
  CHECK_EQ(evaluated.As<Promise>()->State(), Promise::PromiseState::kFulfilled);

  args.GetReturnValue().Set(facade->GetModuleNamespace());
}

void ModuleWrap::CreatePerIsolateProperties(IsolateData* isolate_data,
                                            Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();

  Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New);
  tpl->InstanceTemplate()->SetInternalFieldCount(
      ModuleWrap::kInternalFieldCount);

  SetProtoMethod(isolate, tpl, "link", Link);
  SetProtoMethod(isolate, tpl, "getModuleRequests", GetModuleRequests);
  SetProtoMethod(isolate, tpl, "instantiate", Instantiate);
  SetProtoMethod(isolate, tpl, "evaluateSync", EvaluateSync);
  SetProtoMethod(isolate, tpl, "evaluate", Evaluate);
  SetProtoMethod(isolate, tpl, "setExport", SetSyntheticExport);
  SetProtoMethod(isolate, tpl, "setModuleSourceObject", SetModuleSourceObject);
  SetProtoMethod(isolate, tpl, "getModuleSourceObject", GetModuleSourceObject);
  SetProtoMethodNoSideEffect(
      isolate, tpl, "createCachedData", CreateCachedData);
  SetProtoMethodNoSideEffect(isolate, tpl, "getNamespace", GetNamespace);
  SetProtoMethodNoSideEffect(isolate, tpl, "getStatus", GetStatus);
  SetProtoMethodNoSideEffect(isolate, tpl, "getError", GetError);
  SetConstructorFunction(isolate, target, "ModuleWrap", tpl);

  tpl->InstanceTemplate()->SetLazyDataProperty(
      FIXED_ONE_BYTE_STRING(isolate, "hasAsyncGraph"),
      HasAsyncGraph,
      Local<Value>(),
      PropertyAttribute::DontEnum);

  isolate_data->set_module_wrap_constructor_template(tpl);

  SetMethod(isolate,
            target,
            "setImportModuleDynamicallyCallback",
            SetImportModuleDynamicallyCallback);
  SetMethod(isolate,
            target,
            "setInitializeImportMetaObjectCallback",
            SetInitializeImportMetaObjectCallback);
  SetMethod(isolate,
            target,
            "setImportMetaResolveInitializer",
            SetImportMetaResolveInitializer);
  SetMethod(isolate,
            target,
            "createRequiredModuleFacade",
            CreateRequiredModuleFacade);
  SetMethod(isolate, target, "throwIfPromiseRejected", ThrowIfPromiseRejected);
}

void ModuleWrap::CreatePerContextProperties(Local<Object> target,
                                            Local<Value> unused,
                                            Local<Context> context,
                                            void* priv) {
  Realm* realm = Realm::GetCurrent(context);
  Isolate* isolate = realm->isolate();
#define V(enum_type, name)                                                     \
  target                                                                       \
      ->Set(context,                                                           \
            FIXED_ONE_BYTE_STRING(isolate, #name),                             \
            Integer::New(isolate, enum_type::name))                            \
      .FromJust()
  V(Module::Status, kUninstantiated);
  V(Module::Status, kInstantiating);
  V(Module::Status, kInstantiated);
  V(Module::Status, kEvaluating);
  V(Module::Status, kEvaluated);
  V(Module::Status, kErrored);

  V(ModulePhase, kEvaluationPhase);
  V(ModulePhase, kSourcePhase);
#undef V
}

void ModuleWrap::RegisterExternalReferences(
    ExternalReferenceRegistry* registry) {
  registry->Register(New);

  registry->Register(Link);
  registry->Register(GetModuleRequests);
  registry->Register(EvaluateSync);
  registry->Register(Instantiate);
  registry->Register(Evaluate);
  registry->Register(SetSyntheticExport);
  registry->Register(SetModuleSourceObject);
  registry->Register(GetModuleSourceObject);
  registry->Register(CreateCachedData);
  registry->Register(GetNamespace);
  registry->Register(GetStatus);
  registry->Register(GetError);
  registry->Register(HasAsyncGraph);

  registry->Register(CreateRequiredModuleFacade);

  registry->Register(SetImportModuleDynamicallyCallback);
  registry->Register(SetInitializeImportMetaObjectCallback);
  registry->Register(SetImportMetaResolveInitializer);
  registry->Register(ThrowIfPromiseRejected);
}
}  // namespace loader
}  // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(
    module_wrap, node::loader::ModuleWrap::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(
    module_wrap, node::loader::ModuleWrap::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(
    module_wrap, node::loader::ModuleWrap::RegisterExternalReferences)
