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

[v8.x] async_hooks: C++ Embedder API overhaul #14109

Closed
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
99 changes: 82 additions & 17 deletions src/async-wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -634,9 +634,10 @@ void AsyncWrap::AsyncReset(bool silent) {

if (silent) return;

EmitAsyncInit(env(), object(),
env()->async_hooks()->provider_string(provider_type()),
async_id_, trigger_id_);
AsyncWrap::EmitAsyncInit(
env(), object(),
env()->async_hooks()->provider_string(provider_type()),
async_id_, trigger_id_);
}


Expand Down Expand Up @@ -741,42 +742,106 @@ Local<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
/* Public C++ embedder API */


async_uid AsyncHooksGetExecutionAsyncId(Isolate* isolate) {
async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->current_async_id();
}

async_uid AsyncHooksGetCurrentId(Isolate* isolate) {
async_id AsyncHooksGetCurrentId(Isolate* isolate) {
return AsyncHooksGetExecutionAsyncId(isolate);
}


async_uid AsyncHooksGetTriggerAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->get_init_trigger_id();
async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->trigger_id();
}

async_uid AsyncHooksGetTriggerId(Isolate* isolate) {
async_id AsyncHooksGetTriggerId(Isolate* isolate) {
return AsyncHooksGetTriggerAsyncId(isolate);
}


async_uid EmitAsyncInit(Isolate* isolate,
Local<Object> resource,
const char* name,
async_uid trigger_id) {
async_context EmitAsyncInit(Isolate* isolate,
Local<Object> resource,
const char* name,
async_id trigger_async_id) {
Environment* env = Environment::GetCurrent(isolate);
async_uid async_id = env->new_async_id();

// Initialize async context struct
if (trigger_async_id == -1)
trigger_async_id = env->get_init_trigger_id();

async_context context = {
env->new_async_id(), // async_id_
trigger_async_id // trigger_async_id_
};

// Run init hooks
Local<String> type =
String::NewFromUtf8(isolate, name, v8::NewStringType::kInternalized)
.ToLocalChecked();
AsyncWrap::EmitAsyncInit(env, resource, type, async_id, trigger_id);
return async_id;
AsyncWrap::EmitAsyncInit(env, resource, type, context.async_id,
context.trigger_async_id);

return context;
}

void EmitAsyncDestroy(Isolate* isolate, async_uid id) {
PushBackDestroyId(Environment::GetCurrent(isolate), id);
void EmitAsyncDestroy(Isolate* isolate, async_context asyncContext) {
PushBackDestroyId(Environment::GetCurrent(isolate), asyncContext.async_id);
}

} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(async_wrap, node::AsyncWrap::Initialize)


// Only legacy public API below this line.

namespace node {

MaybeLocal<Value> MakeCallback(Isolate* isolate,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these not in node.cc?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason, except maybe that it kind of belongs to the rest of the legacy code here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All MakeCallback functions are in node.cc including the legacy ones. But since this won't land in master I don't care that much.

Local<Object> recv,
Local<Function> callback,
int argc,
Local<Value>* argv,
async_id asyncId,
async_id triggerAsyncId) {
return MakeCallback(isolate, recv, callback, argc, argv,
{asyncId, triggerAsyncId});
}

MaybeLocal<Value> MakeCallback(Isolate* isolate,
Local<Object> recv,
const char* method,
int argc,
Local<Value>* argv,
async_id asyncId,
async_id triggerAsyncId) {
return MakeCallback(isolate, recv, method, argc, argv,
{asyncId, triggerAsyncId});
}

MaybeLocal<Value> MakeCallback(Isolate* isolate,
Local<Object> recv,
Local<String> symbol,
int argc,
Local<Value>* argv,
async_id asyncId,
async_id triggerAsyncId) {
return MakeCallback(isolate, recv, symbol, argc, argv,
{asyncId, triggerAsyncId});
}

// Undo the Node-8.x-only alias from node.h
#undef EmitAsyncInit

async_uid EmitAsyncInit(Isolate* isolate,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be async_id? Not that it really matters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? I can change it if you like. 😄

Local<Object> resource,
const char* name,
async_id trigger_async_id) {
return EmitAsyncInit__New(isolate,
resource,
name,
trigger_async_id).async_id;
}

} // namespace node
1 change: 1 addition & 0 deletions src/async-wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "base-object.h"
#include "v8.h"
#include "node.h"

#include <stdint.h>

Expand Down
2 changes: 1 addition & 1 deletion src/inspector_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ bool Agent::StartIoThread(bool wait_for_connect) {
message
};
MakeCallback(parent_env_->isolate(), process_object, emit_fn.As<Function>(),
arraysize(argv), argv, 0, 0);
arraysize(argv), argv, {0, 0});

return true;
}
Expand Down
49 changes: 23 additions & 26 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ static void CheckImmediate(uv_check_t* handle) {
env->immediate_callback_string(),
0,
nullptr,
0, 0).ToLocalChecked();
{0, 0}).ToLocalChecked();
}


Expand Down Expand Up @@ -1298,8 +1298,7 @@ MaybeLocal<Value> MakeCallback(Environment* env,
const Local<Function> callback,
int argc,
Local<Value> argv[],
double async_id,
double trigger_id) {
async_context asyncContext) {
// If you hit this assertion, you forgot to enter the v8::Context first.
CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());

