// Copyright 2021 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.

// This file provides core interop helpers used by the code generated by the
// templates.

#ifndef SRC_DAWN_NODE_INTEROP_CORE_H_
#define SRC_DAWN_NODE_INTEROP_CORE_H_

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <limits>
#include <optional>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

#include "src/dawn/node/interop/NodeAPI.h"
#include "src/dawn/node/utils/Debug.h"

#define ENABLE_INTEROP_LOGGING 0  // Enable for verbose interop logging

#if ENABLE_INTEROP_LOGGING
#define INTEROP_LOG(...) LOG(__VA_ARGS__)
#else
#define INTEROP_LOG(...)
#endif

// A helper macro for constructing a PromiseInfo with the current file, function and line.
// See PromiseInfo
#define PROMISE_INFO                     \
    ::wgpu::interop::PromiseInfo {       \
        __FILE__, __FUNCTION__, __LINE__ \
    }

namespace wgpu::interop {

////////////////////////////////////////////////////////////////////////////////
// Primitive JavaScript types
////////////////////////////////////////////////////////////////////////////////
using Object = Napi::Object;
using ArrayBuffer = Napi::ArrayBuffer;
using Int8Array = Napi::TypedArrayOf<int8_t>;
using Int16Array = Napi::TypedArrayOf<int16_t>;
using Int32Array = Napi::TypedArrayOf<int32_t>;
using Uint8Array = Napi::TypedArrayOf<uint8_t>;
using Uint16Array = Napi::TypedArrayOf<uint16_t>;
using Uint32Array = Napi::TypedArrayOf<uint32_t>;
using Float32Array = Napi::TypedArrayOf<float>;
using Float64Array = Napi::TypedArrayOf<double>;
using DataView = Napi::TypedArray;

// Datatype used for undefined values.
struct UndefinedType {};
static constexpr UndefinedType Undefined;

template <typename T>
using FrozenArray = std::vector<T>;

// A wrapper class for integers that's as transparent as possible and is used to distinguish
// that the type is tagged with the [Clamp] WebIDL attribute.
template <typename T>
struct ClampedInteger {
    static_assert(std::is_integral_v<T>);

    using IntegerType = T;
    ClampedInteger() : value(0) {}
    // NOLINTNEXTLINE(runtime/explicit)
    ClampedInteger(T value) : value(value) {}
    operator T() const { return value; }
    T value;
};

// A wrapper class for integers that's as transparent as possible and is used to distinguish
// that the type is tagged with the [EnforceRange] WebIDL attribute.
template <typename T>
struct EnforceRangeInteger {
    static_assert(std::is_integral_v<T>);

    using IntegerType = T;
    EnforceRangeInteger() : value(0) {}
    // NOLINTNEXTLINE(runtime/explicit)
    EnforceRangeInteger(T value) : value(value) {}
    operator T() const { return value; }
    T value;
};

////////////////////////////////////////////////////////////////////////////////
// Result
////////////////////////////////////////////////////////////////////////////////

// Result is used to hold an success / error state by functions that perform JS <-> C++
// conversion
struct [[nodiscard]] Result {
    // Returns true if the operation succeeded, false if there was an error
    inline explicit operator bool() const { return error.empty(); }

    // If Result is an error, then a new Error is returned with the
    // stringified values append to the error message.
    // If Result is a success, then a success Result is returned.
    template <typename... VALUES>
    Result Append(VALUES&&... values) {
        if (*this) {
            return *this;
        }
        std::stringstream ss;
        ss << error << "\n";
        utils::Write(ss, std::forward<VALUES>(values)...);
        return {ss.str()};
    }

    // The error message, if the operation failed.
    std::string error;
};

// A successful result
extern Result Success;

// Returns a Result with the given error message
Result Error(std::string msg);

////////////////////////////////////////////////////////////////////////////////
// Interface<T>
////////////////////////////////////////////////////////////////////////////////

// Interface<T> is a templated wrapper around a JavaScript object, which
// implements the template-generated interface type T. Interfaces are returned
// by either calling T::Bind() or T::Create().
template <typename T>
class Interface {
  public:
    // Constructs an Interface with no JS object.
    inline Interface() {}

    // Constructs an Interface wrapping the given JS object.
    // The JS object must have been created with a call to T::Bind().
    explicit inline Interface(Napi::Object o) : object(o) {}

