inspector: expose original console

Adds require('inspector').console, mapping it to the original
global.console of V8. This enables applications to send messages to
the inspector console programmatically.

Fixes: https://github.com/nodejs/node/issues/21651

PR-URL: https://github.com/nodejs/node/pull/21659
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Matteo Collina 2018-07-04 19:55:12 +02:00
parent dd023df135
commit 19795d8383
5 changed files with 62 additions and 2 deletions

View File

@ -28,6 +28,17 @@ started.
If wait is `true`, will block until a client has connected to the inspect port If wait is `true`, will block until a client has connected to the inspect port
and flow control has been passed to the debugger client. and flow control has been passed to the debugger client.
### inspector.console
An object to send messages to the remote inspector console.
```js
require('inspector').console.log('a message');
```
The inspector console does not have API parity with Node.js
console.
### inspector.close() ### inspector.close()
Deactivate the inspector. Blocks until there are no active connections. Deactivate the inspector. Blocks until there are no active connections.

View File

@ -11,6 +11,7 @@ const {
} = require('internal/errors').codes; } = require('internal/errors').codes;
const util = require('util'); const util = require('util');
const { Connection, open, url } = process.binding('inspector'); const { Connection, open, url } = process.binding('inspector');
const { originalConsole } = require('internal/process/per_thread');
if (!Connection || !require('internal/worker').isMainThread) if (!Connection || !require('internal/worker').isMainThread)
throw new ERR_INSPECTOR_NOT_AVAILABLE(); throw new ERR_INSPECTOR_NOT_AVAILABLE();
@ -103,5 +104,6 @@ module.exports = {
open: (port, host, wait) => open(port, host, !!wait), open: (port, host, wait) => open(port, host, !!wait),
close: process._debugEnd, close: process._debugEnd,
url: url, url: url,
console: originalConsole,
Session Session
}; };

View File

@ -120,6 +120,8 @@
const browserGlobals = !process._noBrowserGlobals; const browserGlobals = !process._noBrowserGlobals;
if (browserGlobals) { if (browserGlobals) {
// we are setting this here to foward it to the inspector later
perThreadSetup.originalConsole = global.console;
setupGlobalTimeouts(); setupGlobalTimeouts();
setupGlobalConsole(); setupGlobalConsole();
setupGlobalURL(); setupGlobalURL();

View File

@ -7,6 +7,7 @@ const fixtures = require('../common/fixtures');
const { spawn } = require('child_process'); const { spawn } = require('child_process');
const { parse: parseURL } = require('url'); const { parse: parseURL } = require('url');
const { getURLFromFilePath } = require('internal/url'); const { getURLFromFilePath } = require('internal/url');
const { EventEmitter } = require('events');
const _MAINSCRIPT = fixtures.path('loop.js'); const _MAINSCRIPT = fixtures.path('loop.js');
const DEBUG = false; const DEBUG = false;
@ -311,10 +312,12 @@ class InspectorSession {
} }
} }
class NodeInstance { class NodeInstance extends EventEmitter {
constructor(inspectorFlags = ['--inspect-brk=0'], constructor(inspectorFlags = ['--inspect-brk=0'],
scriptContents = '', scriptContents = '',
scriptFile = _MAINSCRIPT) { scriptFile = _MAINSCRIPT) {
super();
this._scriptPath = scriptFile; this._scriptPath = scriptFile;
this._script = scriptFile ? null : scriptContents; this._script = scriptFile ? null : scriptContents;
this._portCallback = null; this._portCallback = null;
@ -326,7 +329,10 @@ class NodeInstance {
this._unprocessedStderrLines = []; this._unprocessedStderrLines = [];
this._process.stdout.on('data', makeBufferingDataCallback( this._process.stdout.on('data', makeBufferingDataCallback(
(line) => console.log('[out]', line))); (line) => {
this.emit('stdout', line);
console.log('[out]', line);
}));
this._process.stderr.on('data', makeBufferingDataCallback( this._process.stderr.on('data', makeBufferingDataCallback(
(message) => this.onStderrLine(message))); (message) => this.onStderrLine(message)));

View File

@ -0,0 +1,39 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');
common.skipIfInspectorDisabled();
const { NodeInstance } = require('../common/inspector-helper.js');
const assert = require('assert');
async function runTest() {
const script = 'require(\'inspector\').console.log(\'hello world\');';
const child = new NodeInstance('--inspect-brk=0', script, '');
let out = '';
child.on('stdout', (line) => out += line);
const session = await child.connectInspectorSession();
const commands = [
{ 'method': 'Runtime.enable' },
{ 'method': 'Runtime.runIfWaitingForDebugger' }
];
session.send(commands);
const msg = await session.waitForNotification('Runtime.consoleAPICalled');
assert.strictEqual(msg.params.type, 'log');
assert.deepStrictEqual(msg.params.args, [{
type: 'string',
value: 'hello world'
}]);
assert.strictEqual(out, '');
session.disconnect();
}
common.crashOnUnhandledRejection();
runTest();