Skip to content

Commit 58ed4da

Browse files
committed
test: isolate REPL user error handler test
Use a synchronous VM evaluator so the test exercises handleError without depending on inspector promise retention. Feed the throwing input separately and wait for REPL exit to avoid overlapping evaluation and teardown. Signed-off-by: Matteo Collina <hello@matteocollina.com>
1 parent 59f99df commit 58ed4da

1 file changed

Lines changed: 21 additions & 9 deletions

File tree

test/parallel/test-repl-user-error-handler.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,18 @@ const { PassThrough } = require('node:stream');
66
const { once } = require('node:events');
77
const test = require('node:test');
88
const { spawn } = require('node:child_process');
9+
const vm = require('node:vm');
910

1011
common.skipIfInspectorDisabled();
1112

13+
function evaluate(code, context, filename, callback) {
14+
try {
15+
callback(null, vm.runInContext(code, context, { filename }));
16+
} catch (err) {
17+
callback(err);
18+
}
19+
}
20+
1221
function* generateCases() {
1322
for (const async of [false, true]) {
1423
for (const handleErrorReturn of ['ignore', 'print', 'unhandled', 'badvalue']) {
@@ -23,13 +32,12 @@ function* generateCases() {
2332

2433
for (const { async, handleErrorReturn } of generateCases()) {
2534
test(`async: ${async}, handleErrorReturn: ${handleErrorReturn}`, async () => {
26-
let err;
2735
const options = {
2836
input: new PassThrough(),
2937
output: new PassThrough().setEncoding('utf8'),
30-
handleError: common.mustCall((e) => {
31-
err = e;
32-
queueMicrotask(() => repl.emit('handled-error'));
38+
eval: evaluate,
39+
handleError: common.mustCall((err) => {
40+
queueMicrotask(() => repl.emit('handled-error', err));
3341
return handleErrorReturn;
3442
})
3543
};
@@ -45,13 +53,16 @@ for (const { async, handleErrorReturn } of generateCases()) {
4553
let outputString = '';
4654
options.output.on('data', (chunk) => { outputString += chunk; });
4755

48-
const inputString = async ?
49-
'setImmediate(() => { throw new Error("testerror") })\n42\n' :
50-
'throw new Error("testerror")\n42\n';
51-
options.input.end(inputString);
56+
const errorInput = async ?
57+
'setImmediate(() => { throw new Error("testerror") })\n' :
58+
'throw new Error("testerror")\n';
59+
const handledErrorEvent = once(repl, 'handled-error');
60+
options.input.write(errorInput);
5261

53-
await once(repl, 'handled-error');
62+
const [err] = await handledErrorEvent;
5463
assert.strictEqual(err.message, 'testerror');
64+
const exitEvent = once(repl, 'exit');
65+
options.input.end('42\n');
5566
while (!/42/.test(outputString)) {
5667
await once(options.output, 'data');
5768
}
@@ -66,6 +77,7 @@ for (const { async, handleErrorReturn } of generateCases()) {
6677
const [uncaughtErr] = await uncaughtExceptionEvent;
6778
assert.strictEqual(uncaughtErr, err);
6879
}
80+
await exitEvent;
6981
});
7082
}
7183

0 commit comments

Comments
 (0)