Skip to content

Commit

Permalink
inspector: introduce the --inspect-wait flag
Browse files Browse the repository at this point in the history
  • Loading branch information
cola119 committed Apr 28, 2024
1 parent 1aab22e commit 23e582e
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 10 deletions.
10 changes: 10 additions & 0 deletions doc/api/cli.md
Expand Up @@ -1292,6 +1292,15 @@ Specify ways of the inspector web socket url exposure.
By default inspector websocket url is available in stderr and under `/json/list`
endpoint on `http://host:port/json/list`.

### `--inspect-wait[=[host:]port]`

<!-- YAML
added: REPLACEME
-->

Activate inspector on `host:port` and wait for debugger to be attached.
Default `host:port` is `127.0.0.1:9229`.

### `-i`, `--interactive`

<!-- YAML
Expand Down Expand Up @@ -2676,6 +2685,7 @@ one is included in the list below.
* `--inspect-brk`
* `--inspect-port`, `--debug-port`
* `--inspect-publish-uid`
* `--inspect-wait`
* `--inspect`
* `--max-http-header-size`
* `--napi-modules`
Expand Down
6 changes: 4 additions & 2 deletions doc/api/debugger.md
Expand Up @@ -234,8 +234,10 @@ V8 Inspector can be enabled by passing the `--inspect` flag when starting a
Node.js application. It is also possible to supply a custom port with that flag,
e.g. `--inspect=9222` will accept DevTools connections on port 9222.

To break on the first line of the application code, pass the `--inspect-brk`
flag instead of `--inspect`.
Using the `--inspect` flag will execute the code immediately before debugger
is connected. This could be problematic if you intend to debug the code from the beginning.
In such cases, you can use the `--inspect-wait` flag instead, which waits for debugger to be attached,
or the `inspect-brk` flag to break on the first line of the code.

```console
$ node --inspect index.js
Expand Down
20 changes: 12 additions & 8 deletions src/inspector_agent.cc
Expand Up @@ -743,20 +743,24 @@ bool Agent::Start(const std::string& path,
}, parent_env_);

bool wait_for_connect = options.wait_for_connect();
bool should_break_first_line = options.should_break_first_line();
if (parent_handle_) {
wait_for_connect = parent_handle_->WaitForConnect();
parent_handle_->WorkerStarted(client_->getThreadHandle(), wait_for_connect);
should_break_first_line = parent_handle_->WaitForConnect();
parent_handle_->WorkerStarted(client_->getThreadHandle(),
should_break_first_line);
} else if (!options.inspector_enabled || !options.allow_attaching_debugger ||
!StartIoThread()) {
return false;
}

// Patch the debug options to implement waitForDebuggerOnStart for
// the NodeWorker.enable method.
if (wait_for_connect) {
CHECK(!parent_env_->has_serialized_options());
debug_options_.EnableBreakFirstLine();
parent_env_->options()->get_debug_options()->EnableBreakFirstLine();
if (wait_for_connect || should_break_first_line) {
// Patch the debug options to implement waitForDebuggerOnStart for
// the NodeWorker.enable method.
if (should_break_first_line) {
CHECK(!parent_env_->has_serialized_options());
debug_options_.EnableBreakFirstLine();
parent_env_->options()->get_debug_options()->EnableBreakFirstLine();
}
client_->waitForFrontend();
}
return true;
Expand Down
8 changes: 8 additions & 0 deletions src/node_options.cc
Expand Up @@ -337,6 +337,14 @@ DebugOptionsParser::DebugOptionsParser() {
Implies("--inspect-brk-node", "--inspect");
AddAlias("--inspect-brk-node=", { "--inspect-port", "--inspect-brk-node" });

AddOption(
"--inspect-wait",
"activate inspector on host:port and wait for debugger to be attached",
&DebugOptions::inspect_wait,
kAllowedInEnvvar);
Implies("--inspect-wait", "--inspect");
AddAlias("--inspect-wait=", {"--inspect-port", "--inspect-wait"});

AddOption("--inspect-publish-uid",
"comma separated list of destinations for inspector uid"
"(default: stderr,http)",
Expand Down
6 changes: 6 additions & 0 deletions src/node_options.h
Expand Up @@ -71,6 +71,8 @@ class DebugOptions : public Options {
bool allow_attaching_debugger = true;
// --inspect
bool inspector_enabled = false;
// --inspect-wait
bool inspect_wait = false;
// --debug
bool deprecated_debug = false;
// --inspect-brk
Expand All @@ -93,6 +95,10 @@ class DebugOptions : public Options {
}

bool wait_for_connect() const {
return break_first_line || break_node_first_line || inspect_wait;
}

bool should_break_first_line() const {
return break_first_line || break_node_first_line;
}

Expand Down
28 changes: 28 additions & 0 deletions test/parallel/test-inspector-wait.mjs
@@ -0,0 +1,28 @@
import * as common from '../common/index.mjs';

common.skipIfInspectorDisabled();

import assert from 'node:assert';
import { NodeInstance } from '../common/inspector-helper.js';


async function runTests() {
const child = new NodeInstance(['--inspect-wait'], 'console.log(0);');
const session = await child.connectInspectorSession();
await session.send({ method: 'NodeRuntime.enable' });
await session.waitForNotification('NodeRuntime.waitingForDebugger');

// The execution should be paused until the debugger is attached
while (await child.nextStderrString() !== 'Debugger attached.');

await session.send({ 'method': 'Runtime.runIfWaitingForDebugger' });

// Wait for the execution to finish
while (await child.nextStderrString() !== 'Waiting for the debugger to disconnect...');

await session.send({ method: 'NodeRuntime.disable' });
session.disconnect();
assert.strictEqual((await child.expectShutdown()).exitCode, 0);
}

runTests().then(common.mustCall());

0 comments on commit 23e582e

Please sign in to comment.