    // Implicit conversion operators to Napi objects.
    inline operator napi_value() const { return object; }
    inline operator const Napi::Value&() const { return object; }
    inline operator const Napi::Object&() const { return object; }

    // Member and dereference operators
    inline T* operator->() const { return T::Unwrap(object); }
    inline T* operator*() const { return T::Unwrap(object); }

    // As<IMPL>() returns the unwrapped object cast to the implementation type.
    // The interface implementation *must* be of the template type IMPL.
    template <typename IMPL>
    inline IMPL* As() const {
        return static_cast<IMPL*>(T::Unwrap(object));
    }

  private:
    Napi::Object object;
};

////////////////////////////////////////////////////////////////////////////////
// Promise<T>
////////////////////////////////////////////////////////////////////////////////

// Info holds details about where the promise was constructed.
// Used for printing debug messages when a promise is finalized without being resolved
// or rejected.
// Use the PROMISE_INFO macro to populate this structure.
struct PromiseInfo {
    const char* file = nullptr;
    const char* function = nullptr;
    int line = 0;
};

enum class PromiseState {
    Pending,
    Resolved,
    Rejected,
    Discarded,
};

namespace detail {
// Base class for Promise<T> specializations.
class PromiseBase {
  public:
    // Implicit conversion operators to Napi promises.
    inline operator napi_value() const { return state_->deferred.Promise(); }
    inline operator Napi::Value() const { return state_->deferred.Promise(); }
    inline operator Napi::Promise() const { return state_->deferred.Promise(); }

    // Comparison operator between promises
    bool operator==(const PromiseBase& other) { return state_ == other.state_; }
    bool operator!=(const PromiseBase& other) { return !(*this == other); }

    // Reject() rejects the promise with the given failure value.
    void Reject(Napi::Value value) const {
        state_->deferred.Reject(value);
        state_->state = PromiseState::Rejected;
    }
    void Reject(Napi::Error err) const { Reject(err.Value()); }
    void Reject(std::string err) const { Reject(Napi::Error::New(state_->deferred.Env(), err)); }

    PromiseState GetState() const { return state_->state; }

    // Place the promise into the Discarded state.
    // This state will not throw a fatal error if this promise has not been rejected or resolved by
    // the time it is finalized. This is useful for Node tear-down where the attempting to create
    // new objects will result in a fatal error.
    void Discard() { state_->state = PromiseState::Discarded; }

  protected:
    void Resolve(Napi::Value value) const {
        state_->deferred.Resolve(value);
        state_->state = PromiseState::Resolved;
    }

    struct State {
        Napi::Promise::Deferred deferred;
        PromiseInfo info;
        PromiseState state = PromiseState::Pending;
    };

    PromiseBase(Napi::Env env, const PromiseInfo& info)
        : state_(new State{Napi::Promise::Deferred::New(env), info}) {
        state_->deferred.Promise().AddFinalizer(
            [](Napi::Env, State* state) {
                if (state->state == PromiseState::Pending) {
                    ::wgpu::utils::Fatal("Promise not resolved or rejected", state->info.file,
                                         state->info.line, state->info.function);
                }
                delete state;
            },
            state_);
    }

    State* const state_;
};
}  // namespace detail

// A tag used in a Promise constructor to say it won't be used and doesn't need to be initialized.
struct UnusedPromiseTag {};
static constexpr UnusedPromiseTag kUnusedPromise;

// Promise<T> is a templated wrapper around a JavaScript promise, which can
// resolve to the template type T.
template <typename T>
class Promise : public detail::PromiseBase {
  public:
    // Constructor
    Promise(Napi::Env env, const PromiseInfo& info) : PromiseBase(env, info) {}
    Promise(Napi::Env env, UnusedPromiseTag) : PromiseBase(env, PROMISE_INFO) {
        Reject("Unused Promise, you should never see this!");
    }

    // Resolve() fulfills the promise with the given value.
    void Resolve(T&& value) const {
        PromiseBase::Resolve(ToJS(state_->deferred.Env(), std::forward<T>(value)));
    }
};

// Specialization for Promises that resolve with no value
template <>
class Promise<void> : public detail::PromiseBase {
  public:
    // Constructor
    Promise(Napi::Env env, const PromiseInfo& info) : PromiseBase(env, info) {}
    Promise(Napi::Env env, UnusedPromiseTag) : PromiseBase(env, PROMISE_INFO) {
        Reject("Unused Promise, you should never see this!");
    }

