// Copyright 2026 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/node/standalone/Polyfills.h"

#include <algorithm>
#include <cctype>
#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <optional>
#include <regex>
#include <sstream>
#include <string>
#include <string_view>
#include <system_error>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "src/dawn/common/SystemUtils.h"
#include "src/dawn/node/napi_v8/napi_v8.h"
#include "src/dawn/node/standalone/EventLoop.h"
#include "src/dawn/node/standalone/FileBundle.h"

namespace dawn::node::standalone {

namespace {

// State shared by the polyfills that outlives registration. Owned by the `process` object, which
// deletes it from its finalizer.
struct PolyfillContext {
    struct RequireContext {
        PolyfillContext* ctx;
        std::string from_dir;
    };

    PolyfillContext(EventLoop& event_loop, PolyfillOptions opts)
        : loop(event_loop),
          options(std::move(opts)),
          bundle_root(std::filesystem::path(options.bundle_root).lexically_normal()) {}

    EventLoop& loop;
    PolyfillOptions options;
    // `options.bundle_root` in the form the resolved paths take, so that they compare equal to it.
    std::filesystem::path bundle_root;
    std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
    absl::flat_hash_map<std::string, Napi::ObjectReference> module_cache;
    std::vector<std::unique_ptr<RequireContext>> require_contexts;
};

void DeletePolyfillContext(const Napi::Env&, PolyfillContext* ctx) {
    delete ctx;
}

// Joins the call's arguments with spaces, as the console methods display them.
Napi::Value FormatArgs(const Napi::CallbackInfo& info) {
    std::stringstream ss;
    for (size_t i = 0; i < info.Length(); ++i) {
        if (i > 0) {
            ss << " ";
        }
        ss << info[i].ToString().Utf8Value();
    }
    return Napi::String::New(info.Env(), ss.str());
}

// ---------------------------------------------------------------------------
// console
// ---------------------------------------------------------------------------

// Backs console.log(), console.info() and console.debug(). Node defines the latter two as
// aliases of the first, all writing to stdout with no prefix:
// https://nodejs.org/api/console.html#consoledebugdata-args
Napi::Value ConsoleLog(const Napi::CallbackInfo& info) {
    std::cout << FormatArgs(info).As<Napi::String>().Utf8Value() << std::endl;
    return info.Env().Undefined();
}

Napi::Value ConsoleWarn(const Napi::CallbackInfo& info) {
    std::clog << "[WARN] " << FormatArgs(info).As<Napi::String>().Utf8Value() << std::endl;
    return info.Env().Undefined();
}

Napi::Value ConsoleError(const Napi::CallbackInfo& info) {
    std::cerr << "[ERROR] " << FormatArgs(info).As<Napi::String>().Utf8Value() << std::endl;
    return info.Env().Undefined();
}

// https://developer.mozilla.org/en-US/docs/Web/API/console
void RegisterConsole(Napi::Env env) {
    Napi::Object console = Napi::Object::New(env);
    console.Set("log", Napi::Function::New(env, ConsoleLog, "log"));
    console.Set("info", Napi::Function::New(env, ConsoleLog, "info"));
    console.Set("debug", Napi::Function::New(env, ConsoleLog, "debug"));
    console.Set("warn", Napi::Function::New(env, ConsoleWarn, "warn"));
    console.Set("error", Napi::Function::New(env, ConsoleError, "error"));
    env.Global().Set("console", console);
}

// ---------------------------------------------------------------------------
// Paths
// ---------------------------------------------------------------------------

// Whether `c` can begin a UNC path on this platform.
//
// Windows accepts both "\\server\share" and "//server/share" as UNC. On POSIX only the backslash
// form is treated as one, because a leading "//" is a legal POSIX path.
bool BeginsUncPath(char c) {
#if defined(_WIN32)
    return c == '/' || c == '\\';
#else
    return c == '\\';
#endif
}

// Returns true if the path begins with two separators. That is the whole test: anything beginning
// that way is a UNC path ("\\server\share") or a device path ("\\?\C:\..." and "\\.\...").
bool IsUncPath(std::string_view path) {
    return path.size() >= 2 && BeginsUncPath(path[0]) && BeginsUncPath(path[1]);
}

// Throws a JavaScript exception if `path` is a UNC or device path. Returns true if it threw.
//
// These are deliberately unsupported. Node.js handles them very differently
// than std::filesystem::path. To match Node.js, we would need to implement it
// from scratch. We will not do that unless there is a request from the users.
bool RejectUncPath(Napi::Env env, const std::string& path) {
    if (!IsUncPath(path)) {
        return false;
    }
    Napi::Error::New(env, "UNC and device paths are not supported: " + path)
        .ThrowAsJavaScriptException();
    return true;
}

// ---------------------------------------------------------------------------
// fs
// ---------------------------------------------------------------------------

// Returns the path the fs functions act on for `path`. With a bundle, a relative path is resolved
// against the bundle's root, which stands in for the working directory. An empty path is not
// resolved, so that it names no file, as in Node.
std::string ResolveFsPath(const PolyfillContext& ctx, const std::string& path) {
    if (ctx.options.bundle == nullptr || path.empty()) {
        return path;
    }
    return (ctx.bundle_root / path).lexically_normal().string();
}

// Returns the name in the bundle of `resolved`, a path from ResolveFsPath(), if the context has a
// bundle and the path lies under its root. Returns nullopt for a path on the disk.
std::optional<std::string> PathInBundle(const PolyfillContext& ctx, const std::string& resolved) {
    if (ctx.options.bundle == nullptr) {
        return std::nullopt;
    }
    const std::filesystem::path relative =
        std::filesystem::path(resolved).lexically_relative(ctx.bundle_root);
    if (relative.empty() || relative.begin()->string() == "..") {
        return std::nullopt;
    }
    if (relative == ".") {
        return "";
    }
    // "a/", "a/." and "a/b/.." normalize to "a/", which names the entry "a".
    std::string name = relative.generic_string();
    if (name.ends_with('/')) {
        name.pop_back();
    }
    return name;
}

// Retrieves the path argument from `info` and stores it in `*path`. Every fs
// entry point with a path argument has it in the first position. If the path
// cannot be retrieved or it is a UNC path, a JavaScript exception is thrown.
bool GetPathArgument(const Napi::CallbackInfo& info, std::string* path) {
    if (info.Length() < 1 || !info[0].IsString()) {
        Napi::TypeError::New(info.Env(), "String expected for path").ThrowAsJavaScriptException();
        return false;
    }
    *path = info[0].As<Napi::String>().Utf8Value();
    return !RejectUncPath(info.Env(), *path);
}

// Which encoding the caller asked for. What kNone means is up to the caller: readFileSync()
// answers with bytes, readdirSync() with UTF-8 strings, matching Node's defaults.
enum class Encoding {
    kNone,
    kUtf8,
};

// Reads the options argument the fs entry points take, which may be an encoding on its own or an
// object holding one.
//
// Only UTF-8 is implemented and `encoding` is the only option understood. Anything else throws a
// JavaScript exception.
bool GetEncodingOption(const Napi::CallbackInfo& info, Encoding* encoding) {
    Napi::Env env = info.Env();
    *encoding = Encoding::kNone;
    if (info.Length() < 2 || info[1].IsUndefined() || info[1].IsNull()) {
        return true;
    }

    Napi::Value value = info[1];
    if (value.IsObject()) {
        Napi::Object options = value.As<Napi::Object>();
        Napi::Array names = options.GetPropertyNames();
        for (uint32_t i = 0; i < names.Length(); ++i) {
            std::string name = names.Get(i).ToString().Utf8Value();
            if (name != "encoding") {
                Napi::Error::New(env, "Unsupported fs option: " + name)
                    .ThrowAsJavaScriptException();
                return false;
            }
        }
        value = options.Get("encoding");
        if (value.IsUndefined() || value.IsNull()) {
            return true;
        }
    }

    if (!value.IsString()) {
        Napi::TypeError::New(env, "String expected for encoding").ThrowAsJavaScriptException();
        return false;
    }
    std::string name = value.As<Napi::String>().Utf8Value();
    std::string lower_name = name;
    for (char& c : lower_name) {
        c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
    }
    // Node.js documentation specifies that all buffer encodings are case-insensitive.
    if (lower_name != "utf8" && lower_name != "utf-8") {
        Napi::Error::New(env, "Unsupported fs encoding: " + name).ThrowAsJavaScriptException();
        return false;
    }
    *encoding = Encoding::kUtf8;
    return true;
}

bool OpenAndSizeFile(Napi::Env env,
                     const std::string& path,
                     std::ifstream* file,
                     std::streamoff* size) {
    // Node.js reads the file in binary regardless of the encoding.
    file->open(path, std::ios::binary | std::ios::ate);
    if (!file->is_open()) {
        Napi::Error::New(env, "Failed to open file: " + path).ThrowAsJavaScriptException();
        return false;
    }

    *size = file->tellg();
    if (*size < 0) {
        Napi::Error::New(env, "Failed to size file: " + path).ThrowAsJavaScriptException();
        return false;
    }
    file->seekg(0, std::ios::beg);
    return true;
}

// Reads the file at `path`, from the bundle when the path lies under its root and from the disk
// otherwise, or returns false with an exception pending.
bool ReadFileUtf8(Napi::Env env,
                  const PolyfillContext& ctx,
                  const std::string& path,
                  std::string* out) {
    const std::string resolved = ResolveFsPath(ctx, path);
    if (std::optional<std::string> name = PathInBundle(ctx, resolved)) {
        std::optional<std::string> contents = ctx.options.bundle->ReadFile(*name);
        if (!contents) {
            Napi::Error::New(env, "Failed to open file: " + path).ThrowAsJavaScriptException();
            return false;
        }
        *out = std::move(*contents);
        return true;
    }

    std::ifstream file;
    std::streamoff offset = 0;
    if (!OpenAndSizeFile(env, resolved, &file, &offset)) {
        return false;
    }
    out->resize(static_cast<size_t>(offset));
    file.read(out->data(), static_cast<std::streamsize>(offset));
    out->resize(static_cast<size_t>(file.gcount()));
    return true;
}

Napi::Value ReadFileSync(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    std::string path;
    Encoding encoding = Encoding::kNone;
    if (!GetPathArgument(info, &path) || !GetEncodingOption(info, &encoding)) {
        return env.Undefined();
    }

    if (encoding == Encoding::kUtf8) {
        std::string content;
        if (!ReadFileUtf8(env, *ctx, path, &content)) {
            return env.Undefined();
        }
        return Napi::String::New(env, content);
    }

    const std::string resolved = ResolveFsPath(*ctx, path);
    if (std::optional<std::string> name = PathInBundle(*ctx, resolved)) {
        std::optional<std::string> contents = ctx->options.bundle->ReadFile(*name);
        if (!contents) {
            Napi::Error::New(env, "Failed to open file: " + path).ThrowAsJavaScriptException();
            return env.Undefined();
        }
        Napi::ArrayBuffer array_buffer = Napi::ArrayBuffer::New(env, contents->size());
        std::ranges::copy(*contents, static_cast<char*>(array_buffer.Data()));
        return Napi::Uint8Array::New(env, contents->size(), array_buffer, 0);
    }

    std::ifstream file;
    std::streamoff offset = 0;
    if (!OpenAndSizeFile(env, resolved, &file, &offset)) {
        return env.Undefined();
    }

    // Read straight into the object being returned, so the contents are written once.
    // Resize to gcount() in case the file shrank between the seek and the read.
    Napi::ArrayBuffer array_buffer = Napi::ArrayBuffer::New(env, static_cast<size_t>(offset));
    file.read(static_cast<char*>(array_buffer.Data()), static_cast<std::streamsize>(offset));
    return Napi::Uint8Array::New(env, static_cast<size_t>(file.gcount()), array_buffer, 0);
}

// Returns the type of what is at `path`, in the bundle when the path lies under its root and on the
// disk otherwise, or nullopt if there is nothing there.
std::optional<std::filesystem::file_type> FileType(const PolyfillContext& ctx,
                                                   const std::string& path) {
    const std::string resolved = ResolveFsPath(ctx, path);
    if (std::optional<std::string> name = PathInBundle(ctx, resolved)) {
        FileBundle::Kind kind = ctx.options.bundle->Stat(*name);
        if (kind == FileBundle::Kind::kNotFound) {
            return std::nullopt;
        }
        return kind == FileBundle::Kind::kFile ? std::filesystem::file_type::regular
                                               : std::filesystem::file_type::directory;
    }
    std::error_code ec;
    std::filesystem::file_status status = std::filesystem::status(resolved, ec);
    if (ec || !std::filesystem::exists(status)) {
        return std::nullopt;
    }
    return status.type();
}

// Returns true if the given file exists. A JavaScript exception is thrown if a
// UNC path is given.
Napi::Value ExistsSync(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    if (info.Length() < 1 || !info[0].IsString()) {
        return Napi::Boolean::New(env, false);
    }
    std::string path = info[0].As<Napi::String>().Utf8Value();
    if (RejectUncPath(env, path)) {
        return env.Undefined();
    }
    return Napi::Boolean::New(env, FileType(*ctx, path).has_value());
}

Napi::Value ReaddirSync(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    std::string path;
    // The entries are always strings, so the encoding needs validating rather than honouring; the
    // point of the call is to reject `withFileTypes` and friends.
    Encoding encoding = Encoding::kNone;
    if (!GetPathArgument(info, &path) || !GetEncodingOption(info, &encoding)) {
        return env.Undefined();
    }

    const std::string resolved = ResolveFsPath(*ctx, path);
    if (std::optional<std::string> name = PathInBundle(*ctx, resolved)) {
        std::optional<std::vector<std::string>> entries = ctx->options.bundle->ReadDir(*name);
        if (!entries) {
            Napi::Error::New(env, "Failed to read directory: " + path).ThrowAsJavaScriptException();
            return env.Undefined();
        }
        Napi::Array result = Napi::Array::New(env);
        uint32_t index = 0;
        for (const std::string& entry : *entries) {
            result.Set(index++, Napi::String::New(env, entry));
        }
        return result;
    }

    std::error_code ec;
    std::filesystem::directory_iterator it(resolved, ec);
    if (ec) {
        Napi::Error::New(env, ec.message()).ThrowAsJavaScriptException();
        return env.Undefined();
    }

    Napi::Array result = Napi::Array::New(env);
    uint32_t index = 0;
    for (const auto& entry : it) {
        result.Set(index++, Napi::String::New(env, entry.path().filename().string()));
    }
    return result;
}

Napi::Value ReturnTrue(const Napi::CallbackInfo& info) {
    return Napi::Boolean::New(info.Env(), true);
}

Napi::Value ReturnFalse(const Napi::CallbackInfo& info) {
    return Napi::Boolean::New(info.Env(), false);
}

Napi::Value StatSync(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    std::string path;
    Encoding encoding = Encoding::kNone;
    if (!GetPathArgument(info, &path) || !GetEncodingOption(info, &encoding)) {
        return env.Undefined();
    }

    std::optional<std::filesystem::file_type> type = FileType(*ctx, path);
    if (!type) {
        Napi::Error::New(env, "Failed to stat: " + path).ThrowAsJavaScriptException();
        return env.Undefined();
    }

    const bool is_file = *type == std::filesystem::file_type::regular;
    const bool is_directory = *type == std::filesystem::file_type::directory;
    Napi::Object stats = Napi::Object::New(env);
    stats.Set("isFile", Napi::Function::New(env, is_file ? ReturnTrue : ReturnFalse, "isFile"));
    stats.Set("isDirectory",
              Napi::Function::New(env, is_directory ? ReturnTrue : ReturnFalse, "isDirectory"));
    return stats;
}

// https://nodejs.org/api/fs.html
//
// Only the synchronous entry points are native. The callback and promise forms are built on top of
// them by the bootstrap script.
void RegisterFs(Napi::Env env, PolyfillContext* ctx) {
    Napi::Object fs = Napi::Object::New(env);
    fs.Set("readFileSync", Napi::Function::New(env, ReadFileSync, "readFileSync", ctx));
    fs.Set("existsSync", Napi::Function::New(env, ExistsSync, "existsSync", ctx));
    fs.Set("readdirSync", Napi::Function::New(env, ReaddirSync, "readdirSync", ctx));
    fs.Set("statSync", Napi::Function::New(env, StatSync, "statSync", ctx));
    env.Global().Set("_fs_polyfill", fs);
}

// ---------------------------------------------------------------------------
// path
// ---------------------------------------------------------------------------
//
// Built on std::filesystem, which walks the components and, on Windows, understands drive letters
// and accepts either separator. Its conventions are not Node's, so each function below lets
// std::filesystem handle the general case and then fixes up the places where the two disagree.
//
// UNC and device paths are refused rather than reconciled; see RejectUncPath.

constexpr char kPreferredSeparator = static_cast<char>(std::filesystem::path::preferred_separator);

// What counts as a separator on this host. Windows accepts either; POSIX only the forward slash.
#if defined(_WIN32)
constexpr std::string_view kSeparators = "/\\";
#else
constexpr std::string_view kSeparators = "/";
#endif

bool IsSeparator(char c) {
    return kSeparators.find(c) != std::string_view::npos;
}

// A trailing separator is a flag to Node but a real, empty final component to std::filesystem, so
// filename(), extension() and parent_path() all see one component more than Node does. Dropping it
// first is what makes them agree. The root is never stripped: "/" and "C:\" are not trailing
// separators.
std::string TrimTrailingSeparators(const std::filesystem::path& path) {
    const std::string text = path.string();
    const size_t root = path.root_path().string().size();
    const size_t last = text.find_last_not_of(kSeparators);
    const size_t end = last == std::string::npos ? root : std::max(root, last + 1);
    return text.substr(0, end);
}

// Two or more leading separators collapse to one, which is what Node does on POSIX. On Windows two
// separators would mean UNC, and those are refused at the boundary, so anything arriving here with
// the shape is an ordinary rooted path that concatenation happened to produce - join('/', 'a')
// builds "/\a" on the way to "\a".
std::string CollapseLeadingSeparators(std::string text) {
    size_t run = text.find_first_not_of(kSeparators);
    if (run == std::string::npos) {
        run = text.size();  // nothing but separators
    }
    if (run > 1) {
        text.erase(0, run - 1);
    }
    return text;
}

std::string NormalizePath(const std::string& input) {
    if (input.empty()) {
        return ".";  // lexically_normal() returns ""
    }
    const std::filesystem::path path(input);
    // lexically_normal() both drops a trailing separator ("./" becomes ".") and invents one
    // ("a/b/.." becomes "a/"), so neither its presence nor its absence in the output means
    // anything. Taking it off and putting it back according to the input is what Node does.
    const bool trailing = IsSeparator(input.back());
    std::string result = TrimTrailingSeparators(path.lexically_normal());
    if (result.empty()) {
        result = ".";
    } else if (path.has_root_name() && !path.has_root_directory() &&
               result == path.root_name().string()) {
        // A path like "C:" on Windows implies the "." directory on that drive.
        // Node makes this explicit by turning it into "C:.".
        // This cannot happen for POSIX.
        result += '.';
    }
    if (trailing && !IsSeparator(result.back())) {
        result += kPreferredSeparator;
    }
    return CollapseLeadingSeparators(result);
}

// The one entry point not expressible in terms of a std::filesystem primitive. Node's dirname() is
// a raw string slice that deliberately does not normalize - dirname("/a//b") is "/a/", separator
// run intact - while parent_path() is component-based and has already discarded that. So Node's
// scan is transcribed, with root_path() supplying the one genuinely platform-specific part: where
// the root ends, be that "/" or "C:\".
std::string DirnamePath(const std::string& input) {
    if (input.empty()) {
        return ".";
    }
    const size_t root_length = std::filesystem::path(input).root_path().string().size();
    const bool has_root = root_length > 0;

    // Search for the last separator, ignoring any trailing separators and the
    // root. Separators in the root have a special meaning. The result is
    // everything that appears before the separator preceding the last component.
    const std::string_view path_without_root = std::string_view(input).substr(root_length);

    // Skip any trailing separators to locate the end of the last path component.
    const size_t last_non_separator = path_without_root.find_last_not_of(kSeparators);

    // Find the separator immediately preceding the last component.
    const size_t separator_before_last_component =
        last_non_separator == std::string_view::npos
            ? std::string_view::npos
            : path_without_root.find_last_of(kSeparators, last_non_separator);
    if (separator_before_last_component == std::string_view::npos) {
        // Nothing to cut back to, so the answer is the root, or "." when there is no root.
        return has_root ? input.substr(0, root_length) : ".";
    }

    // Find the index of the separator in the original string.
    const size_t last_separator_index = root_length + separator_before_last_component;

    /*
     * Node's posix dirname() has exactly one special case, quoted from Node's implementation:
     *
     *   // POSIX reserves a leading '//' for implementation-defined purposes.
     *   // (IEEE Std 1003.1-2017, Section 4.13 Pathname Resolution:
     *   //  "A pathname that begins with two successive slashes may be interpreted
     *   //   in an implementation-defined manner, although more than two leading
     *   //   slashes shall be treated as a single slash.")
     *   // Node keeps both slashes: dirname("//a") is "//" rather than "/".
     *
     * On Windows, leading double slashes represent a UNC path, which is rejected
     * earlier before reaching this function.
     */
    if (has_root && last_separator_index == 1) {
        return input.substr(0, 2);
    }

    // Return the substring up to, but not including, the separator before the last component.
    return input.substr(0, last_separator_index);
}

std::string JoinPaths(const std::vector<std::string>& args) {
    // std::filesystem::path::append cannot be used here. If one of `args` is an
    // absolute path, Node will join them: {"/a", "/b"} -> "/a/b". However,
    // std::filesystem::path drops the previous paths: {"/a", "/b"} -> "/b".
    std::string joined;
    for (const std::string& arg : args) {
        if (arg.empty()) {
            continue;  // Node skips empty arguments rather than reading them as "."
        }
        if (!joined.empty()) {
            joined += kPreferredSeparator;
        }
        joined += arg;
    }
    if (joined.empty()) {
        return ".";
    }
    return NormalizePath(joined);
}

// The working directory, or false with an exception pending. Shared by process.cwd() and by
// resolve(), which anchors relative arguments on it. With a bundle, this is the bundle's root,
// regardless of where the process itself was started.
bool CurrentDirectory(Napi::Env env, const PolyfillContext& ctx, std::string* out) {
    if (ctx.options.bundle != nullptr) {
        *out = ctx.bundle_root.string();
        return true;
    }
    std::error_code ec;
    const std::filesystem::path cwd = std::filesystem::current_path(ec);
    if (ec) {
        Napi::Error::New(env, "Could not read the working directory: " + ec.message())
            .ThrowAsJavaScriptException();
        return false;
    }
    *out = cwd.string();
    // A UNC working directory means a checkout on a network share. Everything resolve() produces
    // would be built on it, so it fails here rather than somewhere downstream that gives no hint
    // of the cause.
    return !RejectUncPath(env, *out);
}

bool ResolvePaths(Napi::Env env,
                  const PolyfillContext& ctx,
                  const std::vector<std::string>& args,
                  std::string* out) {
    std::filesystem::path accumulated;
    for (const std::string& arg : args) {
        if (arg.empty()) {
            continue;  // absolute("") fails with EINVAL, and Node ignores empty arguments
        }
        // Here operator/ is exactly right: its rule that a later absolute argument replaces
        // everything before it, including the Windows rule that a rooted argument keeps the
        // left-hand side's drive, is what resolve() specifies.
        accumulated /= std::filesystem::path(arg);
    }

    // The working directory is read here rather than left to absolute() so that a working
    // directory that cannot be read, or that is UNC, is reported as such instead of surfacing as a
    // confusing failure about the argument.
    if (!accumulated.is_absolute()) {
        std::string cwd;
        if (!CurrentDirectory(env, ctx, &cwd)) {
            return false;
        }

        // If `accumulated` is empty, the call to std::filesystem::absolute
        // below will fail. Replacing it with `cwd` to match Node's behaviour.
        if (accumulated.empty()) {
            accumulated = std::filesystem::path(cwd);
        } else if (ctx.options.bundle != nullptr) {
            // absolute() below would anchor on the process's working directory, not the bundle's.
            accumulated = std::filesystem::path(cwd) / accumulated;
        }
    }

    // absolute() rather than `cwd / accumulated`: on Windows a drive-relative argument like "C:a"
    // names the working directory of that drive, which only absolute() knows how to consult -
    // operator/ would see a root-name of its own and keep "C:a" relative. On POSIX the two are the
    // same thing.
    std::error_code ec;
    const std::filesystem::path absolute = std::filesystem::absolute(accumulated, ec);
    if (ec) {
        Napi::Error::New(env, "Could not resolve path: " + ec.message())
            .ThrowAsJavaScriptException();
        return false;
    }
    // Node's resolve() never returns a trailing separator, but lexically_normal() produces one
    // whenever the last component was a dot segment.
    std::string result = TrimTrailingSeparators(absolute.lexically_normal());
    if (result.empty()) {
        result = ".";
    }
    *out = CollapseLeadingSeparators(result);
    return true;
}

bool RelativePath(Napi::Env env,
                  const PolyfillContext& ctx,
                  const std::string& from,
                  const std::string& to,
                  std::string* out) {
    // Node resolves both sides first, so the answer depends only on where they land.
    std::string from_resolved;
    std::string to_resolved;
    if (!ResolvePaths(env, ctx, {from}, &from_resolved) ||
        !ResolvePaths(env, ctx, {to}, &to_resolved)) {
        return false;
    }

    const std::filesystem::path result =
        std::filesystem::path(to_resolved).lexically_relative(std::filesystem::path(from_resolved));
    if (result == std::filesystem::path(".")) {
        *out = "";  // lexically_relative() says "." for identical paths; Node says ""
    } else if (result.empty()) {
        *out = to_resolved;  // unrelated roots, where Node falls back to the resolved `to`
    } else {
        *out = result.string();
    }
    return true;
}

// Reads the string arguments a path entry point takes, throwing the TypeError Node throws for a
// non-string, and refusing UNC paths.
bool GetPathArguments(const Napi::CallbackInfo& info,
                      size_t least,
                      std::vector<std::string>* args) {
    if (info.Length() < least) {
        Napi::TypeError::New(info.Env(), "String expected for path").ThrowAsJavaScriptException();
        return false;
    }
    for (size_t i = 0; i < info.Length(); ++i) {
        if (!info[i].IsString()) {
            Napi::TypeError::New(info.Env(), "String expected for path")
                .ThrowAsJavaScriptException();
            return false;
        }
        std::string arg = info[i].As<Napi::String>().Utf8Value();
        if (RejectUncPath(info.Env(), arg)) {
            return false;
        }
        args->push_back(std::move(arg));
    }
    return true;
}

Napi::Value PathNormalize(const Napi::CallbackInfo& info) {
    std::vector<std::string> args;
    if (!GetPathArguments(info, 1, &args)) {
        return info.Env().Undefined();
    }
    return Napi::String::New(info.Env(), NormalizePath(args[0]));
}

Napi::Value PathDirname(const Napi::CallbackInfo& info) {
    std::vector<std::string> args;
    if (!GetPathArguments(info, 1, &args)) {
        return info.Env().Undefined();
    }
    return Napi::String::New(info.Env(), DirnamePath(args[0]));
}

Napi::Value PathJoin(const Napi::CallbackInfo& info) {
    std::vector<std::string> args;
    if (!GetPathArguments(info, 0, &args)) {
        return info.Env().Undefined();
    }
    return Napi::String::New(info.Env(), JoinPaths(args));
}

Napi::Value PathResolve(const Napi::CallbackInfo& info) {
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    std::vector<std::string> args;
    std::string resolved;
    if (!GetPathArguments(info, 0, &args) || !ResolvePaths(info.Env(), *ctx, args, &resolved)) {
        return info.Env().Undefined();
    }
    return Napi::String::New(info.Env(), resolved);
}

Napi::Value PathRelative(const Napi::CallbackInfo& info) {
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    std::vector<std::string> args;
    std::string relative;
    if (!GetPathArguments(info, 2, &args) ||
        !RelativePath(info.Env(), *ctx, args[0], args[1], &relative)) {
        return info.Env().Undefined();
    }
    return Napi::String::New(info.Env(), relative);
}

// https://nodejs.org/api/path.html
void RegisterPath(Napi::Env env, PolyfillContext* ctx) {
    Napi::Object path = Napi::Object::New(env);
    path.Set("dirname", Napi::Function::New(env, PathDirname, "dirname"));
    path.Set("join", Napi::Function::New(env, PathJoin, "join"));
    path.Set("normalize", Napi::Function::New(env, PathNormalize, "normalize"));
    path.Set("relative", Napi::Function::New(env, PathRelative, "relative", ctx));
    path.Set("resolve", Napi::Function::New(env, PathResolve, "resolve", ctx));
    path.Set("sep", Napi::String::New(env, std::string(1, kPreferredSeparator)));
    env.Global().Set("_path_polyfill", path);
}

// ---------------------------------------------------------------------------
// process
// ---------------------------------------------------------------------------

Napi::Value Cwd(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    const auto* ctx = static_cast<PolyfillContext*>(info.Data());
    // The working directory is the one path the runtime is not handed by its caller, so it is also
    // the one that can go wrong without anybody having asked for anything unusual. Everything
    // resolve() produces is built on it, so CurrentDirectory() throws rather than return a string
    // that would quietly contaminate every path derived from it.
    std::string cwd;
    if (!CurrentDirectory(env, *ctx, &cwd)) {
        return env.Undefined();
    }
    return Napi::String::New(env, cwd);
}

Napi::Value Exit(const Napi::CallbackInfo& info) {
    auto* ctx = static_cast<PolyfillContext*>(info.Data());
    int32_t code = 0;
    if (info.Length() > 0 && info[0].IsNumber()) {
        code = info[0].As<Napi::Number>().Int32Value();
    }
    ctx->loop.Stop(code);

    // Unwind the running JavaScript frames with an uncatchable termination exception so execution
    // does not continue after process.exit().
    napi_env c_env = info.Env();
    reinterpret_cast<napi_env__*>(c_env)->isolate->TerminateExecution();
    return info.Env().Undefined();
}

// https://nodejs.org/api/process.html#processabort
[[noreturn]] void Abort(const Napi::CallbackInfo&) {
    std::abort();
}

Napi::Value HrtimeBigint(const Napi::CallbackInfo& info) {
    auto now = std::chrono::steady_clock::now().time_since_epoch();
    int64_t nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
    return Napi::BigInt::New(info.Env(), nanos);
}

// https://nodejs.org/api/stream.html#writablewritechunk-encoding-callback
//
// write() returns whether the caller may continue writing immediately, or should wait for a
// 'drain' event because the stream buffered the chunk. These writes go straight to the underlying
// stream and buffer nothing, so the answer is always true.
Napi::Value StdoutWrite(const Napi::CallbackInfo& info) {
    if (info.Length() > 0) {
        std::cout << info[0].ToString().Utf8Value() << std::flush;
    }
    return Napi::Boolean::New(info.Env(), true);
}

Napi::Value StderrWrite(const Napi::CallbackInfo& info) {
    if (info.Length() > 0) {
        std::clog << info[0].ToString().Utf8Value() << std::flush;
    }
    return Napi::Boolean::New(info.Env(), true);
}

// https://nodejs.org/api/process.html
void RegisterProcess(Napi::Env env, const PolyfillOptions& options, PolyfillContext* ctx) {
    Napi::Object process = Napi::Object::New(env);
    process.Set("cwd", Napi::Function::New(env, Cwd, "cwd", ctx));
    process.Set("exit", Napi::Function::New(env, Exit, "exit", ctx));
    process.Set("abort", Napi::Function::New(env, Abort, "abort"));

    Napi::Object hrtime = Napi::Object::New(env);
    hrtime.Set("bigint", Napi::Function::New(env, HrtimeBigint, "bigint"));
    process.Set("hrtime", hrtime);

    // Libraries detect a Node-like environment via `process?.versions?.node !== undefined`; the
    // version string itself is not inspected.
    Napi::Object versions = Napi::Object::New(env);
    versions.Set("node", Napi::String::New(env, "0.0.0"));
    process.Set("versions", versions);

    Napi::Object env_obj = Napi::Object::New(env);
    if (auto [dawn_flags, is_set] = dawn::GetEnvironmentVar("DAWN_FLAGS"); is_set) {
        env_obj.Set("DAWN_FLAGS", Napi::String::New(env, dawn_flags));
    }
    process.Set("env", env_obj);

    Napi::Array argv_array = Napi::Array::New(env, options.argv.size());
    for (uint32_t i = 0; i < options.argv.size(); ++i) {
        argv_array.Set(i, Napi::String::New(env, options.argv[i]));
    }
    process.Set("argv", argv_array);

    Napi::Object stdout_obj = Napi::Object::New(env);
    stdout_obj.Set("write", Napi::Function::New(env, StdoutWrite));
    process.Set("stdout", stdout_obj);

    Napi::Object stderr_obj = Napi::Object::New(env);
    stderr_obj.Set("write", Napi::Function::New(env, StderrWrite));
    process.Set("stderr", stderr_obj);

    // `process` owns the context: this releases it once the object is collected.
    process.AddFinalizer(DeletePolyfillContext, ctx);

    env.Global().Set("process", process);
}

// ---------------------------------------------------------------------------
// Scheduling / Timers (setImmediate, setTimeout, clearTimeout)
// ---------------------------------------------------------------------------

// Captures the arguments a timer callback is to be called with: everything from `first` onwards.
std::vector<Napi::Reference<Napi::Value>> CaptureArgs(const Napi::CallbackInfo& info,
                                                      size_t first) {
    std::vector<Napi::Reference<Napi::Value>> args;
    args.reserve(info.Length() > first ? info.Length() - first : 0);
    for (size_t i = first; i < info.Length(); ++i) {
        args.push_back(Napi::Persistent(info[i]));
    }
    return args;
}

// Reads captured arguments back out for a call.
std::vector<napi_value> ResolveArgs(const std::vector<Napi::Reference<Napi::Value>>& args) {
    std::vector<napi_value> values;
    values.reserve(args.size());
    for (const auto& arg : args) {
        values.push_back(arg.Value());
    }
    return values;
}

// Implements setImmediate(). Node runs these in the check phase of its event loop, so the task is
// handed to the embedder rather than run here; the embedder decides when the check phase comes
// around. V8 has no queue of its own to use instead: macrotasks are not an ECMAScript concept, and
// the only queue V8 owns is the microtask queue that backs promise reactions.
//
// Node returns an Immediate object (with ref(), unref() and clearImmediate() cancellation). The
// loop has no cancellation for check-phase tasks and nothing in the CTS or Dawn bindings uses the
// return value, so this returns undefined and clearImmediate is not registered.
Napi::Value SetImmediate(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    if (info.Length() < 1 || !info[0].IsFunction()) {
        Napi::TypeError::New(env, "Function expected for setImmediate")
            .ThrowAsJavaScriptException();
        return env.Undefined();
    }

    auto* ctx = static_cast<PolyfillContext*>(info.Data());
    Napi::FunctionReference fn = Napi::Persistent(info[0].As<Napi::Function>());
    // Any arguments beyond the callback are forwarded to it.
    std::vector<Napi::Reference<Napi::Value>> args = CaptureArgs(info, 1);
    ctx->loop.PostTask(
        [fn = std::move(fn), args = std::move(args)]() mutable { fn.Call(ResolveArgs(args)); });
    return env.Undefined();
}

// Converts a JavaScript delay, which is a possibly fractional count of milliseconds, to the
// duration the loop measures in.
EventLoop::Duration DelayFromMilliseconds(double delay_ms) {
    return std::chrono::duration_cast<EventLoop::Duration>(
        std::chrono::duration<double, std::milli>(delay_ms));
}

// Implements setTimeout(). Returns the EventLoop::TimerId as a number to pass to clearTimeout().
// Node.js returns a Timeout object, but a numeric handle - as on the web - is all the CTS uses.
Napi::Value SetTimeout(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    if (info.Length() < 1 || !info[0].IsFunction()) {
        Napi::TypeError::New(env, "Function expected for setTimeout").ThrowAsJavaScriptException();
        return env.Undefined();
    }

    double delay_ms = 0.0;
    if (info.Length() > 1 && info[1].IsNumber()) {
        delay_ms = info[1].As<Napi::Number>().DoubleValue();
    }
    // Match the web platform: negative, NaN and missing delays are treated as zero.
    if (!(delay_ms > 0.0)) {
        delay_ms = 0.0;
    }

    auto* ctx = static_cast<PolyfillContext*>(info.Data());
    Napi::FunctionReference fn = Napi::Persistent(info[0].As<Napi::Function>());
    std::vector<Napi::Reference<Napi::Value>> args = CaptureArgs(info, 2);
    const EventLoop::TimerId id = ctx->loop.PostDelayedTask(
        [fn = std::move(fn), args = std::move(args)]() mutable { fn.Call(ResolveArgs(args)); },
        DelayFromMilliseconds(delay_ms));
    return Napi::Number::New(env, static_cast<double>(id));
}

// Implements clearTimeout(). Clearing an unknown or already-fired handle is not an error, as
// required by the standard.
Napi::Value ClearTimeout(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    auto* ctx = static_cast<PolyfillContext*>(info.Data());
    if (ctx == nullptr || info.Length() < 1 || !info[0].IsNumber()) {
        return env.Undefined();
    }

    const auto id = static_cast<EventLoop::TimerId>(info[0].As<Napi::Number>().DoubleValue());
    ctx->loop.CancelDelayedTask(id);
    return env.Undefined();
}

void RegisterTimers(Napi::Env env, PolyfillContext* ctx) {
    env.Global().Set("setImmediate", Napi::Function::New(env, SetImmediate, "setImmediate", ctx));
    env.Global().Set("setTimeout", Napi::Function::New(env, SetTimeout, "setTimeout", ctx));
    env.Global().Set("clearTimeout", Napi::Function::New(env, ClearTimeout, "clearTimeout", ctx));
}

// ---------------------------------------------------------------------------
// performance
// ---------------------------------------------------------------------------

Napi::Value PerformanceNow(const Napi::CallbackInfo& info) {
    auto* ctx = static_cast<PolyfillContext*>(info.Data());
    auto now = std::chrono::steady_clock::now();
    double millis = 0.0;
    if (ctx != nullptr) {
        millis = std::chrono::duration<double, std::milli>(now - ctx->start_time).count();
    }
    return Napi::Number::New(info.Env(), millis);
}

// https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
void RegisterPerformance(Napi::Env env, PolyfillContext* ctx) {
    Napi::Object performance = Napi::Object::New(env);
    performance.Set("now", Napi::Function::New(env, PerformanceNow, "now", ctx));
    env.Global().Set("performance", performance);
}

// ---------------------------------------------------------------------------
// TextEncoder
// ---------------------------------------------------------------------------

void TextEncoderConstructor(const Napi::CallbackInfo&) {}

// Implements TextEncoder.prototype.encode(). V8 holds strings as UTF-16, and its UTF-8 conversion
// already implements the WHATWG encode algorithm: unpaired surrogates become U+FFFD rather than an
// error.
Napi::Value EncodeUtf8(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    std::string utf8;
    if (info.Length() > 0 && !info[0].IsUndefined()) {
        utf8 = info[0].ToString().Utf8Value();
    }
    Napi::Uint8Array out = Napi::Uint8Array::New(env, utf8.size());
    std::ranges::copy(utf8, out.Data());
    return out;
}

void RegisterTextEncoder(Napi::Env env) {
    // Only encode() is implemented.
    Napi::Function ctor = Napi::Function::New(env, TextEncoderConstructor, "TextEncoder");
    ctor.Get("prototype")
        .As<Napi::Object>()
        .Set("encode", Napi::Function::New(env, EncodeUtf8, "encode"));
    env.Global().Set("TextEncoder", ctor);
}

// ---------------------------------------------------------------------------
// require
// ---------------------------------------------------------------------------

std::optional<Napi::Value> TryGetBuiltinModule(Napi::Env env, std::string_view specifier) {
    if (specifier.starts_with("node:")) {
        specifier.remove_prefix(5);
    }
    Napi::Object global = env.Global();
    if (specifier == "fs") {
        return global.Get("_fs_polyfill");
    }
    if (specifier == "path") {
        return global.Get("_path_polyfill");
    }
    if (specifier == "process") {
        return global.Get("process");
    }
    if (specifier == "perf_hooks") {
        Napi::Object perf_hooks = Napi::Object::New(env);
        perf_hooks.Set("performance", global.Get("performance"));
        return perf_hooks;
    }
    // `dawn.node` is statically linked into the runner binary and registered on
    // `globalThis._webgpu_module`.
    if (std::filesystem::path(specifier).filename() == "dawn.node") {
        return global.Get("_webgpu_module");
    }
    return std::nullopt;
}

// Returns true if `specifier` is a CommonJS bare package name (such as "ansi-colors" or
// "pkg/subpath") rather than a relative or absolute filesystem path.
bool IsBarePackageName(std::string_view specifier) {
    // If `specifier` starts with an explicit relative path (like `.` or `..`) or a root slash, it
    // is not a bare package name.
    static const std::regex kPathPrefix(R"(^(\.\.?$|\.*[/\\]))");
    if (std::regex_search(specifier.begin(), specifier.end(), kPathPrefix)) {
        return false;
    }
    return !std::filesystem::path(specifier).is_absolute();
}

// Returns a JavaScript function that takes parameters `(exports, require, module, __filename,
// __dirname)` and runs `source` as the body. `filename` is the name of the file the source came
// from. Errors will be reported using their line number in `source` in the given `filename`.
//
// Note, this is different than `napi_run_script()`, which immediately executes a top-level script
// and is not concerned with the file and line number for reporting errors, which is why they have
// different implementations.
Napi::Function CompileModuleFunction(Napi::Env env,
                                     const std::string& source,
                                     const std::string& filename) {
    napi_env c_env = env;
    v8::Isolate* isolate = c_env->isolate;
    v8::Local<v8::Context> context = c_env->GetContext();

    v8::Local<v8::String> v8_source =
        dawn::napi_v8::ToV8(Napi::String::New(env, source)).As<v8::String>();
    v8::Local<v8::String> v8_origin =
        dawn::napi_v8::ToV8(Napi::String::New(env, filename)).As<v8::String>();

    v8::Local<v8::String> params[] = {
        v8::String::NewFromUtf8Literal(isolate, "exports"),
        v8::String::NewFromUtf8Literal(isolate, "require"),
        v8::String::NewFromUtf8Literal(isolate, "module"),
        v8::String::NewFromUtf8Literal(isolate, "__filename"),
        v8::String::NewFromUtf8Literal(isolate, "__dirname"),
    };

    v8::ScriptOrigin origin(v8_origin);
    v8::ScriptCompiler::Source script_source(v8_source, origin);
    v8::MaybeLocal<v8::Function> function;
    v8::Local<v8::Value> exception;
    {
        v8::TryCatch try_catch(isolate);
        function =
            v8::ScriptCompiler::CompileFunction(context, &script_source, std::size(params), params);
        if (function.IsEmpty() || try_catch.HasCaught()) {
            exception = try_catch.Exception();
        }
    }
    if (!exception.IsEmpty()) {
        napi_throw(c_env, dawn::napi_v8::ToNapi(exception));
        return Napi::Function();
    }

    return Napi::Function(env, dawn::napi_v8::ToNapi(function.ToLocalChecked()));
}

Napi::Function MakeRequire(Napi::Env env, PolyfillContext* ctx, std::string from_dir);

Napi::Value LoadModule(Napi::Env env, PolyfillContext* ctx, const std::string& resolved_path) {
    auto cached = ctx->module_cache.find(resolved_path);
    if (cached != ctx->module_cache.end()) {
        return cached->second.Value().Get("exports");
    }

    std::string content;
    if (!ReadFileUtf8(env, *ctx, resolved_path, &content)) {
        return env.Undefined();
    }

    std::string dirname = DirnamePath(resolved_path);
    Napi::Object module = Napi::Object::New(env);
    Napi::Object exports = Napi::Object::New(env);
    module.Set("exports", exports);
    module.Set("id", Napi::String::New(env, resolved_path));
    module.Set("filename", Napi::String::New(env, resolved_path));
    module.Set("path", Napi::String::New(env, dirname));
    module.Set("loaded", Napi::Boolean::New(env, false));

    // Cache before running the module body so circular require() calls receive the in-progress
    // exports object rather than re-entering LoadModule.
    ctx->module_cache.emplace(resolved_path, Napi::Persistent(module));

    Napi::Function fn = CompileModuleFunction(env, content, resolved_path);
    if (fn.IsEmpty()) {
        ctx->module_cache.erase(resolved_path);
        return env.Undefined();
    }

    Napi::Function local_require = MakeRequire(env, ctx, dirname);
    Napi::Value call_result =
        fn.Call({exports, local_require, module, Napi::String::New(env, resolved_path),
                 Napi::String::New(env, dirname)});
    if (call_result.IsEmpty()) {
        ctx->module_cache.erase(resolved_path);
        return env.Undefined();
    }

    module.Set("loaded", Napi::Boolean::New(env, true));
    return module.Get("exports");
}

Napi::Value Require(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    if (info.Length() < 1 || !info[0].IsString()) {
        Napi::TypeError::New(env, "String expected for module specifier")
            .ThrowAsJavaScriptException();
        return env.Undefined();
    }

    std::string specifier = info[0].As<Napi::String>().Utf8Value();
    if (RejectUncPath(env, specifier)) {
        return env.Undefined();
    }

    if (std::optional<Napi::Value> builtin = TryGetBuiltinModule(env, specifier)) {
        return *builtin;
    }

    // Bare package names outside `TryGetBuiltinModule` are not resolved against `node_modules`.
    if (IsBarePackageName(specifier)) {
        Napi::Error::New(env, "Cannot find module '" + specifier + "'")
            .ThrowAsJavaScriptException();
        return env.Undefined();
    }

    auto* req_ctx = static_cast<PolyfillContext::RequireContext*>(info.Data());
    std::string from_dir = req_ctx->from_dir;
    if (from_dir.empty() && !CurrentDirectory(env, *req_ctx->ctx, &from_dir)) {
        return env.Undefined();
    }

    std::string resolved;
    if (!ResolvePaths(env, *req_ctx->ctx, {from_dir, specifier}, &resolved)) {
        return env.Undefined();
    }

    return LoadModule(env, req_ctx->ctx, resolved);
}

Napi::Function MakeRequire(Napi::Env env, PolyfillContext* ctx, std::string from_dir) {
    auto& req_ctx =
        ctx->require_contexts.emplace_back(std::make_unique<PolyfillContext::RequireContext>(
            PolyfillContext::RequireContext{ctx, std::move(from_dir)}));
    return Napi::Function::New(env, Require, "require", req_ctx.get());
}

// https://nodejs.org/api/modules.html
void RegisterRequire(Napi::Env env, PolyfillContext* ctx) {
    env.Global().Set("require", MakeRequire(env, ctx, ""));
}

// ---------------------------------------------------------------------------
// bootstrap
// ---------------------------------------------------------------------------

const char* kBootstrapScript = R"bootstrap(
(function() {
    // DOM / Web Event Globals. Only the fields and methods used by Dawn's bindings and the CTS are
    // implemented.
    class Event {
        constructor(type, eventInitDict) {
            this.type = type;
            this.cancelable = Boolean(eventInitDict && eventInitDict.cancelable);
            this.defaultPrevented = false;
        }
        preventDefault() {
            if (this.cancelable) {
                this.defaultPrevented = true;
            }
        }
    }

    class EventTarget {
        constructor() {
            // Keyed by `type` alone (not `(type, capture)`) so dispatchEvent runs listeners in
            // registration order. There will be at most 2 entries per listener and type (capture
            // true and false).
            this._listeners = {};
        }

        addEventListener(type, listener, options) {
            if (!listener) {
                return;
            }

            if (!this._listeners[type]) {
                this._listeners[type] = [];
            }

            const capture = typeof options === 'boolean'
                ? options : Boolean(options && options.capture);
            if (this._listeners[type].some(
                    e => e.listener === listener && e.capture === capture)) {
                return;
            }

            const once = Boolean(options && typeof options === 'object' && options.once);
            this._listeners[type].push({ listener, once, capture });
        }

        removeEventListener(type, listener, options) {
            if (!this._listeners[type]) {
                return;
            }

            const capture = typeof options === 'boolean'
                ? options : Boolean(options && options.capture);

            this._listeners[type] = this._listeners[type].filter(
                e => e.listener !== listener || e.capture !== capture);
        }

        dispatchEvent(event) {
            const type = event.type;

            // Copied, since a listener may add or remove listeners while it runs - a 'once'
            // listener removes itself before being invoked.
            const entries = this._listeners[type] ? this._listeners[type].slice() : [];

            for (const entry of entries) {
                if (entry.once) {
                    this.removeEventListener(type, entry.listener, entry.capture);
                }

                const listener = entry.listener;
                if (typeof listener === 'function') {
                    listener.call(this, event);
                } else if (listener && typeof listener.handleEvent === 'function') {
                    listener.handleEvent(event);
                }
            }

            // A dispatch reports whether the default action should still be taken.
            return !event.defaultPrevented;
        }
    }

    class DOMException extends Error {
        constructor(message, name) {
            super(message);
            this.name = name || 'Error';
        }
    }

    class CustomEvent extends Event {}

    class MessageEvent extends Event {
        constructor(type, eventInitDict) {
            super(type, eventInitDict);
            this.data = eventInitDict ? eventInitDict.data : undefined;
        }
    }

    globalThis.Event = Event;
    globalThis.CustomEvent = CustomEvent;
    globalThis.EventTarget = EventTarget;
    globalThis.DOMException = DOMException;
    globalThis.MessageEvent = MessageEvent;

    // queueMicrotask
    if (typeof globalThis.queueMicrotask !== 'function') {
        globalThis.queueMicrotask = function(callback) {
            Promise.resolve().then(callback);
        };
    }

    // The callback and promise forms of fs, over the native synchronous calls. Deferring to a
    // microtask is what makes them asynchronous; the work itself still blocks.
    // https://nodejs.org/api/fs.html
    const fs = globalThis._fs_polyfill;

    fs.readFile = function(path, options, callback) {
        if (typeof options === 'function') {
            callback = options;
            options = undefined;
        }
        Promise.resolve().then(() => {
            let data;
            try {
                data = fs.readFileSync(path, options);
            } catch (err) {
                callback(err);
                return;
            }
            callback(null, data);
        });
    };

    fs.promises = {
        readdir: (path) => Promise.resolve().then(() => fs.readdirSync(path)),
        stat: (path) => Promise.resolve().then(() => fs.statSync(path)),
        readFile: (path, options) => Promise.resolve().then(() => fs.readFileSync(path, options)),
    };
})();
)bootstrap";

// Runs the JavaScript half of the polyfills, for the globals that are simpler to express in
// script than to assemble through the C++ API.
void RunBootstrapScript(Napi::Env env) {
    napi_value script_src;
    napi_create_string_utf8(env, kBootstrapScript, NAPI_AUTO_LENGTH, &script_src);
    napi_value result;
    napi_run_script(env, script_src, &result);
}

}  // namespace

void RegisterPolyfills(Napi::Env env, EventLoop& loop, const PolyfillOptions& options) {
    auto* ctx = new PolyfillContext(loop, options);

    RegisterConsole(env);
    RegisterFs(env, ctx);
    RegisterPath(env, ctx);
    RegisterProcess(env, options, ctx);
    RegisterTimers(env, ctx);
    RegisterPerformance(env, ctx);
    RegisterTextEncoder(env);
    RegisterRequire(env, ctx);
    RunBootstrapScript(env);
}

}  // namespace dawn::node::standalone
