// 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 <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"

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)) {}

    EventLoop& loop;
    PolyfillOptions options;
    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
// ---------------------------------------------------------------------------

// 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;
}

bool ReadFileUtf8(Napi::Env env, const std::string& path, std::string* out) {
    std::ifstream file;
    std::streamoff offset = 0;
    if (!OpenAndSizeFile(env, path, &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();
    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, path, &content)) {
            return env.Undefined();
        }
        return Napi::String::New(env, content);
    }

    std::ifstream file;
    std::streamoff offset = 0;
    if (!OpenAndSizeFile(env, path, &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 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();
    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();
    }
    std::error_code ec;
    bool exists = std::filesystem::exists(path, ec);
    return Napi::Boolean::New(env, exists && !ec);
}

Napi::Value ReaddirSync(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    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();
    }

    std::error_code ec;
    std::filesystem::directory_iterator it(path, 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();
    std::string path;
    Encoding encoding = Encoding::kNone;
    if (!GetPathArgument(info, &path) || !GetEncodingOption(info, &encoding)) {
        return env.Undefined();
    }

    std::error_code ec;
    std::filesystem::file_status status = std::filesystem::status(path, ec);
    if (ec || !std::filesystem::exists(status)) {
        Napi::Error::New(env, "Failed to stat: " + path).ThrowAsJavaScriptException();
        return env.Undefined();
    }

    // The answer is settled here, so each predicate is just the constant it will always return.
    Napi::Object stats = Napi::Object::New(env);
    stats.Set(
        "isFile",
        Napi::Function::New(
            env, std::filesystem::is_regular_file(status) ? ReturnTrue : ReturnFalse, "isFile"));
    stats.Set(
        "isDirectory",
        Napi::Function::New(env, std::filesystem::is_directory(status) ? 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) {
    Napi::Object fs = Napi::Object::New(env);
    fs.Set("readFileSync", Napi::Function::New(env, ReadFileSync, "readFileSync"));
    fs.Set("existsSync", Napi::Function::New(env, ExistsSync, "existsSync"));
    fs.Set("readdirSync", Napi::Function::New(env, ReaddirSync, "readdirSync"));
    fs.Set("statSync", Napi::Function::New(env, StatSync, "statSync"));
    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.
bool CurrentDirectory(Napi::Env env, std::string* out) {
    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 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, &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);
        }
    }

    // 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 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, {from}, &from_resolved) || !ResolvePaths(env, {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) {
    std::vector<std::string> args;
    std::string resolved;
    if (!GetPathArguments(info, 0, &args) || !ResolvePaths(info.Env(), args, &resolved)) {
        return info.Env().Undefined();
    }
    return Napi::String::New(info.Env(), resolved);
}

Napi::Value PathRelative(const Napi::CallbackInfo& info) {
    std::vector<std::string> args;
    std::string relative;
    if (!GetPathArguments(info, 2, &args) ||
        !RelativePath(info.Env(), 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) {
    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"));
    path.Set("resolve", Napi::Function::New(env, PathResolve, "resolve"));
    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();
    // 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, &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();
}

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"));
    process.Set("exit", Napi::Function::New(env, Exit, "exit", ctx));

    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, 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, &from_dir)) {
        return env.Undefined();
    }

    std::string resolved;
    if (!ResolvePaths(env, {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);
    RegisterPath(env);
    RegisterProcess(env, options, ctx);
    RegisterTimers(env, ctx);
    RegisterPerformance(env, ctx);
    RegisterTextEncoder(env);
    RegisterRequire(env, ctx);
    RunBootstrapScript(env);
}

}  // namespace dawn::node::standalone
