// 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/napi_v8/napi_v8.h"

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <utility>

#include "src/utils/assert.h"
#include "src/utils/compiler.h"

namespace {

// Hands any exception recorded by napi_throw() to V8 when a native callback returns to JavaScript,
// and clears env->last_exception so it does not stay pending for later calls. Returns true if an
// exception was delivered.
bool DeliverPendingException(napi_env env) {
    if (env->last_exception.IsEmpty()) {
        return false;
    }
    v8::Local<v8::Value> exception = env->last_exception.Get(env->isolate);
    env->last_exception.Reset();
    if (!env->isolate->IsExecutionTerminating()) {
        env->isolate->ThrowException(exception);
    }
    return true;
}

}  // namespace

napi_ref__::napi_ref__(napi_env e,
                       v8::Local<v8::Value> val,
                       uint32_t count,
                       void* native_obj,
                       napi_finalize fin_cb,
                       void* fin_hint,
                       bool wrap_ref,
                       bool userland_ref)
    : env(e),
      handle(e->isolate, val),
      ref_count(count),
      native_object(native_obj),
      finalize_cb(fin_cb),
      finalize_hint(fin_hint),
      is_wrap_ref(wrap_ref),
      is_userland_ref(userland_ref) {
    if (finalize_cb != nullptr) {
        env->finalizable_references.insert(this);
    }
    if (ref_count == 0) {
        SetWeak();
    }
}

napi_ref__::~napi_ref__() {
    env->pending_finalizers.erase(this);
    ClearFinalizer();
    handle.Reset();
}

void napi_ref__::SetWeak() {
    handle.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
}

void napi_ref__::ClearWeak() {
    handle.ClearWeak<void>();
}

void napi_env__::DrainFinalizers() {
    while (!pending_finalizers.empty()) {
        auto it = pending_finalizers.begin();
        napi_ref__* ref = *it;
        pending_finalizers.erase(it);
        if (ref->finalize_cb == nullptr) {
            continue;
        }

        napi_finalize cb = ref->finalize_cb;
        void* native_object = ref->native_object;
        void* finalize_hint = ref->finalize_hint;
        ref->ClearFinalizer();

        ClearLastError();
        cb(this, native_object, finalize_hint);
        if (DeliverPendingException(this)) {
            break;
        }
    }
}

namespace {

void DrainFinalizersV8Callback(const v8::FunctionCallbackInfo<v8::Value>& info) {
    auto* env = static_cast<napi_env>(
        info.DataV2().As<v8::External>()->Value(v8::kExternalPointerTypeTagDefault));
    env->finalizer_drain_scheduled = false;
    env->DrainFinalizers();
}

}  // namespace

// Node-API `napi_finalize` callbacks (https://nodejs.org/api/n-api.html#napi_finalize) receive a
// `napi_env` and are permitted to allocate JavaScript objects and call into the engine. However,
// V8's weak handle callback (`v8::PersistentBase::SetWeak`,
// https://chromium.googlesource.com/v8/v8/+/refs/heads/main/include/v8-persistent-handle.h) runs
// synchronously inside V8's atomic garbage collection pause while the heap is being swept. As
// documented on `v8::WeakCallbackInfo::SetSecondPassCallback`
// (https://chromium.googlesource.com/v8/v8/+/refs/heads/main/include/v8-weak-callback-info.h), the
// initial callback passed to `SetWeak` must call `Reset()` on the weak handle and is prohibited
// from making any other V8 API calls or allocating on the heap; any further work must be deferred
// via `SetSecondPassCallback()`.
//
// Finalization therefore runs in three stages:
//   1. `WeakCallback` (during the GC atomic pause): resets `self->handle`, appends `self` to
//      `env->pending_finalizers`, and registers `PostGarbageCollectionCallback` via
//      `SetSecondPassCallback()` once per GC cycle.
//   2. `PostGarbageCollectionCallback` (after the GC pause finishes): runs once V8's heap is
//      consistent again (`AllowGarbageCollection`). It schedules a single
//      `DrainFinalizersV8Callback` task onto `globalThis.setImmediate` (matching Node.js's
//      `v8impl::Reference::WeakCallback` -> `SetImmediate` ordering so finalizers run in the event
//      loop's check phase rather than inside `Heap::CollectGarbage()`, where V8 prohibits
//      arbitrary JavaScript execution).
//   3. `DrainFinalizers` (on the event loop): invokes each queued `napi_finalize` callback in FIFO
//      order.
void napi_ref__::WeakCallback(const v8::WeakCallbackInfo<napi_ref__>& data) {
    napi_ref__* self = data.GetParameter();
    self->handle.Reset();
    if (self->finalize_cb != nullptr) {
        napi_env env = self->env;
        env->pending_finalizers.insert(self);
        if (!env->post_gc_callback_scheduled && !env->finalizer_drain_scheduled) {
            env->post_gc_callback_scheduled = true;
            data.SetSecondPassCallback(&napi_ref__::PostGarbageCollectionCallback);
        }
    }
}

// Invoked by V8 (`GlobalHandles::InvokeSecondPassPhantomCallbacks`) after the garbage collection
// cycle completes (`Heap::NOT_IN_GC`), when V8 heap allocations are permitted again. Schedules
// `DrainFinalizers` onto `globalThis.setImmediate`.
void napi_ref__::PostGarbageCollectionCallback(const v8::WeakCallbackInfo<napi_ref__>& data) {
    napi_env env = data.GetParameter()->env;
    env->post_gc_callback_scheduled = false;
    if (env->pending_finalizers.empty() || env->finalizer_drain_scheduled) {
        return;
    }

    // V8 lifts `DisallowGarbageCollection` before invoking second-pass callbacks, but leaves
    // `DisallowJavascriptExecution` active on the isolate; re-enable JS execution so we can call
    // `globalThis.setImmediate` to enqueue `DrainFinalizersV8Callback`.
    v8::Isolate::AllowJavascriptExecutionScope allow_js(env->isolate);
    v8::HandleScope handle_scope(env->isolate);
    v8::Local<v8::Context> ctx = env->GetContext();
    v8::Context::Scope context_scope(ctx);

    // `napi_v8` does not depend on `standalone::EventLoop`, so it schedules the batch drain once
    // per GC cycle through `globalThis.setImmediate`, and then drains all queued references in C++
    // inside `DrainFinalizers()`.
    v8::Local<v8::String> key = v8::String::NewFromUtf8Literal(env->isolate, "setImmediate");
    v8::Local<v8::Value> set_immediate_val;
    [[maybe_unused]] bool has_set_immediate =
        ctx->Global()->Get(ctx, key).ToLocal(&set_immediate_val) && set_immediate_val->IsFunction();
    DAWN_ASSERT(has_set_immediate);

    v8::Local<v8::External> ext =
        v8::External::New(env->isolate, env, v8::kExternalPointerTypeTagDefault);
    v8::Local<v8::Function> drain_fn;
    [[maybe_unused]] bool has_drain_fn =
        v8::Function::New(ctx, DrainFinalizersV8Callback, ext).ToLocal(&drain_fn);
    DAWN_ASSERT(has_drain_fn);

    env->finalizer_drain_scheduled = true;
    v8::Local<v8::Value> arg = drain_fn;
    (void)set_immediate_val.As<v8::Function>()->Call(ctx, ctx->Global(), 1, &arg);
}

namespace {

// Validates that the environment pointer and all required argument pointers are non-null.
// Clears any previous error on the environment if the environment is valid.
template <typename... Args>
bool ValidateArgs(napi_env env, Args... args) {
    if (env == nullptr) {
        return false;
    }
    env->ClearLastError();
    if (((args == nullptr) || ...)) {
        env->SetLastError(napi_invalid_arg, "Invalid argument: null pointer");
        return false;
    }
    return true;
}

// Converts a JavaScript value into a numeric primitive type using a conversion callback.
template <typename V8Type, typename OutType, typename ConvertFn>
napi_status ExtractNumber(napi_env env,
                          napi_value value,
                          OutType* result,
                          const char* error_message,
                          ConvertFn&& convert) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::MaybeLocal<V8Type> maybe_num = convert(dawn::napi_v8::ToV8(value), env->GetContext());
    if (maybe_num.IsEmpty()) {
        return env->SetLastError(napi_number_expected, error_message);
    }
    *result = static_cast<OutType>(maybe_num.ToLocalChecked()->Value());
    return napi_ok;
}

// Coerces a JavaScript value into another JavaScript value type.
template <typename V8Type, typename ConvertFn>
napi_status CoerceTo(napi_env env,
                     napi_value value,
                     napi_value* result,
                     const char* error_message,
                     ConvertFn&& convert) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::MaybeLocal<V8Type> maybe_val = convert(dawn::napi_v8::ToV8(value), env->GetContext());
    if (maybe_val.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, error_message);
    }
    *result = dawn::napi_v8::ToNapi(maybe_val.ToLocalChecked());
    return napi_ok;
}

