@@ -49,8 +49,13 @@ export function start(opts: AsyncREPLOptions): REPLServer {
49
49
repl . emit ( evalStart , { input } as EvalStartEvent ) ;
50
50
51
51
try {
52
+ let exitEventPending = false ;
53
+ const exitListener = ( ) => { exitEventPending = true ; } ;
54
+ let previousExitListeners : any [ ] = [ ] ;
55
+
52
56
let sigintListener : ( ( ) => void ) | undefined = undefined ;
53
57
let previousSigintListeners : any [ ] = [ ] ;
58
+
54
59
try {
55
60
result = await new Promise ( ( resolve , reject ) => {
56
61
if ( breakEvalOnSigint ) {
@@ -68,6 +73,13 @@ export function start(opts: AsyncREPLOptions): REPLServer {
68
73
repl . once ( 'SIGINT' , sigintListener ) ;
69
74
}
70
75
76
+ // The REPL may become over-eager and emit 'exit' events while our
77
+ // evaluation is still in progress (because it doesn't expect async
78
+ // evaluation). If that happens, defer the event until later.
79
+ previousExitListeners = repl . rawListeners ( 'exit' ) ;
80
+ repl . removeAllListeners ( 'exit' ) ;
81
+ repl . once ( 'exit' , exitListener ) ;
82
+
71
83
const evalResult = asyncEval ( originalEval , input , context , filename ) ;
72
84
73
85
if ( sigintListener !== undefined ) {
@@ -84,6 +96,14 @@ export function start(opts: AsyncREPLOptions): REPLServer {
84
96
for ( const listener of previousSigintListeners ) {
85
97
repl . on ( 'SIGINT' , listener ) ;
86
98
}
99
+
100
+ repl . removeListener ( 'exit' , exitListener ) ;
101
+ for ( const listener of previousExitListeners ) {
102
+ repl . on ( 'exit' , listener ) ;
103
+ }
104
+ if ( exitEventPending ) {
105
+ process . nextTick ( ( ) => repl . emit ( 'exit' ) ) ;
106
+ }
87
107
}
88
108
} catch ( err ) {
89
109
try {
0 commit comments