Skip to content

Commit

Permalink
Add resource parameters to AsyncWorker constructor
Browse files Browse the repository at this point in the history
This change is initiated from
#140 (comment).

PR-URL: #253
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Nicola Del Gobbo <[email protected]>
  • Loading branch information
romandev authored and mhdawson committed May 25, 2018
1 parent 1ecf7c1 commit 4b8918b
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 22 deletions.
42 changes: 36 additions & 6 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3079,21 +3079,51 @@ inline Value EscapableHandleScope::Escape(napi_value escapee) {
////////////////////////////////////////////////////////////////////////////////

inline AsyncWorker::AsyncWorker(const Function& callback)
: AsyncWorker(Object::New(callback.Env()), callback) {
: AsyncWorker(callback, "generic") {
}

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

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

inline AsyncWorker::AsyncWorker(const Object& receiver,
const Function& callback)
: AsyncWorker(receiver, callback, "generic") {
}

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

inline AsyncWorker::AsyncWorker(const Object& receiver,
const Function& callback,
const char* resource_name,
const Object& resource)
: _env(callback.Env()),
_receiver(Napi::Persistent(receiver)),
_callback(Napi::Persistent(callback)) {

napi_value resource_id;
napi_status status = napi_create_string_latin1(
_env, "generic", NAPI_AUTO_LENGTH, &resource_id);
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
NAPI_THROW_IF_FAILED(_env, status);

status = napi_create_async_work(
_env, nullptr, resource_id, OnExecute, OnWorkComplete, this, &_work);
status = napi_create_async_work(_env, resource, resource_id, OnExecute,
OnWorkComplete, this, &_work);
NAPI_THROW_IF_FAILED(_env, status);
}

Expand Down
15 changes: 14 additions & 1 deletion napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1515,7 +1515,20 @@ namespace Napi {

protected:
explicit AsyncWorker(const Function& callback);
explicit AsyncWorker(const Object& receiver, const Function& callback);
explicit AsyncWorker(const Function& callback,
const char* resource_name);
explicit AsyncWorker(const Function& callback,
const char* resource_name,
const Object& resource);
explicit AsyncWorker(const Object& receiver,
const Function& callback);
explicit AsyncWorker(const Object& receiver,
const Function& callback,
const char* resource_name);
explicit AsyncWorker(const Object& receiver,
const Function& callback,
const char* resource_name,
const Object& resource);

virtual void Execute() = 0;
virtual void OnOK();
Expand Down
10 changes: 6 additions & 4 deletions test/asyncworker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ class TestWorker : public AsyncWorker {
public:
static void DoWork(const CallbackInfo& info) {
bool succeed = info[0].As<Boolean>();
Function cb = info[1].As<Function>();
Value data = info[2];
Object resource = info[1].As<Object>();
Function cb = info[2].As<Function>();
Value data = info[3];

TestWorker* worker = new TestWorker(cb);
TestWorker* worker = new TestWorker(cb, "TestResource", resource);
worker->Receiver().Set("data", data);
worker->_succeed = succeed;
worker->Queue();
Expand All @@ -23,7 +24,8 @@ class TestWorker : public AsyncWorker {
}

private:
TestWorker(Function cb) : AsyncWorker(cb) {}
TestWorker(Function cb, const char* resource_name, const Object& resource)
: AsyncWorker(cb, resource_name, resource) {}
bool _succeed;
};

Expand Down
89 changes: 78 additions & 11 deletions test/asyncworker.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,88 @@
'use strict';
const buildType = process.config.target_defaults.default_configuration;
const assert = require('assert');
const async_hooks = require('async_hooks');
const common = require('./common');

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

function installAsyncHooksForTest() {
return new Promise((resolve, reject) => {
let id;
const events = [];
const hook = async_hooks.createHook({
init(asyncId, type, triggerAsyncId, resource) {
if (id === undefined && type === 'TestResource') {
id = asyncId;
events.push({ eventName: 'init', type, triggerAsyncId, resource });
}
},
before(asyncId) {
if (asyncId === id) {
events.push({ eventName: 'before' });
}
},
after(asyncId) {
if (asyncId === id) {
events.push({ eventName: 'after' });
}
},
destroy(asyncId) {
if (asyncId === id) {
events.push({ eventName: 'destroy' });
hook.disable();
resolve(events);
}
}
}).enable();
});
}

function test(binding) {
binding.asyncworker.doWork(true, function (e) {
assert.strictEqual(typeof e, 'undefined');
assert.strictEqual(typeof this, 'object');
assert.strictEqual(this.data, 'test data');
}, 'test data');
{
const hooks = installAsyncHooksForTest();
const triggerAsyncId = async_hooks.executionAsyncId();
binding.asyncworker.doWork(true, { foo: 'foo' }, function (e) {
assert.strictEqual(typeof e, 'undefined');
assert.strictEqual(typeof this, 'object');
assert.strictEqual(this.data, 'test data');
}, 'test data');

hooks.then(actual => {
assert.deepStrictEqual(actual, [
{ eventName: 'init',
type: 'TestResource',
triggerAsyncId: triggerAsyncId,
resource: { foo: 'foo' } },
{ eventName: 'before' },
{ eventName: 'after' },
{ eventName: 'destroy' }
]);
}).catch(common.mustNotCall());
}

{
const hooks = installAsyncHooksForTest();
const triggerAsyncId = async_hooks.executionAsyncId();

binding.asyncworker.doWork(false, { foo: 'foo' }, function (e) {
assert.ok(e instanceof Error);
assert.strictEqual(e.message, 'test error');
assert.strictEqual(typeof this, 'object');
assert.strictEqual(this.data, 'test data');
}, 'test data');

binding.asyncworker.doWork(false, function (e) {
assert.ok(e instanceof Error);
assert.strictEqual(e.message, 'test error');
assert.strictEqual(typeof this, 'object');
assert.strictEqual(this.data, 'test data');
}, 'test data');
hooks.then(actual => {
assert.deepStrictEqual(actual, [
{ eventName: 'init',
type: 'TestResource',
triggerAsyncId: triggerAsyncId,
resource: { foo: 'foo' } },
{ eventName: 'before' },
{ eventName: 'after' },
{ eventName: 'destroy' }
]);
}).catch(common.mustNotCall());
}
}

0 comments on commit 4b8918b

Please sign in to comment.