    // Resolve() fulfills the promise.
    void Resolve() const { PromiseBase::Resolve(state_->deferred.Env().Undefined()); }
};

////////////////////////////////////////////////////////////////////////////////
// Converter<T>
////////////////////////////////////////////////////////////////////////////////

// Converter<T> is specialized for each type T which can be converted from C++
// to JavaScript, or JavaScript to C++.
// Each specialization of Converter<T> is expected to have two static methods
// with the signatures:
//
//  // FromJS() converts the JavaScript value 'in' to the C++ value 'out'.
//  static Result FromJS(Napi::Env, Napi::Value in, T& out);
//
//  // ToJS() converts the C++ value 'in' to a JavaScript value, and returns
//  // this value.
//  static Napi::Value ToJS(Napi::Env, T in);
template <typename T>
class Converter {};

template <>
class Converter<Napi::Object> {
  public:
    static inline Result FromJS(Napi::Env, Napi::Value value, Napi::Object& out) {
        if (value.IsObject()) {
            out = value.ToObject();
            return Success;
        }
        return Error("value is not an object");
    }
    static inline Napi::Value ToJS(Napi::Env, Napi::Object value) { return value; }
};

template <>
class Converter<ArrayBuffer> {
  public:
    static inline Result FromJS(Napi::Env, Napi::Value value, ArrayBuffer& out) {
        if (value.IsArrayBuffer()) {
            out = value.As<ArrayBuffer>();
            return Success;
        }
        return Error("value is not a ArrayBuffer");
    }
    static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) { return value; }
};

template <>
class Converter<Napi::TypedArray> {
  public:
    static inline Result FromJS(Napi::Env, Napi::Value value, Napi::TypedArray& out) {
        if (value.IsTypedArray()) {
            out = value.As<Napi::TypedArray>();
            return Success;
        }
        return Error("value is not a TypedArray");
    }
    static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) { return value; }
};

template <typename T>
class Converter<Napi::TypedArrayOf<T>> {
  public:
    // clang-format off
        // The Napi element type of T
        static constexpr napi_typedarray_type element_type =
              std::is_same<T, int8_t>::value   ? napi_int8_array
            : std::is_same<T, uint8_t>::value  ? napi_uint8_array
            : std::is_same<T, int16_t>::value  ? napi_int16_array
            : std::is_same<T, uint16_t>::value ? napi_uint16_array
            : std::is_same<T, int32_t>::value  ? napi_int32_array
            : std::is_same<T, uint32_t>::value ? napi_uint32_array
            : std::is_same<T, float>::value    ? napi_float32_array
            : std::is_same<T, double>::value   ? napi_float64_array
            : std::is_same<T, int64_t>::value  ? napi_bigint64_array
            : std::is_same<T, uint64_t>::value ? napi_biguint64_array
            : static_cast<napi_typedarray_type>(-1);
    // clang-format on
    static_assert(static_cast<int>(element_type) >= 0,
                  "unsupported T type for Napi::TypedArrayOf<T>");
    static inline Result FromJS(Napi::Env, Napi::Value value, Napi::TypedArrayOf<T>& out) {
        if (value.IsTypedArray()) {
            auto arr = value.As<Napi::TypedArrayOf<T>>();
            if (arr.TypedArrayType() == element_type) {
                out = arr;
                return Success;
            }
            return Error("value is not a TypedArray of the correct element type");
        }
        return Error("value is not a TypedArray");
    }
    static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) { return value; }
};

template <>
class Converter<std::string> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, std::string&);
    static Napi::Value ToJS(Napi::Env, std::string);
};

template <>
class Converter<bool> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, bool&);
    static Napi::Value ToJS(Napi::Env, bool);
};

template <>
class Converter<int8_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, int8_t&);
    static Napi::Value ToJS(Napi::Env, int8_t);
};

template <>
class Converter<uint8_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, uint8_t&);
    static Napi::Value ToJS(Napi::Env, uint8_t);
};

template <>
class Converter<int16_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, int16_t&);
    static Napi::Value ToJS(Napi::Env, int16_t);
};

template <>
class Converter<uint16_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, uint16_t&);
    static Napi::Value ToJS(Napi::Env, uint16_t);
};

