Skip to content

Commit 7972ebb

Browse files
committed
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.
1 parent 8d0a3b8 commit 7972ebb

18 files changed

Lines changed: 10 additions & 345 deletions

doc/api/cli.md

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,17 +2002,6 @@ Disable the `node-addons` exports condition as well as disable loading
20022002
native addons. When `--no-addons` is specified, calling `process.dlopen` or
20032003
requiring a native C++ addon will fail and throw an exception.
20042004

2005-
### `--no-async-context-frame`
2006-
2007-
<!-- YAML
2008-
added: v24.0.0
2009-
-->
2010-
2011-
Disables the use of [`AsyncLocalStorage`][] backed by `AsyncContextFrame` and
2012-
uses the prior implementation which relied on async\_hooks. The previous model
2013-
is retained for compatibility with Electron and for cases where the context
2014-
flow may differ. However, if a difference in flow is found please report it.
2015-
20162005
### `--no-deprecation`
20172006

20182007
<!-- YAML
@@ -3825,7 +3814,6 @@ one is included in the list below.
38253814
* `--napi-modules`
38263815
* `--network-family-autoselection-attempt-timeout`
38273816
* `--no-addons`
3828-
* `--no-async-context-frame`
38293817
* `--no-deprecation`
38303818
* `--no-experimental-global-navigator`
38313819
* `--no-experimental-repl-await`
@@ -4420,7 +4408,6 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
44204408
[`--require`]: #-r---require-module
44214409
[`--use-env-proxy`]: #--use-env-proxy
44224410
[`--use-system-ca`]: #--use-system-ca
4423-
[`AsyncLocalStorage`]: async_context.md#class-asynclocalstorage
44244411
[`Buffer`]: buffer.md#class-buffer
44254412
[`CRYPTO_secure_malloc_init`]: https://www.openssl.org/docs/man3.0/man3/CRYPTO_secure_malloc_init.html
44264413
[`ERR_INVALID_TYPESCRIPT_SYNTAX`]: errors.md#err_invalid_typescript_syntax

