Skip to content

Commit 8be0d97

Browse files
committed
async_hooks: add --allow-async-hooks flag
Add a new `--allow-async-hooks` flag that must be passed to enable `async_hooks.createHook()`. This is a breaking change - createHook is now disabled by default. When createHook() is called without the flag, it throws ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED with a message indicating that the flag is required. This change affects all code using async_hooks.createHook(), including APM tools and debugging utilities. Users must now explicitly opt-in to this functionality. BREAKING CHANGE: async_hooks.createHook() now requires --allow-async-hooks Signed-off-by: Matteo Collina <hello@matteocollina.com>
1 parent 77609be commit 8be0d97

184 files changed

Lines changed: 313 additions & 77 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,46 @@ Error: Cannot load native addon because loading addons is disabled.
139139
}
140140
```
141141

142+
### `--allow-async-hooks`
143+
144+
<!-- YAML
145+
added: REPLACEME
146+
-->
147+
148+
Allow use of `async_hooks.createHook()`. This flag is required to enable
149+
the `createHook` API, which is disabled by default.
150+
151+
Example:
152+
153+
```mjs
154+
import { createHook } from 'node:async_hooks';
155+
156+
createHook({ init() {} }).enable();
157+
```
158+
159+
```cjs
160+
const { createHook } = require('node:async_hooks');
161+
162+
createHook({ init() {} }).enable();
163+
```
164+
165+
```console
166+
$ node index.js
167+
node:async_hooks:160
168+
throw new ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED();
169+
^
170+
171+
Error [ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED]: async_hooks.createHook() is disabled. Use --allow-async-hooks to enable it.
172+
at createHook (node:async_hooks:160:11)
173+
at Object.<anonymous> (/home/user/index.js:3:1)
174+
...
175+
```
176+
177+
```console
178+
$ node --allow-async-hooks index.js
179+
# Works without error
180+
```
181+
142182
### `--allow-child-process`
143183

144184
<!-- YAML

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,17 @@ by the `node:assert` module.
733733
An attempt was made to register something that is not a function as an
734734
`AsyncHooks` callback.
735735

736+
<a id="ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED"></a>
737+
738+
### `ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED`
739+
740+
<!-- YAML
741+
added: REPLACEME
742+
-->
743+
744+
An attempt was made to call [`async_hooks.createHook()`][] without the
745+
[`--allow-async-hooks`][] flag.
746+
736747
<a id="ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED"></a>
737748

738749
### `ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED`
@@ -4770,6 +4781,7 @@ An error occurred trying to allocate memory. This should never happen.
47704781
[`"exports"`]: packages.md#exports
47714782
[`"imports"`]: packages.md#imports
47724783
[`'uncaughtException'`]: process.md#event-uncaughtexception
4784+
[`--allow-async-hooks`]: cli.md#--allow-async-hooks
47734785
[`--disable-proto=throw`]: cli.md#--disable-protomode
47744786
[`--force-fips`]: cli.md#--force-fips
47754787
[`--no-addons`]: cli.md#--no-addons
@@ -4795,6 +4807,7 @@ An error occurred trying to allocate memory. This should never happen.
47954807
[`Writable`]: stream.md#class-streamwritable
47964808
[`ZipBuffer`]: zlib.md#class-zlibzipbuffer
47974809
[`ZipFile`]: zlib.md#class-zlibzipfile
4810+
[`async_hooks.createHook()`]: async_hooks.md#async_hookscreatehookoptions
47984811
[`child_process`]: child_process.md
47994812
[`cipher.getAuthTag()`]: crypto.md#ciphergetauthtag
48004813
[`crypto.getDiffieHellman()`]: crypto.md#cryptogetdiffiehellmangroupname

β€Ždoc/node.1β€Ž

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,36 @@ Error: Cannot load native addon because loading addons is disabled.
8686
}
8787
.Ed
8888
.
89+
.It Fl -allow-async-hooks
90+
Allow use of \fBasync_hooks.createHook()\fR. This flag is required to enable
91+
the \fBcreateHook\fR API, which is disabled by default.
92+
Example:
93+
.Bd -literal
94+
import { createHook } from 'node:async_hooks';
95+
96+
createHook({ init() {} }).enable();
97+
.Ed
98+
.Bd -literal
99+
const { createHook } = require('node:async_hooks');
100+
101+
createHook({ init() {} }).enable();
102+
.Ed
103+
.Bd -literal
104+
$ node index.js
105+
node:async_hooks:160
106+
throw new ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED();
107+
^
108+
109+
Error [ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED]: async_hooks.createHook() is disabled. Use --allow-async-hooks to enable it.
110+
at createHook (node:async_hooks:160:11)
111+
at Object.<anonymous> (/home/user/index.js:3:1)
112+
...
113+
.Ed
114+
.Bd -literal
115+
$ node --allow-async-hooks index.js
116+
# Works without error
117+
.Ed
118+
.
89119
.It Fl -allow-child-process
90120
When using the Permission Model, the process will not be able to spawn any
91121
child process by default.

β€Žlib/async_hooks.jsβ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {
1616

1717
const {
1818
ERR_ASYNC_CALLBACK,
19+
ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED,
1920
ERR_ASYNC_RESOURCE_DOMAIN_REMOVED,
2021
ERR_ASYNC_TYPE,
2122
ERR_INVALID_ASYNC_ID,
@@ -29,6 +30,7 @@ const {
2930
validateFunction,
3031
validateString,
3132
} = require('internal/validators');
33+
const { getOptionValue } = require('internal/options');
3234
const internal_async_hooks = require('internal/async_hooks');
3335

3436
const AsyncContextFrame = require('internal/async_context_frame');
@@ -168,6 +170,9 @@ class AsyncHook {
168170

169171

170172
function createHook(fns) {
173+
if (!getOptionValue('--allow-async-hooks')) {
174+
throw new ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED();
175+
}
171176
return new AsyncHook(fns);
172177
}
173178

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,8 @@ E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
11431143
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
11441144
E('ERR_ASSERTION', '%s', Error);
11451145
E('ERR_ASYNC_CALLBACK', '%s must be a function', TypeError);
1146+
E('ERR_ASYNC_HOOKS_CREATE_HOOK_DISABLED',
1147+
'async_hooks.createHook() is disabled. Use --allow-async-hooks to enable it.', Error);
11461148
E('ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED',
11471149
'Async loader request never settled', Error);
11481150
E('ERR_ASYNC_RESOURCE_DOMAIN_REMOVED',

β€Žsrc/node_options.ccβ€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
947947
kAllowedInEnvvar,
948948
false,
949949
OptionNamespaces::kPermissionNamespace);
950+
AddOption("--allow-async-hooks",
951+
"allow use of async_hooks.createHook",
952+
BOOL_FIELD(allow_async_hooks),
953+
kAllowedInEnvvar);
950954
AddOption("--allow-openssl-store",
951955
"allow use of OpenSSL STORE loaders when any permissions are set",
952956
BOOL_FIELD(allow_openssl_store),

β€Žsrc/node_options.hβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class EnvironmentOptions : public Options {
238238
DEFINE_BOOL_FIELD(allow_ffi) = false;
239239
DEFINE_BOOL_FIELD(allow_openssl_store) = false;
240240
DEFINE_BOOL_FIELD(allow_worker_threads) = false;
241+
DEFINE_BOOL_FIELD(allow_async_hooks) = false;
241242
DEFINE_BOOL_FIELD(experimental_vm_modules) = EXPERIMENTALS_DEFAULT_VALUE;
242243
DEFINE_BOOL_FIELD(expose_internals) = false;
243244
DEFINE_BOOL_FIELD(force_node_api_uncaught_exceptions_policy) = false;

β€Žtest/addons/async-resource/test.jsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
// Flags: --allow-async-hooks
23

34
const common = require('../../common');
45
const assert = require('assert');

β€Žtest/addons/callback-scope/test-async-hooks.jsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict';
2+
// Flags: --allow-async-hooks
23

34
const common = require('../../common');
45
const assert = require('assert');

β€Žtest/async-hooks/init-hooks.jsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict';
2-
// Flags: --expose-gc
2+
// Flags: --allow-async-hooks --expose-gc
33

44
require('../common');
55
const assert = require('assert');

0 commit comments

Comments
Β (0)