Commit 984aa0c25e1 for nodejs
commit 984aa0c25e1ad64f4e80bb76ad438cdf3330b834
Author: Matteo Collina <hello@matteocollina.com>
Date: Sat Oct 3 08:41:28 2026 +0200
async_hooks: remove legacy AsyncLocalStorage implementation
Remove the async_hooks-based AsyncLocalStorage fallback and the
--no-async-context-frame flag, making AsyncContextFrame the sole
implementation.
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/63641
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
diff --git a/doc/api/cli.md b/doc/api/cli.md
index b57714a0bfa..4e17d81169d 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -2277,17 +2277,6 @@ Disable the `node-addons` exports condition as well as disable loading
native addons. When `--no-addons` is specified, calling `process.dlopen` or
requiring a native C++ addon will fail and throw an exception.
-### `--no-async-context-frame`
-
-<!-- YAML
-added: v24.0.0
--->
-
-Disables the use of [`AsyncLocalStorage`][] backed by `AsyncContextFrame` and
-uses the prior implementation which relied on async\_hooks. The previous model
-is retained for compatibility with Electron and for cases where the context
-flow may differ. However, if a difference in flow is found please report it.
-
### `--no-deprecation`
<!-- YAML
@@ -4317,7 +4306,6 @@ one is included in the list below.
* `--max-old-space-size-percentage`
* `--network-family-autoselection-attempt-timeout`
* `--no-addons`
-* `--no-async-context-frame`
* `--no-deprecation`
* `--no-experimental-ffi`
* `--no-experimental-global-navigator`
@@ -4937,7 +4925,6 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
[`--use-env-proxy`]: #--use-env-proxy
[`--use-system-ca`]: #--use-system-ca
[`--watch`]: #--watch
-[`AsyncLocalStorage`]: async_context.md#class-asynclocalstorage
[`Buffer`]: buffer.md#class-buffer
[`CRYPTO_secure_malloc_init`]: https://www.openssl.org/docs/man3.0/man3/CRYPTO_secure_malloc_init.html
[`ERR_INVALID_TYPESCRIPT_SYNTAX`]: errors.md#err_invalid_typescript_syntax
diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json
index 07d4ac4a64e..22523a4868f 100644
--- a/doc/node-config-schema.json
+++ b/doc/node-config-schema.json
@@ -172,10 +172,6 @@
"type": "boolean",
"description": "allow worker threads when any permissions are set"
},
- "async-context-frame": {
- "type": "boolean",
- "description": "Improve AsyncLocalStorage performance with AsyncContextFrame"
- },
"bench-isolation": {
"type": "string",
"description": "configures the type of benchmark isolation used in the benchmark runner"
diff --git a/doc/node.1 b/doc/node.1
index 36a7cc72044..70488dff26c 100644
--- a/doc/node.1
+++ b/doc/node.1
@@ -1212,12 +1212,6 @@ Disable the \fBnode-addons\fR exports condition as well as disable loading
native addons. When \fB--no-addons\fR is specified, calling \fBprocess.dlopen\fR or
requiring a native C++ addon will fail and throw an exception.
.
-.It Fl -no-async-context-frame
-Disables the use of \fBAsyncLocalStorage\fR backed by \fBAsyncContextFrame\fR and
-uses the prior implementation which relied on async_hooks. The previous model
-is retained for compatibility with Electron and for cases where the context
-flow may differ. However, if a difference in flow is found please report it.
-.
.It Fl -no-deprecation
Silence deprecation warnings.
.
@@ -2335,8 +2329,6 @@ one is included in the list below.
.It
\fB--no-addons\fR
.It
-\fB--no-async-context-frame\fR
-.It
\fB--no-deprecation\fR
.It
\fB--no-experimental-ffi\fR
diff --git a/lib/async_hooks.js b/lib/async_hooks.js
index 31a390dfc91..b0106020d64 100644
--- a/lib/async_hooks.js
+++ b/lib/async_hooks.js
@@ -287,9 +287,7 @@ class AsyncResource {
module.exports = {
// Public API
get AsyncLocalStorage() {
- return AsyncContextFrame.enabled ?
- require('internal/async_local_storage/async_context_frame') :
- require('internal/async_local_storage/async_hooks');
+ return require('internal/async_local_storage/async_context_frame');
},
createHook,
executionAsyncId,
diff --git a/lib/internal/async_context_frame.js b/lib/internal/async_context_frame.js
index cd03eafe6fa..c12e74124a2 100644
--- a/lib/internal/async_context_frame.js
+++ b/lib/internal/async_context_frame.js
@@ -9,63 +9,34 @@ const {
setContinuationPreservedEmbedderData,
} = internalBinding('async_context_frame');
-function activeCurrent() {
- return getContinuationPreservedEmbedderData();
-}
-
-function activeSet(frame) {
- setContinuationPreservedEmbedderData(frame);
-}
-
-function activeExchange(frame) {
- const prior = getContinuationPreservedEmbedderData();
- setContinuationPreservedEmbedderData(frame);
- return prior;
-}
-
-function activeDisable(store) {
- getContinuationPreservedEmbedderData()?.disable(store);
-}
-
-class InactiveAsyncContextFrame extends SafeMap {
- static get enabled() {
- enabled_ ??= checkEnabled();
- return enabled_;
- }
-
- static current() {}
- static set(frame) {}
- static exchange(frame) {}
- static disable(store) {}
-}
-
-class AsyncContextFrame extends InactiveAsyncContextFrame {
+class AsyncContextFrame extends SafeMap {
constructor(store, data) {
super(AsyncContextFrame.current());
this.set(store, data);
}
- disable(store) {
- this.delete(store);
+ static current() {
+ return getContinuationPreservedEmbedderData();
}
-}
-let enabled_;
+ static set(frame) {
+ setContinuationPreservedEmbedderData(frame);
+ }
-function checkEnabled() {
- const enabled = require('internal/options')
- .getOptionValue('--async-context-frame');
+ static exchange(frame) {
+ const prior = this.current();
+ this.set(frame);
+ return prior;
+ }
- // If enabled, install the active implementations directly. We use props
- // rather than a prototype replacement to preserve V8 optimizations.
- if (enabled) {
- AsyncContextFrame.current = activeCurrent;
- AsyncContextFrame.set = activeSet;
- AsyncContextFrame.exchange = activeExchange;
- AsyncContextFrame.disable = activeDisable;
+ static disable(store) {
+ const frame = this.current();
+ frame?.disable(store);
}
- return enabled;
+ disable(store) {
+ this.delete(store);
+ }
}
module.exports = AsyncContextFrame;
diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js
index 89666ffa6c5..8a60b9a6ce5 100644
--- a/lib/internal/async_hooks.js
+++ b/lib/internal/async_hooks.js
@@ -105,7 +105,6 @@ const before_symbol = Symbol('before');
const after_symbol = Symbol('after');
const destroy_symbol = Symbol('destroy');
const promise_resolve_symbol = Symbol('promiseResolve');
-const async_local_storage_context_symbol = Symbol('kAsyncLocalStorageContext');
const emitBeforeNative = emitHookFactory(before_symbol, 'emitBeforeNative');
const emitAfterNative = emitHookFactory(after_symbol, 'emitAfterNative');
const emitDestroyNative = emitHookFactory(destroy_symbol, 'emitDestroyNative');
@@ -585,7 +584,7 @@ module.exports = {
symbols: {
async_id_symbol, trigger_async_id_symbol,
init_symbol, before_symbol, after_symbol, destroy_symbol,
- promise_resolve_symbol, async_local_storage_context_symbol,
+ promise_resolve_symbol,
owner_symbol,
},
constants: {
diff --git a/lib/internal/async_local_storage/async_hooks.js b/lib/internal/async_local_storage/async_hooks.js
deleted file mode 100644
index 2d39e1f1832..00000000000
--- a/lib/internal/async_local_storage/async_hooks.js
+++ /dev/null
@@ -1,168 +0,0 @@
-'use strict';
-
-const {
- ArrayPrototypeIndexOf,
- ArrayPrototypePush,
- ArrayPrototypeSplice,
- ObjectIs,
- ReflectApply,
- Symbol,
-} = primordials;
-
-const {
- validateObject,
-} = require('internal/validators');
-const {
- symbols: {
- async_local_storage_context_symbol,
- },
-} = require('internal/async_hooks');
-
-const {
- AsyncResource,
- createHook,
- executionAsyncResource,
-} = require('async_hooks');
-
-const RunScope = require('internal/async_local_storage/run_scope');
-const { kEmptyObject } = require('internal/util');
-
-const storageList = [];
-
-function getOrCreateResourceStore(resource) {
- return resource[async_local_storage_context_symbol] ??= { __proto__: null };
-}
-
-const storageHook = createHook({
- init(asyncId, type, triggerAsyncId, resource) {
- const currentResource = executionAsyncResource();
- // Value of currentResource is always a non null object
- for (let i = 0; i < storageList.length; ++i) {
- storageList[i]._propagate(resource, currentResource, type);
- }
- },
-});
-
-class AsyncLocalStorage {
- #defaultValue = undefined;
- #name = undefined;
-
- /**
- * @typedef {object} AsyncLocalStorageOptions
- * @property {any} [defaultValue] - The default value to use when no value is set.
- * @property {string} [name] - The name of the storage.
- */
- /**
- * @param {AsyncLocalStorageOptions} [options]
- */
- constructor(options = kEmptyObject) {
- this.kResourceStore = Symbol('kResourceStore');
- this.enabled = false;
- validateObject(options, 'options');
- this.#defaultValue = options.defaultValue;
-
- if (options.name !== undefined) {
- this.#name = `${options.name}`;
- }
-
- this._enable();
- }
-
- /** @type {string} */
- get name() { return this.#name || ''; }
-
- static bind(fn) {
- return AsyncResource.bind(fn);
- }
-
- static snapshot() {
- return AsyncLocalStorage.bind((cb, ...args) => cb(...args));
- }
-
- disable() {
- if (this.enabled) {
- this.enabled = false;
- // If this.enabled, the instance must be in storageList
- const index = ArrayPrototypeIndexOf(storageList, this);
- ArrayPrototypeSplice(storageList, index, 1);
- if (storageList.length === 0) {
- storageHook.disable();
- }
- }
- }
-
- _enable() {
- if (!this.enabled) {
- this.enabled = true;
- ArrayPrototypePush(storageList, this);
- storageHook.enable();
- }
- }
-
- // Propagate the context from a parent resource to a child one
- _propagate(resource, triggerResource, type) {
- const store = triggerResource[async_local_storage_context_symbol]?.[this.kResourceStore];
- if (this.enabled) {
- const resourceStore = getOrCreateResourceStore(resource);
- resourceStore[this.kResourceStore] = store;
- }
- }
-
- enterWith(store) {
- this._enable();
- const resource = executionAsyncResource();
- const resourceStore = getOrCreateResourceStore(resource);
- resourceStore[this.kResourceStore] = store;
- }
-
- run(store, callback, ...args) {
- // Avoid creation of an AsyncResource if store is already active
- if (ObjectIs(store, this.getStore())) {
- return ReflectApply(callback, null, args);
- }
-
- this._enable();
-
- const resource = executionAsyncResource();
- const resourceStore = getOrCreateResourceStore(resource);
- const oldStore = resourceStore[this.kResourceStore];
-
- resourceStore[this.kResourceStore] = store;
-
- try {
- return ReflectApply(callback, null, args);
- } finally {
- resourceStore[this.kResourceStore] = oldStore;
- }
- }
-
- exit(callback, ...args) {
- if (!this.enabled) {
- return ReflectApply(callback, null, args);
- }
- this.disable();
- try {
- return ReflectApply(callback, null, args);
- } finally {
- this._enable();
- }
- }
-
- getStore() {
- if (this.enabled) {
- const resource = executionAsyncResource();
- const resourceStore = resource[async_local_storage_context_symbol];
- if (resourceStore === undefined || !(this.kResourceStore in resourceStore)) {
- return this.#defaultValue;
- }
- return resourceStore[this.kResourceStore];
- }
- return this.#defaultValue;
- }
-
- withScope(store) {
- return new RunScope(this, store);
- }
-}
-
-module.exports = AsyncLocalStorage;
diff --git a/lib/internal/timers.js b/lib/internal/timers.js
index 9904cb7cb2e..30208253d60 100644
--- a/lib/internal/timers.js
+++ b/lib/internal/timers.js
@@ -100,9 +100,6 @@ const {
emitBefore,
emitAfter,
emitDestroy,
- symbols: {
- async_local_storage_context_symbol,
- },
} = require('internal/async_hooks');
// Symbols for storing async id state.
@@ -132,12 +129,8 @@ const AsyncContextFrame = require('internal/async_context_frame');
const async_context_frame = Symbol('kAsyncContextFrame');
function removeStoresFromResource(resource) {
- if (AsyncContextFrame.enabled) {
- if (resource[async_context_frame] !== undefined) {
- resource[async_context_frame] = undefined;
- }
- } else if (resource[async_local_storage_context_symbol] !== undefined) {
- resource[async_local_storage_context_symbol] = undefined;
+ if (resource[async_context_frame] !== undefined) {
+ resource[async_context_frame] = undefined;
}
}
diff --git a/src/async_context_frame.cc b/src/async_context_frame.cc
index 2e637904573..b2b6514d9a2 100644
--- a/src/async_context_frame.cc
+++ b/src/async_context_frame.cc
@@ -38,10 +38,6 @@ Local<Value> current(Isolate* isolate) {
}
void set(Environment* env, Local<Value> value) {
- if (!env->async_context_frame_enabled()) {
- return;
- }
-
env->isolate()->SetContinuationPreservedEmbedderDataV2(value);
}
diff --git a/src/env-inl.h b/src/env-inl.h
index 12ffdb48a0b..c2abf1c29a8 100644
--- a/src/env-inl.h
+++ b/src/env-inl.h
@@ -460,10 +460,6 @@ inline std::shared_ptr<EnvironmentOptions> Environment::options() {
return options_;
}
-inline bool Environment::async_context_frame_enabled() const {
- return options_->async_context_frame;
-}
-
inline const std::vector<std::string>& Environment::argv() {
return argv_;
}
diff --git a/src/env.h b/src/env.h
index 75f3a66eda7..63c52524695 100644
--- a/src/env.h
+++ b/src/env.h
@@ -1112,7 +1112,6 @@ class Environment final : public MemoryRetainer {
void* data);
inline std::shared_ptr<EnvironmentOptions> options();
- inline bool async_context_frame_enabled() const;
inline std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port();
inline int64_t stack_trace_limit() const;
diff --git a/src/node_options.cc b/src/node_options.cc
index 917f6a4f47c..72c8a9a2aef 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -950,11 +950,6 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
AddOption(
"--experimental-wasi-unstable-preview1", "", NoOp{}, kAllowedInEnvvar);
AddOption("--expose-gc", "expose gc extension", V8Option{}, kAllowedInEnvvar);
- AddOption("--async-context-frame",
- "Improve AsyncLocalStorage performance with AsyncContextFrame",
- BOOL_FIELD(async_context_frame),
- kAllowedInEnvvar,
- true);
AddOption("--expose-internals", "", BOOL_FIELD(expose_internals));
AddOption("--frozen-intrinsics",
"experimental frozen intrinsics support",
diff --git a/src/node_options.h b/src/node_options.h
index 78de1111ce9..ae3ddeb3120 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -238,7 +238,6 @@ class EnvironmentOptions : public Options {
DEFINE_BOOL_FIELD(allow_openssl_store) = false;
DEFINE_BOOL_FIELD(allow_worker_threads) = false;
DEFINE_BOOL_FIELD(experimental_vm_modules) = EXPERIMENTALS_DEFAULT_VALUE;
- DEFINE_BOOL_FIELD(async_context_frame) = true;
DEFINE_BOOL_FIELD(expose_internals) = false;
DEFINE_BOOL_FIELD(force_node_api_uncaught_exceptions_policy) = false;
DEFINE_BOOL_FIELD(frozen_intrinsics) = false;
diff --git a/test/async-hooks/test-async-local-storage-gcable.js b/test/async-hooks/test-async-local-storage-gcable.js
index 57bb1b7ace1..303442e60c8 100644
--- a/test/async-hooks/test-async-local-storage-gcable.js
+++ b/test/async-hooks/test-async-local-storage-gcable.js
@@ -1,12 +1,11 @@
'use strict';
-// Flags: --expose_gc --expose-internals
+// Flags: --expose_gc
// This test ensures that AsyncLocalStorage gets gced once it was disabled
// and no strong references remain in userland.
const common = require('../common');
const { AsyncLocalStorage } = require('async_hooks');
-const AsyncContextFrame = require('internal/async_context_frame');
const { onGC } = require('../common/gc');
let asyncLocalStorage = new AsyncLocalStorage();
@@ -17,11 +16,9 @@ asyncLocalStorage.run({}, common.mustCall(() => {
onGC(asyncLocalStorage, { ongc: common.mustCall() });
}));
-if (AsyncContextFrame.enabled) {
- // This disable() is needed to remove reference form AsyncContextFrame
- // created during exit of run() to the AsyncLocalStore instance.
- asyncLocalStorage.disable();
-}
+// This disable() is needed to remove reference from AsyncContextFrame
+// created during exit of run() to the AsyncLocalStore instance.
+asyncLocalStorage.disable();
asyncLocalStorage = null;
global.gc();
diff --git a/test/parallel/test-als-defaultvalue-original.js b/test/parallel/test-als-defaultvalue-original.js
deleted file mode 100644
index 1bfe239abfc..00000000000
--- a/test/parallel/test-als-defaultvalue-original.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Flags: --no-async-context-frame
-'use strict';
-
-require('../common');
-
-const {
- AsyncLocalStorage,
-} = require('async_hooks');
-
-const assert = require('assert');
-
-// ============================================================================
-// The defaultValue option
-const als1 = new AsyncLocalStorage();
-assert.strictEqual(als1.getStore(), undefined);
-
-const als2 = new AsyncLocalStorage({ defaultValue: 'default' });
-assert.strictEqual(als2.getStore(), 'default');
-
-const als3 = new AsyncLocalStorage({ defaultValue: 42 });
-assert.strictEqual(als3.getStore(), 42);
-
-const als4 = new AsyncLocalStorage({ defaultValue: null });
-assert.strictEqual(als4.getStore(), null);
-
-assert.throws(() => new AsyncLocalStorage(null), {
- code: 'ERR_INVALID_ARG_TYPE',
-});
-
-// ============================================================================
-// The name option
-
-const als5 = new AsyncLocalStorage({ name: 'test' });
-assert.strictEqual(als5.name, 'test');
-
-const als6 = new AsyncLocalStorage();
-assert.strictEqual(als6.name, '');
diff --git a/test/parallel/test-als-defaultvalue.js b/test/parallel/test-als-defaultvalue.js
index 5b5b43b57a7..f86cec3c962 100644
--- a/test/parallel/test-als-defaultvalue.js
+++ b/test/parallel/test-als-defaultvalue.js
@@ -1,4 +1,3 @@
-// Flags: --async-context-frame
'use strict';
require('../common');
diff --git a/test/parallel/test-internal-async-context-frame-disable.js b/test/parallel/test-internal-async-context-frame-disable.js
deleted file mode 100644
index 61e351dc795..00000000000
--- a/test/parallel/test-internal-async-context-frame-disable.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Flags: --expose-internals --no-async-context-frame
-'use strict';
-
-require('../common');
-const assert = require('assert');
-const AsyncContextFrame = require('internal/async_context_frame');
-
-// Test that AsyncContextFrame can be disabled.
-assert(!AsyncContextFrame.enabled);
diff --git a/test/parallel/test-internal-async-context-frame-enabled.js b/test/parallel/test-internal-async-context-frame-enabled.js
deleted file mode 100644
index 1c99ff42519..00000000000
--- a/test/parallel/test-internal-async-context-frame-enabled.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Flags: --expose-internals
-'use strict';
-
-require('../common');
-const assert = require('assert');
-const AsyncContextFrame = require('internal/async_context_frame');
-
-// Test that AsyncContextFrame is enabled by default.
-assert(AsyncContextFrame.enabled);
diff --git a/test/parallel/test-stream-finished-async-local-storage.js b/test/parallel/test-stream-finished-async-local-storage.js
index b6d8f6722b0..876fc476f59 100644
--- a/test/parallel/test-stream-finished-async-local-storage.js
+++ b/test/parallel/test-stream-finished-async-local-storage.js
@@ -1,12 +1,9 @@
-// Flags: --expose-internals
'use strict';
const common = require('../common');
const { Readable, finished } = require('stream');
const { AsyncLocalStorage } = require('async_hooks');
const assert = require('assert');
-const AsyncContextFrame = require('internal/async_context_frame');
-const { enabledHooksExist } = require('internal/async_hooks');
// This test verifies that ALS context is preserved when using stream.finished()
@@ -15,7 +12,6 @@ const readable = new Readable();
als.run('test-context-1', common.mustCall(() => {
finished(readable, common.mustCall(() => {
- assert.strictEqual(AsyncContextFrame.enabled || enabledHooksExist(), true);
assert.strictEqual(als.getStore(), 'test-context-1');
}));
}));
diff --git a/test/parallel/test-stream-finished-default-path.js b/test/parallel/test-stream-finished-default-path.js
deleted file mode 100644
index 5d992ab657a..00000000000
--- a/test/parallel/test-stream-finished-default-path.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Flags: --expose-internals --no-async-context-frame
-'use strict';
-
-const common = require('../common');
-const { Readable, finished } = require('stream');
-const assert = require('assert');
-const AsyncContextFrame = require('internal/async_context_frame');
-const { enabledHooksExist } = require('internal/async_hooks');
-
-// This test verifies that when there are no active async hooks, stream.finished() uses the default callback path
-
-const readable = new Readable();
-
-finished(readable, common.mustCall(() => {
- assert.strictEqual(enabledHooksExist(), false);
- assert.strictEqual(
- AsyncContextFrame.current() || enabledHooksExist(),
- false,
- );
-}));
-
-readable.destroy();
diff --git a/test/parallel/test-timers-async-store-leak.js b/test/parallel/test-timers-async-store-leak.js
index 1f95b2ea55f..4775472a104 100644
--- a/test/parallel/test-timers-async-store-leak.js
+++ b/test/parallel/test-timers-async-store-leak.js
@@ -2,61 +2,20 @@
'use strict';
const common = require('../common');
-const { spawnSyncAndAssert } = require('../common/child_process');
const { AsyncLocalStorage } = require('async_hooks');
const assert = require('assert');
-
-if (process.argv[2] !== 'child') {
- // Test with async-context-frame disabled (legacy ALS mode)
- spawnSyncAndAssert(process.execPath, [
- '--expose-internals',
- '--expose-gc',
- '--no-async-context-frame',
- __filename,
- 'child',
- ], {});
-
- // Test with async-context-frame enabled (default)
- spawnSyncAndAssert(process.execPath, [
- '--expose-internals',
- '--expose-gc',
- __filename,
- 'child',
- ], {});
-}
-
-const AsyncContextFrame = require('internal/async_context_frame');
const {
async_context_frame,
} = require('internal/timers');
-const {
- symbols: {
- async_local_storage_context_symbol,
- },
-} = require('internal/async_hooks');
-
-// When async-context-frame is enabled, stores are stored in the async context
-// frame, not directly on the resource. The resource holds a reference to the
-// frame via async_context_frame.
-const isACFEnabled = AsyncContextFrame.enabled;
-
-function getStore(resource, als) {
- if (isACFEnabled) {
- return resource[async_context_frame]?.get(als);
- }
- return resource[async_local_storage_context_symbol]?.[als.kResourceStore];
-}
+// Stores live in the async context frame, not directly on the resource. The
+// resource holds a reference to the frame via async_context_frame.
function assertStore(resource, als, store) {
- assert.strictEqual(getStore(resource, als), store);
+ assert.strictEqual(resource[async_context_frame]?.get(als), store);
}
function assertNoStore(resource) {
- if (isACFEnabled) {
- assert.strictEqual(resource[async_context_frame], undefined);
- } else {
- assert.strictEqual(resource[async_local_storage_context_symbol], undefined);
- }
+ assert.strictEqual(resource[async_context_frame], undefined);
}
// Test that setTimeout does not retain a reference to the async store after
diff --git a/test/sequential/test-without-async-context-frame.mjs b/test/sequential/test-without-async-context-frame.mjs
deleted file mode 100644
index e7342f03a4e..00000000000
--- a/test/sequential/test-without-async-context-frame.mjs
+++ /dev/null
@@ -1,24 +0,0 @@
-import { isWindows } from '../common/index.mjs';
-import { spawn } from 'node:child_process';
-import { once } from 'node:events';
-import { fileURLToPath } from 'node:url';
-import assert from 'node:assert';
-
-const python = process.env.PYTHON || (isWindows ? 'python' : 'python3');
-
-const testRunner = fileURLToPath(
- new URL('../../tools/test.py', import.meta.url)
-);
-
-const proc = spawn(python, [
- testRunner,
- `--mode=${process.features.debug ? 'debug' : 'release'}`,
- `--shell=${process.execPath}`,
- '--node-args=--no-async-context-frame',
- '*/test-async-local-storage-*',
-], {
- stdio: ['inherit', 'inherit', 'inherit'],
-});
-
-const [code] = await once(proc, 'exit');
-assert.strictEqual(code, 0);