231103.1 · 7f4a9ed91bbecb84e39f4bc8030247ce5116ddf8
Reorganize examples into categorized folders (#341)
* refactor: create directory structure to organize exmaples
* test: update test_all to work with new directory structure
* fix: bug in test_all if no package.json scripts
* test: cleanup output of test_all
* fix: remove default test script that throws from thread_safe_function_with_object_wrap
* fix: remove build_with_cmake from .gitignore
* fix: swith to ' from " and remove subdir from getAllTests call
* test: add extra test cases for npm start and just running the pkgJson.main with node
* refactor: move all examples to src directory
* refactor: add numbers to categories so they are ordered in the src folder
* refactor: simplify getAllExamples in test_all.js
* docs: add directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure to README.md
* docs: update directory structure example in readme
* add back build_with_cmake
---------
Co-authored-by: legendecas <legendecas@gmail.com>
reading declarations
Changes to src/2-js-to-native-conversion/object-template-demo/napi/. All files
src/2-js-to-native-conversion/object-template-demo/napi/binding.gyp
@@ -0,0 +1,8 @@+{+ "targets": [+ {+ "target_name": "object_template_demo",+ "sources": [ "object-template-demo.cc", "proxy-template.cc" ]+ }+ ]+}
src/2-js-to-native-conversion/object-template-demo/napi/index.js
@@ -0,0 +1,10 @@+const addon = require('bindings')('object_template_demo');++const interceptor = addon.create();+console.log(interceptor.prop); // 'foo'+interceptor.prop = 'setting a value';+console.log(interceptor.prop); // 'setting a value'+delete interceptor.something;+console.log(interceptor.prop); // 'goober';+console.log(Object.prototype.hasOwnProperty.call(interceptor, "thing")); // true+console.log(Object.keys(interceptor)[0]); // 'value'
src/2-js-to-native-conversion/object-template-demo/napi/node-api-common.h
@@ -0,0 +1,141 @@+#include <node_api.h>+#include <initializer_list>+#include <utility>++// Empty value so that macros here are able to return NULL or void+#define NODE_API_RETVAL_NOTHING // Intentionally blank #define++#define GET_AND_THROW_LAST_ERROR(env) \+ do { \+ const napi_extended_error_info* error_info; \+ napi_get_last_error_info((env), &error_info); \+ bool is_pending; \+ const char* err_message = error_info->error_message; \+ napi_is_exception_pending((env), &is_pending); \+ /* If an exception is already pending, don't rethrow it */ \+ if (!is_pending) { \+ const char* error_message = \+ err_message != NULL ? err_message : "empty error message"; \+ napi_throw_error((env), NULL, error_message); \+ } \+ } while (0)++#define NODE_API_ASSERT_BASE(env, assertion, message, ret_val) \+ do { \+ if (!(assertion)) { \+ napi_throw_error( \+ (env), NULL, "assertion (" #assertion ") failed: " message); \+ return ret_val; \+ } \+ } while (0)++// Returns NULL on failed assertion.+// This is meant to be used inside napi_callback methods.+#define NODE_API_ASSERT(env, assertion, message) \+ NODE_API_ASSERT_BASE(env, assertion, message, NULL)++#define NODE_API_CALL_BASE(env, the_call, ret_val) \+ do { \+ if ((the_call) != napi_ok) { \+ GET_AND_THROW_LAST_ERROR((env)); \+ return ret_val; \+ } \+ } while (0)++// Returns NULL if the_call doesn't return napi_ok.+#define NODE_API_CALL(env, the_call) NODE_API_CALL_BASE(env, the_call, NULL)++// Returns empty if the_call doesn't return napi_ok.+#define NODE_API_CALL_RETURN_VOID(env, the_call) \+ NODE_API_CALL_BASE(env, the_call, NODE_API_RETVAL_NOTHING)++#define CHECK_NAPI(...) \+ do { \+ napi_status res__ = (__VA_ARGS__); \+ if (res__ != napi_ok) { \+ return res__; \+ } \+ } while (0)++#define NAPI_CALL(expr) NODE_API_CALL(env, expr);++#ifdef __cpp_lib_span+#include <span>+using std::span;+#else+/**+ * @brief A span of values that can be used to pass arguments to function.+ *+ * For C++20 we should consider to replace it with std::span.+ */+template <typename T>+struct span {+ constexpr span(std::initializer_list<T> il) noexcept+ : data_{const_cast<T*>(il.begin())}, size_{il.size()} {}+ constexpr span(T* data, size_t size) noexcept : data_{data}, size_{size} {}+ [[nodiscard]] constexpr T* data() const noexcept { return data_; }+ [[nodiscard]] constexpr size_t size() const noexcept { return size_; }+ [[nodiscard]] constexpr T* begin() const noexcept { return data_; }+ [[nodiscard]] constexpr T* end() const noexcept { return data_ + size_; }+ const T& operator[](size_t index) const noexcept { return *(data_ + index); }++ private:+ T* data_;+ size_t size_;+};+#endif // __cpp_lib_span++struct RefHolder {+ RefHolder(std::nullptr_t = nullptr) noexcept {}+ explicit RefHolder(napi_env env, napi_value value) : env_(env) {+ // Start with 2 to avoid ever going to 0 that creates a weak ref.+ napi_create_reference(env, value, 2, &ref_);+ }++ // The class is movable.+ RefHolder(RefHolder&& other) noexcept+ : env_(std::exchange(other.env_, nullptr)),+ ref_(std::exchange(other.ref_, nullptr)) {}++ RefHolder& operator=(RefHolder&& other) noexcept {+ if (this != &other) {+ swap(*this, other);+ RefHolder temp(std::move(other));+ }+ return *this;+ }++ // The class is not copyable.+ RefHolder(const RefHolder& other) = delete;+ RefHolder& operator=(const RefHolder& other) = delete;++ ~RefHolder() noexcept {+ if (env_ != nullptr && ref_ != nullptr) {+ uint32_t refCount{};+ napi_reference_unref(env_, ref_, &refCount);+ if (refCount == 1) {+ napi_delete_reference(env_, ref_);+ }+ }+ }++ operator napi_value() const {+ napi_value result{};+ if (ref_ != nullptr) {+ napi_get_reference_value(env_, ref_, &result);+ }+ return result;+ }++ explicit operator bool() const noexcept { return ref_ != nullptr; }++ friend void swap(RefHolder& left, RefHolder& right) noexcept {+ using std::swap;+ swap(left.env_, right.env_);+ swap(left.ref_, right.ref_);+ }++ private:+ napi_env env_{};+ napi_ref ref_{};+};
src/2-js-to-native-conversion/object-template-demo/napi/object-template-demo.cc
@@ -0,0 +1,306 @@+#include <cstring>+#include <memory>+#include <string>+#include "proxy-template.h"++struct InstanceData {+ RefHolder constructor_;+ std::unique_ptr<ProxyTemplate> proxyTemplate_;+};++class NamedInterceptor {+ char buf[256];++ public:+ NamedInterceptor() { std::strncpy(this->buf, "foo", sizeof(this->buf)); }+ static napi_value Init(napi_env env, napi_value exports);+ static napi_value Constructor(napi_env env);+ static napi_value NewInstance(napi_env env);+ static napi_value New(napi_env env, napi_callback_info info);+ static napi_value CreateNew(napi_env env, napi_callback_info info);++ static napi_status ToUtf8String(napi_env env,+ napi_value value,+ std::string* result);+ static napi_status PropertyGetter(napi_env env,+ napi_value target,+ napi_value key,+ napi_value receiver,+ napi_value* result);+ static napi_status PropertySetter(napi_env env,+ napi_value target,+ napi_value key,+ napi_value value,+ napi_value receiver,+ bool* result);+ static napi_status PropertyDeleter(napi_env env,+ napi_value target,+ napi_value key,+ bool* result);+ static napi_status PropertyQuery(napi_env env,+ napi_value target,+ napi_value key,+ bool* result);+ static napi_status GetOwnPropertyDescriptor(napi_env env,+ napi_value target,+ napi_value key,+ napi_value* result);+ static napi_status OwnKeys(napi_env env,+ napi_value target,+ napi_value* result);+};++napi_value NamedInterceptor::CreateNew(napi_env env, napi_callback_info info) {+ return NamedInterceptor::NewInstance(env);+}++napi_value NamedInterceptor::Init(napi_env env, napi_value exports) {+ napi_value constructor{};+ NAPI_CALL(napi_define_class(env,+ "NamedInterceptor",+ NAPI_AUTO_LENGTH,+ NamedInterceptor::New,+ nullptr,+ 0,+ nullptr,+ &constructor));++ ProxyHandlerBuilder handlerBuilder{};+ NAPI_CALL(handlerBuilder.Get(env, &PropertyGetter));+ NAPI_CALL(handlerBuilder.Set(env, &PropertySetter));+ NAPI_CALL(handlerBuilder.DeleteProperty(env, &PropertyDeleter));+ NAPI_CALL(handlerBuilder.Has(env, &PropertyQuery));+ NAPI_CALL(+ handlerBuilder.GetOwnPropertyDescriptor(env, &GetOwnPropertyDescriptor));+ NAPI_CALL(handlerBuilder.OwnKeys(env, &OwnKeys));+ napi_value proxyHandler{};+ NAPI_CALL(handlerBuilder.NewHandler(env, &proxyHandler));+ NAPI_CALL(napi_set_instance_data(+ env,+ new InstanceData{RefHolder(env, constructor),+ std::make_unique<ProxyTemplate>(env, proxyHandler)},+ [](napi_env /*env*/, void* data, void* /*hint*/) {+ delete static_cast<InstanceData*>(data);+ },+ nullptr));++ napi_value createFunc{};+ NAPI_CALL(napi_create_function(+ env, "create", NAPI_AUTO_LENGTH, CreateNew, nullptr, &createFunc));++ NAPI_CALL(napi_set_named_property(env, exports, "create", createFunc));+ return exports;+}++napi_value NamedInterceptor::Constructor(napi_env env) {+ InstanceData* instanceData{};+ NAPI_CALL(+ napi_get_instance_data(env, reinterpret_cast<void**>(&instanceData)));+ return instanceData->constructor_;+}++napi_value NamedInterceptor::NewInstance(napi_env env) {+ napi_escapable_handle_scope scope{};+ NAPI_CALL(napi_open_escapable_handle_scope(env, &scope));++ napi_value instance{};+ NAPI_CALL(napi_new_instance(env, Constructor(env), 0, nullptr, &instance));++ napi_value result{};+ NAPI_CALL(napi_escape_handle(env, scope, instance, &result));+ NAPI_CALL(napi_close_escapable_handle_scope(env, scope));+ return result;+}++napi_value NamedInterceptor::New(napi_env env, napi_callback_info info) {+ napi_value newTarget{};+ NAPI_CALL(napi_get_new_target(env, info, &newTarget));+ NODE_API_ASSERT_BASE(+ env, newTarget != nullptr, "Must be invoked as a constructor.", nullptr);++ napi_value proxyTarget{}, result{};+ NAPI_CALL(napi_create_function(+ env,+ "target",+ NAPI_AUTO_LENGTH,+ [](napi_env, napi_callback_info) -> napi_value { return nullptr; },+ nullptr,+ &proxyTarget));++ NamedInterceptor* obj = new NamedInterceptor();++ NAPI_CALL(napi_wrap(+ env,+ proxyTarget,+ obj,+ [](napi_env /*env*/, void* data, void* /*hint*/) {+ delete reinterpret_cast<NamedInterceptor*>(data);+ },+ nullptr,+ nullptr));++ InstanceData* instanceData{};+ NAPI_CALL(+ napi_get_instance_data(env, reinterpret_cast<void**>(&instanceData)));+ NAPI_CALL(+ instanceData->proxyTemplate_->NewInstance(env, proxyTarget, &result));+ return result;+}++napi_status NamedInterceptor::ToUtf8String(napi_env env,+ napi_value value,+ std::string* result) {+ size_t size{};+ CHECK_NAPI(napi_get_value_string_utf8(env, value, nullptr, 0, &size));+ result->assign(size, ' ');+ return napi_get_value_string_utf8(+ env, value, &(*result)[0], size + 1, nullptr);+}++napi_status NamedInterceptor::PropertyGetter(napi_env env,+ napi_value target,+ napi_value key,+ napi_value receiver,+ napi_value* result) {+ NamedInterceptor* interceptor{};+ CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));+ std::string keyStr;+ CHECK_NAPI(ToUtf8String(env, key, &keyStr));+ if (keyStr == "prop") {+ return napi_create_string_utf8(+ env, interceptor->buf, NAPI_AUTO_LENGTH, result);+ } else {+ return napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, result);+ }+}++napi_status NamedInterceptor::PropertySetter(napi_env env,+ napi_value target,+ napi_value key,+ napi_value value,+ napi_value receiver,+ bool* result) {+ NamedInterceptor* interceptor{};+ CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));+ std::string keyStr;+ CHECK_NAPI(ToUtf8String(env, key, &keyStr));+ if (keyStr == "prop") {+ std::string valueStr;+ CHECK_NAPI(ToUtf8String(env, value, &valueStr));+ std::strncpy(interceptor->buf, valueStr.data(), sizeof(interceptor->buf));+ *result = true;+ } else {+ *result = false;+ }+ return napi_ok;+}++napi_status NamedInterceptor::PropertyDeleter(napi_env env,+ napi_value target,+ napi_value key,+ bool* result) {+ NamedInterceptor* interceptor{};+ CHECK_NAPI(napi_unwrap(env, target, reinterpret_cast<void**>(&interceptor)));+ std::strncpy(interceptor->buf, "goober", sizeof(interceptor->buf));+ *result = true;+ return napi_ok;+}++napi_status NamedInterceptor::PropertyQuery(napi_env env,+ napi_value target,+ napi_value key,+ bool* result) {+ std::string keyStr;+ CHECK_NAPI(ToUtf8String(env, key, &keyStr));++ if (keyStr == "thing") {+ *result = true;+ }+ if (keyStr == "value") {+ *result = true;+ }+ return napi_ok;+}++napi_status NamedInterceptor::GetOwnPropertyDescriptor(napi_env env,+ napi_value target,+ napi_value key,+ napi_value* result) {+ std::string keyStr;+ CHECK_NAPI(ToUtf8String(env, key, &keyStr));++ if (keyStr == "thing") {+ CHECK_NAPI(napi_create_object(env, result));+ napi_value trueValue{};+ CHECK_NAPI(napi_get_boolean(env, true, &trueValue));+ CHECK_NAPI(+ napi_set_named_property(env, *result, "configurable", trueValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));+ }+ if (keyStr == "value") {+ CHECK_NAPI(napi_create_object(env, result));+ napi_value trueValue{};+ CHECK_NAPI(napi_get_boolean(env, true, &trueValue));+ CHECK_NAPI(+ napi_set_named_property(env, *result, "configurable", trueValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", trueValue));+ }+ if (keyStr == "arguments" || keyStr == "caller") {+ CHECK_NAPI(napi_create_object(env, result));+ napi_value trueValue{}, falseValue{};+ CHECK_NAPI(napi_get_boolean(env, false, &falseValue));+ CHECK_NAPI(napi_get_boolean(env, false, &trueValue));+ CHECK_NAPI(+ napi_set_named_property(env, *result, "configurable", falseValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "writable", falseValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", falseValue));+ napi_value nullValue{};+ CHECK_NAPI(napi_get_null(env, &nullValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "value", nullValue));+ }+ if (keyStr == "prototype") {+ CHECK_NAPI(napi_create_object(env, result));+ napi_value trueValue{}, falseValue{};+ CHECK_NAPI(napi_get_boolean(env, false, &falseValue));+ CHECK_NAPI(napi_get_boolean(env, true, &trueValue));+ CHECK_NAPI(+ napi_set_named_property(env, *result, "configurable", falseValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "writable", trueValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "enumerable", falseValue));+ napi_value nullValue{};+ CHECK_NAPI(napi_get_null(env, &nullValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "value", nullValue));+ }+ return napi_ok;+}++napi_status NamedInterceptor::OwnKeys(napi_env env,+ napi_value target,+ napi_value* result) {+ CHECK_NAPI(napi_get_all_property_names(env,+ target,+ napi_key_own_only,+ napi_key_all_properties,+ napi_key_keep_numbers,+ result));++ uint32_t arraySize{};+ CHECK_NAPI(napi_get_array_length(env, *result, &arraySize));+ napi_value firstElement{};+ CHECK_NAPI(napi_get_element(env, *result, 0, &firstElement));+ CHECK_NAPI(napi_set_element(env, *result, arraySize, firstElement));+ napi_value arraySizeValue{};+ CHECK_NAPI(napi_create_uint32(env, arraySize, &arraySizeValue));+ CHECK_NAPI(napi_set_named_property(env, *result, "length", arraySizeValue));+ napi_value value{};+ CHECK_NAPI(napi_create_string_utf8(env, "value", NAPI_AUTO_LENGTH, &value));+ CHECK_NAPI(napi_set_element(env, *result, 0, value));+ return napi_ok;+}++extern "C" napi_value Init(napi_env env, napi_value exports) {+ return NamedInterceptor::Init(env, exports);+}++NAPI_MODULE(NODE_GYP_MODULE_NAME, Init);
src/2-js-to-native-conversion/object-template-demo/napi/package.json
@@ -0,0 +1,14 @@+{+ "name": "object_template_demo",+ "version": "0.0.0",+ "description": "Intercept named property access using Proxy",+ "main": "index.js",+ "private": true,+ "gypfile": true,+ "scripts": {+ "test": "node index.js"+ },+ "dependencies": {+ "bindings": "~1.5.0"+ }+}
src/2-js-to-native-conversion/object-template-demo/napi/proxy-template.cc
@@ -0,0 +1,726 @@+#include "proxy-template.h"+#include <vector>++namespace {++static napi_status SetTrap(napi_env env,+ napi_value handler,+ const char* propertyName,+ napi_value trap) noexcept {+ if (trap != nullptr) {+ CHECK_NAPI(napi_set_named_property(env, handler, propertyName, trap));+ }+ return napi_ok;+}++using TrapCaller = napi_status (*)(napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result);++struct TrapCallInfo {+ TrapCaller Caller;+ void* trap;+};++template <size_t argCount>+napi_callback CreateTrapCallback() noexcept {+ return [](napi_env env, napi_callback_info info) noexcept -> napi_value {+ TrapCallInfo* trapCallInfo{};+ napi_value args[argCount]{};+ size_t actualArgCount{argCount};+ NAPI_CALL(napi_get_cb_info(env,+ info,+ &actualArgCount,+ args,+ nullptr,+ reinterpret_cast<void**>(&trapCallInfo)));+ NODE_API_ASSERT_BASE(env,+ actualArgCount == argCount,+ "proxy trap requires argCount arguments.",+ nullptr);+ napi_value result{};+ NAPI_CALL(trapCallInfo->Caller(+ env, trapCallInfo->trap, span<napi_value>(args, argCount), &result));+ return result;+ };+}++napi_status ToVector(napi_env env,+ napi_value arrayValue,+ std::vector<napi_value>* result) {+ bool isArray{};+ CHECK_NAPI(napi_is_array(env, arrayValue, &isArray));+ if (isArray) {+ uint32_t arraySize{};+ CHECK_NAPI(napi_get_array_length(env, arrayValue, &arraySize));+ result->reserve(result->size() + arraySize);+ for (uint32_t i = 0; i < arraySize; ++i) {+ napi_value arrayElement{};+ CHECK_NAPI(napi_get_element(env, arrayValue, i, &arrayElement));+ result->push_back(arrayElement);+ }+ }+ return napi_ok;+}++} // namespace++napi_status ProxyHandlerBuilder::NewHandler(napi_env env,+ napi_value* result) noexcept {+ CHECK_NAPI(napi_create_object(env, result));++ CHECK_NAPI(SetTrap(env, *result, "apply", apply_));+ CHECK_NAPI(SetTrap(env, *result, "construct", construct_));+ CHECK_NAPI(SetTrap(env, *result, "defineProperty", defineProperty_));+ CHECK_NAPI(SetTrap(env, *result, "deleteProperty", deleteProperty_));+ CHECK_NAPI(SetTrap(env, *result, "get", get_));+ CHECK_NAPI(SetTrap(+ env, *result, "getOwnPropertyDescriptor", getOwnPropertyDescriptor_));+ CHECK_NAPI(SetTrap(env, *result, "getPrototypeOf", getPrototypeOf_));+ CHECK_NAPI(SetTrap(env, *result, "has", has_));+ CHECK_NAPI(SetTrap(env, *result, "isExtensible", isExtensible_));+ CHECK_NAPI(SetTrap(env, *result, "ownKeys", ownKeys_));+ CHECK_NAPI(SetTrap(env, *result, "preventExtensions", preventExtensions_));+ CHECK_NAPI(SetTrap(env, *result, "set", set_));+ CHECK_NAPI(SetTrap(env, *result, "setPrototypeOf", setPrototypeOf_));+ return napi_ok;+}++napi_value ProxyHandlerBuilder::Apply() noexcept {+ return apply_;+}++void ProxyHandlerBuilder::Apply(napi_value trap) noexcept {+ apply_ = trap;+}++napi_status ProxyHandlerBuilder::Apply(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "apply", NAPI_AUTO_LENGTH, trap, data, &apply_);+}++napi_status ProxyHandlerBuilder::Apply(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value thisArg,+ napi_value argumentList,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], result);+ },+ reinterpret_cast<void*>(trap)};+ return Apply(env, CreateTrapCallback<3>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Apply(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value thisArg,+ napi_span<napi_value> argumentList,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ std::vector<napi_value> argVector;+ CHECK_NAPI(ToVector(env, args[2], &argVector));+ return reinterpret_cast<TrapType>(trap)(+ env,+ args[0],+ args[1],+ span<napi_value>(argVector.data(), argVector.size()),+ result);+ },+ reinterpret_cast<void*>(trap)};+ return Apply(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Construct() noexcept {+ return construct_;+}++void ProxyHandlerBuilder::Construct(napi_value trap) noexcept {+ construct_ = trap;+}++napi_status ProxyHandlerBuilder::Construct(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "construct", NAPI_AUTO_LENGTH, trap, data, &construct_);+}++napi_status ProxyHandlerBuilder::Construct(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value argumentList,+ napi_value newTarget,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], result);+ },+ reinterpret_cast<void*>(trap)};+ return Construct(env, CreateTrapCallback<3>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Construct(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_span<napi_value> argumentList,+ napi_value newTarget,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ std::vector<napi_value> argVector;+ CHECK_NAPI(ToVector(env, args[1], &argVector));+ return reinterpret_cast<TrapType>(trap)(+ env,+ args[0],+ span<napi_value>(argVector.data(), argVector.size()),+ args[2],+ result);+ },+ reinterpret_cast<void*>(trap)};+ return Construct(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::DefineProperty() noexcept {+ return defineProperty_;+}++void ProxyHandlerBuilder::DefineProperty(napi_value trap) noexcept {+ defineProperty_ = trap;+}++napi_status ProxyHandlerBuilder::DefineProperty(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "defineProperty", NAPI_AUTO_LENGTH, trap, data, &defineProperty_);+}++napi_status ProxyHandlerBuilder::DefineProperty(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value descriptor,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], result);+ },+ reinterpret_cast<void*>(trap)};+ return DefineProperty(env, CreateTrapCallback<3>(), &callInfo);+}++napi_status ProxyHandlerBuilder::DefineProperty(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value descriptor,+ bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], &boolResult));+ return napi_get_boolean(env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return DefineProperty(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::DeleteProperty() noexcept {+ return deleteProperty_;+}++void ProxyHandlerBuilder::DeleteProperty(napi_value trap) noexcept {+ deleteProperty_ = trap;+}++napi_status ProxyHandlerBuilder::DeleteProperty(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "deleteProperty", NAPI_AUTO_LENGTH, trap, data, &deleteProperty_);+}++napi_status ProxyHandlerBuilder::DeleteProperty(+ napi_env env,+ napi_status (*trap)(+ napi_env env, napi_value target, napi_value key, napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], result);+ },+ reinterpret_cast<void*>(trap)};+ return DeleteProperty(env, CreateTrapCallback<2>(), &callInfo);+}++napi_status ProxyHandlerBuilder::DeleteProperty(+ napi_env env,+ napi_status (*trap)(+ napi_env env, napi_value target, napi_value key, bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], &boolResult));+ return napi_get_boolean(+ env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return DeleteProperty(env, CreateTrapCallback<2>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Get() noexcept {+ return get_;+}++void ProxyHandlerBuilder::Get(napi_value trap) noexcept {+ get_ = trap;+}++napi_status ProxyHandlerBuilder::Get(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(env, "get", NAPI_AUTO_LENGTH, trap, data, &get_);+}++napi_status ProxyHandlerBuilder::Get(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value receiver,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], result);+ },+ reinterpret_cast<void*>(trap)};+ return Get(env, CreateTrapCallback<3>(), &callInfo);+}++napi_value ProxyHandlerBuilder::GetOwnPropertyDescriptor() noexcept {+ return getOwnPropertyDescriptor_;+}++void ProxyHandlerBuilder::GetOwnPropertyDescriptor(napi_value trap) noexcept {+ getOwnPropertyDescriptor_ = trap;+}++napi_status ProxyHandlerBuilder::GetOwnPropertyDescriptor(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(env,+ "getOwnPropertyDescriptor",+ NAPI_AUTO_LENGTH,+ trap,+ data,+ &getOwnPropertyDescriptor_);+}++napi_status ProxyHandlerBuilder::GetOwnPropertyDescriptor(+ napi_env env,+ napi_status (*trap)(+ napi_env env, napi_value target, napi_value key, napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], result);+ },+ reinterpret_cast<void*>(trap)};+ return GetOwnPropertyDescriptor(env, CreateTrapCallback<2>(), &callInfo);+}++napi_value ProxyHandlerBuilder::GetPrototypeOf() noexcept {+ return getPrototypeOf_;+}++void ProxyHandlerBuilder::GetPrototypeOf(napi_value trap) noexcept {+ getPrototypeOf_ = trap;+}++napi_status ProxyHandlerBuilder::GetPrototypeOf(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "getPrototypeOf", NAPI_AUTO_LENGTH, trap, data, &getPrototypeOf_);+}++napi_status ProxyHandlerBuilder::GetPrototypeOf(+ napi_env env,+ napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], result);+ },+ reinterpret_cast<void*>(trap)};+ return GetPrototypeOf(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Has() noexcept {+ return has_;+}++void ProxyHandlerBuilder::Has(napi_value trap) noexcept {+ has_ = trap;+}++napi_status ProxyHandlerBuilder::Has(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(env, "has", NAPI_AUTO_LENGTH, trap, data, &has_);+}++napi_status ProxyHandlerBuilder::Has(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], result);+ },+ reinterpret_cast<void*>(trap)};+ return Has(env, CreateTrapCallback<2>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Has(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], &boolResult));+ return napi_get_boolean(+ env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return Has(env, CreateTrapCallback<2>(), &callInfo);+}++napi_value ProxyHandlerBuilder::IsExtensible() noexcept {+ return isExtensible_;+}++void ProxyHandlerBuilder::IsExtensible(napi_value trap) noexcept {+ isExtensible_ = trap;+}++napi_status ProxyHandlerBuilder::IsExtensible(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "isExtensible", NAPI_AUTO_LENGTH, trap, data, &isExtensible_);+}++napi_status ProxyHandlerBuilder::IsExtensible(+ napi_env env,+ napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], result);+ },+ reinterpret_cast<void*>(trap)};+ return IsExtensible(env, CreateTrapCallback<1>(), &callInfo);+}++napi_status ProxyHandlerBuilder::IsExtensible(+ napi_env env,+ napi_status (*trap)(napi_env env, napi_value target, bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(env, args[0], &boolResult));+ return napi_get_boolean(env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return IsExtensible(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::OwnKeys() noexcept {+ return ownKeys_;+}++void ProxyHandlerBuilder::OwnKeys(napi_value trap) noexcept {+ ownKeys_ = trap;+}++napi_status ProxyHandlerBuilder::OwnKeys(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "ownKeys", NAPI_AUTO_LENGTH, trap, data, &ownKeys_);+}++napi_status ProxyHandlerBuilder::OwnKeys(+ napi_env env,+ napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], result);+ },+ reinterpret_cast<void*>(trap)};+ return OwnKeys(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::PreventExtensions() noexcept {+ return preventExtensions_;+}++void ProxyHandlerBuilder::PreventExtensions(napi_value trap) noexcept {+ preventExtensions_ = trap;+}++napi_status ProxyHandlerBuilder::PreventExtensions(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(env,+ "preventExtensions",+ NAPI_AUTO_LENGTH,+ trap,+ data,+ &preventExtensions_);+}++napi_status ProxyHandlerBuilder::PreventExtensions(+ napi_env env,+ napi_status (*trap)(napi_env env, napi_value target, napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], result);+ },+ reinterpret_cast<void*>(trap)};+ return PreventExtensions(env, CreateTrapCallback<1>(), &callInfo);+}++napi_status ProxyHandlerBuilder::PreventExtensions(+ napi_env env,+ napi_status (*trap)(napi_env env, napi_value target, bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(env, args[0], &boolResult));+ return napi_get_boolean(env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return PreventExtensions(env, CreateTrapCallback<1>(), &callInfo);+}++napi_value ProxyHandlerBuilder::Set() noexcept {+ return set_;+}++void ProxyHandlerBuilder::Set(napi_value trap) noexcept {+ set_ = trap;+}++napi_status ProxyHandlerBuilder::Set(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(env, "set", NAPI_AUTO_LENGTH, trap, data, &set_);+}++napi_status ProxyHandlerBuilder::Set(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value value,+ napi_value receiver,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], args[3], result);+ },+ reinterpret_cast<void*>(trap)};+ return Set(env, CreateTrapCallback<4>(), &callInfo);+}++napi_status ProxyHandlerBuilder::Set(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value value,+ napi_value receiver,+ bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{+ [](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], args[2], args[3], &boolResult));+ return napi_get_boolean(env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return Set(env, CreateTrapCallback<4>(), &callInfo);+}++napi_value ProxyHandlerBuilder::SetPrototypeOf() noexcept {+ return setPrototypeOf_;+}++void ProxyHandlerBuilder::SetPrototypeOf(napi_value trap) noexcept {+ setPrototypeOf_ = trap;+}++napi_status ProxyHandlerBuilder::SetPrototypeOf(napi_env env,+ napi_callback trap,+ void* data) noexcept {+ return napi_create_function(+ env, "setPrototypeOf", NAPI_AUTO_LENGTH, trap, data, &setPrototypeOf_);+}++napi_status ProxyHandlerBuilder::SetPrototypeOf(+ napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value prototype,+ napi_value* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ return reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], result);+ },+ reinterpret_cast<void*>(trap)};+ return SetPrototypeOf(env, CreateTrapCallback<2>(), &callInfo);+}++napi_status ProxyHandlerBuilder::SetPrototypeOf(+ napi_env env,+ napi_status (*trap)(+ napi_env env, napi_value target, napi_value prototype, bool* result)) {+ using TrapType = decltype(trap);+ static TrapCallInfo callInfo{[](napi_env env,+ void* trap,+ napi_span<napi_value> args,+ napi_value* result) noexcept {+ bool boolResult{};+ CHECK_NAPI(reinterpret_cast<TrapType>(trap)(+ env, args[0], args[1], &boolResult));+ return napi_get_boolean(+ env, boolResult, result);+ },+ reinterpret_cast<void*>(trap)};+ return SetPrototypeOf(env, CreateTrapCallback<2>(), &callInfo);+}++//=============++ProxyTemplate::ProxyTemplate(napi_env env, napi_value proxyHandler) noexcept+ : proxyHandler_(RefHolder(env, proxyHandler)) {}++napi_status ProxyTemplate::NewInstance(napi_env env,+ napi_value target,+ napi_value* result) noexcept {+ napi_value proxyConstructor{};+ CHECK_NAPI(GetProxyConstructor(env, &proxyConstructor));++ napi_value args[] = {target, static_cast<napi_value>(proxyHandler_)};+ return napi_new_instance(env, proxyConstructor, 2, args, result);+}++napi_status ProxyTemplate::GetProxyConstructor(napi_env env,+ napi_value* result) noexcept {+ if (!proxyConstructor_) {+ napi_value global{}, proxyConstructor{};+ CHECK_NAPI(napi_get_global(env, &global));+ CHECK_NAPI(+ napi_get_named_property(env, global, "Proxy", &proxyConstructor));+ proxyConstructor_ = RefHolder(env, proxyConstructor);+ }+ *result = proxyConstructor_;+ return napi_ok;+}
src/2-js-to-native-conversion/object-template-demo/napi/proxy-template.h
@@ -0,0 +1,249 @@+#include "node-api-common.h"++template <typename T>+using napi_span = span<T>;++// Creates a handler object for a JavaScript Proxy.+// See+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy+// for details about JavaScript Proxy.+//+// There are four different ways we can set each Proxy handler trap:+// - using napi_value function.+// - using napi_callback that creates function.+// - using a callback signature that matches Proxy handler definition arguments.+// - using a callback based on the Proxy handler trap signature where we replace+// napi_value with strongly typed values such as bool or+// napi_span<napi_value>.+//+// Note that ProxyHandlerBuilder keeps handler trap functions as napi_value+// and thus cannot be persisted. The typical usage is to create new+// ProxyHandlerBuilder instance on the call stack, set handler traps, create+// handler to pass to Proxy constructor or ProxyTemplate, and not to reuse the+// ProxyHandlerBuilder instance.+struct ProxyHandlerBuilder {+ napi_status NewHandler(napi_env env, napi_value* result) noexcept;++ napi_value Apply() noexcept;+ void Apply(napi_value trap) noexcept;+ napi_status Apply(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status Apply(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value thisArg,+ napi_value argumentList,+ napi_value* result));+ napi_status Apply(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value thisArg,+ napi_span<napi_value> argumentList,+ napi_value* result));++ napi_value Construct() noexcept;+ void Construct(napi_value trap) noexcept;+ napi_status Construct(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status Construct(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value argumentList,+ napi_value newTarget,+ napi_value* result));+ napi_status Construct(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_span<napi_value> argumentList,+ napi_value newTarget,+ napi_value* result));++ napi_value DefineProperty() noexcept;+ void DefineProperty(napi_value trap) noexcept;+ napi_status DefineProperty(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status DefineProperty(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value descriptor,+ napi_value* result));+ napi_status DefineProperty(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value descriptor,+ bool* result));++ napi_value DeleteProperty() noexcept;+ void DeleteProperty(napi_value trap) noexcept;+ napi_status DeleteProperty(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status DeleteProperty(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value* result));+ napi_status DeleteProperty(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ bool* result));++ napi_value Get() noexcept;+ void Get(napi_value trap) noexcept;+ napi_status Get(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status Get(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value receiver,+ napi_value* result));++ napi_value GetOwnPropertyDescriptor() noexcept;+ void GetOwnPropertyDescriptor(napi_value trap) noexcept;+ napi_status GetOwnPropertyDescriptor(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status GetOwnPropertyDescriptor(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value* result));++ napi_value GetPrototypeOf() noexcept;+ void GetPrototypeOf(napi_value trap) noexcept;+ napi_status GetPrototypeOf(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status GetPrototypeOf(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value* result));++ napi_value Has() noexcept;+ void Has(napi_value trap) noexcept;+ napi_status Has(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status Has(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value* result));+ napi_status Has(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ bool* result));++ napi_value IsExtensible() noexcept;+ void IsExtensible(napi_value trap) noexcept;+ napi_status IsExtensible(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status IsExtensible(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value* result));+ napi_status IsExtensible(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ bool* result));++ napi_value OwnKeys() noexcept;+ void OwnKeys(napi_value trap) noexcept;+ napi_status OwnKeys(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status OwnKeys(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value* result));++ napi_value PreventExtensions() noexcept;+ void PreventExtensions(napi_value trap) noexcept;+ napi_status PreventExtensions(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status PreventExtensions(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value* result));+ napi_status PreventExtensions(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ bool* result));++ napi_value Set() noexcept;+ void Set(napi_value trap) noexcept;+ napi_status Set(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status Set(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value value,+ napi_value receiver,+ napi_value* result));+ napi_status Set(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value key,+ napi_value value,+ napi_value receiver,+ bool* result));++ napi_value SetPrototypeOf() noexcept;+ void SetPrototypeOf(napi_value trap) noexcept;+ napi_status SetPrototypeOf(napi_env env,+ napi_callback trap,+ void* data = nullptr) noexcept;+ napi_status SetPrototypeOf(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value prototype,+ napi_value* result));+ napi_status SetPrototypeOf(napi_env env,+ napi_status (*trap)(napi_env env,+ napi_value target,+ napi_value prototype,+ bool* result));++ private:+ napi_value apply_{};+ napi_value construct_{};+ napi_value defineProperty_{};+ napi_value deleteProperty_{};+ napi_value get_{};+ napi_value getOwnPropertyDescriptor_{};+ napi_value getPrototypeOf_{};+ napi_value has_{};+ napi_value isExtensible_{};+ napi_value ownKeys_{};+ napi_value preventExtensions_{};+ napi_value set_{};+ napi_value setPrototypeOf_{};+};++struct ProxyTemplate {+ ProxyTemplate(napi_env env, napi_value proxyHandler) noexcept;++ napi_status NewInstance(napi_env env,+ napi_value target,+ napi_value* result) noexcept;++ private:+ napi_status GetProxyConstructor(napi_env env, napi_value* result) noexcept;++ private:+ RefHolder proxyConstructor_{};+ RefHolder proxyHandler_{};+};