template <>
class Converter<int32_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, int32_t&);
    static Napi::Value ToJS(Napi::Env, int32_t);
};

template <>
class Converter<uint32_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, uint32_t&);
    static Napi::Value ToJS(Napi::Env, uint32_t);
};

template <>
class Converter<int64_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, int64_t&);
    static Napi::Value ToJS(Napi::Env, int64_t);
};

template <>
class Converter<uint64_t> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, uint64_t&);
    static Napi::Value ToJS(Napi::Env, uint64_t);
};

// Sometimes size_t is uint32_t, or uint64_t. Only define the conversion to size_t if it is a
// unique type, otherwise we have C++ compilation error for the redefinition of a template.
namespace detail {
struct InvalidType;
static constexpr bool kSizetIsUniqueType =
    !std::is_same_v<size_t, uint32_t> && !std::is_same_v<size_t, uint64_t>;
}  // namespace detail

template <>
class Converter<std::conditional_t<detail::kSizetIsUniqueType, size_t, detail::InvalidType>> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, size_t&);
    static Napi::Value ToJS(Napi::Env, size_t);
};

template <>
class Converter<float> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, float&);
    static Napi::Value ToJS(Napi::Env, float);
};

template <>
class Converter<double> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, double&);
    static Napi::Value ToJS(Napi::Env, double);
};

// [Clamp]ed integers must convert values outside of the integer range by clamping them.
template <typename T>
class Converter<ClampedInteger<T>> {
  public:
    static Result FromJS(Napi::Env env, Napi::Value value, ClampedInteger<T>& out) {
        double doubleValue;
        Result res = Converter<double>::FromJS(env, value, doubleValue);
        if (!res) {
            return res;
        }

        // Check for clamping first.
        constexpr T kMin = std::numeric_limits<T>::min();
        constexpr T kMax = std::numeric_limits<T>::max();
        if (doubleValue < kMin) {
            out = kMin;
            return Success;
        }
        if (doubleValue > kMax) {
            out = kMax;
            return Success;
        }

        // Yay, no clamping! We can convert the integer type as usual.
        T correctValue;
        res = Converter<T>::FromJS(env, value, correctValue);
        if (!res) {
            return res;
        }
        out = correctValue;
        return Success;
    }
    static Napi::Value ToJS(Napi::Env env, const ClampedInteger<T>& value) {
        return Converter<T>::ToJS(env, value.value);
    }
};

// [EnforceRange] integers cause a TypeError when converted from out of range values
template <typename T>
class Converter<EnforceRangeInteger<T>> {
  public:
    static Result FromJS(Napi::Env env, Napi::Value value, EnforceRangeInteger<T>& out) {
        double doubleValue;
        Result res = Converter<double>::FromJS(env, value, doubleValue);
        if (!res) {
            return res;
        }

        // Check for out of range and throw a type error.
        // Note that the number must both be representable in the integer type, but also below
        // MAX_SAFE_INTEGER after which consecutive double values might skip over some integer
        // values.
        constexpr double kMaxSafeInteger = (uint64_t(1) << 53) - uint64_t(1);
        constexpr double kMinSafeInteger = -kMaxSafeInteger;

        constexpr double kMin =
            std::max(kMinSafeInteger, static_cast<double>(std::numeric_limits<T>::min()));
        constexpr double kMax =
            std::min(kMaxSafeInteger, static_cast<double>(std::numeric_limits<T>::max()));
        if (!(kMin <= doubleValue && doubleValue <= kMax)) {
            return Error("Values are out of the range of that integer.");
        }

        // Yay, no error! We can convert the integer type as usual.
        T correctValue;
        res = Converter<T>::FromJS(env, value, correctValue);
        if (!res) {
            return res;
        }
        out = correctValue;
        return Success;
    }
    static Napi::Value ToJS(Napi::Env env, const EnforceRangeInteger<T>& value) {
        return Converter<T>::ToJS(env, value.value);
    }
};

template <>
class Converter<UndefinedType> {
  public:
    static Result FromJS(Napi::Env, Napi::Value, UndefinedType&);
    static Napi::Value ToJS(Napi::Env, UndefinedType);
};

