@@ -19,6 +19,41 @@ import {flags, refs, sharedWorkerTeardowns} from './state.cjs';
19
19
import { isRunningInThread , isRunningInChildProcess } from './utils.cjs' ;
20
20
21
21
const currentlyUnhandled = setUpCurrentlyUnhandled ( ) ;
22
+ let runner ;
23
+
24
+ // Override process.exit with an undetectable replacement
25
+ // to report when it is called from a test (which it should never be).
26
+ const { apply} = Reflect ;
27
+ const realExit = process . exit ;
28
+
29
+ async function exit ( code , forceSync = false ) {
30
+ dependencyTracking . flush ( ) ;
31
+ const flushing = channel . flush ( ) ;
32
+ if ( ! forceSync ) {
33
+ await flushing ;
34
+ }
35
+
36
+ apply ( realExit , process , [ code ] ) ;
37
+ }
38
+
39
+ const handleProcessExit = ( fn , receiver , args ) => {
40
+ const error = new Error ( 'Unexpected process.exit()' ) ;
41
+ Error . captureStackTrace ( error , handleProcessExit ) ;
42
+ const { stack} = serializeError ( '' , true , error ) ;
43
+ channel . send ( { type : 'process-exit' , stack} ) ;
44
+
45
+ // Make sure to extract the code only from `args` rather than e.g. `Array.prototype`.
46
+ // This level of paranoia is usually unwarranted, but we're dealing with test code
47
+ // that has already colored outside the lines.
48
+ const code = args . length > 0 ? args [ 0 ] : undefined ;
49
+
50
+ // Force a synchronous exit as guaranteed by the real process.exit().
51
+ exit ( code , true ) ;
52
+ } ;
53
+
54
+ process . exit = new Proxy ( realExit , {
55
+ apply : handleProcessExit ,
56
+ } ) ;
22
57
23
58
const run = async options => {
24
59
setOptions ( options ) ;
@@ -29,16 +64,6 @@ const run = async options => {
29
64
global . console = Object . assign ( global . console , new console . Console ( { stdout, stderr, colorMode : true } ) ) ;
30
65
}
31
66
32
- async function exit ( code ) {
33
- if ( ! process . exitCode ) {
34
- process . exitCode = code ;
35
- }
36
-
37
- dependencyTracking . flush ( ) ;
38
- await channel . flush ( ) ;
39
- process . exit ( ) ; // eslint-disable-line unicorn/no-process-exit
40
- }
41
-
42
67
let checkSelectedByLineNumbers ;
43
68
try {
44
69
checkSelectedByLineNumbers = lineNumberSelection ( {
@@ -50,7 +75,7 @@ const run = async options => {
50
75
checkSelectedByLineNumbers = ( ) => false ;
51
76
}
52
77
53
- const runner = new Runner ( {
78
+ runner = new Runner ( {
54
79
checkSelectedByLineNumbers,
55
80
experiments : options . experiments ,
56
81
failFast : options . failFast ,
0 commit comments