Skip to content

Commit

Permalink
inspector: open add SymbolDispose
Browse files Browse the repository at this point in the history
PR-URL: #48765
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
  • Loading branch information
atlowChemi authored and RafaelGSS committed Aug 15, 2023
1 parent e01cce5 commit 67f9896
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
9 changes: 9 additions & 0 deletions doc/api/inspector.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,20 @@ console.

### `inspector.open([port[, host[, wait]]])`

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/48765
description: inspector.open() now returns a `Disposable` object.
-->

* `port` {number} Port to listen on for inspector connections. Optional.
**Default:** what was specified on the CLI.
* `host` {string} Host to listen on for inspector connections. Optional.
**Default:** what was specified on the CLI.
* `wait` {boolean} Block until a client has connected. Optional.
**Default:** `false`.
* Returns: {Disposable} that calls [`inspector.close()`][].

Activate inspector on host and port. Equivalent to
`node --inspect=[[host:]port]`, but can be done programmatically after node has
Expand Down Expand Up @@ -472,5 +480,6 @@ An exception will be thrown if there is no active inspector.
[Chrome DevTools Protocol Viewer]: https://chromedevtools.github.io/devtools-protocol/v8/
[Heap Profiler]: https://chromedevtools.github.io/devtools-protocol/v8/HeapProfiler
[`'Debugger.paused'`]: https://chromedevtools.github.io/devtools-protocol/v8/Debugger#event-paused
[`inspector.close()`]: #inspectorclose
[`session.connect()`]: #sessionconnect
[security warning]: cli.md#warning-binding-inspector-to-a-public-ipport-combination-is-insecure
3 changes: 3 additions & 0 deletions lib/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
JSONStringify,
SafeMap,
Symbol,
SymbolDispose,
} = primordials;

const {
Expand Down Expand Up @@ -181,6 +182,8 @@ function inspectorOpen(port, host, wait) {
open(port, host);
if (wait)
waitForDebugger();

return { __proto__: null, [SymbolDispose]() { _debugEnd(); } };
}

/**
Expand Down
76 changes: 76 additions & 0 deletions test/parallel/test-inspector-open-dispose.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import * as common from '../common/index.mjs';
import assert from 'node:assert';
import net from 'node:net';
import url from 'node:url';
import { fork } from 'node:child_process';

common.skipIfInspectorDisabled();
if (process.env.BE_CHILD) {
await beChild();
} else {
let firstPort;

const filename = url.fileURLToPath(import.meta.url);
const child = fork(filename, { env: { ...process.env, BE_CHILD: 1 } });

child.once('message', common.mustCall((msg) => {
assert.strictEqual(msg.cmd, 'started');

child.send({ cmd: 'open', args: [] });
child.once('message', common.mustCall(wasOpenedHandler));
}));

function wasOpenedHandler(msg) {
assert.strictEqual(msg.cmd, 'url');
const port = url.parse(msg.url).port;
ping(port, common.mustSucceed(() => {
// Inspector is already open, and won't be reopened, so args don't matter.
child.send({ cmd: 'dispose' });
child.once('message', common.mustCall(wasDisposedWhenOpenHandler));
firstPort = port;
}));
}

function wasDisposedWhenOpenHandler(msg) {
assert.strictEqual(msg.cmd, 'url');
assert.strictEqual(msg.url, undefined);
ping(firstPort, (err) => {
assert(err);
child.send({ cmd: 'dispose' });
child.once('message', common.mustCall(wasReDisposedHandler));
});
}

function wasReDisposedHandler(msg) {
assert.strictEqual(msg.cmd, 'url');
assert.strictEqual(msg.url, undefined);
process.exit();
}
}

function ping(port, callback) {
net.connect({ port, family: 4 })
.on('connect', function() { close(this); })
.on('error', function(err) { close(this, err); });

function close(self, err) {
self.end();
self.on('close', () => callback(err));
}
}

async function beChild() {
const inspector = await import('node:inspector');
let inspectorDisposer;
process.send({ cmd: 'started' });

process.on('message', (msg) => {
if (msg.cmd === 'open') {
inspectorDisposer = inspector.open(0, false, undefined);
}
if (msg.cmd === 'dispose') {
inspectorDisposer[Symbol.dispose]();
}
process.send({ cmd: 'url', url: inspector.url() });
});
}

0 comments on commit 67f9896

Please sign in to comment.