dawn_node: Add interop/Core.[h,cpp]
Core hand-written interop classes, which the template-generated code makes heavy use of. There's currently no build rules for these files. These will come in a followup change. Bug: dawn:1123 Change-Id: Id56f96533070acc8ee581d6f44f83b5374662215 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64901 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
aea848e1ac
commit
6d8a03e707
|
@ -0,0 +1,154 @@
|
|||
// Copyright 2021 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/dawn_node/interop/Core.h"
|
||||
|
||||
namespace wgpu { namespace interop {
|
||||
|
||||
bool Converter<bool>::FromJS(Napi::Env env, Napi::Value value, bool& out) {
|
||||
if (value.IsBoolean()) {
|
||||
out = value.ToBoolean();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<bool>::ToJS(Napi::Env env, bool value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<std::string>::FromJS(Napi::Env env, Napi::Value value, std::string& out) {
|
||||
if (value.IsString()) {
|
||||
out = value.ToString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<std::string>::ToJS(Napi::Env env, std::string value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<int8_t>::FromJS(Napi::Env env, Napi::Value value, int8_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Int32Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<int8_t>::ToJS(Napi::Env env, int8_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<uint8_t>::FromJS(Napi::Env env, Napi::Value value, uint8_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Uint32Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<uint8_t>::ToJS(Napi::Env env, uint8_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<int16_t>::FromJS(Napi::Env env, Napi::Value value, int16_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Int32Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<int16_t>::ToJS(Napi::Env env, int16_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<uint16_t>::FromJS(Napi::Env env, Napi::Value value, uint16_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Uint32Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<uint16_t>::ToJS(Napi::Env env, uint16_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<int32_t>::FromJS(Napi::Env env, Napi::Value value, int32_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Int32Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<int32_t>::ToJS(Napi::Env env, int32_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<uint32_t>::FromJS(Napi::Env env, Napi::Value value, uint32_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Uint32Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<uint32_t>::ToJS(Napi::Env env, uint32_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<int64_t>::FromJS(Napi::Env env, Napi::Value value, int64_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().Int64Value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<int64_t>::ToJS(Napi::Env env, int64_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<uint64_t>::FromJS(Napi::Env env, Napi::Value value, uint64_t& out) {
|
||||
if (value.IsNumber()) {
|
||||
// Note that the JS Number type only stores doubles, so the max integer
|
||||
// range of values without precision loss is -2^53 to 2^53 (52 bit mantissa
|
||||
// with 1 implicit bit). This is why there's no UInt64Value() function.
|
||||
out = static_cast<uint64_t>(value.ToNumber().Int64Value());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<uint64_t>::ToJS(Napi::Env env, uint64_t value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<float>::FromJS(Napi::Env env, Napi::Value value, float& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().FloatValue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<float>::ToJS(Napi::Env env, float value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
bool Converter<double>::FromJS(Napi::Env env, Napi::Value value, double& out) {
|
||||
if (value.IsNumber()) {
|
||||
out = value.ToNumber().DoubleValue();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Napi::Value Converter<double>::ToJS(Napi::Env env, double value) {
|
||||
return Napi::Value::From(env, value);
|
||||
}
|
||||
|
||||
}} // namespace wgpu::interop
|
|
@ -0,0 +1,571 @@
|
|||
// Copyright 2021 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file provides core interop helpers used by the code generated by the
|
||||
// templates.
|
||||
|
||||
#ifndef DAWN_NODE_INTEROP_CORE_WEBGPU_H_
|
||||
#define DAWN_NODE_INTEROP_CORE_WEBGPU_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "napi.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
|
||||
|
||||
namespace wgpu { namespace 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;
|
||||
|
||||
template <typename T>
|
||||
using FrozenArray = std::vector<T>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Promise<T> is a templated wrapper around a JavaScript promise, which can
|
||||
// resolve to the template type T.
|
||||
template <typename T>
|
||||
class Promise {
|
||||
public:
|
||||
// Constructor
|
||||
Promise(Napi::Env env) : deferred(Napi::Promise::Deferred::New(env)) {
|
||||
}
|
||||
|
||||
// Implicit conversion operators to Napi promises.
|
||||
inline operator napi_value() const {
|
||||
return deferred.Promise();
|
||||
}
|
||||
inline operator Napi::Value() const {
|
||||
return deferred.Promise();
|
||||
}
|
||||
inline operator Napi::Promise() const {
|
||||
return deferred.Promise();
|
||||
}
|
||||
|
||||
// Resolve() fulfills the promise with the given value.
|
||||
void Resolve(T&& value) const {
|
||||
deferred.Resolve(ToJS(deferred.Env(), std::forward<T>(value)));
|
||||
}
|
||||
|
||||
// Reject() rejects the promise with the given failure value.
|
||||
void Reject(Napi::Object obj) const {
|
||||
deferred.Reject(obj);
|
||||
}
|
||||
void Reject(Napi::Error err) const {
|
||||
deferred.Reject(err.Value());
|
||||
}
|
||||
void Reject(std::string err) const {
|
||||
Reject(Napi::Error::New(deferred.Env(), err));
|
||||
}
|
||||
|
||||
private:
|
||||
Napi::Promise::Deferred deferred;
|
||||
};
|
||||
|
||||
// Specialization for Promises that resolve with no value
|
||||
template <>
|
||||
class Promise<void> {
|
||||
public:
|
||||
// Constructor
|
||||
Promise(Napi::Env env) : deferred(Napi::Promise::Deferred::New(env)) {
|
||||
}
|
||||
|
||||
// Implicit conversion operators to Napi promises.
|
||||
inline operator napi_value() const {
|
||||
return deferred.Promise();
|
||||
}
|
||||
inline operator Napi::Value() const {
|
||||
return deferred.Promise();
|
||||
}
|
||||
inline operator Napi::Promise() const {
|
||||
return deferred.Promise();
|
||||
}
|
||||
|
||||
// Resolve() fulfills the promise.
|
||||
void Resolve() const {
|
||||
deferred.Resolve(deferred.Env().Undefined());
|
||||
}
|
||||
|
||||
// Reject() rejects the promise with the given failure value.
|
||||
void Reject(Napi::Object obj) const {
|
||||
deferred.Reject(obj);
|
||||
}
|
||||
void Reject(Napi::Error err) const {
|
||||
deferred.Reject(err.Value());
|
||||
}
|
||||
void Reject(std::string err) const {
|
||||
Reject(Napi::Error::New(deferred.Env(), err));
|
||||
}
|
||||
|
||||
private:
|
||||
Napi::Promise::Deferred deferred;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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'.
|
||||
// // Returns true on success, false on failure.
|
||||
// static bool 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 bool FromJS(Napi::Env, Napi::Value value, Napi::Object& out) {
|
||||
if (value.IsObject()) {
|
||||
out = value.ToObject();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static inline Napi::Value ToJS(Napi::Env, Napi::Object value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<ArrayBuffer> {
|
||||
public:
|
||||
static inline bool FromJS(Napi::Env, Napi::Value value, ArrayBuffer& out) {
|
||||
if (value.IsArrayBuffer()) {
|
||||
out = value.As<ArrayBuffer>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<Napi::TypedArray> {
|
||||
public:
|
||||
static inline bool FromJS(Napi::Env, Napi::Value value, Napi::TypedArray& out) {
|
||||
if (value.IsTypedArray()) {
|
||||
out = value.As<Napi::TypedArray>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
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 bool 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 true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
static inline Napi::Value ToJS(Napi::Env, ArrayBuffer value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<std::string> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, std::string&);
|
||||
static Napi::Value ToJS(Napi::Env, std::string);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<bool> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, bool&);
|
||||
static Napi::Value ToJS(Napi::Env, bool);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<int8_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, int8_t&);
|
||||
static Napi::Value ToJS(Napi::Env, int8_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<uint8_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, uint8_t&);
|
||||
static Napi::Value ToJS(Napi::Env, uint8_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<int16_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, int16_t&);
|
||||
static Napi::Value ToJS(Napi::Env, int16_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<uint16_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, uint16_t&);
|
||||
static Napi::Value ToJS(Napi::Env, uint16_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<int32_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, int32_t&);
|
||||
static Napi::Value ToJS(Napi::Env, int32_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<uint32_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, uint32_t&);
|
||||
static Napi::Value ToJS(Napi::Env, uint32_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<int64_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, int64_t&);
|
||||
static Napi::Value ToJS(Napi::Env, int64_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<uint64_t> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, uint64_t&);
|
||||
static Napi::Value ToJS(Napi::Env, uint64_t);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<float> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, float&);
|
||||
static Napi::Value ToJS(Napi::Env, float);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Converter<double> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env, Napi::Value, double&);
|
||||
static Napi::Value ToJS(Napi::Env, double);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Converter<Interface<T>> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env env, Napi::Value value, Interface<T>& out) {
|
||||
if (value.IsObject()) {
|
||||
auto obj = value.As<Napi::Object>();
|
||||
if (T::Unwrap(obj)) {
|
||||
out = Interface<T>(obj);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static Napi::Value ToJS(Napi::Env env, const Interface<T>& value) {
|
||||
return {env, value};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Converter<std::optional<T>> {
|
||||
public:
|
||||
static bool FromJS(Napi::Env env, Napi::Value value, std::optional<T>& out) {
|
||||
if (value.IsNull() || value.IsUndefined()) {
|
||||
out.reset();
|
||||
return true;
|
||||
}
|
||||
T v{};
|
||||
if (!Converter<T>::FromJS(env, value, v)) {
|
||||
return false;
|
||||
}
|
||||
out = std::move(v);
|
||||
return true;
|
||||
}
|
||||
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 bool FromJS(Napi::Env env, Napi::Value value, std::vector<T>& out) {
|
||||
if (!value.IsArray()) {
|
||||
return false;
|
||||
}
|
||||
auto arr = value.As<Napi::Array>();
|
||||
std::vector<T> vec(arr.Length());
|
||||
for (size_t i = 0; i < vec.size(); i++) {
|
||||
if (!Converter<T>::FromJS(env, arr[static_cast<uint32_t>(i)], vec[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
out = std::move(vec);
|
||||
return true;
|
||||
}
|
||||
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 bool FromJS(Napi::Env env, Napi::Value value, std::unordered_map<K, V>& out) {
|
||||
if (!value.IsObject()) {
|
||||
return false;
|
||||
}
|
||||
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>(map.size()); i++) {
|
||||
K key{};
|
||||
V value{};
|
||||
if (!Converter<K>::FromJS(env, keys[i], key) ||
|
||||
!Converter<V>::FromJS(env, obj.Get(keys[i]), value)) {
|
||||
return false;
|
||||
}
|
||||
map[key] = value;
|
||||
}
|
||||
out = std::move(map);
|
||||
return true;
|
||||
}
|
||||
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 bool TryFromJS(Napi::Env env,
|
||||
Napi::Value value,
|
||||
std::variant<TYPES...>& out) {
|
||||
TY v{};
|
||||
if (Converter<TY>::FromJS(env, value, v)) {
|
||||
out = std::move(v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename... TN>
|
||||
static inline bool TryFromJS(Napi::Env env,
|
||||
Napi::Value value,
|
||||
std::variant<TYPES...>& out) {
|
||||
if (TryFromJS<T0>(env, value, out)) {
|
||||
return true;
|
||||
}
|
||||
return TryFromJS<T1, TN...>(env, value, out);
|
||||
}
|
||||
|
||||
public:
|
||||
static inline bool 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 bool FromJS(Napi::Env, Napi::Value, Promise<T>&) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
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 bool 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 FromJSOptional() returns true and 'out' is left
|
||||
// unassigned.
|
||||
// Returns true on success, false on failure.
|
||||
template <typename T>
|
||||
inline bool FromJSOptional(Napi::Env env, Napi::Value value, T& out) {
|
||||
if (value.IsNull() || value.IsUndefined()) {
|
||||
return true;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
// FromJS() is a helper function for bulk converting the arguments of 'info'.
|
||||
// PARAM_TYPES is a std::tuple<> describing the C++ function parameter types.
|
||||
// Returns true on success, false on failure.
|
||||
template <typename PARAM_TYPES, int BASE_INDEX = 0>
|
||||
inline bool 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>;
|
||||
if (!FromJS<T>(info.Env(), info[BASE_INDEX], std::get<BASE_INDEX>(args))) {
|
||||
return false;
|
||||
}
|
||||
return FromJS<PARAM_TYPES, BASE_INDEX + 1>(info, args);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace wgpu::interop
|
||||
|
||||
#endif // DAWN_NODE_INTEROP_CORE_WEBGPU_H_
|
Loading…
Reference in New Issue