// Validates and extracts a v8::Object and its associated Context.
napi_status UnwrapObject(napi_env env,
                         napi_value object,
                         v8::Local<v8::Object>* out_obj,
                         v8::Local<v8::Context>* out_ctx) {
    *out_ctx = env->GetContext();
    v8::MaybeLocal<v8::Object> maybe_obj = dawn::napi_v8::ToV8(object)->ToObject(*out_ctx);
    if (maybe_obj.IsEmpty()) {
        return env->SetLastError(napi_object_expected, "An object was expected");
    }
    *out_obj = maybe_obj.ToLocalChecked();
    return napi_ok;
}

// Creates an internalized V8 string from a UTF-8 C string.
napi_status CreateInternalizedName(napi_env env,
                                   const char* utf8name,
                                   v8::Local<v8::String>* out_name) {
    if (!ValidateArgs(env, utf8name)) {
        return napi_invalid_arg;
    }
    v8::MaybeLocal<v8::String> maybe_name =
        v8::String::NewFromUtf8(env->isolate, utf8name, v8::NewStringType::kInternalized);
    if (maybe_name.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to create property name");
    }
    *out_name = maybe_name.ToLocalChecked();
    return napi_ok;
}

// Generic property setter supporting Local<Value> names or uint32_t indices.
template <typename NameType>
napi_status WriteProperty(napi_env env,
                          napi_value object,
                          NameType name,
                          napi_value value,
                          const char* error_message) {
    if (!ValidateArgs(env, object, value)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Object> obj;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapObject(env, object, &obj, &ctx);
    if (status != napi_ok) {
        return status;
    }
    v8::Maybe<bool> res = obj->Set(ctx, name, dawn::napi_v8::ToV8(value));
    if (!res.FromMaybe(false)) {
        return env->SetLastError(napi_generic_failure, error_message);
    }
    return napi_ok;
}

// Generic property getter supporting Local<Value> names or uint32_t indices.
template <typename NameType>
napi_status ReadProperty(napi_env env,
                         napi_value object,
                         NameType name,
                         napi_value* result,
                         const char* error_message) {
    if (!ValidateArgs(env, object, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Object> obj;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapObject(env, object, &obj, &ctx);
    if (status != napi_ok) {
        return status;
    }
    v8::MaybeLocal<v8::Value> val = obj->Get(ctx, name);
    if (val.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, error_message);
    }
    *result = dawn::napi_v8::ToNapi(val.ToLocalChecked());
    return napi_ok;
}

// Generic property existence check supporting Local<Value> names or uint32_t indices.
template <typename NameType>
napi_status QueryProperty(napi_env env,
                          napi_value object,
                          NameType name,
                          bool* result,
                          const char* error_message) {
    if (!ValidateArgs(env, object, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Object> obj;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapObject(env, object, &obj, &ctx);
    if (status != napi_ok) {
        return status;
    }
    v8::Maybe<bool> has = obj->Has(ctx, name);
    if (has.IsNothing()) {
        return env->SetLastError(napi_generic_failure, error_message);
    }
    *result = has.FromJust();
    return napi_ok;
}

// V8 and Node-API use different callback conventions:
// - V8 callbacks use `void (const v8::FunctionCallbackInfo<v8::Value>&)` and pass user context via
//   an attached `v8::External` value in `v8_info.DataV2()`.
// - Node-API callbacks use `napi_value (*)(napi_env, napi_callback_info)` and retrieve user context
//   via `napi_get_cb_info()`.
//
// `NativeCallbackTrampoline` acts as the universal bridge: it unpacks the persistent
// `CallbackBinding` from the `v8::External`, constructs a lightweight `napi_callback_info__` stack
// wrapper referencing the active V8 callback arguments, executes the target `napi_callback`, and
// forwards the returned `napi_value` back to V8.
void NativeCallbackTrampoline(const v8::FunctionCallbackInfo<v8::Value>& v8_info) {
    v8::Local<v8::External> ext = v8_info.DataV2().As<v8::External>();
    auto* binding = static_cast<CallbackBinding*>(ext->Value(v8::kExternalPointerTypeTagDefault));
    napi_env env = binding->env;

    napi_callback_info__ invocation_info;
    invocation_info.v8_info = &v8_info;
    invocation_info.data = binding->user_data;

    v8::HandleScope scope(env->isolate);
    env->ClearLastError();
    napi_value return_val = binding->callback(env, &invocation_info);
    if (!DeliverPendingException(env) && return_val != nullptr) {
        v8_info.GetReturnValue().Set(dawn::napi_v8::ToV8(return_val));
    }
}

// Base helper to create a `v8::FunctionTemplate` from a v8::Name.
// To ensure the callback function pointer and user data remain valid across the environment's
// lifetime, an internal `CallbackBinding` structure is allocated and stored in
// `env->callback_bindings`. A pointer to this binding is attached to the `v8::FunctionTemplate` as
// a `v8::External`.
napi_status CreateFunctionTemplate(napi_env env,
                                   v8::Local<v8::Name> name,
                                   napi_callback callback,
                                   void* user_data,
                                   v8::Local<v8::FunctionTemplate>* out_template) {
    auto binding = std::make_unique<CallbackBinding>();
    binding->env = env;
    binding->callback = callback;
    binding->user_data = user_data;
    CallbackBinding* binding_ptr = binding.get();
    env->callback_bindings.push_back(std::move(binding));

    v8::Local<v8::External> ext =
        v8::External::New(env->isolate, binding_ptr, v8::kExternalPointerTypeTagDefault);
    auto function_template = v8::FunctionTemplate::New(env->isolate, NativeCallbackTrampoline, ext);
    if (!name.IsEmpty() && name->IsString()) {
        function_template->SetClassName(name.As<v8::String>());
    }
    *out_template = function_template;
    return napi_ok;
}

// UTF-8 string wrapper for CreateFunctionTemplate.
napi_status CreateFunctionTemplate(napi_env env,
                                   const char* utf8name,
                                   size_t length,
                                   napi_callback callback,
                                   void* user_data,
                                   v8::Local<v8::FunctionTemplate>* out_template) {
    v8::Local<v8::Name> name;
    if (utf8name != nullptr) {
        int len = (length == NAPI_AUTO_LENGTH) ? -1 : static_cast<int>(length);
        v8::MaybeLocal<v8::String> v8_name =
            v8::String::NewFromUtf8(env->isolate, utf8name, v8::NewStringType::kInternalized, len);
        if (v8_name.IsEmpty()) {
            return env->SetLastError(napi_generic_failure, "Failed to create function name");
        }
        name = v8_name.ToLocalChecked();
    }
    return CreateFunctionTemplate(env, name, callback, user_data, out_template);
}

// Extracts a property name from a Node-API property descriptor.
napi_status GetDescriptorName(napi_env env,
                              const napi_property_descriptor& desc,
                              v8::Local<v8::Name>* out_name) {
    if (desc.utf8name != nullptr) {
        v8::MaybeLocal<v8::String> name =
            v8::String::NewFromUtf8(env->isolate, desc.utf8name, v8::NewStringType::kInternalized);
        if (name.IsEmpty()) {
            return env->SetLastError(napi_generic_failure, "Failed to create property name");
        }
        *out_name = name.ToLocalChecked();
        return napi_ok;
    }
    if (desc.name != nullptr) {
        v8::Local<v8::Value> v8_name = dawn::napi_v8::ToV8(desc.name);
        if (!v8_name->IsName()) {
            return env->SetLastError(napi_name_expected, "A name or symbol was expected");
        }
        *out_name = v8_name.As<v8::Name>();
        return napi_ok;
    }
    return env->SetLastError(napi_invalid_arg, "Property descriptor missing name");
}

// Validates and extracts a v8::Function and its associated Context.
napi_status UnwrapFunction(napi_env env,
                           napi_value function_value,
                           v8::Local<v8::Function>* out_fn,
                           v8::Local<v8::Context>* out_ctx) {
    v8::Local<v8::Value> v8_func = dawn::napi_v8::ToV8(function_value);
    if (!v8_func->IsFunction()) {
        return env->SetLastError(napi_function_expected, "A function was expected");
    }
    *out_ctx = env->GetContext();
    *out_fn = v8_func.As<v8::Function>();
    return napi_ok;
}

// Unpacks and validates a Node-API argument array into a vector of V8 values.
napi_status UnpackArgs(napi_env env,
                       size_t argc,
                       const napi_value* argv,
                       std::vector<v8::Local<v8::Value>>* out_args) {
    if (argc > 0 && argv == nullptr) {
        return env->SetLastError(napi_invalid_arg, "Invalid argument: null argv");
    }
    out_args->resize(argc);
    for (size_t i = 0; i < argc; ++i) {
        // SAFETY: The caller guarantees argv points to an array with at least argc elements.
        napi_value arg = DAWN_UNSAFE_BUFFERS(argv[i]);
        if (arg == nullptr) {
            return env->SetLastError(napi_invalid_arg, "Invalid argument in argv");
        }
        (*out_args)[i] = dawn::napi_v8::ToV8(arg);
    }
    return napi_ok;
}

// Evaluates the result of a V8 function or constructor invocation within TryCatch.
template <typename T>
napi_status ProcessCallResult(napi_env env,
                              v8::TryCatch& try_catch,
                              v8::MaybeLocal<T> maybe_result,
                              napi_value* out_result) {
    if (try_catch.HasTerminated()) {
        return env->SetLastError(napi_generic_failure, "Execution was terminated");
    }
    if (try_catch.HasCaught()) {
        env->last_exception.Reset(env->isolate, try_catch.Exception());
        return env->SetLastError(napi_pending_exception,
                                 "An exception was thrown during execution");
    }
    if (maybe_result.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Function invocation failed");
    }
    if (out_result != nullptr) {
        *out_result = dawn::napi_v8::ToNapi(maybe_result.ToLocalChecked());
    }
    return napi_ok;
}

// Instantiates a JavaScript function from a native Node-API callback.
napi_status CreateCallbackFunction(napi_env env,
                                   v8::Local<v8::Context> ctx,
                                   v8::Local<v8::Name> name,
                                   napi_callback callback,
                                   void* data,
                                   v8::Local<v8::Function>* out_fn) {
    if (callback == nullptr) {
        return napi_ok;
    }
    v8::Local<v8::FunctionTemplate> function_template;
    napi_status status = CreateFunctionTemplate(env, name, callback, data, &function_template);
    if (status != napi_ok) {
        return status;
    }
    v8::MaybeLocal<v8::Function> maybe_fn = function_template->GetFunction(ctx);
    if (maybe_fn.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to create callback function");
    }
    *out_fn = maybe_fn.ToLocalChecked();
    return napi_ok;
}
// Converts Node-API property attributes to V8 PropertyAttribute.
v8::PropertyAttribute ToV8PropertyAttribute(napi_property_attributes attributes) {
    int v8_attr = v8::None;
    if ((attributes & napi_writable) == 0) {
        v8_attr |= v8::ReadOnly;
    }
    if ((attributes & napi_enumerable) == 0) {
        v8_attr |= v8::DontEnum;
    }
    if ((attributes & napi_configurable) == 0) {
        v8_attr |= v8::DontDelete;
    }
    return static_cast<v8::PropertyAttribute>(v8_attr);
}
// Attaches a single property descriptor to an existing JavaScript object.
napi_status AttachObjectProperty(napi_env env,
                                 v8::Local<v8::Context> ctx,
                                 v8::Local<v8::Object> obj,
                                 const napi_property_descriptor& desc) {
    v8::Local<v8::Name> name;
    napi_status status = GetDescriptorName(env, desc, &name);
    if (status != napi_ok) {
        return status;
    }

    v8::PropertyAttribute v8_attr = ToV8PropertyAttribute(desc.attributes);
    if (desc.method != nullptr) {
        v8::Local<v8::Function> method_fn;
        status = CreateCallbackFunction(env, ctx, name, desc.method, desc.data, &method_fn);
        if (status != napi_ok) {
            return status;
        }
        if (obj->DefineOwnProperty(ctx, name, method_fn, v8_attr).IsNothing()) {
            return env->SetLastError(napi_generic_failure, "Failed to define method");
        }
    } else if (desc.getter != nullptr || desc.setter != nullptr) {
        v8::Local<v8::Function> getter_fn;
        status = CreateCallbackFunction(env, ctx, {}, desc.getter, desc.data, &getter_fn);
        if (status != napi_ok) {
            return status;
        }
        v8::Local<v8::Function> setter_fn;
        status = CreateCallbackFunction(env, ctx, {}, desc.setter, desc.data, &setter_fn);
        if (status != napi_ok) {
            return status;
        }
        obj->SetAccessorProperty(name, getter_fn, setter_fn, v8_attr);
    } else if (desc.value != nullptr) {
        if (obj->DefineOwnProperty(ctx, name, dawn::napi_v8::ToV8(desc.value), v8_attr)
                .IsNothing()) {
            return env->SetLastError(napi_generic_failure, "Failed to set property value");
        }
    }
    return napi_ok;
}

enum class ErrorType {
    Error,
    TypeError,
    RangeError,
};

// Helper to create JavaScript Error objects.
napi_status CreateError(napi_env env,
                        ErrorType error_type,
                        napi_value code,
                        napi_value msg,
                        napi_value* result) {
    if (!ValidateArgs(env, msg, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_msg = dawn::napi_v8::ToV8(msg);
    if (!v8_msg->IsString()) {
        return env->SetLastError(napi_string_expected, "A string was expected for error message");
    }
    v8::Local<v8::String> str_msg = v8_msg.As<v8::String>();
    v8::Local<v8::Value> err;
    switch (error_type) {
        case ErrorType::Error:
            err = v8::Exception::Error(str_msg);
            break;
        case ErrorType::TypeError:
            err = v8::Exception::TypeError(str_msg);
            break;
        case ErrorType::RangeError:
            err = v8::Exception::RangeError(str_msg);
            break;
    }
    if (code != nullptr) {
        v8::Local<v8::Context> ctx = env->GetContext();
        v8::Local<v8::String> code_name;
        napi_status status = CreateInternalizedName(env, "code", &code_name);
        if (status != napi_ok) {
            return status;
        }
        if (err.As<v8::Object>()->Set(ctx, code_name, dawn::napi_v8::ToV8(code)).IsNothing()) {
            return env->SetLastError(napi_generic_failure, "Failed to set error code");
        }
    }
    *result = dawn::napi_v8::ToNapi(err);
    return napi_ok;
}

napi_status GetWrapObject(napi_env env, napi_value js_object, v8::Local<v8::Object>* out_obj) {
    if (!ValidateArgs(env, js_object)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(js_object);
    if (!v8_val->IsObject()) {
        return env->SetLastError(napi_object_expected, "An object was expected");
    }
    *out_obj = v8_val.As<v8::Object>();
    return napi_ok;
}

// Returns the key used to retrieve the private member of a wrapper object.
// The name "node:napi:wrapper" is used for the key. The namespace should ensure
// no conflict with user names.
v8::Local<v8::Private> GetWrapperKey(napi_env env) {
    if (env->wrapper_key.IsEmpty()) {
        v8::Local<v8::String> name = v8::String::NewFromUtf8Literal(
            env->isolate, "node:napi:wrapper", v8::NewStringType::kInternalized);
        env->wrapper_key.Reset(env->isolate, v8::Private::New(env->isolate, name));
    }
    return env->wrapper_key.Get(env->isolate);
}

// Retrieves the `napi_ref__` previously attached to `js_object` by napi_wrap().
// Returns napi_invalid_arg if the object is not wrapped.
napi_status GetWrapReference(napi_env env,
                             napi_value js_object,
                             v8::Local<v8::Object>* out_obj,
                             napi_ref__** out_ref) {
    napi_status status = GetWrapObject(env, js_object, out_obj);
    if (status != napi_ok) {
        return status;
    }
    v8::Local<v8::Value> val;
    if (!(*out_obj)->GetPrivate(env->GetContext(), GetWrapperKey(env)).ToLocal(&val)) {
        return env->SetLastError(napi_generic_failure, "Failed to read the object's wrapper");
    }
    if (!val->IsExternal()) {
        return env->SetLastError(napi_invalid_arg, "Object is not wrapped");
    }
    *out_ref =
        static_cast<napi_ref__*>(val.As<v8::External>()->Value(v8::kExternalPointerTypeTagDefault));
    return napi_ok;
}

napi_status GetArrayBuffer(napi_env env, napi_value value, v8::Local<v8::ArrayBuffer>* out_ab) {
    if (!ValidateArgs(env, value)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    if (!v8_val->IsArrayBuffer()) {
        return env->SetLastError(napi_arraybuffer_expected, "An ArrayBuffer was expected");
    }
    *out_ab = v8_val.As<v8::ArrayBuffer>();
    return napi_ok;
}

napi_status ConcludeDeferred(napi_env env,
                             napi_deferred deferred,
                             napi_value value,
                             bool is_resolve) {
    if (!ValidateArgs(env, deferred, value)) {
        return napi_invalid_arg;
    }
    if (!env->last_exception.IsEmpty()) {
        return env->SetLastError(napi_pending_exception, "An exception is pending");
    }
    auto it = std::ranges::find_if(env->deferreds.begin(), env->deferreds.end(),
                                   [deferred](const auto& d) { return d.get() == deferred; });
    if (it == env->deferreds.end()) {
        return env->SetLastError(napi_invalid_arg, "Deferred not found");
    }
    v8::Local<v8::Promise::Resolver> resolver = deferred->resolver.Get(env->isolate);
    v8::Local<v8::Context> ctx = env->GetContext();
    v8::Maybe<bool> success = is_resolve ? resolver->Resolve(ctx, dawn::napi_v8::ToV8(value))
                                         : resolver->Reject(ctx, dawn::napi_v8::ToV8(value));
    env->deferreds.erase(it);
    if (success.IsNothing() || !success.FromJust()) {
        return env->SetLastError(napi_generic_failure, is_resolve ? "Failed to resolve promise"
                                                                  : "Failed to reject promise");
    }
    return napi_ok;
}

#ifndef V8_ENABLE_SANDBOX
struct ExternalArrayBufferFinalizer {
    napi_env env;
    node_api_nogc_finalize finalize_cb;
    void* finalize_hint;
};

void ExternalArrayBufferDeleter(void* data, size_t, void* deleter_data) {
    auto* fin = static_cast<ExternalArrayBufferFinalizer*>(deleter_data);
    if (fin != nullptr) {
        if (fin->finalize_cb != nullptr) {
            fin->finalize_cb(fin->env, data, fin->finalize_hint);
        }
        delete fin;
    }
}
#endif

size_t ElementSizeForTypedArray(napi_typedarray_type type) {
    switch (type) {
        case napi_int8_array:
        case napi_uint8_array:
        case napi_uint8_clamped_array:
            return 1;
        case napi_int16_array:
        case napi_uint16_array:
            return 2;
        case napi_int32_array:
        case napi_uint32_array:
        case napi_float32_array:
            return 4;
        case napi_float64_array:
        case napi_bigint64_array:
        case napi_biguint64_array:
            return 8;
    }
    return 0;
}

}  // namespace

using dawn::napi_v8::ToNapi;
using dawn::napi_v8::ToV8;

extern "C" {

// ============================================================================
// Error Handling & Environment Info
// ============================================================================

napi_status napi_get_last_error_info(node_api_nogc_env env,
                                     const napi_extended_error_info** result) {
    if (env == nullptr || result == nullptr) {
        return napi_invalid_arg;
    }
    *result = &(env->last_error);
    return napi_ok;
}

// ============================================================================
// Handle Scopes
// ============================================================================

napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    env->open_handle_scopes.push_back(std::make_unique<napi_standard_handle_scope__>(env->isolate));
    *result = env->open_handle_scopes.back().get();
    return napi_ok;
}

napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) {
    if (!ValidateArgs(env, scope)) {
        return napi_invalid_arg;
    }
    if (env->open_handle_scopes.empty() || env->open_handle_scopes.back().get() != scope) {
        return env->SetLastError(napi_handle_scope_mismatch, "Handle scope closed out of order");
    }
    env->open_handle_scopes.pop_back();
    return napi_ok;
}

napi_status napi_open_escapable_handle_scope(napi_env env, napi_escapable_handle_scope* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    auto scope = std::make_unique<napi_escapable_handle_scope__>(env->isolate);
    *result = scope.get();
    env->open_handle_scopes.push_back(std::move(scope));
    return napi_ok;
}

napi_status napi_close_escapable_handle_scope(napi_env env, napi_escapable_handle_scope scope) {
    if (!ValidateArgs(env, scope)) {
        return napi_invalid_arg;
    }
    if (env->open_handle_scopes.empty() || env->open_handle_scopes.back().get() != scope) {
        return env->SetLastError(napi_handle_scope_mismatch, "Handle scope closed out of order");
    }
    env->open_handle_scopes.pop_back();
    return napi_ok;
}

napi_status napi_escape_handle(napi_env env,
                               napi_escapable_handle_scope scope,
                               napi_value src,
                               napi_value* result) {
    if (!ValidateArgs(env, scope, src, result)) {
        return napi_invalid_arg;
    }
    if (scope->escape_called) {
        return env->SetLastError(napi_escape_called_twice,
                                 "Handle already escaped from this scope");
    }
    scope->escape_called = true;
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(src);
    *result = dawn::napi_v8::ToNapi(scope->scope.Escape(v8_val));
    return napi_ok;
}

// ============================================================================
// Primitives & Singletons
// ============================================================================

napi_status napi_get_undefined(napi_env env, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Undefined(env->isolate));
    return napi_ok;
}

napi_status napi_get_null(napi_env env, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Null(env->isolate));
    return napi_ok;
}

napi_status napi_get_global(napi_env env, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(env->GetContext()->Global());
    return napi_ok;
}

napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Boolean::New(env->isolate, value));
    return napi_ok;
}

napi_status napi_create_double(napi_env env, double value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Number::New(env->isolate, value));
    return napi_ok;
}

napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Integer::New(env->isolate, value));
    return napi_ok;
}

napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Integer::NewFromUnsigned(env->isolate, value));
    return napi_ok;
}

napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Number::New(env->isolate, static_cast<double>(value)));
    return napi_ok;
}

napi_status napi_create_bigint_int64(napi_env env, int64_t value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = dawn::napi_v8::ToNapi(v8::BigInt::New(env->isolate, value));
    return napi_ok;
}

napi_status napi_create_bigint_uint64(napi_env env, uint64_t value, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = dawn::napi_v8::ToNapi(v8::BigInt::NewFromUnsigned(env->isolate, value));
    return napi_ok;
}

napi_status napi_create_string_utf8(napi_env env,
                                    const char* str,
                                    size_t length,
                                    napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    int len = (length == NAPI_AUTO_LENGTH) ? -1 : static_cast<int>(length);
    v8::MaybeLocal<v8::String> v8_str =
        v8::String::NewFromUtf8(env->isolate, str ? str : "", v8::NewStringType::kNormal, len);
    if (v8_str.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to create UTF-8 string");
    }
    *result = ToNapi(v8_str.ToLocalChecked());
    return napi_ok;
}

napi_status napi_create_symbol(napi_env env, napi_value description, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::String> desc;
    if (description != nullptr) {
        desc = ToV8(description).As<v8::String>();
    }
    *result = ToNapi(v8::Symbol::New(env->isolate, desc));
    return napi_ok;
}

