Skip to content

Commit

Permalink
n-api: change async resource name to napi_value
Browse files Browse the repository at this point in the history
Backport-PR-URL: #19447
PR-URL: #14697
Reviewed-By: Anna Henningsen <[email protected]>
  • Loading branch information
jasongin authored and MylesBorins committed Apr 16, 2018
1 parent 7588eea commit 156a8b6
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 13 deletions.
2 changes: 1 addition & 1 deletion doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3265,7 +3265,7 @@ changes:
NAPI_EXTERN
napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
const char* async_resource_name,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
Expand Down
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
'src/handle_wrap.cc',
'src/js_stream.cc',
'src/node.cc',
'src/node_api_backport.cc',
'src/node_api.cc',
'src/node_api.h',
'src/node_api_types.h',
Expand Down
17 changes: 10 additions & 7 deletions src/node_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3255,7 +3255,7 @@ class Work : public node::AsyncResource {
private:
explicit Work(napi_env env,
v8::Local<v8::Object> async_resource,
const char* async_resource_name,
v8::Local<v8::String> async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete = nullptr,
void* data = nullptr)
Expand All @@ -3275,7 +3275,7 @@ class Work : public node::AsyncResource {
public:
static Work* New(napi_env env,
v8::Local<v8::Object> async_resource,
const char* async_resource_name,
v8::Local<v8::String> async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data) {
Expand Down Expand Up @@ -3345,7 +3345,7 @@ class Work : public node::AsyncResource {

napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
const char* async_resource_name,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
Expand All @@ -3354,17 +3354,20 @@ napi_status napi_create_async_work(napi_env env,
CHECK_ARG(env, execute);
CHECK_ARG(env, result);

v8::Local<v8::Context> context = env->isolate->GetCurrentContext();

v8::Local<v8::Object> resource;
if (async_resource != nullptr) {
auto value = v8impl::V8LocalValueFromJsValue(async_resource);
RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg);
resource = value.As<v8::Object>();
CHECK_TO_OBJECT(env, context, resource, async_resource);
} else {
resource = v8::Object::New(env->isolate);
}

v8::Local<v8::String> resource_name;
CHECK_TO_STRING(env, context, resource_name, async_resource_name);

uvimpl::Work* work =
uvimpl::Work::New(env, resource, async_resource_name,
uvimpl::Work::New(env, resource, resource_name,
execute, complete, data);

*result = reinterpret_cast<napi_async_work>(work);
Expand Down
2 changes: 1 addition & 1 deletion src/node_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ NAPI_EXTERN napi_status napi_get_dataview_info(napi_env env,
NAPI_EXTERN
napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
const char* async_resource_name,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
Expand Down
89 changes: 89 additions & 0 deletions src/node_api_backport.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "node_api_backport.h"

using v8::Function;
using v8::HandleScope;
using v8::Local;
using v8::MaybeLocal;
using v8::Object;
using v8::TryCatch;
using v8::Value;

namespace node {

CallbackScope::CallbackScope(v8::Isolate *_isolate,
v8::Local<v8::Object> _object,
node::async_context context) :
isolate(_isolate),
env(node::Environment::GetCurrent(isolate->GetCurrentContext())),
_try_catch(isolate),
object(_object),
callback_scope(
node::Environment::GetCurrent(isolate->GetCurrentContext())) {
Local<Function> pre_fn = env->async_hooks_pre_function();

Local<Value> async_queue_v = object->Get(env->async_queue_string());
if (async_queue_v->IsObject())
ran_init_callback = true;

if (ran_init_callback && !pre_fn.IsEmpty()) {
TryCatch try_catch(env->isolate());
MaybeLocal<Value> ar = pre_fn->Call(env->context(), object, 0, nullptr);
if (ar.IsEmpty()) {
ClearFatalExceptionHandlers(env);
FatalException(env->isolate(), try_catch);
}
}
}

CallbackScope::~CallbackScope() {
Local<Function> post_fn = env->async_hooks_post_function();
if (ran_init_callback && !post_fn.IsEmpty()) {
Local<Value> did_throw = v8::Boolean::New(isolate, _try_catch.HasCaught());
// Currently there's no way to retrieve an uid from node::MakeCallback().
// This needs to be fixed.
Local<Value> vals[] =
{ Undefined(env->isolate()).As<Value>(), did_throw };
TryCatch try_catch(env->isolate());
MaybeLocal<Value> ar =
post_fn->Call(env->context(), object, arraysize(vals), vals);
if (ar.IsEmpty()) {
ClearFatalExceptionHandlers(env);
FatalException(env->isolate(), try_catch);
return;
}
}

if (callback_scope.in_makecallback()) {
return;
}

Environment::TickInfo* tick_info = env->tick_info();

if (tick_info->length() == 0) {
env->isolate()->RunMicrotasks();
}

if (tick_info->length() == 0) {
tick_info->set_index(0);
return;
}

env->tick_callback_function()->Call(env->process_object(), 0, nullptr);
}

AsyncResource::AsyncResource(v8::Isolate* _isolate,
v8::Local<v8::Object> _object,
v8::Local<v8::String> name) : isolate(_isolate) {
object.Reset(isolate, _object);
}

AsyncResource::~AsyncResource() {
object.Reset();
}

} // end of namespace node

CallbackScope::CallbackScope(node::AsyncResource* work) :
scope(work->isolate,
v8::Local<Object>::New(work->isolate,
work->object), {0, 0}) {}
44 changes: 43 additions & 1 deletion src/node_api_backport.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,48 @@
// which have appeared in later versions of Node.js, and which are required for
// N-API.

#define ToChecked FromJust
#include "node_internals.h"

namespace node {

typedef int async_id;

typedef struct async_context {
node::async_id async_id;
node::async_id trigger_async_id;
} async_context;

class CallbackScope {
public:
CallbackScope(v8::Isolate *isolate,
v8::Local<v8::Object> object,
node::async_context context);
~CallbackScope();
private:
v8::Isolate* isolate = nullptr;
node::Environment* env = nullptr;
v8::TryCatch _try_catch;
bool ran_init_callback = false;
v8::Local<v8::Object> object;
Environment::AsyncCallbackScope callback_scope;
};

class AsyncResource {
public:
AsyncResource(v8::Isolate* _isolate,
v8::Local<v8::Object> _object,
v8::Local<v8::String> name);
~AsyncResource();
v8::Isolate* isolate;
v8::Persistent<v8::Object> object;
};
} // end of namespace node

class CallbackScope {
public:
explicit CallbackScope(node::AsyncResource* work);
private:
node::CallbackScope scope;
};

#endif // SRC_NODE_API_BACKPORT_H_
14 changes: 11 additions & 3 deletions test/addons-napi/test_async/test_async.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ napi_value Test(napi_env env, napi_callback_info info) {
size_t argc = 3;
napi_value argv[3];
napi_value _this;
napi_value resource_name;
void* data;
NAPI_CALL(env,
napi_get_cb_info(env, info, &argc, argv, &_this, &data));
Expand All @@ -93,7 +94,10 @@ napi_value Test(napi_env env, napi_callback_info info) {
napi_get_value_int32(env, argv[0], &the_carrier._input));
NAPI_CALL(env,
napi_create_reference(env, argv[2], 1, &the_carrier._callback));
NAPI_CALL(env, napi_create_async_work(env, argv[1], "TestResource",

NAPI_CALL(env,
napi_create_string_utf8(env, "TestResource", -1, &resource_name));
NAPI_CALL(env, napi_create_async_work(env, argv[1], resource_name,
Execute, Complete, &the_carrier, &the_carrier._request));
NAPI_CALL(env,
napi_queue_async_work(env, the_carrier._request));
Expand Down Expand Up @@ -138,12 +142,16 @@ napi_value TestCancel(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value argv[1];
napi_value _this;
napi_value resource_name;
void* data;

NAPI_CALL(env,
napi_create_string_utf8(env, "TestResource", -1, &resource_name));

// make sure the work we are going to cancel will not be
// able to start by using all the threads in the pool
for (int i = 1; i < MAX_CANCEL_THREADS; i++) {
NAPI_CALL(env, napi_create_async_work(env, nullptr, "TestCancelBusy",
NAPI_CALL(env, napi_create_async_work(env, nullptr, resource_name,
CancelExecute, BusyCancelComplete,
&async_carrier[i], &async_carrier[i]._request));
NAPI_CALL(env, napi_queue_async_work(env, async_carrier[i]._request));
Expand All @@ -155,7 +163,7 @@ napi_value TestCancel(napi_env env, napi_callback_info info) {
// workers above.
NAPI_CALL(env,
napi_get_cb_info(env, info, &argc, argv, &_this, &data));
NAPI_CALL(env, napi_create_async_work(env, nullptr, "TestCancelled",
NAPI_CALL(env, napi_create_async_work(env, nullptr, resource_name,
CancelExecute, CancelComplete,
&async_carrier[0], &async_carrier[0]._request));
NAPI_CALL(env,
Expand Down

0 comments on commit 156a8b6

Please sign in to comment.