Skip to content

Commit

Permalink
Add Function::Call Value override
Browse files Browse the repository at this point in the history
  • Loading branch information
rgerd committed Jul 23, 2021
1 parent 6697c51 commit f211f45
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 5 deletions.
24 changes: 23 additions & 1 deletion napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ template <typename ContextType, typename DataType, typename CallJs, CallJs call>
typename std::enable_if<call == nullptr>::type static inline CallJsWrapper(
napi_env env, napi_value jsCallback, void* /*context*/, void* /*data*/) {
if (jsCallback != nullptr) {
Function(env, jsCallback).Call(0, nullptr);
Function(env, jsCallback).Call(0, static_cast<const napi_value*>(nullptr));
}
}

Expand Down Expand Up @@ -2094,6 +2094,10 @@ inline Value Function::Call(size_t argc, const napi_value* args) const {
return Call(Env().Undefined(), argc, args);
}

inline Value Function::Call(size_t argc, const Value* args) const {
return Call(Env().Undefined(), argc, args);
}

inline Value Function::Call(napi_value recv, const std::initializer_list<napi_value>& args) const {
return Call(recv, args.size(), args.begin());
}
Expand All @@ -2110,6 +2114,24 @@ inline Value Function::Call(napi_value recv, size_t argc, const napi_value* args
return Value(_env, result);
}

inline Value Function::Call(napi_value recv, size_t argc, const Value* args) const {
napi_value stackArgs[6];
std::vector<napi_value> heapArgs;
napi_value* argv;
if (argc <= std::size(stackArgs)) {
argv = stackArgs;
} else {
heapArgs.resize(argc);
argv = heapArgs.data();
}

for (size_t index = 0; index < argc; index++) {
argv[index] = static_cast<napi_value>(args[index]);
}

return Call(recv, argc, argv);
}

inline Value Function::MakeCallback(
napi_value recv,
const std::initializer_list<napi_value>& args,
Expand Down
2 changes: 2 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1125,10 +1125,12 @@ namespace Napi {
Value Call(const std::initializer_list<napi_value>& args) const;
Value Call(const std::vector<napi_value>& args) const;
Value Call(size_t argc, const napi_value* args) const;
Value Call(size_t argc, const Value* args) const;
Value Call(napi_value recv,
const std::initializer_list<napi_value>& args) const;
Value Call(napi_value recv, const std::vector<napi_value>& args) const;
Value Call(napi_value recv, size_t argc, const napi_value* args) const;
Value Call(napi_value recv, size_t argc, const Value* args) const;

Value MakeCallback(napi_value recv,
const std::initializer_list<napi_value>& args,
Expand Down
27 changes: 27 additions & 0 deletions test/function.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ Value CallWithCStyleArray(const CallbackInfo& info) {
return func.Call(args.size(), args.data());
}

Value CallWithCStyleArrayUsingCppWrapper(const CallbackInfo& info) {
Function func = info[0].As<Function>();
std::vector<Value> args;
args.reserve(3);
args.push_back(info[1]);
args.push_back(info[2]);
args.push_back(info[3]);
return func.Call(args.size(), args.data());
}

Value CallWithReceiverAndCStyleArray(const CallbackInfo& info) {
Function func = info[0].As<Function>();
Value receiver = info[1];
Expand All @@ -88,6 +98,17 @@ Value CallWithReceiverAndCStyleArray(const CallbackInfo& info) {
return func.Call(receiver, args.size(), args.data());
}

Value CallWithReceiverAndCStyleArrayUsingCppWrapper(const CallbackInfo& info) {
Function func = info[0].As<Function>();
Value receiver = info[1];
std::vector<Value> args;
args.reserve(3);
args.push_back(info[2]);
args.push_back(info[3]);
args.push_back(info[4]);
return func.Call(receiver, args.size(), args.data());
}

Value CallWithReceiverAndArgs(const CallbackInfo& info) {
Function func = info[0].As<Function>();
Value receiver = info[1];
Expand Down Expand Up @@ -209,8 +230,11 @@ Object InitFunction(Env env) {
exports["callWithArgs"] = Function::New(env, CallWithArgs);
exports["callWithVector"] = Function::New(env, CallWithVector);
exports["callWithCStyleArray"] = Function::New(env, CallWithCStyleArray);
exports["callWithCStyleArrayUsingCppWrapper"] = Function::New(env, CallWithCStyleArrayUsingCppWrapper);
exports["callWithReceiverAndCStyleArray"] =
Function::New(env, CallWithReceiverAndCStyleArray);
exports["callWithReceiverAndCStyleArrayUsingCppWrapper"] =
Function::New(env, CallWithReceiverAndCStyleArrayUsingCppWrapper);
exports["callWithReceiverAndArgs"] = Function::New(env, CallWithReceiverAndArgs);
exports["callWithReceiverAndVector"] = Function::New(env, CallWithReceiverAndVector);
exports["callWithInvalidReceiver"] = Function::New(env, CallWithInvalidReceiver);
Expand Down Expand Up @@ -242,8 +266,11 @@ Object InitFunction(Env env) {
exports["callWithArgs"] = Function::New<CallWithArgs>(env);
exports["callWithVector"] = Function::New<CallWithVector>(env);
exports["callWithCStyleArray"] = Function::New<CallWithCStyleArray>(env);
exports["callWithCStyleArrayUsingCppWrapper"] = Function::New<CallWithCStyleArrayUsingCppWrapper>(env);
exports["callWithReceiverAndCStyleArray"] =
Function::New<CallWithReceiverAndCStyleArray>(env);
exports["callWithReceiverAndCStyleArrayUsingCppWrapper"] =
Function::New<CallWithReceiverAndCStyleArrayUsingCppWrapper>(env);
exports["callWithReceiverAndArgs"] =
Function::New<CallWithReceiverAndArgs>(env);
exports["callWithReceiverAndVector"] =
Expand Down
18 changes: 14 additions & 4 deletions test/function.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,25 @@ function test(binding) {
assert.deepStrictEqual(args, [ 5, 6, 7 ]);

ret = 9;
assert.strictEqual(binding.callWithReceiverAndCStyleArray(testFunction, obj, 6, 7, 8), ret);
assert.deepStrictEqual(receiver, obj);
assert.strictEqual(binding.callWithCStyleArrayUsingCppWrapper(testFunction, 6, 7, 8), ret);
assert.deepStrictEqual(receiver, undefined);
assert.deepStrictEqual(args, [ 6, 7, 8 ]);

ret = 10;
assert.strictEqual(binding.callWithFunctionOperator(testFunction, 7, 8, 9), ret);
assert.strictEqual(receiver, undefined);
assert.strictEqual(binding.callWithReceiverAndCStyleArray(testFunction, obj, 7, 8, 9), ret);
assert.deepStrictEqual(receiver, obj);
assert.deepStrictEqual(args, [ 7, 8, 9 ]);

ret = 11;
assert.strictEqual(binding.callWithReceiverAndCStyleArrayUsingCppWrapper(testFunction, obj, 8, 9, 10), ret);
assert.deepStrictEqual(receiver, obj);
assert.deepStrictEqual(args, [ 8, 9, 10 ]);

ret = 12;
assert.strictEqual(binding.callWithFunctionOperator(testFunction, 9, 10, 11), ret);
assert.strictEqual(receiver, undefined);
assert.deepStrictEqual(args, [ 9, 10, 11 ]);

assert.throws(() => {
binding.callWithInvalidReceiver();
}, /Invalid (pointer passed as )?argument/);
Expand Down

0 comments on commit f211f45

Please sign in to comment.