template <typename T>
class Converter<Interface<T>> {
  public:
    static Result FromJS(Napi::Env env, Napi::Value value, Interface<T>& out) {
        if (!value.IsObject()) {
            return Error("value is not object");
        }
        auto obj = value.As<Napi::Object>();
        if (!T::Unwrap(obj)) {
            return Error("object is not of the correct interface type");
        }
        out = Interface<T>(obj);
        return Success;
    }
    static Napi::Value ToJS(Napi::Env env, const Interface<T>& value) { return {env, value}; }
};

template <typename T>
class Converter<std::optional<T>> {
  public:
    static Result FromJS(Napi::Env env, Napi::Value value, std::optional<T>& out) {
        if (value.IsNull() || value.IsUndefined()) {
            out.reset();
            return Success;
        }
        T v{};
        auto res = Converter<T>::FromJS(env, value, v);
        if (!res) {
            return res;
        }
        out = std::move(v);
        return Success;
    }
    static Napi::Value ToJS(Napi::Env env, std::optional<T> value) {
        if (value.has_value()) {
            return Converter<T>::ToJS(env, value.value());
        }
        return env.Null();
    }
};

template <typename T>
class Converter<std::vector<T>> {
  public:
    static inline Result FromJS(Napi::Env env, Napi::Value value, std::vector<T>& out) {
        if (!value.IsArray()) {
            return Error("value is not an array");
        }
        auto arr = value.As<Napi::Array>();
        std::vector<T> vec(arr.Length());
        for (size_t i = 0; i < vec.size(); i++) {
            auto res = Converter<T>::FromJS(env, arr[static_cast<uint32_t>(i)], vec[i]);
            if (!res) {
                return res.Append("for array element ", i);
            }
        }
        out = std::move(vec);
        return Success;
    }
    static inline Napi::Value ToJS(Napi::Env env, const std::vector<T>& vec) {
        auto arr = Napi::Array::New(env, vec.size());
        for (size_t i = 0; i < vec.size(); i++) {
            arr.Set(static_cast<uint32_t>(i), Converter<T>::ToJS(env, vec[i]));
        }
        return arr;
    }
};

template <typename K, typename V>
class Converter<std::unordered_map<K, V>> {
  public:
    static inline Result FromJS(Napi::Env env, Napi::Value value, std::unordered_map<K, V>& out) {
        if (!value.IsObject()) {
            return Error("value is not an object");
        }
        auto obj = value.ToObject();
        auto keys = obj.GetPropertyNames();
        std::unordered_map<K, V> map(keys.Length());
        for (uint32_t i = 0; i < static_cast<uint32_t>(keys.Length()); i++) {
            K key{};
            V value{};
            auto key_res = Converter<K>::FromJS(env, keys[i], key);
            if (!key_res) {
                return key_res.Append("for object key");
            }
            auto value_res = Converter<V>::FromJS(env, obj.Get(keys[i]), value);
            if (!value_res) {
                return value_res.Append("for object value of key: ", key);
            }
            map[key] = value;
        }
        out = std::move(map);
        return Success;
    }
    static inline Napi::Value ToJS(Napi::Env env, std::unordered_map<K, V> value) {
        auto obj = Napi::Object::New(env);
        for (auto it : value) {
            obj.Set(Converter<K>::ToJS(env, it.first), Converter<V>::ToJS(env, it.second));
        }
        return obj;
    }
};

template <typename... TYPES>
class Converter<std::variant<TYPES...>> {
    template <typename TY>
    static inline Result TryFromJS(Napi::Env env, Napi::Value value, std::variant<TYPES...>& out) {
        TY v{};
        auto res = Converter<TY>::FromJS(env, value, v);
        if (!res) {
            return Error("no possible types matched");
        }
        out = std::move(v);
        return Success;
    }

    template <typename T0, typename T1, typename... TN>
    static inline Result TryFromJS(Napi::Env env, Napi::Value value, std::variant<TYPES...>& out) {
        if (TryFromJS<T0>(env, value, out)) {
            return Success;
        }
        return TryFromJS<T1, TN...>(env, value, out);
    }

  public:
    static inline Result FromJS(Napi::Env env, Napi::Value value, std::variant<TYPES...>& out) {
        return TryFromJS<TYPES...>(env, value, out);
    }
    static inline Napi::Value ToJS(Napi::Env env, std::variant<TYPES...> value) {
        return std::visit(
            [&](auto&& v) {
                using T = std::remove_cv_t<std::remove_reference_t<decltype(v)>>;
                return Converter<T>::ToJS(env, v);
            },
            value);
    }
};

