Skip to content

Commit 75bace0

Browse files
committed
repl: catch promise errors during eval in completion
Fixes: #58903
1 parent 8b199ee commit 75bace0

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

lib/repl.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const {
9898

9999
const {
100100
isProxy,
101+
isPromise,
101102
} = require('internal/util/types');
102103

103104
const { BuiltinModule } = require('internal/bootstrap/realm');
@@ -1544,6 +1545,10 @@ function complete(line, callback) {
15441545
const evalExpr = `try { ${expr} } catch {}`;
15451546
this.eval(evalExpr, this.context, getREPLResourceName(), (e, obj) => {
15461547
try {
1548+
if (isPromise(obj)) {
1549+
obj.catch(() => {});
1550+
}
1551+
15471552
let p;
15481553
if ((typeof obj === 'object' && obj !== null) ||
15491554
typeof obj === 'function') {
@@ -1733,6 +1738,9 @@ function includesProxiesOrGetters(exprSegments, evalFn, context, callback, curre
17331738
const currentSegment = exprSegments[idx];
17341739
currentExpr += `${currentExpr.length === 0 ? '' : '.'}${currentSegment}`;
17351740
evalFn(`try { ${currentExpr} } catch { }`, context, getREPLResourceName(), (_, currentObj) => {
1741+
if (isPromise(currentObj)) {
1742+
currentObj.catch(() => {});
1743+
}
17361744
if (typeof currentObj !== 'object' || currentObj === null) {
17371745
return callback(false);
17381746
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const repl = require('repl');
5+
const ArrayStream = require('../common/arraystream');
6+
const assert = require('assert');
7+
8+
const completionTests = [
9+
{ send: 'Promise.reject().' },
10+
{ send: 'let p = Promise.reject().' },
11+
{ send: 'Promise.resolve().' },
12+
{ send: 'Promise.resolve().then(() => {}).' },
13+
{ send: `async function f() {throw new Error('test');}; f().` },
14+
{ send: `async function f() {}; f().` },
15+
];
16+
17+
const tests = [
18+
{
19+
send: 'Promise.reject()',
20+
expect: /Promise \{[\s\S]*?Uncaught undefined\n?$/
21+
},
22+
{
23+
send: 'let p = Promise.reject()',
24+
expect: /undefined\nUncaught undefined\n?$/
25+
},
26+
{
27+
send: `Promise.resolve()`,
28+
expect: /Promise \{[\s\S]*?}\n?$/
29+
},
30+
{
31+
send: `Promise.resolve().then(() => {})`,
32+
expect: /Promise \{[\s\S]*?}\n?$/
33+
},
34+
{
35+
send: `async function f() { throw new Error('test'); };f();`,
36+
expect: /Promise \{[\s\S]*?<rejected> Error: test[\s\S]*?Uncaught Error: test[\s\S]*?\n?$/
37+
},
38+
{
39+
send: `async function f() {};f();`,
40+
expect: /Promise \{[\s\S]*?}\n?$/
41+
},
42+
];
43+
44+
45+
(async function() {
46+
await runReplCompleteTests(completionTests);
47+
await runReplTests(tests);
48+
})().then(common.mustCall());
49+
50+
async function runReplCompleteTests(tests) {
51+
let outputText = '';
52+
for (const { send } of tests) {
53+
const input = new ArrayStream();
54+
const output = new ArrayStream();
55+
56+
function write(data) {
57+
outputText += data;
58+
}
59+
output.write = write;
60+
const replServer = repl.start({
61+
prompt: '',
62+
input,
63+
output: output,
64+
allowBlockingCompletions: true,
65+
terminal: true
66+
});
67+
68+
input.emit('data', send);
69+
await new Promise((resolve) => {
70+
setTimeout(() => {
71+
assert.strictEqual(outputText.includes(send), true);
72+
assert.strictEqual(outputText.split(send).length - 1, 1);
73+
replServer.close();
74+
resolve();
75+
}, 10);
76+
});
77+
}
78+
}
79+
80+
async function runReplTests(tests) {
81+
for (const { send, expect } of tests) {
82+
const input = new ArrayStream();
83+
const output = new ArrayStream();
84+
let outputText = '';
85+
function write(data) {
86+
outputText += data;
87+
}
88+
output.write = write;
89+
const replServer = repl.start({
90+
prompt: '',
91+
input,
92+
output: output,
93+
});
94+
input.emit('data', `${send}\n`);
95+
await new Promise((resolve) => {
96+
setTimeout(() => {
97+
assert.match(outputText, expect);
98+
replServer.close();
99+
resolve();
100+
}, 10);
101+
});
102+
}
103+
}

0 commit comments

Comments
 (0)