Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9b2c013

Browse filesBrowse files
islandryurichardlau
authored andcommitted
inspector: prevent propagation of promise hooks to noPromise hooks
PR-URL: #58841 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 3c4541f commit 9b2c013
Copy full SHA for 9b2c013

File tree

Expand file treeCollapse file tree

2 files changed

+49
-10
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+49
-10
lines changed
Open diff view settings
Collapse file

‎lib/internal/async_hooks.js‎

Copy file name to clipboardExpand all lines: lib/internal/async_hooks.js
+18-10Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ function lookupPublicResource(resource) {
189189
// Used by C++ to call all init() callbacks. Because some state can be setup
190190
// from C++ there's no need to perform all the same operations as in
191191
// emitInitScript.
192-
function emitInitNative(asyncId, type, triggerAsyncId, resource) {
192+
function emitInitNative(asyncId, type, triggerAsyncId, resource, isPromiseHook) {
193193
active_hooks.call_depth += 1;
194194
resource = lookupPublicResource(resource);
195195
// Use a single try/catch for all hooks to avoid setting up one per iteration.
@@ -199,6 +199,10 @@ function emitInitNative(asyncId, type, triggerAsyncId, resource) {
199199
// eslint-disable-next-line no-var
200200
for (var i = 0; i < active_hooks.array.length; i++) {
201201
if (typeof active_hooks.array[i][init_symbol] === 'function') {
202+
if (isPromiseHook &&
203+
active_hooks.array[i][kNoPromiseHook]) {
204+
continue;
205+
}
202206
active_hooks.array[i][init_symbol](
203207
asyncId, type, triggerAsyncId,
204208
resource,
@@ -222,7 +226,7 @@ function emitInitNative(asyncId, type, triggerAsyncId, resource) {
222226

223227
// Called from native. The asyncId stack handling is taken care of there
224228
// before this is called.
225-
function emitHook(symbol, asyncId) {
229+
function emitHook(symbol, asyncId, isPromiseHook) {
226230
active_hooks.call_depth += 1;
227231
// Use a single try/catch for all hook to avoid setting up one per
228232
// iteration.
@@ -232,6 +236,10 @@ function emitHook(symbol, asyncId) {
232236
// eslint-disable-next-line no-var
233237
for (var i = 0; i < active_hooks.array.length; i++) {
234238
if (typeof active_hooks.array[i][symbol] === 'function') {
239+
if (isPromiseHook &&
240+
active_hooks.array[i][kNoPromiseHook]) {
241+
continue;
242+
}
235243
active_hooks.array[i][symbol](asyncId);
236244
}
237245
}
@@ -321,7 +329,7 @@ function promiseInitHook(promise, parent) {
321329
trackPromise(promise, parent);
322330
const asyncId = promise[async_id_symbol];
323331
const triggerAsyncId = promise[trigger_async_id_symbol];
324-
emitInitScript(asyncId, 'PROMISE', triggerAsyncId, promise);
332+
emitInitScript(asyncId, 'PROMISE', triggerAsyncId, promise, true);
325333
}
326334

327335
function promiseInitHookWithDestroyTracking(promise, parent) {
@@ -339,14 +347,14 @@ function promiseBeforeHook(promise) {
339347
trackPromise(promise);
340348
const asyncId = promise[async_id_symbol];
341349
const triggerId = promise[trigger_async_id_symbol];
342-
emitBeforeScript(asyncId, triggerId, promise);
350+
emitBeforeScript(asyncId, triggerId, promise, true);
343351
}
344352

345353
function promiseAfterHook(promise) {
346354
trackPromise(promise);
347355
const asyncId = promise[async_id_symbol];
348356
if (hasHooks(kAfter)) {
349-
emitAfterNative(asyncId);
357+
emitAfterNative(asyncId, true);
350358
}
351359
if (asyncId === executionAsyncId()) {
352360
// This condition might not be true if async_hooks was enabled during
@@ -361,7 +369,7 @@ function promiseAfterHook(promise) {
361369
function promiseResolveHook(promise) {
362370
trackPromise(promise);
363371
const asyncId = promise[async_id_symbol];
364-
emitPromiseResolveNative(asyncId);
372+
emitPromiseResolveNative(asyncId, true);
365373
}
366374

367375
let wantPromiseHook = false;
@@ -492,7 +500,7 @@ function promiseResolveHooksExist() {
492500
}
493501

494502

495-
function emitInitScript(asyncId, type, triggerAsyncId, resource) {
503+
function emitInitScript(asyncId, type, triggerAsyncId, resource, isPromiseHook = false) {
496504
// Short circuit all checks for the common case. Which is that no hooks have
497505
// been set. Do this to remove performance impact for embedders (and core).
498506
if (!hasHooks(kInit))
@@ -502,15 +510,15 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
502510
triggerAsyncId = getDefaultTriggerAsyncId();
503511
}
504512

505-
emitInitNative(asyncId, type, triggerAsyncId, resource);
513+
emitInitNative(asyncId, type, triggerAsyncId, resource, isPromiseHook);
506514
}
507515

508516

509-
function emitBeforeScript(asyncId, triggerAsyncId, resource) {
517+
function emitBeforeScript(asyncId, triggerAsyncId, resource, isPromiseHook = false) {
510518
pushAsyncContext(asyncId, triggerAsyncId, resource);
511519

512520
if (hasHooks(kBefore))
513-
emitBeforeNative(asyncId);
521+
emitBeforeNative(asyncId, isPromiseHook);
514522
}
515523

516524

Collapse file
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
const common = require('../common');
3+
common.skipIfInspectorDisabled();
4+
const test = require('node:test');
5+
const { NodeInstance } = require('../common/inspector-helper');
6+
7+
const script = `
8+
import { createHook } from "async_hooks"
9+
import fs from "fs"
10+
11+
const hook = createHook({
12+
after() {
13+
}
14+
});
15+
hook.enable(true);
16+
console.log('Async hook enabled');
17+
`;
18+
19+
test('inspector async hooks should not crash in debug build', async () => {
20+
const instance = new NodeInstance([
21+
'--inspect-brk=0',
22+
], script);
23+
const session = await instance.connectInspectorSession();
24+
await session.send({ method: 'NodeRuntime.enable' });
25+
await session.waitForNotification('NodeRuntime.waitingForDebugger');
26+
await session.send({ method: 'Runtime.enable' });
27+
await session.send({ method: 'Debugger.enable' });
28+
await session.send({ id: 6, method: 'Debugger.setAsyncCallStackDepth', params: { maxDepth: 32 } });
29+
await session.send({ method: 'Runtime.runIfWaitingForDebugger' });
30+
await session.waitForDisconnect();
31+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.