napi_status napi_get_value_double(napi_env env, napi_value value, double* result) {
    return ExtractNumber<v8::Number>(env, value, result, "A number was expected",
                                     [](auto v, auto ctx) { return v->ToNumber(ctx); });
}

napi_status napi_get_value_int32(napi_env env, napi_value value, int32_t* result) {
    return ExtractNumber<v8::Int32>(env, value, result, "A 32-bit integer was expected",
                                    [](auto v, auto ctx) { return v->ToInt32(ctx); });
}

napi_status napi_get_value_uint32(napi_env env, napi_value value, uint32_t* result) {
    return ExtractNumber<v8::Uint32>(env, value, result, "An unsigned 32-bit integer was expected",
                                     [](auto v, auto ctx) { return v->ToUint32(ctx); });
}

napi_status napi_get_value_int64(napi_env env, napi_value value, int64_t* result) {
    return ExtractNumber<v8::Integer>(env, value, result, "An integer was expected",
                                      [](auto v, auto ctx) { return v->ToInteger(ctx); });
}

napi_status napi_get_value_bigint_int64(napi_env env,
                                        napi_value value,
                                        int64_t* result,
                                        bool* lossless) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    if (!v8_val->IsBigInt()) {
        return env->SetLastError(napi_bigint_expected, "BigInt expected");
    }
    v8::Local<v8::BigInt> bi = v8_val.As<v8::BigInt>();
    *result = bi->Int64Value(lossless);
    return napi_ok;
}

napi_status napi_get_value_bigint_uint64(napi_env env,
                                         napi_value value,
                                         uint64_t* result,
                                         bool* lossless) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    if (!v8_val->IsBigInt()) {
        return env->SetLastError(napi_bigint_expected, "BigInt expected");
    }
    v8::Local<v8::BigInt> bi = v8_val.As<v8::BigInt>();
    *result = bi->Uint64Value(lossless);
    return napi_ok;
}

napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    *result = ToV8(value)->BooleanValue(env->isolate);
    return napi_ok;
}

