Skip to content

Commit 57238f0

Browse files
author
Stephen Belanger
committed
lib: improve async_context_frame structure
1 parent d1229ee commit 57238f0

File tree

6 files changed

+40
-20
lines changed

6 files changed

+40
-20
lines changed

β€Ždoc/api/cli.mdβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,8 @@ added: REPLACEME
894894

895895
> Stability: 1 - Experimental
896896
897-
Enables the use of AsyncLocalStorage backed by AsyncContextFrame rather than
898-
the default implementation which relies on async\_hooks. This new model is
897+
Enables the use of [`AsyncLocalStorage`][] backed by `AsyncContextFrame` rather
898+
than the default implementation which relies on async\_hooks. This new model is
899899
implemented very differently and so could have differences in how context data
900900
flows within the application. As such, it is presently recommended to be sure
901901
your application behaviour is unaffected by this change before using it in
@@ -3472,6 +3472,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
34723472
[`--print`]: #-p---print-script
34733473
[`--redirect-warnings`]: #--redirect-warningsfile
34743474
[`--require`]: #-r---require-module
3475+
[`AsyncLocalStorage`]: async_context.md#class-asynclocalstorage
34753476
[`Buffer`]: buffer.md#class-buffer
34763477
[`CRYPTO_secure_malloc_init`]: https://www.openssl.org/docs/man3.0/man3/CRYPTO_secure_malloc_init.html
34773478
[`NODE_OPTIONS`]: #node_optionsoptions

β€Žlib/async_hooks.jsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ module.exports = {
280280
// Public API
281281
get AsyncLocalStorage() {
282282
return AsyncContextFrame.enabled ?
283-
require('internal/async_local_storage/native') :
283+
require('internal/async_local_storage/async_context_frame') :
284284
require('internal/async_local_storage/async_hooks');
285285
},
286286
createHook,

β€Žlib/internal/async_context_frame.jsβ€Ž

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,17 @@ const {
77

88
let enabled_;
99

10-
class AsyncContextFrame extends Map {
11-
constructor(store, data) {
12-
super(AsyncContextFrame.current());
13-
this.set(store, data);
14-
}
15-
10+
class ActiveAsyncContextFrame {
1611
static get enabled() {
17-
enabled_ ??= require('internal/options')
18-
.getOptionValue('--experimental-async-context-frame');
19-
return enabled_;
12+
return true;
2013
}
2114

2215
static current() {
23-
if (this.enabled) {
24-
return getContinuationPreservedEmbedderData();
25-
}
16+
return getContinuationPreservedEmbedderData();
2617
}
2718

2819
static set(frame) {
29-
if (this.enabled) {
30-
setContinuationPreservedEmbedderData(frame);
31-
}
20+
setContinuationPreservedEmbedderData(frame);
3221
}
3322

3423
static exchange(frame) {
@@ -41,6 +30,36 @@ class AsyncContextFrame extends Map {
4130
const frame = this.current();
4231
frame?.disable(store);
4332
}
33+
}
34+
35+
function checkEnabled() {
36+
const enabled = require('internal/options')
37+
.getOptionValue('--experimental-async-context-frame');
38+
39+
// If enabled, swap to active prototype so we don't need to check status
40+
// on every interaction with the async context frame.
41+
if (enabled) {
42+
ObjectSetPrototypeOf(AsyncContextFrame, ActiveAsyncContextFrame);
43+
}
44+
45+
return enabled;
46+
}
47+
48+
class AsyncContextFrame extends Map {
49+
constructor(store, data) {
50+
super(AsyncContextFrame.current());
51+
this.set(store, data);
52+
}
53+
54+
static get enabled() {
55+
enabled_ ??= checkEnabled();
56+
return enabled_;
57+
}
58+
59+
static current() {}
60+
static set(frame) {}
61+
static exchange(frame) {}
62+
static disable(store) {}
4463

4564
disable(store) {
4665
this.delete(store);

β€Žlib/internal/process/task_queues.jsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const { AsyncResource } = require('async_hooks');
4444

4545
const AsyncContextFrame = require('internal/async_context_frame');
4646

47-
const async_context_frame = Symbol('asyncContextFrame');
47+
const async_context_frame = Symbol('kAsyncContextFrame');
4848

4949
// *Must* match Environment::TickInfo::Fields in src/env.h.
5050
const kHasTickScheduled = 0;

β€Žsrc/api/async_resource.ccβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ AsyncResource::AsyncResource(Isolate* isolate,
2727

2828
AsyncResource::~AsyncResource() {
2929
CHECK_NOT_NULL(env_);
30-
env_->RemoveAsyncResourceContextFrame(reinterpret_cast<std::uintptr_t>(this));
3130
EmitAsyncDestroy(env_, async_context_);
31+
env_->RemoveAsyncResourceContextFrame(reinterpret_cast<std::uintptr_t>(this));
3232
}
3333

3434
MaybeLocal<Value> AsyncResource::MakeCallback(Local<Function> callback,

0 commit comments

Comments
Β (0)