|
| 1 | +#include <napi.h> |
| 2 | +#include <unordered_map> |
| 3 | +#include "test_helper.h" |
| 4 | + |
| 5 | +class FunctionTest : public Napi::ObjectWrap<FunctionTest> { |
| 6 | + public: |
| 7 | + FunctionTest(const Napi::CallbackInfo& info) |
| 8 | + : Napi::ObjectWrap<FunctionTest>(info) {} |
| 9 | + |
| 10 | + static Napi::Value OnCalledAsFunction(const Napi::CallbackInfo& info) { |
| 11 | + // If called with a "true" argument, throw an exeption to test the handling. |
| 12 | + if (!info[0].IsUndefined() && MaybeUnwrap(info[0].ToBoolean())) { |
| 13 | + NAPI_THROW(Napi::Error::New(info.Env(), "an exception"), Napi::Value()); |
| 14 | + } |
| 15 | + // Otherwise, act as a factory. |
| 16 | + std::vector<napi_value> args; |
| 17 | + for (size_t i = 0; i < info.Length(); i++) args.push_back(info[i]); |
| 18 | + return MaybeUnwrap(GetConstructor(info.Env()).New(args)); |
| 19 | + } |
| 20 | + |
| 21 | + // Constructor-per-env map in a static member because env.SetInstanceData() |
| 22 | + // would interfere with Napi::Addon<T> |
| 23 | + static std::unordered_map<napi_env, Napi::FunctionReference> constructors; |
| 24 | + |
| 25 | + static void Initialize(Napi::Env env, Napi::Object exports) { |
| 26 | + const char* name = "FunctionTest"; |
| 27 | + Napi::Function func = DefineClass(env, name, {}); |
| 28 | + constructors[env] = Napi::Persistent(func); |
| 29 | + env.AddCleanupHook([env] { constructors.erase(env); }); |
| 30 | + exports.Set(name, func); |
| 31 | + } |
| 32 | + |
| 33 | + static Napi::Function GetConstructor(Napi::Env env) { |
| 34 | + return constructors[env].Value(); |
| 35 | + } |
| 36 | +}; |
| 37 | + |
| 38 | +std::unordered_map<napi_env, Napi::FunctionReference> |
| 39 | + FunctionTest::constructors = {}; |
| 40 | + |
| 41 | +Napi::Object InitObjectWrapFunction(Napi::Env env) { |
| 42 | + Napi::Object exports = Napi::Object::New(env); |
| 43 | + FunctionTest::Initialize(env, exports); |
| 44 | + return exports; |
| 45 | +} |
0 commit comments