Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add resource_name and resource parameters to AsyncWorker constructor #253

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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());
}
}