From 0ee37f3909ed9564a97506a633090374141dc8e5 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Fri, 25 Apr 2025 22:34:37 +0100 Subject: [PATCH] async_hooks: enable AsyncLocalStorage once constructed This fixes the leak behavior when using `enterWith` when no `AsyncLocalStorage`s were enabled inside a promise. --- .../async_local_storage/async_hooks.js | 2 + .../test-async-local-storage-enter-with.js | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/parallel/test-async-local-storage-enter-with.js diff --git a/lib/internal/async_local_storage/async_hooks.js b/lib/internal/async_local_storage/async_hooks.js index 0ed423f5932ed7..d227549412bf61 100644 --- a/lib/internal/async_local_storage/async_hooks.js +++ b/lib/internal/async_local_storage/async_hooks.js @@ -51,6 +51,8 @@ class AsyncLocalStorage { if (options.name !== undefined) { this.#name = `${options.name}`; } + + this._enable(); } /** @type {string} */ diff --git a/test/parallel/test-async-local-storage-enter-with.js b/test/parallel/test-async-local-storage-enter-with.js new file mode 100644 index 00000000000000..1b6ec061e0a4bd --- /dev/null +++ b/test/parallel/test-async-local-storage-enter-with.js @@ -0,0 +1,37 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +// Verify that `enterWith()` does not leak the store to the parent context in a promise. + +const als = new AsyncLocalStorage(); + +async function asyncFunctionAfterAwait() { + await 0; + als.enterWith('after await'); +} + +function promiseThen() { + return Promise.resolve() + .then(() => { + als.enterWith('inside then'); + }); +} + +async function asyncFunctionBeforeAwait() { + als.enterWith('before await'); + await 0; +} + +async function main() { + await asyncFunctionAfterAwait(); + await promiseThen(); + assert.strictEqual(als.getStore(), undefined); + + // This is a known limitation of the `enterWith` API. + await asyncFunctionBeforeAwait(); + assert.strictEqual(als.getStore(), 'before await'); +} + +main().then(common.mustCall());