Skip to content
This repository was archived by the owner on Feb 1, 2022. It is now read-only.

Commit fa8c4c7

Browse files
author
Jan Krems
committed
feat: breakOn{Exception,Uncaught,None}
Fixes #6
1 parent 40e9362 commit fa8c4c7

File tree

4 files changed

+97
-2
lines changed

4 files changed

+97
-2
lines changed

examples/exceptions.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
let error = null;
3+
try {
4+
throw new Error('Caught');
5+
} catch (e) {
6+
error = e;
7+
}
8+
9+
if (error) {
10+
throw new Error('Uncaught');
11+
}

lib/internal/inspect-repl.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ list Print the source around the line where execution is curren
5454
setBreakpoint, sb Set a breakpoint
5555
clearBreakpoint, cb Clear a breakpoint
5656
breakpoints List all known breakpoints
57+
breakOnException Pause execution whenever an exception is thrown
58+
breakOnUncaught Pause execution whenever an exception isn't caught
59+
breakOnNone Don't pause on exceptions (this is the default)
5760
5861
watch(expr) Start watching the given expression
5962
unwatch(expr) Stop watching an expression
@@ -222,12 +225,13 @@ function createRepl(inspector) {
222225
const { Debugger, Runtime } = inspector;
223226

224227
let repl; // eslint-disable-line prefer-const
225-
let lastCommand;
226228

227229
// Things we want to keep around
228230
const history = { control: [], debug: [] };
229231
const watchedExpressions = [];
230232
const knownBreakpoints = [];
233+
let pauseOnExceptionState = 'none';
234+
let lastCommand;
231235

232236
// Things we need to reset when the app restarts
233237
let knownScripts;
@@ -619,6 +623,13 @@ function createRepl(inspector) {
619623
});
620624
}
621625

626+
function setPauseOnExceptions(state) {
627+
return Debugger.setPauseOnExceptions({ state })
628+
.then(() => {
629+
pauseOnExceptionState = state;
630+
});
631+
}
632+
622633
Debugger.on('paused', ({ callFrames, reason /* , hitBreakpoints */ }) => {
623634
// Save execution context's data
624635
currentBacktrace = Backtrace.from(callFrames);
@@ -787,8 +798,20 @@ function createRepl(inspector) {
787798
},
788799

789800
scripts: listScripts,
801+
790802
setBreakpoint,
791803
clearBreakpoint,
804+
setPauseOnExceptions,
805+
get breakOnException() {
806+
return setPauseOnExceptions('all');
807+
},
808+
get breakOnUncaught() {
809+
return setPauseOnExceptions('uncaught');
810+
},
811+
get breakOnNone() {
812+
return setPauseOnExceptions('none');
813+
},
814+
792815
list,
793816
});
794817
aliasProperties(context, SHORTCUTS);
@@ -818,6 +841,7 @@ function createRepl(inspector) {
818841

819842
inspector.client.on('ready', () => {
820843
restoreBreakpoints();
844+
Debugger.setPauseOnExceptions({ state: pauseOnExceptionState });
821845
});
822846

823847
return repl;

test/cli/exceptions.test.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use strict';
2+
const { test } = require('tap');
3+
4+
const startCLI = require('./start-cli');
5+
6+
test('break on (uncaught) exceptions', (t) => {
7+
const cli = startCLI(['examples/exceptions.js']);
8+
9+
function onFatal(error) {
10+
cli.quit();
11+
throw error;
12+
}
13+
14+
return cli.waitFor(/break/)
15+
.then(() => cli.waitForPrompt())
16+
.then(() => {
17+
t.match(cli.output, 'break in examples/exceptions.js:1');
18+
})
19+
// making sure it will die by default:
20+
.then(() => cli.command('c'))
21+
.then(() => cli.waitFor(/disconnect/))
22+
23+
// Next run: With `breakOnException` it pauses in both places
24+
.then(() => cli.stepCommand('r'))
25+
.then(() => {
26+
t.match(cli.output, 'break in examples/exceptions.js:1');
27+
})
28+
.then(() => cli.command('breakOnException'))
29+
.then(() => cli.stepCommand('c'))
30+
.then(() => {
31+
t.match(cli.output, 'exception in examples/exceptions.js:4');
32+
})
33+
.then(() => cli.stepCommand('c'))
34+
.then(() => {
35+
t.match(cli.output, 'exception in examples/exceptions.js:10');
36+
})
37+
38+
// Next run: With `breakOnUncaught` it only pauses on the 2nd exception
39+
.then(() => cli.command('breakOnUncaught'))
40+
.then(() => cli.stepCommand('r')) // also, the setting survives the restart
41+
.then(() => {
42+
t.match(cli.output, 'break in examples/exceptions.js:1');
43+
})
44+
.then(() => cli.stepCommand('c'))
45+
.then(() => {
46+
t.match(cli.output, 'exception in examples/exceptions.js:10');
47+
})
48+
49+
// Next run: Back to the initial state! It should die again.
50+
.then(() => cli.command('breakOnNone'))
51+
.then(() => cli.stepCommand('r'))
52+
.then(() => {
53+
t.match(cli.output, 'break in examples/exceptions.js:1');
54+
})
55+
.then(() => cli.command('c'))
56+
.then(() => cli.waitFor(/disconnect/))
57+
58+
.then(() => cli.quit())
59+
.then(null, onFatal);
60+
});

test/cli/start-cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ function startCLI(args) {
113113
this.flushOutput();
114114
child.stdin.write(input);
115115
child.stdin.write('\n');
116-
return this.waitFor(/break/)
116+
return this.waitFor(/(?:assert|break|debugCommand|exception|other|promiseRejection) in/)
117117
.then(() => this.waitForPrompt());
118118
},
119119

0 commit comments

Comments
 (0)