napi_status napi_get_value_string_utf8(napi_env env,
                                       napi_value value,
                                       char* buf,
                                       size_t bufsize,
                                       size_t* result) {
    if (!ValidateArgs(env, value)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> val = ToV8(value);
    if (!val->IsString()) {
        return env->SetLastError(napi_string_expected, "A string was expected");
    }

    v8::Local<v8::String> str = val.As<v8::String>();
    size_t utf8_len = static_cast<size_t>(str->Utf8Length(env->isolate));
    if (buf == nullptr) {
        if (result == nullptr) {
            return env->SetLastError(napi_invalid_arg, "Invalid argument: null pointer");
        }
        *result = utf8_len;
    } else if (bufsize == 0) {
        if (result != nullptr) {
            *result = 0;
        }
    } else {
        size_t written = str->WriteUtf8(env->isolate, buf, bufsize - 1,
                                        v8::String::WriteFlags::kReplaceInvalidUtf8);
        // SAFETY: written is guaranteed to be <= bufsize - 1 by WriteUtf8, so written is a valid
        // index in buf.
        DAWN_UNSAFE_BUFFERS(buf[written] = '\0');
        if (result != nullptr) {
            *result = written;
        }
    }
    return napi_ok;
}

// ============================================================================
// Type Coercions, Type Checking & Equality
// ============================================================================

napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }

    v8::Local<v8::Value> val = ToV8(value);
    if (val->IsNumber()) {
        *result = napi_number;
    } else if (val->IsString()) {
        *result = napi_string;
    } else if (val->IsFunction()) {
        *result = napi_function;
    } else if (val->IsArray()) {
        *result = napi_object;
    } else if (val->IsBoolean()) {
        *result = napi_boolean;
    } else if (val->IsUndefined()) {
        *result = napi_undefined;
    } else if (val->IsNull()) {
        *result = napi_null;
    } else if (val->IsSymbol()) {
        *result = napi_symbol;
    } else if (val->IsBigInt()) {
        *result = napi_bigint;
    } else if (val->IsExternal()) {
        *result = napi_external;
    } else if (val->IsObject()) {
        *result = napi_object;
    } else {
        *result = napi_undefined;
    }
    return napi_ok;
}

napi_status napi_coerce_to_bool(napi_env env, napi_value value, napi_value* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(ToV8(value)->ToBoolean(env->isolate));
    return napi_ok;
}

napi_status napi_coerce_to_number(napi_env env, napi_value value, napi_value* result) {
    return CoerceTo<v8::Number>(env, value, result, "Failed to coerce value to number",
                                [](auto v, auto ctx) { return v->ToNumber(ctx); });
}

napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result) {
    return CoerceTo<v8::String>(env, value, result, "Failed to coerce value to string",
                                [](auto v, auto ctx) { return v->ToString(ctx); });
}

napi_status napi_coerce_to_object(napi_env env, napi_value value, napi_value* result) {
    return CoerceTo<v8::Object>(env, value, result, "Failed to coerce value to object",
                                [](auto v, auto ctx) { return v->ToObject(ctx); });
}

napi_status napi_strict_equals(napi_env env, napi_value lhs, napi_value rhs, bool* result) {
    if (!ValidateArgs(env, lhs, rhs, result)) {
        return napi_invalid_arg;
    }
    *result = ToV8(lhs)->StrictEquals(ToV8(rhs));
    return napi_ok;
}

napi_status napi_instanceof(napi_env env, napi_value object, napi_value constructor, bool* result) {
    if (!ValidateArgs(env, object, constructor, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_obj = dawn::napi_v8::ToV8(object);
    v8::Local<v8::Value> v8_ctor = dawn::napi_v8::ToV8(constructor);
    if (!v8_ctor->IsObject()) {
        return env->SetLastError(napi_object_expected, "Constructor must be an object");
    }
    v8::Local<v8::Context> ctx = env->GetContext();
    v8::TryCatch try_catch(env->isolate);
    v8::Maybe<bool> res = v8_obj->InstanceOf(ctx, v8_ctor.As<v8::Object>());
    if (res.IsNothing()) {
        if (try_catch.HasCaught()) {
            env->last_exception.Reset(env->isolate, try_catch.Exception());
            return env->SetLastError(napi_pending_exception,
                                     "An exception was thrown during the InstanceOf check");
        }
        return env->SetLastError(napi_generic_failure, "InstanceOf check failed");
    }
    *result = res.FromJust();
    return napi_ok;
}

// ============================================================================
// Objects & Properties
// ============================================================================

napi_status napi_create_object(napi_env env, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Object::New(env->isolate));
    return napi_ok;
}

napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result) {
    if (!ValidateArgs(env, object, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Object> obj;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapObject(env, object, &obj, &ctx);
    if (status != napi_ok) {
        return status;
    }
    v8::MaybeLocal<v8::Array> names = obj->GetPropertyNames(ctx);
    if (names.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to get property names");
    }
    *result = ToNapi(names.ToLocalChecked());
    return napi_ok;
}

napi_status napi_set_property(napi_env env, napi_value object, napi_value name, napi_value value) {
    if (!ValidateArgs(env, name)) {
        return napi_invalid_arg;
    }
    return WriteProperty(env, object, ToV8(name), value, "Failed to set property");
}

napi_status napi_get_property(napi_env env,
                              napi_value object,
                              napi_value name,
                              napi_value* result) {
    if (!ValidateArgs(env, name)) {
        return napi_invalid_arg;
    }
    return ReadProperty(env, object, ToV8(name), result, "Failed to get property");
}

napi_status napi_has_property(napi_env env, napi_value object, napi_value name, bool* result) {
    if (!ValidateArgs(env, name)) {
        return napi_invalid_arg;
    }
    return QueryProperty(env, object, ToV8(name), result, "Failed to check property");
}

napi_status napi_set_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8name,
                                    napi_value value) {
    v8::Local<v8::String> name;
    napi_status status = CreateInternalizedName(env, utf8name, &name);
    if (status != napi_ok) {
        return status;
    }
    return WriteProperty(env, object, name, value, "Failed to set named property");
}

napi_status napi_get_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8name,
                                    napi_value* result) {
    v8::Local<v8::String> name;
    napi_status status = CreateInternalizedName(env, utf8name, &name);
    if (status != napi_ok) {
        return status;
    }
    return ReadProperty(env, object, name, result, "Failed to get named property");
}

napi_status napi_has_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8name,
                                    bool* result) {
    v8::Local<v8::String> name;
    napi_status status = CreateInternalizedName(env, utf8name, &name);
    if (status != napi_ok) {
        return status;
    }
    return QueryProperty(env, object, name, result, "Failed to check named property");
}

// ============================================================================
// Arrays & Indexed Properties
// ============================================================================

napi_status napi_create_array(napi_env env, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Array::New(env->isolate));
    return napi_ok;
}

napi_status napi_create_array_with_length(napi_env env, size_t length, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = ToNapi(v8::Array::New(env->isolate, static_cast<int>(length)));
    return napi_ok;
}

napi_status napi_get_array_length(napi_env env, napi_value value, uint32_t* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = ToV8(value);
    if (!v8_val->IsArray()) {
        return env->SetLastError(napi_array_expected, "An array was expected");
    }
    *result = v8_val.As<v8::Array>()->Length();
    return napi_ok;
}

napi_status napi_is_array(napi_env env, napi_value value, bool* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    *result = v8_val->IsArray();
    return napi_ok;
}

napi_status napi_get_element(napi_env env, napi_value object, uint32_t index, napi_value* result) {
    return ReadProperty(env, object, index, result, "Failed to get element");
}

napi_status napi_set_element(napi_env env, napi_value object, uint32_t index, napi_value value) {
    return WriteProperty(env, object, index, value, "Failed to set element");
}

// ============================================================================
// Functions, Classes & Callbacks
// ============================================================================

