• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2'use strict';
3const common = require('../common');
4common.skipIfInspectorDisabled();
5common.skipIf32Bits();
6const { NodeInstance } = require('../common/inspector-helper.js');
7const assert = require('assert');
8
9common.skipIfWorker(); // Signal starts a server for a main thread inspector
10
11const script = `
12process._rawDebug('Waiting until a signal enables the inspector...');
13let waiting = setInterval(waitUntilDebugged, 50);
14
15function waitUntilDebugged() {
16  const { internalBinding } = require('internal/test/binding');
17  if (!internalBinding('inspector').isEnabled()) return;
18  clearInterval(waiting);
19  // At this point, even though the Inspector is enabled, the default async
20  // call stack depth is 0. We need a chance to call
21  // Debugger.setAsyncCallStackDepth *before* activating the actual timer for
22  // async stack traces to work. Directly using a debugger statement would be
23  // too brittle, and using a longer timeout would unnecessarily slow down the
24  // test on most machines. Triggering a debugger break through an interval is
25  // a faster and more reliable way.
26  process._rawDebug('Signal received, waiting for debugger setup');
27  waiting = setInterval(() => { debugger; }, 50);
28}
29
30// This function is called by the inspector client (session)
31function setupTimeoutWithBreak() {
32  clearInterval(waiting);
33  process._rawDebug('Debugger ready, setting up timeout with a break');
34  setTimeout(() => { debugger; }, 50);
35}
36`;
37
38async function waitForInitialSetup(session) {
39  console.error('[test]', 'Waiting for initial setup');
40  await session.waitForBreakOnLine(16, '[eval]');
41}
42
43async function setupTimeoutForStackTrace(session) {
44  console.error('[test]', 'Setting up timeout for async stack trace');
45  await session.send([
46    { 'method': 'Runtime.evaluate',
47      'params': { expression: 'setupTimeoutWithBreak()' } },
48    { 'method': 'Debugger.resume' },
49  ]);
50}
51
52async function checkAsyncStackTrace(session) {
53  console.error('[test]', 'Verify basic properties of asyncStackTrace');
54  const paused = await session.waitForBreakOnLine(23, '[eval]');
55  assert(paused.params.asyncStackTrace,
56         `${Object.keys(paused.params)} contains "asyncStackTrace" property`);
57  assert(paused.params.asyncStackTrace.description, 'Timeout');
58  assert(paused.params.asyncStackTrace.callFrames
59           .some((frame) => frame.functionName === 'setupTimeoutWithBreak'));
60}
61
62async function runTests() {
63  const instance = await NodeInstance.startViaSignal(script);
64  const session = await instance.connectInspectorSession();
65  await session.send([
66    { 'method': 'Runtime.enable' },
67    { 'method': 'Debugger.enable' },
68    { 'method': 'Debugger.setAsyncCallStackDepth',
69      'params': { 'maxDepth': 10 } },
70    { 'method': 'Debugger.setBlackboxPatterns',
71      'params': { 'patterns': [] } },
72    { 'method': 'Runtime.runIfWaitingForDebugger' },
73  ]);
74
75  await waitForInitialSetup(session);
76  await setupTimeoutForStackTrace(session);
77  await checkAsyncStackTrace(session);
78
79  console.error('[test]', 'Stopping child instance');
80  session.disconnect();
81  instance.kill();
82}
83
84runTests().then(common.mustCall());
85