Skip to content

Commit c91b325

Browse files
authored
ensure --debug becomes --inspect; closes #3697 (#3698)
* ensure --debug becomes --inspect; closes #3697 - add some handiness to the integration test helpers - update docstrings in integration test helpers * add some warnings around debug/inspect usage - add `utils.warn()` for a generic non-deprecation warning
1 parent 1f36ec5 commit c91b325

File tree

8 files changed

+451
-295
lines changed

8 files changed

+451
-295
lines changed

bin/mocha

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* @private
1010
*/
1111

12-
const {deprecate} = require('../lib/utils');
12+
const {deprecate, warn} = require('../lib/utils');
1313
const {spawn} = require('child_process');
1414
const {loadOptions} = require('../lib/cli/options');
1515
const {isNodeFlag, impliesNoTimeouts} = require('../lib/cli/node-flags');
@@ -18,62 +18,65 @@ const debug = require('debug')('mocha:cli');
1818
const {aliases} = require('../lib/cli/run-option-metadata');
1919

2020
const mochaPath = require.resolve('./_mocha');
21-
const childOpts = {};
22-
const nodeOpts = {};
21+
const mochaArgs = {};
22+
const nodeArgs = {};
2323

2424
const opts = loadOptions(process.argv.slice(2));
2525
debug('loaded opts', opts);
2626

27+
/**
28+
* Given option/command `value`, disable timeouts if applicable
29+
* @param {string} [value] - Value to check
30+
* @ignore
31+
*/
32+
const disableTimeouts = value => {
33+
if (impliesNoTimeouts(value)) {
34+
debug(`option "${value}" disabled timeouts`);
35+
mochaArgs.timeout = false;
36+
delete mochaArgs.timeouts;
37+
delete mochaArgs.t;
38+
}
39+
};
40+
41+
/**
42+
* If `value` begins with `v8-` and is not explicitly `v8-options`, remove prefix
43+
* @param {string} [value] - Value to check
44+
* @returns {string} `value` with prefix (maybe) removed
45+
* @ignore
46+
*/
47+
const trimV8Option = value =>
48+
value !== 'v8-options' && /^v8-/.test(value) ? value.slice(2) : value;
49+
50+
// sort options into "node" and "mocha" buckets
2751
Object.keys(opts).forEach(opt => {
52+
opt = trimV8Option(opt);
2853
if (isNodeFlag(opt)) {
29-
if (/^v8-/.test(opt)) {
30-
opt = opt.slice(2);
31-
}
32-
nodeOpts[opt] = opts[opt];
33-
if (impliesNoTimeouts(opt)) {
34-
debug(`option "${opt}" disabled timeouts`);
35-
childOpts.timeout = false;
36-
}
54+
nodeArgs[opt] = opts[opt];
55+
disableTimeouts(opt);
3756
} else {
38-
childOpts[opt] = opts[opt];
57+
mochaArgs[opt] = opts[opt];
3958
}
4059
});
4160