napi_status napi_create_function(napi_env env,
                                 const char* utf8name,
                                 size_t length,
                                 napi_callback cb,
                                 void* data,
                                 napi_value* result) {
    if (!ValidateArgs(env, cb, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::FunctionTemplate> function_template;
    napi_status status =
        CreateFunctionTemplate(env, utf8name, length, cb, data, &function_template);
    if (status != napi_ok) {
        return status;
    }
    v8::MaybeLocal<v8::Function> fn = function_template->GetFunction(env->GetContext());
    if (fn.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to create function");
    }
    *result = dawn::napi_v8::ToNapi(fn.ToLocalChecked());
    return napi_ok;
}

napi_status napi_call_function(napi_env env,
                               napi_value recv,
                               napi_value func,
                               size_t argc,
                               const napi_value* argv,
                               napi_value* result) {
    if (!ValidateArgs(env, func)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Function> fn;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapFunction(env, func, &fn, &ctx);
    if (status != napi_ok) {
        return status;
    }

    std::vector<v8::Local<v8::Value>> args;
    status = UnpackArgs(env, argc, argv, &args);
    if (status != napi_ok) {
        return status;
    }

    v8::Local<v8::Value> v8_recv = (recv != nullptr)
                                       ? dawn::napi_v8::ToV8(recv)
                                       : v8::Local<v8::Value>(v8::Undefined(env->isolate));

    v8::TryCatch try_catch(env->isolate);
    v8::MaybeLocal<v8::Value> ret = fn->Call(ctx, v8_recv, static_cast<int>(argc), args.data());
    return ProcessCallResult(env, try_catch, ret, result);
}

napi_status napi_get_cb_info(napi_env env,
                             napi_callback_info cbinfo,
                             size_t* argc,
                             napi_value* argv,
                             napi_value* this_arg,
                             void** data) {
    if (!ValidateArgs(env, cbinfo)) {
        return napi_invalid_arg;
    }
    if (data != nullptr) {
        *data = cbinfo->data;
    }
    const auto& info = *(cbinfo->v8_info);
    if (this_arg != nullptr) {
        *this_arg = dawn::napi_v8::ToNapi(info.This());
    }
    if (argc != nullptr) {
        size_t available_argc = static_cast<size_t>(info.Length());
        if (argv != nullptr) {
            size_t copy_count = std::min(*argc, available_argc);
            for (size_t i = 0; i < copy_count; ++i) {
                // SAFETY: When argv is non-null, the caller guarantees it points to a buffer of at
                // least *argc elements.
                DAWN_UNSAFE_BUFFERS(argv[i]) = dawn::napi_v8::ToNapi(info[static_cast<int>(i)]);
            }
            for (size_t i = copy_count; i < *argc; ++i) {
                // SAFETY: When argv is non-null, the caller guarantees it points to a buffer of at
                // least *argc elements.
                DAWN_UNSAFE_BUFFERS(argv[i]) = dawn::napi_v8::ToNapi(v8::Undefined(env->isolate));
            }
        }
        *argc = available_argc;
    }
    return napi_ok;
}

napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, napi_value* result) {
    if (!ValidateArgs(env, cbinfo, result)) {
        return napi_invalid_arg;
    }
    if (cbinfo->v8_info == nullptr) {
        return env->SetLastError(napi_invalid_arg, "Callback info has no V8 info");
    }
    v8::Local<v8::Value> new_target = cbinfo->v8_info->NewTarget();
    if (new_target.IsEmpty()) {
        new_target = v8::Undefined(env->isolate);
    }
    *result = dawn::napi_v8::ToNapi(new_target);
    return napi_ok;
}

napi_status napi_new_instance(napi_env env,
                              napi_value constructor,
                              size_t argc,
                              const napi_value* argv,
                              napi_value* result) {
    if (!ValidateArgs(env, constructor, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Function> ctor;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapFunction(env, constructor, &ctor, &ctx);
    if (status != napi_ok) {
        return status;
    }

    std::vector<v8::Local<v8::Value>> args;
    status = UnpackArgs(env, argc, argv, &args);
    if (status != napi_ok) {
        return status;
    }

    v8::TryCatch try_catch(env->isolate);
    v8::MaybeLocal<v8::Object> ret = ctor->NewInstance(ctx, static_cast<int>(argc), args.data());
    return ProcessCallResult(env, try_catch, ret, result);
}

napi_status napi_define_class(napi_env env,
                              const char* utf8name,
                              size_t length,
                              napi_callback constructor,
                              void* data,
                              size_t property_count,
                              const napi_property_descriptor* properties,
                              napi_value* result) {
    if (!ValidateArgs(env, constructor, result)) {
        return napi_invalid_arg;
    }
    if (property_count > 0 && properties == nullptr) {
        return env->SetLastError(napi_invalid_arg, "Invalid argument: null properties");
    }

    v8::Local<v8::FunctionTemplate> class_template;
    napi_status status =
        CreateFunctionTemplate(env, utf8name, length, constructor, data, &class_template);
    if (status != napi_ok) {
        return status;
    }

    v8::Local<v8::Context> ctx = env->GetContext();
    v8::MaybeLocal<v8::Function> maybe_ctor = class_template->GetFunction(ctx);
    if (maybe_ctor.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to create class constructor");
    }
    v8::Local<v8::Function> ctor_fn = maybe_ctor.ToLocalChecked();

    v8::Local<v8::Object> proto_obj;
    if (property_count > 0) {
        v8::Local<v8::String> proto_name;
        status = CreateInternalizedName(env, "prototype", &proto_name);
        if (status != napi_ok) {
            return status;
        }
        v8::Local<v8::Value> proto_val;
        if (!ctor_fn->Get(ctx, proto_name).ToLocal(&proto_val) || !proto_val->IsObject()) {
            return env->SetLastError(napi_generic_failure, "Failed to get class prototype object");
        }
        proto_obj = proto_val.As<v8::Object>();
    }

    for (size_t i = 0; i < property_count; ++i) {
        // SAFETY: The caller guarantees properties points to an array of at least property_count
        // descriptors.
        const napi_property_descriptor& prop = DAWN_UNSAFE_BUFFERS(properties[i]);
        bool is_static = (prop.attributes & napi_static) != 0;
        v8::Local<v8::Object> target = is_static ? ctor_fn : proto_obj;
        status = AttachObjectProperty(env, ctx, target, prop);
        if (status != napi_ok) {
            return status;
        }
    }

    *result = dawn::napi_v8::ToNapi(ctor_fn);
    return napi_ok;
}

napi_status napi_define_properties(napi_env env,
                                   napi_value object,
                                   size_t property_count,
                                   const napi_property_descriptor* properties) {
    if (!ValidateArgs(env, object)) {
        return napi_invalid_arg;
    }
    if (property_count > 0 && properties == nullptr) {
        return env->SetLastError(napi_invalid_arg, "Invalid argument: null properties");
    }

    v8::Local<v8::Object> obj;
    v8::Local<v8::Context> ctx;
    napi_status status = UnwrapObject(env, object, &obj, &ctx);
    if (status != napi_ok) {
        return status;
    }

    for (size_t i = 0; i < property_count; ++i) {
        // SAFETY: The caller guarantees properties points to an array of at least property_count
        // descriptors.
        const napi_property_descriptor& prop = DAWN_UNSAFE_BUFFERS(properties[i]);
        status = AttachObjectProperty(env, ctx, obj, prop);
        if (status != napi_ok) {
            return status;
        }
    }
    return napi_ok;
}

// ============================================================================
// Exceptions & Errors
// ============================================================================

napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value* result) {
    return CreateError(env, ErrorType::Error, code, msg, result);
}

napi_status napi_create_type_error(napi_env env,
                                   napi_value code,
                                   napi_value msg,
                                   napi_value* result) {
    return CreateError(env, ErrorType::TypeError, code, msg, result);
}

napi_status napi_create_range_error(napi_env env,
                                    napi_value code,
                                    napi_value msg,
                                    napi_value* result) {
    return CreateError(env, ErrorType::RangeError, code, msg, result);
}

napi_status napi_throw(napi_env env, napi_value error) {
    if (!ValidateArgs(env, error)) {
        return napi_invalid_arg;
    }
    // Record the exception rather than calling Isolate::ThrowException() immediately so native
    // callers can inspect or clear it with napi_is_exception_pending() and
    // napi_get_and_clear_last_exception() before DeliverPendingException() hands it to V8.
    env->last_exception.Reset(env->isolate, dawn::napi_v8::ToV8(error));
    return napi_ok;
}

napi_status napi_is_exception_pending(napi_env env, bool* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    *result = !env->last_exception.IsEmpty();
    return napi_ok;
}

napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    if (!env->last_exception.IsEmpty()) {
        *result = dawn::napi_v8::ToNapi(env->last_exception.Get(env->isolate));
        env->last_exception.Reset();
    } else {
        *result = dawn::napi_v8::ToNapi(v8::Undefined(env->isolate));
    }
    return napi_ok;
}

napi_status napi_is_error(napi_env env, napi_value value, bool* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    *result = dawn::napi_v8::ToV8(value)->IsNativeError();
    return napi_ok;
}

void napi_fatal_error(const char* location,
                      size_t location_len,
                      const char* message,
                      size_t message_len) {
    std::string loc =
        (location != nullptr)
            ? (location_len == NAPI_AUTO_LENGTH ? location : std::string(location, location_len))
            : "";
    std::string msg =
        (message != nullptr)
            ? (message_len == NAPI_AUTO_LENGTH ? message : std::string(message, message_len))
            : "";
    fprintf(stderr, "FATAL ERROR in %s: %s\n", loc.c_str(), msg.c_str());
    fflush(stderr);
    std::abort();
}

// ============================================================================
// References, ObjectWrap & Instance Data
// ============================================================================

napi_status napi_create_reference(napi_env env,
                                  napi_value value,
                                  uint32_t initial_refcount,
                                  napi_ref* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    auto ref = std::make_unique<napi_ref__>(env, v8_val, initial_refcount);
    napi_ref__* key = ref.get();
    *result = key;
    env->references.insert({key, std::move(ref)});
    return napi_ok;
}

napi_status napi_delete_reference(napi_env env, napi_ref ref) {
    if (!ValidateArgs(env, ref)) {
        return napi_invalid_arg;
    }
    if (env->references.erase(ref) > 0) {
        return napi_ok;
    }
    return env->SetLastError(napi_invalid_arg, "Reference not found");
}

napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) {
    if (!ValidateArgs(env, ref)) {
        return napi_invalid_arg;
    }
    if (ref->ref_count == 0) {
        ref->ClearWeak();
    }
    ref->ref_count++;
    if (result != nullptr) {
        *result = ref->ref_count;
    }
    return napi_ok;
}

napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) {
    if (!ValidateArgs(env, ref)) {
        return napi_invalid_arg;
    }
    if (ref->ref_count == 0) {
        return env->SetLastError(napi_generic_failure, "Cannot unref a reference with refcount 0");
    }
    ref->ref_count--;
    if (ref->ref_count == 0) {
        ref->SetWeak();
    }
    if (result != nullptr) {
        *result = ref->ref_count;
    }
    return napi_ok;
}

napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result) {
    if (!ValidateArgs(env, ref, result)) {
        return napi_invalid_arg;
    }
    if (ref->handle.IsEmpty()) {
        *result = nullptr;
    } else {
        *result = dawn::napi_v8::ToNapi(ref->handle.Get(env->isolate));
    }
    return napi_ok;
}

napi_status napi_wrap(napi_env env,
                      napi_value js_object,
                      void* native_object,
                      napi_finalize finalize_cb,
                      void* finalize_hint,
                      napi_ref* result) {
    v8::Local<v8::Object> obj;
    napi_status status = GetWrapObject(env, js_object, &obj);
    if (status != napi_ok) {
        return status;
    }
    v8::Local<v8::Context> ctx = env->GetContext();
    v8::Local<v8::Private> key = GetWrapperKey(env);

    v8::Maybe<bool> has_wrapper = obj->HasPrivate(ctx, key);
    if (has_wrapper.IsNothing()) {
        return env->SetLastError(napi_generic_failure, "Failed to read the object's wrapper");
    }
    if (has_wrapper.FromJust()) {
        return env->SetLastError(napi_invalid_arg, "Object is already wrapped");
    }

    // A reference is created even when the caller asks for neither a finalizer nor a napi_ref:
    // it is what holds the native pointer for napi_unwrap() to read back.
    auto ref = std::make_unique<napi_ref__>(env, obj, 0, native_object, finalize_cb, finalize_hint,
                                            /*wrap_ref=*/true,
                                            /*userland_ref=*/result != nullptr);
    napi_ref__* key_ref = ref.get();
    v8::Local<v8::External> ext =
        v8::External::New(env->isolate, key_ref, v8::kExternalPointerTypeTagDefault);
    if (obj->SetPrivate(ctx, key, ext).IsNothing()) {
        return env->SetLastError(napi_generic_failure, "Failed to attach the object's wrapper");
    }
    if (result != nullptr) {
        *result = key_ref;
    }
    env->references.insert({key_ref, std::move(ref)});
    return napi_ok;
}

napi_status napi_unwrap(napi_env env, napi_value js_object, void** result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Object> obj;
    napi_ref__* ref = nullptr;
    napi_status status = GetWrapReference(env, js_object, &obj, &ref);
    if (status != napi_ok) {
        return status;
    }
    *result = ref->native_object;
    return napi_ok;
}

napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result) {
    v8::Local<v8::Object> obj;
    napi_ref__* ref = nullptr;
    napi_status status = GetWrapReference(env, js_object, &obj, &ref);
    if (status != napi_ok) {
        return status;
    }
    if (result != nullptr) {
        *result = ref->native_object;
    }
    if (obj->DeletePrivate(env->GetContext(), GetWrapperKey(env)).IsNothing()) {
        return env->SetLastError(napi_generic_failure, "Failed to detach the object's wrapper");
    }

    // Detach the reference, clearing the finalizer so it never runs on the removed native object.
    ref->ClearFinalizer();
    ref->native_object = nullptr;
    ref->is_wrap_ref = false;

    if (!ref->is_userland_ref) {
        // Internal runtime reference: erasing it destroys the unique_ptr, whose
        // destructor calls handle.Reset(), deregistering the weak callback in V8.
        env->references.erase(ref);
    }
    return napi_ok;
}

napi_status napi_add_finalizer(napi_env env,
                               napi_value js_object,
                               void* finalize_data,
                               napi_finalize finalize_cb,
                               void* finalize_hint,
                               napi_ref* result) {
    if (!ValidateArgs(env, js_object)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> val = dawn::napi_v8::ToV8(js_object);
    if (!val->IsObject()) {
        return env->SetLastError(napi_object_expected, "Object expected");
    }
    auto ref = std::make_unique<napi_ref__>(env, val, 0, finalize_data, finalize_cb, finalize_hint,
                                            /*wrap_ref=*/false,
                                            /*userland_ref=*/result != nullptr);
    napi_ref__* key_ref = ref.get();
    if (result != nullptr) {
        *result = key_ref;
    }
    env->references.insert({key_ref, std::move(ref)});
    return napi_ok;
}

napi_status napi_create_external(napi_env env,
                                 void* data,
                                 napi_finalize finalize_cb,
                                 void* finalize_hint,
                                 napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::External> ext =
        v8::External::New(env->isolate, data, v8::kExternalPointerTypeTagDefault);
    if (finalize_cb != nullptr) {
        auto ref = std::make_unique<napi_ref__>(env, ext, 0, data, finalize_cb, finalize_hint,
                                                /*wrap_ref=*/false, /*userland_ref=*/false);
        napi_ref__* key_ref = ref.get();
        env->references.insert({key_ref, std::move(ref)});
    }
    *result = dawn::napi_v8::ToNapi(ext);
    return napi_ok;
}

napi_status napi_get_value_external(napi_env env, napi_value value, void** result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    if (!v8_val->IsExternal()) {
        return env->SetLastError(napi_invalid_arg, "Value is not an external");
    }
    *result = v8_val.As<v8::External>()->Value(v8::kExternalPointerTypeTagDefault);
    return napi_ok;
}

napi_status napi_set_instance_data(napi_env env,
                                   void* data,
                                   napi_finalize finalize_cb,
                                   void* finalize_hint) {
    if (!ValidateArgs(env)) {
        return napi_invalid_arg;
    }
    if (env->instance_data.finalize_cb != nullptr) {
        env->instance_data.finalize_cb(env, env->instance_data.data,
                                       env->instance_data.finalize_hint);
    }
    env->instance_data.data = data;
    env->instance_data.finalize_cb = finalize_cb;
    env->instance_data.finalize_hint = finalize_hint;
    return napi_ok;
}

napi_status napi_get_instance_data(napi_env env, void** data) {
    if (!ValidateArgs(env, data)) {
        return napi_invalid_arg;
    }
    *data = env->instance_data.data;
    return napi_ok;
}

// ============================================================================
// ArrayBuffer, TypedArray & DataView
// ============================================================================

napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    *result = v8_val->IsArrayBuffer();
    return napi_ok;
}

napi_status napi_create_arraybuffer(napi_env env,
                                    size_t byte_length,
                                    void** data,
                                    napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(env->isolate, byte_length);
    if (data != nullptr) {
        *data = ab->Data();
    }
    *result = dawn::napi_v8::ToNapi(ab);
    return napi_ok;
}

napi_status napi_get_arraybuffer_info(napi_env env,
                                      napi_value arraybuffer,
                                      void** data,
                                      size_t* byte_length) {
    v8::Local<v8::ArrayBuffer> ab;
    napi_status status = GetArrayBuffer(env, arraybuffer, &ab);
    if (status != napi_ok) {
        return status;
    }
    if (data != nullptr) {
        *data = ab->Data();
    }
    if (byte_length != nullptr) {
        *byte_length = ab->ByteLength();
    }
    return napi_ok;
}

napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) {
    v8::Local<v8::ArrayBuffer> ab;
    napi_status status = GetArrayBuffer(env, arraybuffer, &ab);
    if (status != napi_ok) {
        return status;
    }
    if (!ab->IsDetachable()) {
        return env->SetLastError(napi_detachable_arraybuffer_expected,
                                 "ArrayBuffer is not detachable");
    }
    ab->Detach(v8::Local<v8::Value>()).Check();
    return napi_ok;
}

napi_status napi_create_external_arraybuffer(napi_env env,
                                             void* external_data,
                                             size_t byte_length,
                                             node_api_nogc_finalize finalize_cb,
                                             void* finalize_hint,
                                             napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
#ifdef V8_ENABLE_SANDBOX
    return env->SetLastError(napi_no_external_buffers_allowed,
                             "External buffers are not allowed when V8 Sandbox is enabled");
#else
    ExternalArrayBufferFinalizer* fin = nullptr;
    if (finalize_cb != nullptr) {
        fin = new ExternalArrayBufferFinalizer{env, finalize_cb, finalize_hint};
    }
    auto backing_store = v8::ArrayBuffer::NewBackingStore(external_data, byte_length,
                                                          ExternalArrayBufferDeleter, fin);
    v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
        env->isolate, std::shared_ptr<v8::BackingStore>(std::move(backing_store)));
    *result = dawn::napi_v8::ToNapi(ab);
    return napi_ok;