template <typename T>
class Converter<Promise<T>> {
  public:
    static inline Result FromJS(Napi::Env env, Napi::Value, Promise<T>&) { UNIMPLEMENTED(env, {}); }
    static inline Napi::Value ToJS(Napi::Env, Promise<T> promise) { return promise; }
};

////////////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////////////

// FromJS() is a helper function which delegates to
// Converter<T>::FromJS()
template <typename T>
inline Result FromJS(Napi::Env env, Napi::Value value, T& out) {
    return Converter<T>::FromJS(env, value, out);
}

// FromJSOptional() is similar to FromJS(), but if 'value' is either null
// or undefined then 'out' is left unassigned.
template <typename T>
inline Result FromJSOptional(Napi::Env env, Napi::Value value, T& out) {
    if (value.IsNull() || value.IsUndefined()) {
        return Success;
    }
    return Converter<T>::FromJS(env, value, out);
}

// ToJS() is a helper function which delegates to Converter<T>::ToJS()
template <typename T>
inline Napi::Value ToJS(Napi::Env env, T&& value) {
    return Converter<std::remove_cv_t<std::remove_reference_t<T>>>::ToJS(env,
                                                                         std::forward<T>(value));
}

// DefaultedParameter can be used in the tuple parameter types passed to
// FromJS(const Napi::CallbackInfo& info, PARAM_TYPES& args), for parameters
// that have a default value. If the argument is omitted in the call, then
// DefaultedParameter::default_value will be assigned to
// DefaultedParameter::value.
template <typename T>
struct DefaultedParameter {
    T value;          // The argument value assigned by FromJS()
    T default_value;  // The default value if no argument supplied

    // Implicit conversion operator. Returns value.
    inline operator const T&() const { return value; }
};

// IsDefaultedParameter<T>::value is true iff T is of type DefaultedParameter.
template <typename T>
struct IsDefaultedParameter {
    static constexpr bool value = false;
};
template <typename T>
struct IsDefaultedParameter<DefaultedParameter<T>> {
    static constexpr bool value = true;
};

// FromJS() is a helper function for bulk converting the arguments of 'info'.
// PARAM_TYPES is a std::tuple<> describing the C++ function parameter types.
// Parameters may be of the templated DefaultedParameter type, in which case
// the parameter will default to the default-value if omitted.
template <typename PARAM_TYPES, int BASE_INDEX = 0>
inline Result FromJS(const Napi::CallbackInfo& info, PARAM_TYPES& args) {
    if constexpr (BASE_INDEX < std::tuple_size_v<PARAM_TYPES>) {
        using T = std::tuple_element_t<BASE_INDEX, PARAM_TYPES>;
        auto& value = info[BASE_INDEX];
        auto& out = std::get<BASE_INDEX>(args);
        if constexpr (IsDefaultedParameter<T>::value) {
            // Parameter has a default value.
            // Check whether the argument was provided.
            if (value.IsNull() || value.IsUndefined()) {
                // Use default value for this parameter
                out.value = out.default_value;
            } else {
                // Argument was provided
                auto res = FromJS(info.Env(), value, out.value);
                if (!res) {
                    return res;
                }
            }
        } else {
            // Parameter does not have a default value.
            auto res = FromJS(info.Env(), value, out);
            if (!res) {
                return res;
            }
        }
        // Convert the rest of the arguments
        return FromJS<PARAM_TYPES, BASE_INDEX + 1>(info, args);
    } else {
        return Success;
    }
}

// Calls a promise-returning function f, catching exceptions and returning them into a rejected
// promise instead. This is used to implement the WebIDL semantics for exceptions in
// promise-returning functions.
template <typename F>
Napi::Value CatchExceptionIntoPromise(Napi::Env env, F&& f) {
    Napi::Value result = f();
    assert(result.IsEmpty() || result.IsPromise());
    if (!env.IsExceptionPending()) {
        return result;
    }

    // For some reason these two calls MUST be in this order or Node crashes in Reject().
    Napi::Error error = env.GetAndClearPendingException();
    Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);

    deferred.Reject(error.Value());
    return deferred.Promise();
}

}  // namespace wgpu::interop

#endif  // SRC_DAWN_NODE_INTEROP_CORE_H_
