From cb6d0d8d39a55223db35d2a6d3b9399351e11947 Mon Sep 17 00:00:00 2001 From: atlowChemi Date: Fri, 14 Jul 2023 10:28:36 +0300 Subject: [PATCH] inspector: open add `SymbolDispose` --- doc/api/inspector.md | 9 +++ lib/inspector.js | 3 + test/parallel/test-inspector-open-dispose.mjs | 76 +++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 test/parallel/test-inspector-open-dispose.mjs diff --git a/doc/api/inspector.md b/doc/api/inspector.md index 34fad2a0ca1805..4353ee696b4941 100644 --- a/doc/api/inspector.md +++ b/doc/api/inspector.md @@ -419,12 +419,20 @@ console. ### `inspector.open([port[, host[, wait]]])` + + * `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 @@ -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 diff --git a/lib/inspector.js b/lib/inspector.js index 567d825c4f6a72..70796c83fcffe3 100644 --- a/lib/inspector.js +++ b/lib/inspector.js @@ -5,6 +5,7 @@ const { JSONStringify, SafeMap, Symbol, + SymbolDispose, } = primordials; const { @@ -181,6 +182,8 @@ function inspectorOpen(port, host, wait) { open(port, host); if (wait) waitForDebugger(); + + return { __proto__: null, [SymbolDispose]() { _debugEnd(); } }; } /** diff --git a/test/parallel/test-inspector-open-dispose.mjs b/test/parallel/test-inspector-open-dispose.mjs new file mode 100644 index 00000000000000..0964b78a8f8c58 --- /dev/null +++ b/test/parallel/test-inspector-open-dispose.mjs @@ -0,0 +1,76 @@ +import * as common from '../common/index.mjs'; +import * as inspector from 'node:inspector'; +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) { + console.log(process.argv) + 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)); + } +} +function beChild() { + 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() }); + }); +} \ No newline at end of file