#endif
}

napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) {
    if (!ValidateArgs(env, value, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    *result = v8_val->IsTypedArray();
    return napi_ok;
}

napi_status napi_create_typedarray(napi_env env,
                                   napi_typedarray_type type,
                                   size_t length,
                                   napi_value arraybuffer,
                                   size_t byte_offset,
                                   napi_value* result) {
    if (!ValidateArgs(env, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::ArrayBuffer> ab;
    napi_status status = GetArrayBuffer(env, arraybuffer, &ab);
    if (status != napi_ok) {
        return status;
    }
    size_t element_size = ElementSizeForTypedArray(type);
    if (element_size == 0) {
        return env->SetLastError(napi_invalid_arg, "Invalid typedarray type");
    }
    if (byte_offset % element_size != 0) {
        return env->SetLastError(napi_invalid_arg, "Offset must be aligned to element size");
    }
    if (length > (std::numeric_limits<size_t>::max() - byte_offset) / element_size ||
        byte_offset + length * element_size > ab->ByteLength()) {
        return env->SetLastError(napi_invalid_arg, "Range out of bounds");
    }
    v8::Local<v8::TypedArray> ta;
    switch (type) {
        case napi_int8_array:
            ta = v8::Int8Array::New(ab, byte_offset, length);
            break;
        case napi_uint8_array:
            ta = v8::Uint8Array::New(ab, byte_offset, length);
            break;
        case napi_uint8_clamped_array:
            ta = v8::Uint8ClampedArray::New(ab, byte_offset, length);
            break;
        case napi_int16_array:
            ta = v8::Int16Array::New(ab, byte_offset, length);
            break;
        case napi_uint16_array:
            ta = v8::Uint16Array::New(ab, byte_offset, length);
            break;
        case napi_int32_array:
            ta = v8::Int32Array::New(ab, byte_offset, length);
            break;
        case napi_uint32_array:
            ta = v8::Uint32Array::New(ab, byte_offset, length);
            break;
        case napi_float32_array:
            ta = v8::Float32Array::New(ab, byte_offset, length);
            break;
        case napi_float64_array:
            ta = v8::Float64Array::New(ab, byte_offset, length);
            break;
        case napi_bigint64_array:
            ta = v8::BigInt64Array::New(ab, byte_offset, length);
            break;
        case napi_biguint64_array:
            ta = v8::BigUint64Array::New(ab, byte_offset, length);
            break;
    }
    *result = dawn::napi_v8::ToNapi(ta);
    return napi_ok;
}

napi_status napi_get_typedarray_info(napi_env env,
                                     napi_value typedarray,
                                     napi_typedarray_type* type,
                                     size_t* length,
                                     void** data,
                                     napi_value* arraybuffer,
                                     size_t* byte_offset) {
    if (!ValidateArgs(env, typedarray)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(typedarray);
    if (!v8_val->IsTypedArray()) {
        return env->SetLastError(napi_invalid_arg, "A TypedArray was expected");
    }
    v8::Local<v8::TypedArray> ta = v8_val.As<v8::TypedArray>();
    if (type != nullptr) {
        if (v8_val->IsInt8Array()) {
            *type = napi_int8_array;
        } else if (v8_val->IsUint8Array()) {
            *type = napi_uint8_array;
        } else if (v8_val->IsUint8ClampedArray()) {
            *type = napi_uint8_clamped_array;
        } else if (v8_val->IsInt16Array()) {
            *type = napi_int16_array;
        } else if (v8_val->IsUint16Array()) {
            *type = napi_uint16_array;
        } else if (v8_val->IsInt32Array()) {
            *type = napi_int32_array;
        } else if (v8_val->IsUint32Array()) {
            *type = napi_uint32_array;
        } else if (v8_val->IsFloat32Array()) {
            *type = napi_float32_array;
        } else if (v8_val->IsFloat64Array()) {
            *type = napi_float64_array;
        } else if (v8_val->IsBigInt64Array()) {
            *type = napi_bigint64_array;
        } else if (v8_val->IsBigUint64Array()) {
            *type = napi_biguint64_array;
        }
    }
    if (length != nullptr) {
        *length = ta->Length();
    }
    if (byte_offset != nullptr) {
        *byte_offset = ta->ByteOffset();
    }
    if (arraybuffer != nullptr) {
        *arraybuffer = dawn::napi_v8::ToNapi(ta->GetBuffer());
    }
    if (data != nullptr) {
        // SAFETY: ta->Buffer() provides data storage of at least ta->ByteOffset() +
        // ta->ByteLength() bytes.
        *data =
            DAWN_UNSAFE_BUFFERS(static_cast<uint8_t*>(ta->GetBuffer()->Data()) + ta->ByteOffset());
    }
    return napi_ok;
}

// ============================================================================
// Promises & Scripts
// ============================================================================

napi_status napi_create_promise(napi_env env, napi_deferred* deferred, napi_value* promise) {
    if (!ValidateArgs(env, deferred, promise)) {
        return napi_invalid_arg;
    }
    if (!env->last_exception.IsEmpty()) {
        return env->SetLastError(napi_pending_exception, "An exception is pending");
    }
    v8::Local<v8::Context> ctx = env->GetContext();
    v8::MaybeLocal<v8::Promise::Resolver> maybe_resolver = v8::Promise::Resolver::New(ctx);
    if (maybe_resolver.IsEmpty()) {
        return env->SetLastError(napi_generic_failure, "Failed to create promise resolver");
    }
    v8::Local<v8::Promise::Resolver> resolver = maybe_resolver.ToLocalChecked();
    auto def = std::make_unique<napi_deferred__>();
    def->resolver.Reset(env->isolate, resolver);
    *deferred = def.get();
    *promise = dawn::napi_v8::ToNapi(resolver->GetPromise());
    env->deferreds.push_back(std::move(def));
    return napi_ok;
}

napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_value resolution) {
    return ConcludeDeferred(env, deferred, resolution, /*is_resolve=*/true);
}

napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_value rejection) {
    return ConcludeDeferred(env, deferred, rejection, /*is_resolve=*/false);
}

napi_status napi_is_promise(napi_env env, napi_value value, bool* is_promise) {
    if (!ValidateArgs(env, value, is_promise)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_val = dawn::napi_v8::ToV8(value);
    *is_promise = v8_val->IsPromise();
    return napi_ok;
}

napi_status napi_run_script(napi_env env, napi_value script, napi_value* result) {
    if (!ValidateArgs(env, script, result)) {
        return napi_invalid_arg;
    }
    v8::Local<v8::Value> v8_script = dawn::napi_v8::ToV8(script);
    if (!v8_script->IsString()) {
        return env->SetLastError(napi_string_expected, "A string was expected");
    }
    v8::Local<v8::Context> ctx = env->GetContext();
    v8::TryCatch try_catch(env->isolate);
    v8::MaybeLocal<v8::Script> compiled = v8::Script::Compile(ctx, v8_script.As<v8::String>());
    if (compiled.IsEmpty()) {
        return ProcessCallResult(env, try_catch, v8::MaybeLocal<v8::Value>(), nullptr);
    }
    v8::MaybeLocal<v8::Value> eval_result = compiled.ToLocalChecked()->Run(ctx);
    return ProcessCallResult(env, try_catch, eval_result, result);
}

napi_status napi_get_version(node_api_nogc_env env, uint32_t* result) {
    if (env == nullptr || result == nullptr) {
        return napi_invalid_arg;
    }
    *result = NAPI_VERSION;
    return napi_ok;
}

// ============================================================================
// Node-API Stubs
//
// The following functions are not used by dawn.node or the CTS runner.
// However, node-addon-api (<napi-inl.h>) defines inline and virtual destructors
// for Napi::AsyncContext, Napi::CallbackScope, and Napi::AsyncWorker that
// reference these symbols. In debug or unoptimized builds, the compiler emits
// these unused destructors into every translation unit including <napi.h>,
// requiring these symbols to exist at link time to avoid undefined reference errors.
// ============================================================================

napi_status napi_async_destroy(napi_env env, napi_async_context async_context) {
    if (!ValidateArgs(env, async_context)) {
        return napi_invalid_arg;
    }
    return env->SetLastError(napi_generic_failure, "napi_async_destroy is not supported");
}

napi_status napi_close_callback_scope(napi_env env, napi_callback_scope scope) {
    if (!ValidateArgs(env, scope)) {
        return napi_invalid_arg;
    }
    return env->SetLastError(napi_generic_failure, "napi_close_callback_scope is not supported");
}

napi_status napi_delete_async_work(napi_env env, napi_async_work work) {
    if (!ValidateArgs(env, work)) {
        return napi_invalid_arg;
    }
    return env->SetLastError(napi_generic_failure, "napi_delete_async_work is not supported");
}

}  // extern "C"
