Skip to content

Commit 6567930

Browse files
committed
async_hooks: use new v8::Context PromiseHook API
1 parent 0eb6853 commit 6567930

File tree

2 files changed

+59
-48
lines changed

2 files changed

+59
-48
lines changed

lib/internal/async_hooks.js

+48-48
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const {
88
FunctionPrototypeBind,
99
ObjectPrototypeHasOwnProperty,
1010
ObjectDefineProperty,
11-
Promise,
1211
ReflectApply,
1312
Symbol,
1413
} = primordials;
@@ -57,7 +56,7 @@ const {
5756
clearAsyncIdStack,
5857
} = async_wrap;
5958
// For performance reasons, only track Promises when a hook is enabled.
60-
const { enablePromiseHook, disablePromiseHook } = async_wrap;
59+
const { enablePromiseHook, disablePromiseHook, setPromiseHooks } = async_wrap;
6160
// Properties in active_hooks are used to keep track of the set of hooks being
6261
// executed in case another hook is enabled/disabled. The new set of hooks is
6362
// then restored once the active set of hooks is finished executing.
@@ -298,71 +297,68 @@ function restoreActiveHooks() {
298297
active_hooks.tmp_fields = null;
299298
}
300299

301-
function trackPromise(promise, parent, silent) {
302-
const asyncId = getOrSetAsyncId(promise);
300+
function trackPromise(promise, parent) {
301+
if (promise[async_id_symbol]) {
302+
return;
303+
}
303304

305+
promise[async_id_symbol] = newAsyncId();
304306
promise[trigger_async_id_symbol] = parent ? getOrSetAsyncId(parent) :
305307
getDefaultTriggerAsyncId();
308+
}
306309

307-
if (!silent && initHooksExist()) {
308-
const triggerId = promise[trigger_async_id_symbol];
309-
emitInitScript(asyncId, 'PROMISE', triggerId, promise);
310-
}
310+
function promiseInitHook(promise, parent) {
311+
trackPromise(promise, parent);
312+
const asyncId = promise[async_id_symbol];
313+
const triggerAsyncId = promise[trigger_async_id_symbol];
314+
emitInitScript(asyncId, 'PROMISE', triggerAsyncId, promise);
311315
}
312316

313-
function fastPromiseHook(type, promise, parent) {
314-
if (type === kInit || !promise[async_id_symbol]) {
315-
const silent = type !== kInit;
316-
if (parent instanceof Promise) {
317-
trackPromise(promise, parent, silent);
318-
} else {
319-
trackPromise(promise, null, silent);
320-
}
317+
function promiseBeforeHook(promise) {
318+
trackPromise(promise);
319+
const asyncId = promise[async_id_symbol];
320+
const triggerId = promise[trigger_async_id_symbol];
321+
emitBeforeScript(asyncId, triggerId, promise);
322+
}
321323

322-
if (!silent) return;
324+
function promiseAfterHook(promise) {
325+
trackPromise(promise);
326+
const asyncId = promise[async_id_symbol];
327+
if (hasHooks(kAfter)) {
328+
emitAfterNative(asyncId);
323329
}
330+
if (asyncId === executionAsyncId()) {
331+
// This condition might not be true if async_hooks was enabled during
332+
// the promise callback execution.
333+
// Popping it off the stack can be skipped in that case, because it is
334+
// known that it would correspond to exactly one call with
335+
// PromiseHookType::kBefore that was not witnessed by the PromiseHook.
336+
popAsyncContext(asyncId);
337+
}
338+
}
324339

340+
function promiseResolveHook(promise) {
341+
trackPromise(promise);
325342
const asyncId = promise[async_id_symbol];
326-
switch (type) {
327-
case kBefore:
328-
const triggerId = promise[trigger_async_id_symbol];
329-
emitBeforeScript(asyncId, triggerId, promise);
330-
break;
331-
case kAfter:
332-
if (hasHooks(kAfter)) {
333-
emitAfterNative(asyncId);
334-
}
335-
if (asyncId === executionAsyncId()) {
336-
// This condition might not be true if async_hooks was enabled during
337-
// the promise callback execution.
338-
// Popping it off the stack can be skipped in that case, because it is
339-
// known that it would correspond to exactly one call with
340-
// PromiseHookType::kBefore that was not witnessed by the PromiseHook.
341-
popAsyncContext(asyncId);
342-
}
343-
break;
344-
case kPromiseResolve:
345-
emitPromiseResolveNative(asyncId);
346-
break;
347-
}
343+
emitPromiseResolveNative(asyncId);
348344
}
349345

350346
let wantPromiseHook = false;
351347
function enableHooks() {
352348
async_hook_fields[kCheck] += 1;
353349
}
354350

355-
let promiseHookMode = -1;
356351
function updatePromiseHookMode() {
357352
wantPromiseHook = true;
358353
if (destroyHooksExist()) {
359-
if (promiseHookMode !== 1) {
360-
promiseHookMode = 1;
361-
enablePromiseHook();
362-
}
363-
} else if (promiseHookMode !== 0) {
364-
promiseHookMode = 0;
365-
enablePromiseHook(fastPromiseHook);
354+
enablePromiseHook();
355+
} else {
356+
setPromiseHooks(
357+
initHooksExist() ? promiseInitHook : undefined,
358+
promiseBeforeHook,
359+
promiseAfterHook,
360+
promiseResolveHooksExist() ? promiseResolveHook : undefined,
361+
);
366362
}
367363
}
368364

@@ -378,8 +374,8 @@ function disableHooks() {
378374

379375
function disablePromiseHookIfNecessary() {
380376
if (!wantPromiseHook) {
381-
promiseHookMode = -1;
382377
disablePromiseHook();
378+
setPromiseHooks(undefined, undefined, undefined, undefined);
383379
}
384380
}
385381

@@ -453,6 +449,10 @@ function destroyHooksExist() {
453449
return hasHooks(kDestroy);
454450
}
455451

452+
function promiseResolveHooksExist() {
453+
return hasHooks(kPromiseResolve);
454+
}
455+
456456

457457
function emitInitScript(asyncId, type, triggerAsyncId, resource) {
458458
// Short circuit all checks for the common case. Which is that no hooks have

src/async_wrap.cc

+11
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,15 @@ static void EnablePromiseHook(const FunctionCallbackInfo<Value>& args) {
452452
}
453453
}
454454

455+
static void SetPromiseHooks(const FunctionCallbackInfo<Value>& args) {
456+
Environment* env = Environment::GetCurrent(args);
457+
Local<Context> ctx = env->context();
458+
Local<Value> init_hook = args[0];
459+
Local<Value> before_hook = args[1];
460+
Local<Value> after_hook = args[2];
461+
Local<Value> resolve_hook = args[3];
462+
ctx->SetPromiseHooks(init_hook, before_hook, after_hook, resolve_hook);
463+
}
455464

456465
static void DisablePromiseHook(const FunctionCallbackInfo<Value>& args) {
457466
Environment* env = Environment::GetCurrent(args);
@@ -631,6 +640,7 @@ void AsyncWrap::Initialize(Local<Object> target,
631640
env->SetMethod(target, "clearAsyncIdStack", ClearAsyncIdStack);
632641
env->SetMethod(target, "queueDestroyAsyncId", QueueDestroyAsyncId);
633642
env->SetMethod(target, "enablePromiseHook", EnablePromiseHook);
643+
env->SetMethod(target, "setPromiseHooks", SetPromiseHooks);
634644
env->SetMethod(target, "disablePromiseHook", DisablePromiseHook);
635645
env->SetMethod(target, "registerDestroyHook", RegisterDestroyHook);
636646

@@ -725,6 +735,7 @@ void AsyncWrap::RegisterExternalReferences(
725735
registry->Register(ClearAsyncIdStack);
726736
registry->Register(QueueDestroyAsyncId);
727737
registry->Register(EnablePromiseHook);
738+
registry->Register(SetPromiseHooks);
728739
registry->Register(DisablePromiseHook);
729740
registry->Register(RegisterDestroyHook);
730741
registry->Register(AsyncWrap::GetAsyncId);

0 commit comments

Comments
 (0)