inspector: --debug* deprecation and invalidation

PR-URL: https://github.com/nodejs/node/pull/12949
Fixes: https://github.com/nodejs/node/issues/12364
Fixes: https://github.com/nodejs/node/issues/12630
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jan Krems <jan.krems@gmail.com>
This commit is contained in:
Refael Ackermann 2017-05-28 23:28:01 -04:00
parent dbbe1faf30
commit 16689e30ae
10 changed files with 180 additions and 36 deletions

View File

@ -65,6 +65,20 @@
}); });
process.argv[0] = process.execPath; process.argv[0] = process.execPath;
// Handle `--debug*` deprecation and invalidation
if (process._invalidDebug) {
process.emitWarning(
'`node --debug` and `node --debug-brk` are invalid. ' +
'Please use `node --inspect` or `node --inspect-brk` instead.',
'DeprecationWarning', 'DEP0062', startup, true);
process.exit(9);
} else if (process._deprecatedDebugBrk) {
process.emitWarning(
'`node --inspect --debug-brk` is deprecated. ' +
'Please use `node --inspect-brk` instead.',
'DeprecationWarning', 'DEP0062', startup, true);
}
// There are various modes that Node can run in. The most common two // There are various modes that Node can run in. The most common two
// are running from a script and running the REPL - but there are a few // are running from a script and running the REPL - but there are a few
// others like the debugger or running --eval arguments. Here we decide // others like the debugger or running --eval arguments. Here we decide

View File

@ -111,7 +111,7 @@ function setupProcessWarnings() {
// process.emitWarning(error) // process.emitWarning(error)
// process.emitWarning(str[, type[, code]][, ctor]) // process.emitWarning(str[, type[, code]][, ctor])
// process.emitWarning(str[, options]) // process.emitWarning(str[, options])
process.emitWarning = function(warning, type, code, ctor) { process.emitWarning = function(warning, type, code, ctor, now) {
const errors = lazyErrors(); const errors = lazyErrors();
var detail; var detail;
if (type !== null && typeof type === 'object' && !Array.isArray(type)) { if (type !== null && typeof type === 'object' && !Array.isArray(type)) {
@ -150,6 +150,7 @@ function setupProcessWarnings() {
if (process.throwDeprecation) if (process.throwDeprecation)
throw warning; throw warning;
} }
process.nextTick(doEmitWarning(warning)); if (now) process.emit('warning', warning);
else process.nextTick(doEmitWarning(warning));
}; };
} }

View File

