Skip to content

Commit

Permalink
Implement AsyncContext class
Browse files Browse the repository at this point in the history
  • Loading branch information
romandev committed Apr 30, 2018
1 parent cf6c93e commit b272a22
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 0 deletions.
72 changes: 72 additions & 0 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3074,6 +3074,78 @@ inline Value EscapableHandleScope::Escape(napi_value escapee) {
return Value(_env, result);
}

////////////////////////////////////////////////////////////////////////////////
// AsyncContext class
////////////////////////////////////////////////////////////////////////////////

inline AsyncContext::AsyncContext()
: _env(nullptr),
_context(nullptr) {
}

inline AsyncContext::AsyncContext(const char* resource_name,
const Function& callback)
: AsyncContext(resource_name, Object::New(callback.Env()), callback) {
}

inline AsyncContext::AsyncContext(const char* resource_name,
const Object& resource,
const Function& callback)
: _env(callback.Env()),
_context(nullptr),
_callback(Napi::Persistent(callback)) {
napi_value resource_id;
napi_status status = napi_create_string_utf8(
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
NAPI_THROW_IF_FAILED(_env, status);

status = napi_async_init(_env, resource, resource_id, &_context);
NAPI_THROW_IF_FAILED(_env, status);
}

inline AsyncContext::~AsyncContext() {
if (_context != nullptr) {
napi_async_destroy(_env, _context);
_context = nullptr;
}
}

inline AsyncContext::AsyncContext(AsyncContext&& other) {
_env = other._env;
other._env = nullptr;
_context = other._context;
other._context = nullptr;
_callback = std::move(other._callback);
}

inline AsyncContext& AsyncContext::operator =(AsyncContext&& other) {
_env = other._env;
other._env = nullptr;
_context = other._context;
other._context = nullptr;
_callback = std::move(other._callback);
return *this;
}

inline Value AsyncContext::MakeCallback() const {
return MakeCallback(Object::New(_env));
}

inline Value AsyncContext::MakeCallback(const Object& receiver) const {
return _callback.MakeCallback(receiver, std::initializer_list<napi_value>{});
}

inline Value AsyncContext::MakeCallback(
const std::initializer_list<napi_value>& args) const {
return MakeCallback(Object::New(_env), args);
}

inline Value AsyncContext::MakeCallback(
const Object& receiver,
const std::initializer_list<napi_value>& args) const {
return _callback.MakeCallback(receiver, args);
}

////////////////////////////////////////////////////////////////////////////////
// AsyncWorker class
////////////////////////////////////////////////////////////////////////////////
Expand Down
26 changes: 26 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1493,6 +1493,32 @@ namespace Napi {
napi_escapable_handle_scope _scope;
};

class AsyncContext {
public:
AsyncContext();
AsyncContext(const char* resource_name, const Function& callback);
AsyncContext(const char* resource_name,
const Object& resource,
const Function& callback);
virtual ~AsyncContext();

AsyncContext(AsyncContext&& other);
AsyncContext& operator =(AsyncContext&& other);
AsyncContext(const AsyncContext&) = delete;
AsyncContext& operator =(AsyncContext&) = delete;

Value MakeCallback() const;
Value MakeCallback(const Object& receiver) const;
Value MakeCallback(const std::initializer_list<napi_value>& args) const;
Value MakeCallback(const Object& receiver,
const std::initializer_list<napi_value>& args) const;

private:
napi_env _env;
napi_async_context _context;
FunctionReference _callback;
};

class AsyncWorker {
public:
virtual ~AsyncWorker();
Expand Down
26 changes: 26 additions & 0 deletions test/asynccontext.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "napi.h"

using namespace Napi;

namespace {

static AsyncContext* context;

static void CreateAsyncContext(const CallbackInfo& info) {
Function callback = info[0].As<Function>();
context = new AsyncContext("TestResource", callback);
}

static void MakeCallback(const CallbackInfo& info) {
context->MakeCallback();
delete context;
}

} // end anonymous namespace

Object InitAsyncContext(Env env) {
Object exports = Object::New(env);
exports["createAsyncContext"] = Function::New(env, CreateAsyncContext);
exports["makeCallback"] = Function::New(env, MakeCallback);
return exports;
}
16 changes: 16 additions & 0 deletions test/asynccontext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict';
const buildType = process.config.target_defaults.default_configuration;
const assert = require('assert');

test(require(`./build/${buildType}/binding.node`));
test(require(`./build/${buildType}/binding_noexcept.node`));

function test(binding) {
let called = false;
binding.asynccontext.createAsyncContext(function() {
called = true;
});
assert.strictEqual(called, false);
binding.asynccontext.makeCallback();
assert.strictEqual(called, true);
}
2 changes: 2 additions & 0 deletions test/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using namespace Napi;

Object InitArrayBuffer(Env env);
Object InitAsyncContext(Env env);
Object InitAsyncWorker(Env env);
Object InitBasicTypesNumber(Env env);
Object InitBasicTypesValue(Env env);
Expand All @@ -20,6 +21,7 @@ Object InitObjectWrap(Env env);

Object Init(Env env, Object exports) {
exports.Set("arraybuffer", InitArrayBuffer(env));
exports.Set("asynccontext", InitAsyncContext(env));
exports.Set("asyncworker", InitAsyncWorker(env));
exports.Set("basic_types_number", InitBasicTypesNumber(env));
exports.Set("basic_types_value", InitBasicTypesValue(env));
Expand Down
1 change: 1 addition & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
'target_defaults': {
'sources': [
'arraybuffer.cc',
'asynccontext.cc',
'asyncworker.cc',
'basic_types/number.cc',
'basic_types/value.cc',
Expand Down
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ process.config.target_defaults.default_configuration =
// explicit declaration as follows.
let testModules = [
'arraybuffer',
'asynccontext',
'asyncworker',
'basic_types/number',
'basic_types/value',
Expand Down

0 comments on commit b272a22

Please sign in to comment.