aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/internal/async_hooks.js17
-rw-r--r--src/async_wrap.cc13
-rw-r--r--test/parallel/test-async-hooks-enable-disable-enable.js17
3 files changed, 36 insertions, 11 deletions
diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js
index 64f5cb2462..bf803885ca 100644
--- a/lib/internal/async_hooks.js
+++ b/lib/internal/async_hooks.js
@@ -69,6 +69,7 @@ const active_hooks = {
};
const { registerDestroyHook } = async_wrap;
+const { enqueueMicrotask } = internalBinding('task_queue');
// Each constant tracks how many callbacks there are for any given step of
// async execution. These are tracked so if the user didn't include callbacks
@@ -231,14 +232,26 @@ function restoreActiveHooks() {
}
+let wantPromiseHook = false;
function enableHooks() {
- enablePromiseHook();
async_hook_fields[kCheck] += 1;
+
+ wantPromiseHook = true;
+ enablePromiseHook();
}
function disableHooks() {
- disablePromiseHook();
async_hook_fields[kCheck] -= 1;
+
+ wantPromiseHook = false;
+ // Delay the call to `disablePromiseHook()` because we might currently be
+ // between the `before` and `after` calls of a Promise.
+ enqueueMicrotask(disablePromiseHookIfNecessary);
+}
+
+function disablePromiseHookIfNecessary() {
+ if (!wantPromiseHook)
+ disablePromiseHook();
}
// Internal Embedder API //
diff --git a/src/async_wrap.cc b/src/async_wrap.cc
index 8a487a9dd3..8cb30a6f6a 100644
--- a/src/async_wrap.cc
+++ b/src/async_wrap.cc
@@ -334,15 +334,10 @@ static void EnablePromiseHook(const FunctionCallbackInfo<Value>& args) {
static void DisablePromiseHook(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
- // Delay the call to `RemovePromiseHook` because we might currently be
- // between the `before` and `after` calls of a Promise.
- isolate->EnqueueMicrotask([](void* data) {
- // The per-Isolate API provides no way of knowing whether there are multiple
- // users of the PromiseHook. That hopefully goes away when V8 introduces
- // a per-context API.
- Isolate* isolate = static_cast<Isolate*>(data);
- isolate->SetPromiseHook(nullptr);
- }, static_cast<void*>(isolate));
+ // The per-Isolate API provides no way of knowing whether there are multiple
+ // users of the PromiseHook. That hopefully goes away when V8 introduces
+ // a per-context API.
+ isolate->SetPromiseHook(nullptr);
}
diff --git a/test/parallel/test-async-hooks-enable-disable-enable.js b/test/parallel/test-async-hooks-enable-disable-enable.js
new file mode 100644
index 0000000000..640815e14c
--- /dev/null
+++ b/test/parallel/test-async-hooks-enable-disable-enable.js
@@ -0,0 +1,17 @@
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const async_hooks = require('async_hooks');
+
+// Regression test for https://github.com/nodejs/node/issues/27585.
+
+async_hooks.createHook({ init: () => {} }).enable().disable().enable();
+async_hooks.createHook({ init: () => {} }).enable();
+
+async function main() {
+ const initialAsyncId = async_hooks.executionAsyncId();
+ await 0;
+ assert.notStrictEqual(async_hooks.executionAsyncId(), initialAsyncId);
+}
+
+main().then(common.mustCall());