@ -537,7 +537,7 @@ Module.prototype._compile = function(content, filename) {
}); });
var inspectorWrapper = null; var inspectorWrapper = null;
if (process._debugWaitConnect && process._eval == null) { if (process._breakFirstLine && process._eval == null) {
if (!resolvedArgv) { if (!resolvedArgv) {
// we enter the repl if we're not given a filename argument. // we enter the repl if we're not given a filename argument.
if (process.argv[1]) { if (process.argv[1]) {
@ -549,7 +549,7 @@ Module.prototype._compile = function(content, filename) {
// Set breakpoint on module start // Set breakpoint on module start
if (filename === resolvedArgv) { if (filename === resolvedArgv) {
delete process._debugWaitConnect; delete process._breakFirstLine;
inspectorWrapper = process.binding('inspector').callAndPauseOnStart; inspectorWrapper = process.binding('inspector').callAndPauseOnStart;
if (!inspectorWrapper) { if (!inspectorWrapper) {
const Debug = vm.runInDebugContext('Debug'); const Debug = vm.runInDebugContext('Debug');

View File

@ -3391,9 +3391,29 @@ void SetupProcessObject(Environment* env,
READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate())); READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
} }
// TODO(refack): move the following 4 to `node_config`
// --inspect
if (debug_options.inspector_enabled()) {
READONLY_DONT_ENUM_PROPERTY(process,
"_inspectorEnbale", True(env->isolate()));
}
// --inspect-brk // --inspect-brk
if (debug_options.wait_for_connect()) { if (debug_options.wait_for_connect()) {
READONLY_PROPERTY(process, "_debugWaitConnect", True(env->isolate())); READONLY_DONT_ENUM_PROPERTY(process,
"_breakFirstLine", True(env->isolate()));
}
// --inspect --debug-brk
if (debug_options.deprecated_invocation()) {
READONLY_DONT_ENUM_PROPERTY(process,
"_deprecatedDebugBrk", True(env->isolate()));
}
// --debug or, --debug-brk without --inspect
if (debug_options.invalid_invocation()) {
READONLY_DONT_ENUM_PROPERTY(process,
"_invalidDebug", True(env->isolate()));
} }
// --security-revert flags // --security-revert flags

View File

@ -8,9 +8,7 @@
namespace node { namespace node {
namespace { namespace {
#if HAVE_INSPECTOR
const int default_inspector_port = 9229; const int default_inspector_port = 9229;
#endif // HAVE_INSPECTOR
inline std::string remove_brackets(const std::string& host) { inline std::string remove_brackets(const std::string& host) {
if (!host.empty() && host.front() == '[' && host.back() == ']') if (!host.empty() && host.front() == '[' && host.back() == ']')
@ -56,14 +54,12 @@ std::pair<std::string, int> split_host_port(const std::string& arg) {
} // namespace } // namespace
DebugOptions::DebugOptions() : DebugOptions::DebugOptions() :
#if HAVE_INSPECTOR
inspector_enabled_(false), inspector_enabled_(false),
#endif // HAVE_INSPECTOR deprecated_debug_(false),
wait_connect_(false), http_enabled_(false), break_first_line_(false),
host_name_("127.0.0.1"), port_(-1) { } host_name_("127.0.0.1"), port_(-1) { }
bool DebugOptions::ParseOption(const char* argv0, const std::string& option) { bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
bool enable_inspector = false;
bool has_argument = false; bool has_argument = false;
std::string option_name; std::string option_name;
std::string argument; std::string argument;
@ -81,11 +77,21 @@ bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
argument.clear(); argument.clear();
} }
// Note that --debug-port and --debug-brk in conjuction with --inspect
// work but are undocumented.
// --debug is no longer valid.
// Ref: https://github.com/nodejs/node/issues/12630
// Ref: https://github.com/nodejs/node/pull/12949
if (option_name == "--inspect") { if (option_name == "--inspect") {
enable_inspector = true; inspector_enabled_ = true;
} else if (option_name == "--debug") {
deprecated_debug_ = true;
} else if (option_name == "--inspect-brk") { } else if (option_name == "--inspect-brk") {
enable_inspector = true; inspector_enabled_ = true;
wait_connect_ = true; break_first_line_ = true;
} else if (option_name == "--debug-brk") {
break_first_line_ = true;
deprecated_debug_ = true;
} else if (option_name == "--debug-port" || } else if (option_name == "--debug-port" ||
option_name == "--inspect-port") { option_name == "--inspect-port") {
if (!has_argument) { if (!has_argument) {
@ -97,15 +103,14 @@ bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
return false; return false;
} }
if (enable_inspector) { #if !HAVE_INSPECTOR
#if HAVE_INSPECTOR if (inspector_enabled_) {
inspector_enabled_ = true;
#else
fprintf(stderr, fprintf(stderr,
"Inspector support is not available with this Node.js build\n"); "Inspector support is not available with this Node.js build\n");
}
inspector_enabled_ = false;
return false; return false;
#endif #endif
}
// argument can be specified for *any* option to specify host:port // argument can be specified for *any* option to specify host:port
if (has_argument) { if (has_argument) {
@ -124,9 +129,7 @@ bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
int DebugOptions::port() const { int DebugOptions::port() const {
int port = port_; int port = port_;
if (port < 0) { if (port < 0) {
#if HAVE_INSPECTOR
port = default_inspector_port; port = default_inspector_port;
#endif // HAVE_INSPECTOR
} }
return port; return port;
} }

View File

@ -10,25 +10,24 @@ class DebugOptions {
public: public:
DebugOptions(); DebugOptions();
bool ParseOption(const char* argv0, const std::string& option); bool ParseOption(const char* argv0, const std::string& option);
bool inspector_enabled() const { bool inspector_enabled() const { return inspector_enabled_; }
#if HAVE_INSPECTOR bool deprecated_invocation() const {
return inspector_enabled_; return deprecated_debug_ &&
#else inspector_enabled_ &&
return false; break_first_line_;
#endif // HAVE_INSPECTOR
} }
bool ToolsServerEnabled(); bool invalid_invocation() const {
bool wait_for_connect() const { return wait_connect_; } return deprecated_debug_ && !inspector_enabled_;
}
bool wait_for_connect() const { return break_first_line_; }
std::string host_name() const { return host_name_; } std::string host_name() const { return host_name_; }
int port() const; int port() const;
void set_port(int port) { port_ = port; } void set_port(int port) { port_ = port; }
private: private:
#if HAVE_INSPECTOR
bool inspector_enabled_; bool inspector_enabled_;
#endif // HAVE_INSPECTOR bool deprecated_debug_;
bool wait_connect_; bool break_first_line_;
bool http_enabled_;
std::string host_name_; std::string host_name_;
int port_; int port_;
}; };

View File

@ -496,9 +496,9 @@ Harness.prototype.kill = function() {
}; };
exports.startNodeForInspectorTest = function(callback, exports.startNodeForInspectorTest = function(callback,
inspectorFlag = '--inspect-brk', inspectorFlags = ['--inspect-brk'],
opt_script_contents) { opt_script_contents) {
const args = [inspectorFlag]; const args = [].concat(inspectorFlags);
if (opt_script_contents) { if (opt_script_contents) {
args.push('-e', opt_script_contents); args.push('-e', opt_script_contents);
} else { } else {

View File

@ -0,0 +1,57 @@
'use strict';
const common = require('../common');
common.skipIfInspectorDisabled();
const assert = require('assert');
const helper = require('./inspector-helper.js');
function setupExpectBreakOnLine(line, url, session, scopeIdCallback) {
return function(message) {
if ('Debugger.paused' === message['method']) {
const callFrame = message['params']['callFrames'][0];
const location = callFrame['location'];
assert.strictEqual(url, session.scriptUrlForId(location['scriptId']));
assert.strictEqual(line, location['lineNumber']);
scopeIdCallback &&
scopeIdCallback(callFrame['scopeChain'][0]['object']['objectId']);
return true;
}
};
}
function testBreakpointOnStart(session) {
const commands = [
{ 'method': 'Runtime.enable' },
{ 'method': 'Debugger.enable' },
{ 'method': 'Debugger.setPauseOnExceptions',
'params': {'state': 'none'} },
{ 'method': 'Debugger.setAsyncCallStackDepth',
'params': {'maxDepth': 0} },
{ 'method': 'Profiler.enable' },
{ 'method': 'Profiler.setSamplingInterval',
'params': {'interval': 100} },
{ 'method': 'Debugger.setBlackboxPatterns',
'params': {'patterns': []} },
{ 'method': 'Runtime.runIfWaitingForDebugger' }
];
session
.sendInspectorCommands(commands)
.expectMessages(setupExpectBreakOnLine(0, session.mainScriptPath, session));
}
function testWaitsForFrontendDisconnect(session, harness) {
console.log('[test]', 'Verify node waits for the frontend to disconnect');
session.sendInspectorCommands({ 'method': 'Debugger.resume'})
.expectStderrOutput('Waiting for the debugger to disconnect...')
.disconnect(true);
}
function runTests(harness) {
harness
.runFrontendSession([
testBreakpointOnStart,
testWaitsForFrontendDisconnect
]).expectShutDown(55);
}
helper.startNodeForInspectorTest(runTests, ['--inspect', '--debug-brk']);

View File

@ -0,0 +1,23 @@
'use strict';
const assert = require('assert');
const execFile = require('child_process').execFile;
const path = require('path');
const common = require('../common');
common.skipIfInspectorDisabled();
const mainScript = path.join(common.fixturesDir, 'loop.js');
const expected =
'`node --debug` and `node --debug-brk` are invalid. ' +
'Please use `node --inspect` or `node --inspect-brk` instead.';
for (const invalidArg of ['--debug-brk', '--debug']) {
execFile(
process.execPath,
[ invalidArg, mainScript ],
common.mustCall((error, stdout, stderr) => {
assert.strictEqual(error.code, 9, `node ${invalidArg} should exit 9`);
assert.strictEqual(stderr.includes(expected), true,
`${stderr} should include '${expected}'`);
})
);
}

View File

@ -0,0 +1,27 @@
'use strict';
const common = require('../common');
common.skipIfInspectorDisabled();
const assert = require('assert');
const spawn = require('child_process').spawn;
const script = common.fixturesDir + '/empty.js';
function test(arg) {
const child = spawn(process.execPath, ['--inspect', arg, script]);
const argStr = child.spawnargs.join(' ');
const fail = () => assert.fail(true, false, `'${argStr}' should not quit`);
child.on('exit', fail);
// give node time to start up the debugger
setTimeout(function() {
child.removeListener('exit', fail);
child.kill();
}, 2000);
process.on('exit', function() {
assert(child.killed);
});
}
test('--debug-brk');
test('--debug-brk=5959');