mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
repl: handle exceptions from async context after close
a9da9ffc04 recently restructured async context handling
in the REPL source so that it no longer uses the domain module,
and instead performs its own async context tracking.
That change was not intended to be breaking, but it affected
behavior for uncaught exceptions thrown after the REPL was closed.
Those would now be treated as uncaught exceptions on the process
level, which is probably not intentional in most situations.
While it's understandably not great that we handle execptions
after closing the REPL instance, I am confident that it's
best to restore the previous behavior for now and add more
granular handling options separately and intentionally
in a (potentially semver-major) follow-up change.
Refs: https://github.com/nodejs/node/pull/61227
PR-URL: https://github.com/nodejs/node/pull/62165
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
1 parent
70b35704a0
commit
bd3cba5633
2 files changed
+29
-1
No files matched your search
+6
-1
@@ -195,7 +195,12 @@ function setupExceptionCapture() {
|
||||
|
||||
process.addUncaughtExceptionCaptureCallback((err) => {
|
||||
const store = replContext.getStore();
|
||||
if (store?.replServer && !store.replServer.closed) {
|
||||
// TODO(addaleax): Add back a `store.replServer.closed` check here
|
||||
// as a semver-major change.
|
||||
// This check may need to allow for an opt-out, since the change in
|
||||
// behavior could lead to DoS vulnerabilities (e.g. in the case of
|
||||
// the net-based REPL described in our docs).
|
||||
if (store?.replServer) {
|
||||
store.replServer._handleError(err);
|
||||
return true; // We handled it
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const { start } = require('node:repl');
|
||||
const { PassThrough } = require('node:stream');
|
||||
const assert = require('node:assert');
|
||||
|
||||
// This test verifies that uncaught exceptions in the REPL
|
||||
// do not bring down the process, even if stdin may already
|
||||
// have been ended at that point (and the REPL closed as
|
||||
// a result of that).
|
||||
const input = new PassThrough();
|
||||
const output = new PassThrough().setEncoding('utf8');
|
||||
start({
|
||||
input,
|
||||
output,
|
||||
terminal: false,
|
||||
});
|
||||
|
||||
input.end('setImmediate(() => { throw new Error("test"); });\n');
|
||||
|
||||
setImmediate(common.mustCall(() => {
|
||||
assert.match(output.read(), /Uncaught Error: test/);
|
||||
}));
|
||||
Reference in new issue
Block a user