42-
// allow --debug to invoke --inspect on Node.js v8 or newer nodeOpts.inspect = childOpts.debug;
43-
if (childOpts.debug) {
44-
childOpts.timeout = false;
45-
delete childOpts.debug;
46-
debug('--debug -> --inspect');
47-
} else if (childOpts['debug-brk']) {
48-
nodeOpts['inspect-brk'] = childOpts['debug-brk'];
49-
childOpts.timeout = false;
50-
delete childOpts['debug-brk'];
51-
debug('--debug-brk -> --inspect-brk');
52-
}
53-
54-
// historical
55-
if (nodeOpts.gc) {
56-
deprecate(
57-
'"-gc" is deprecated and will be removed from a future version of Mocha. Use "--gc-global" instead.'
58-
);
59-
nodeOpts['gc-global'] = nodeOpts.gc;
60-
delete nodeOpts.gc;
61-
}
62-
6361
// Native debugger handling
6462
// see https://nodejs.org/api/debugger.html#debugger_debugger
6563
// look for 'debug' or 'inspect' that would launch this debugger,
6664
// remove it from Mocha's opts and prepend it to Node's opts.
6765
// also coerce depending on Node.js version.
68-
if (/^(debug|inspect)$/.test(childOpts._[0])) {
69-
childOpts.timeout = false;
70-
childOpts._.shift();
66+
// A deprecation warning will be printed by node, if applicable.
67+
// (mochaArgs._ are "positional" arguments, not prefixed with - or --)
68+
if (/^(debug|inspect)$/.test(mochaArgs._[0])) {
69+
const command = mochaArgs._.shift();
70+
disableTimeouts(command);
7171
// don't conflict with inspector
72-
delete nodeOpts['debug'];
73-
delete nodeOpts['inspect'];
74-
delete nodeOpts['debug-brk'];
75-
delete nodeOpts['inspect-brk'];
76-
nodeOpts._ = [
72+
['debug', 'inspect', 'debug-brk', 'inspect-brk']
73+
.filter(opt => opt in nodeArgs || opt in mochaArgs)
74+
.forEach(opt => {
75+
warn(`command "${command}" provided; --${opt} ignored`);
76+
delete nodeArgs[opt];
77+
delete mochaArgs[opt];
78+
});
79+
nodeArgs._ = [
7780
parseInt(
7881
process.version
7982
.slice(1)
@@ -86,10 +89,36 @@ if (/^(debug|inspect)$/.test(childOpts._[0])) {
8689
];
8790
}
8891

92+
// allow --debug to invoke --inspect on Node.js v8 or newer.
93+
// these show up in childOpts because they are not recognized as valid node flags in this version of node.
94+
['debug', 'debug-brk']
95+
.filter(opt => opt in mochaArgs)
96+
.forEach(opt => {
97+
const newOpt = opt === 'debug' ? 'inspect' : 'inspect-brk';
98+
warn(
99+
`"--${opt}" is not available in Node.js ${
100+
process.version
101+
}; use "--${newOpt}" instead.`
102+
);
103+
nodeArgs[newOpt] = mochaArgs[opt];
104+
mochaArgs.timeout = false;
105+
debug(`--${opt} -> ${newOpt}`);
106+
delete mochaArgs[opt];
107+
});
108+
109+
// historical
110+
if (nodeArgs.gc) {
111+
deprecate(
112+
'"-gc" is deprecated and will be removed from a future version of Mocha. Use "--gc-global" instead.'
113+
);
114+
nodeArgs['gc-global'] = nodeArgs.gc;
115+
delete nodeArgs.gc;
116+
}
117+
89118
const args = [].concat(
90-
unparse(nodeOpts),
119+
unparse(nodeArgs),
91120
mochaPath,
92-
unparse(childOpts, {alias: aliases})
121+
unparse(mochaArgs, {alias: aliases})
93122
);
94123

95124
debug(`exec ${process.execPath} w/ args:`, args);

lib/utils.js

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -600,26 +600,50 @@ exports.getError = function(err) {
600600
return err || exports.undefinedError();
601601
};
602602

603+
/**
604+
* process.emitWarning or a polyfill
605+
* @see https://nodejs.org/api/process.html#process_process_emitwarning_warning_options
606+
* @ignore
607+
*/
608+
function emitWarning(msg, type) {
609+
if (process.emitWarning) {
610+
process.emitWarning(msg, type);
611+
} else {
612+
process.nextTick(function() {
613+
console.warn(type + ': ' + msg);
614+
});
615+
}
616+
}
617+
603618
/**
604619
* Show a deprecation warning. Each distinct message is only displayed once.
620+
* Ignores empty messages.
605621
*
606-
* @param {string} msg
622+
* @param {string} [msg] - Warning to print
623+
* @private
607624
*/
608625
exports.deprecate = function deprecate(msg) {
609626
msg = String(msg);
610627
if (msg && !deprecate.cache[msg]) {
611628
deprecate.cache[msg] = true;
612-
if (process.emitWarning) {
613-
process.emitWarning(msg, 'DeprecationWarning');
614-
} else {
615-
process.nextTick(function() {
616-
console.warn(msg);
617-
});
618-
}
629+
emitWarning(msg, 'DeprecationWarning');
619630
}
620631
};
621632
exports.deprecate.cache = {};
622633

634+
/**
635+
* Show a generic warning.
636+
* Ignores empty messages.
637+
*
638+
* @param {string} [msg] - Warning to print
639+
* @private
640+
*/
641+
exports.warn = function warn(msg) {
642+
if (msg) {
643+
emitWarning(msg);
644+
}
645+
};
646+
623647
/**
624648
* @summary
625649
* This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`)

0 commit comments

Comments
 (0)