doc/node-config-schema.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@
111111
"type": "boolean",
112112
"description": "allow worker threads when any permissions are set"
113113
},
114-
"async-context-frame": {
115-
"type": "boolean",
116-
"description": "Improve AsyncLocalStorage performance with AsyncContextFrame"
117-
},
118114
"conditions": {
119115
"oneOf": [
120116
{

doc/node.1

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,12 +1051,6 @@ Disable the \fBnode-addons\fR exports condition as well as disable loading
10511051
native addons. When \fB--no-addons\fR is specified, calling \fBprocess.dlopen\fR or
10521052
requiring a native C++ addon will fail and throw an exception.
10531053
.
1054-
.It Fl -no-async-context-frame
1055-
Disables the use of \fBAsyncLocalStorage\fR backed by \fBAsyncContextFrame\fR and
1056-
uses the prior implementation which relied on async_hooks. The previous model
1057-
is retained for compatibility with Electron and for cases where the context
1058-
flow may differ. However, if a difference in flow is found please report it.
1059-
.
10601054
.It Fl -no-deprecation
10611055
Silence deprecation warnings.
10621056
.
@@ -2008,8 +2002,6 @@ one is included in the list below.
20082002
.It
20092003
\fB--no-addons\fR
20102004
.It
2011-
\fB--no-async-context-frame\fR
2012-
.It
20132005
\fB--no-deprecation\fR
20142006
.It
20152007
\fB--no-experimental-global-navigator\fR

lib/async_hooks.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,7 @@ class AsyncResource {
282282
module.exports = {
283283
// Public API
284284
get AsyncLocalStorage() {
285-
return AsyncContextFrame.enabled ?
286-
require('internal/async_local_storage/async_context_frame') :
287-
require('internal/async_local_storage/async_hooks');
285+
return require('internal/async_local_storage/async_context_frame');
288286
},
289287
createHook,
290288
executionAsyncId,

lib/internal/async_context_frame.js

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const {
4-
ObjectSetPrototypeOf,
54
SafeMap,
65
} = primordials;
76

@@ -10,11 +9,10 @@ const {
109
setContinuationPreservedEmbedderData,
1110
} = internalBinding('async_context_frame');
1211

13-
let enabled_;
14-
15-
class ActiveAsyncContextFrame extends SafeMap {
16-
static get enabled() {
17-
return true;
12+
class AsyncContextFrame extends SafeMap {
13+
constructor(store, data) {
14+
super(AsyncContextFrame.current());
15+
this.set(store, data);
1816
}
1917

2018
static current() {
@@ -35,39 +33,6 @@ class ActiveAsyncContextFrame extends SafeMap {
3533
const frame = this.current();
3634
frame?.disable(store);
3735
}
38-
}
39-
40-
function checkEnabled() {
41-
const enabled = require('internal/options')
42-
.getOptionValue('--async-context-frame');
43-
44-
// If enabled, swap to active prototype so we don't need to check status
45-
// on every interaction with the async context frame.
46-
if (enabled) {
47-
// eslint-disable-next-line no-use-before-define
48-
ObjectSetPrototypeOf(AsyncContextFrame, ActiveAsyncContextFrame);
49-
}
50-
51-
return enabled;
52-
}
53-
54-
class InactiveAsyncContextFrame extends SafeMap {
55-
static get enabled() {
56-
enabled_ ??= checkEnabled();
57-
return enabled_;
58-
}
59-
60-
static current() {}
61-
static set(frame) {}
62-
static exchange(frame) {}
63-
static disable(store) {}
64-
}
65-
66-
class AsyncContextFrame extends InactiveAsyncContextFrame {
67-
constructor(store, data) {
68-
super(AsyncContextFrame.current());
69-
this.set(store, data);
70-
}
7136

7237
disable(store) {
7338
this.delete(store);

lib/internal/async_local_storage/async_hooks.js

Lines changed: 0 additions & 153 deletions
This file was deleted.

src/async_context_frame.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ Local<Value> current(Isolate* isolate) {
3838
}
3939

4040
void set(Isolate* isolate, Local<Value> value) {
41-
auto env = Environment::GetCurrent(isolate);
42-
if (!env->options()->async_context_frame) {
43-
return;
44-
}
45-
4641
isolate->SetContinuationPreservedEmbedderDataV2(value);
4742
}
4843

src/node_options.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -739,11 +739,6 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
739739
AddOption(
740740
"--experimental-wasi-unstable-preview1", "", NoOp{}, kAllowedInEnvvar);
741741
AddOption("--expose-gc", "expose gc extension", V8Option{}, kAllowedInEnvvar);
742-
AddOption("--async-context-frame",
743-
"Improve AsyncLocalStorage performance with AsyncContextFrame",
744-
&EnvironmentOptions::async_context_frame,
745-
kAllowedInEnvvar,
746-
true);
747742
AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals);
748743
AddOption("--frozen-intrinsics",
749744
"experimental frozen intrinsics support",

src/node_options.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ class EnvironmentOptions : public Options {
155155
bool allow_worker_threads = false;
156156
bool experimental_repl_await = true;
157157
bool experimental_vm_modules = EXPERIMENTALS_DEFAULT_VALUE;
158-
bool async_context_frame = true;
159158
bool expose_internals = false;
160159
bool force_node_api_uncaught_exceptions_policy = false;
161160
bool frozen_intrinsics = false;
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
'use strict';
2-
// Flags: --expose_gc --expose-internals
2+
// Flags: --expose_gc
33

44
// This test ensures that AsyncLocalStorage gets gced once it was disabled
55
// and no strong references remain in userland.
66

77
const common = require('../common');
88
const { AsyncLocalStorage } = require('async_hooks');
9-
const AsyncContextFrame = require('internal/async_context_frame');
109
const { onGC } = require('../common/gc');
1110

1211
let asyncLocalStorage = new AsyncLocalStorage();
@@ -17,11 +16,9 @@ asyncLocalStorage.run({}, common.mustCall(() => {
1716
onGC(asyncLocalStorage, { ongc: common.mustCall() });
1817
}));
1918

20-
if (AsyncContextFrame.enabled) {
21-
// This disable() is needed to remove reference form AsyncContextFrame
22-
// created during exit of run() to the AsyncLocalStore instance.
23-
asyncLocalStorage.disable();
24-
}
19+
// This disable() is needed to remove reference from AsyncContextFrame
20+
// created during exit of run() to the AsyncLocalStore instance.
21+
asyncLocalStorage.disable();
2522

2623
asyncLocalStorage = null;
2724
global.gc();

0 commit comments

Comments
 (0)