Skip to content

Commit

Permalink
tsfn: add error checking on GetContext
Browse files Browse the repository at this point in the history
Fixes: #581
  • Loading branch information
KevinEady committed Oct 31, 2019
1 parent 9e955a8 commit e142a1e
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 1 deletion.
3 changes: 2 additions & 1 deletion napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4110,7 +4110,8 @@ inline napi_status ThreadSafeFunction::Abort() {
inline ThreadSafeFunction::ConvertibleContext
ThreadSafeFunction::GetContext() const {
void* context;
napi_get_threadsafe_function_context(*_tsfn, &context);
napi_status status = napi_get_threadsafe_function_context(*_tsfn, &context);
NAPI_FATAL_IF_FAILED(status, "ThreadSafeFunction::GetContext", "napi_get_threadsafe_function_context");
return ConvertibleContext({ context });
}

Expand Down
2 changes: 2 additions & 0 deletions test/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Object InitObjectDeprecated(Env env);
#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
Object InitPromise(Env env);
#if (NAPI_VERSION > 3)
Object InitThreadSafeFunctionCtx(Env env);
Object InitThreadSafeFunctionPtr(Env env);
Object InitThreadSafeFunctionUnref(Env env);
Object InitThreadSafeFunction(Env env);
Expand Down Expand Up @@ -83,6 +84,7 @@ Object Init(Env env, Object exports) {
#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
exports.Set("promise", InitPromise(env));
#if (NAPI_VERSION > 3)
exports.Set("threadsafe_function_ctx", InitThreadSafeFunctionCtx(env));
exports.Set("threadsafe_function_ptr", InitThreadSafeFunctionPtr(env));
exports.Set("threadsafe_function_unref", InitThreadSafeFunctionUnref(env));
exports.Set("threadsafe_function", InitThreadSafeFunction(env));
Expand Down
1 change: 1 addition & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
'object/object.cc',
'object/set_property.cc',
'promise.cc',
'threadsafe_function/threadsafe_function_ctx.cc',
'threadsafe_function/threadsafe_function_ptr.cc',
'threadsafe_function/threadsafe_function_unref.cc',
'threadsafe_function/threadsafe_function.cc',
Expand Down
2 changes: 2 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let testModules = [
'object/object_deprecated',
'object/set_property',
'promise',
'threadsafe_function/threadsafe_function_ctx',
'threadsafe_function/threadsafe_function_ptr',
'threadsafe_function/threadsafe_function_unref',
'threadsafe_function/threadsafe_function',
Expand Down Expand Up @@ -68,6 +69,7 @@ if ((process.env.npm_config_NAPI_VERSION !== undefined) &&

if ((process.env.npm_config_NAPI_VERSION !== undefined) &&
(process.env.npm_config_NAPI_VERSION < 4)) {
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function_ctx'), 1);
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function_ptr'), 1);
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function_unref'), 1);
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function'), 1);
Expand Down
64 changes: 64 additions & 0 deletions test/threadsafe_function/threadsafe_function_ctx.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "napi.h"

#if (NAPI_VERSION > 3)

using namespace Napi;

namespace {

class TSFNWrap : public ObjectWrap<TSFNWrap> {
public:
static Object Init(Napi::Env env, Object exports);
TSFNWrap(const CallbackInfo &info);

Napi::Value GetContext(const CallbackInfo & /*info*/) {
Reference<Napi::Value> *ctx = _tsfn.GetContext();
return ctx->Value();
};

Napi::Value Release(const CallbackInfo &info) {
Napi::Env env = info.Env();
_deferred = std::unique_ptr<Promise::Deferred>(new Promise::Deferred(env));
_tsfn.Release();
return _deferred->Promise();
};

private:
ThreadSafeFunction _tsfn;
std::unique_ptr<Promise::Deferred> _deferred;
};

Object TSFNWrap::Init(Napi::Env env, Object exports) {
Function func =
DefineClass(env, "TSFNWrap",
{InstanceMethod("getContext", &TSFNWrap::GetContext),
InstanceMethod("release", &TSFNWrap::Release)});

exports.Set("TSFNWrap", func);
return exports;
}

TSFNWrap::TSFNWrap(const CallbackInfo &info) : ObjectWrap<TSFNWrap>(info) {
Napi::Env env = info.Env();

Reference<Napi::Value> *_ctx = new Reference<Napi::Value>;
*_ctx = Persistent(info[0]);

_tsfn = ThreadSafeFunction::New(
info.Env(), Function::New(env, [](const CallbackInfo & /*info*/) {}),
Object::New(env), "Test", 1, 1, _ctx,
[this](Napi::Env env, Reference<Napi::Value> *ctx) {
_deferred->Resolve(env.Undefined());
_deferred.reset();
ctx->Reset();
delete ctx;
});
}

} // namespace

Object InitThreadSafeFunctionCtx(Env env) {
return TSFNWrap::Init(env, Object::New(env));
}

#endif
16 changes: 16 additions & 0 deletions test/threadsafe_function/threadsafe_function_ctx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';

const assert = require('assert');
const buildType = process.config.target_defaults.default_configuration;

module.exports = Promise.all[
test(require(`../build/${buildType}/binding.node`)),
test(require(`../build/${buildType}/binding_noexcept.node`))
];

async function test(binding) {
const ctx = { };
const tsfn = new binding.threadsafe_function_ctx.TSFNWrap(ctx);
assert(tsfn.getContext() === ctx);
await tsfn.release();
}

0 comments on commit e142a1e

Please sign in to comment.