Expand All @@ -1321,10 +1320,12 @@ MaybeLocal<Value> MakeCallback(Environment* env,
MaybeLocal<Value> ret;

{
AsyncHooks::ExecScope exec_scope(env, async_id, trigger_id);
AsyncHooks::ExecScope exec_scope(env, asyncContext.async_id,
asyncContext.trigger_async_id);

if (async_id != 0) {
if (!AsyncWrap::EmitBefore(env, async_id)) return Local<Value>();
if (asyncContext.async_id != 0) {
if (!AsyncWrap::EmitBefore(env, asyncContext.async_id))
return Local<Value>();
}

ret = callback->Call(env->context(), recv, argc, argv);
Expand All @@ -1336,8 +1337,9 @@ MaybeLocal<Value> MakeCallback(Environment* env,
ret : Undefined(env->isolate());
}

if (async_id != 0) {
if (!AsyncWrap::EmitAfter(env, async_id)) return Local<Value>();
if (asyncContext.async_id != 0) {
if (!AsyncWrap::EmitAfter(env, asyncContext.async_id))
return Local<Value>();
}
}

Expand All @@ -1358,8 +1360,8 @@ MaybeLocal<Value> MakeCallback(Environment* env,

// Make sure the stack unwound properly. If there are nested MakeCallback's
// then it should return early and not reach this code.
CHECK_EQ(env->current_async_id(), async_id);
CHECK_EQ(env->trigger_id(), trigger_id);
CHECK_EQ(env->current_async_id(), asyncContext.async_id);
CHECK_EQ(env->trigger_id(), asyncContext.trigger_async_id);

Local<Object> process = env->process_object();

Expand All @@ -1384,13 +1386,11 @@ MaybeLocal<Value> MakeCallback(Isolate* isolate,
const char* method,
int argc,
Local<Value> argv[],
async_uid async_id,
async_uid trigger_id) {
async_context asyncContext) {
Local<String> method_string =
String::NewFromUtf8(isolate, method, v8::NewStringType::kNormal)
.ToLocalChecked();
return MakeCallback(isolate, recv, method_string, argc, argv,
async_id, trigger_id);
return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
}


Expand All @@ -1399,14 +1399,12 @@ MaybeLocal<Value> MakeCallback(Isolate* isolate,
Local<String> symbol,
int argc,
Local<Value> argv[],
async_uid async_id,
async_uid trigger_id) {
async_context asyncContext) {
Local<Value> callback_v = recv->Get(symbol);
if (callback_v.IsEmpty()) return Local<Value>();
if (!callback_v->IsFunction()) return Local<Value>();
Local<Function> callback = callback_v.As<Function>();
return MakeCallback(isolate, recv, callback, argc, argv,
async_id, trigger_id);
return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
}


Expand All @@ -1415,8 +1413,7 @@ MaybeLocal<Value> MakeCallback(Isolate* isolate,
Local<Function> callback,
int argc,
Local<Value> argv[],
async_uid async_id,
async_uid trigger_id) {
async_context asyncContext) {
// Observe the following two subtleties:
//
// 1. The environment is retrieved from the callback function's context.
Expand All @@ -1427,7 +1424,7 @@ MaybeLocal<Value> MakeCallback(Isolate* isolate,
Environment* env = Environment::GetCurrent(callback->CreationContext());
Context::Scope context_scope(env->context());
return MakeCallback(env, recv.As<Value>(), callback, argc, argv,
async_id, trigger_id);
asyncContext);
}


Expand All @@ -1440,7 +1437,7 @@ Local<Value> MakeCallback(Isolate* isolate,
Local<Value>* argv) {
EscapableHandleScope handle_scope(isolate);
return handle_scope.Escape(
MakeCallback(isolate, recv, method, argc, argv, 0, 0)
MakeCallback(isolate, recv, method, argc, argv, {0, 0})
.FromMaybe(Local<Value>()));
}

Expand All @@ -1452,7 +1449,7 @@ Local<Value> MakeCallback(Isolate* isolate,
Local<Value>* argv) {
EscapableHandleScope handle_scope(isolate);
return handle_scope.Escape(
MakeCallback(isolate, recv, symbol, argc, argv, 0, 0)
MakeCallback(isolate, recv, symbol, argc, argv, {0, 0})
.FromMaybe(Local<Value>()));
}

Expand All @@ -1464,7 +1461,7 @@ Local<Value> MakeCallback(Isolate* isolate,
Local<Value>* argv) {
EscapableHandleScope handle_scope(isolate);
return handle_scope.Escape(
MakeCallback(isolate, recv, callback, argc, argv, 0, 0)
MakeCallback(isolate, recv, callback, argc, argv, {0, 0})
.FromMaybe(Local<Value>()));
}

Expand Down Expand Up @@ -4448,7 +4445,7 @@ void EmitBeforeExit(Environment* env) {
};
MakeCallback(env->isolate(),
process_object, "emit", arraysize(args), args,
0, 0).ToLocalChecked();
{0, 0}).ToLocalChecked();
}


Expand All @@ -4469,7 +4466,7 @@ int EmitExit(Environment* env) {

MakeCallback(env->isolate(),
process_object, "emit", arraysize(args), args,
0, 0).ToLocalChecked();
{0, 0}).ToLocalChecked();

// Reload exit code, it may be changed by `emit('exit')`
return process_object->Get(exitCode)->Int32Value();
Expand Down
Loading