@@ -2,8 +2,9 @@ import { createContext } from "./context.ts";
22import type { Operation } from "./types.ts" ;
33import { callcc } from "./callcc.ts" ;
44import { run } from "./run.ts" ;
5- import { useScope } from "./scope.ts" ;
5+ import { global , useScope } from "./scope.ts" ;
66import { call } from "./call.ts" ;
7+ import { api } from "./api.ts" ;
78
89/**
910 * Halt process execution immediately and initiate shutdown. If a message is
@@ -60,103 +61,109 @@ export function* exit(status: number, message?: string): Operation<void> {
6061 * @since 3.0
6162 */
6263
63- export async function main (
64+ export function main (
6465 body : ( args : string [ ] ) => Operation < void > ,
6566) : Promise < void > {
66- let hardexit = ( _status : number ) => { } ;
67-
68- let result = await run ( ( ) =>
69- callcc < Exit > ( function * ( resolve ) {
70- // action will return shutdown immediately upon resolve, so stash
71- // this function in the exit context so it can be called anywhere.
72- yield * ExitContext . set ( resolve ) ;
73-
74- // this will hold the event loop and prevent runtimes such as
75- // Node and Deno from exiting prematurely.
76- let interval = setInterval ( ( ) => { } , Math . pow ( 2 , 30 ) ) ;
77-
78- let scope = yield * useScope ( ) ;
79-
80- try {
81- let interrupt = {
82- SIGINT : ( ) =>
83- scope . run ( ( ) => resolve ( { status : 130 , signal : "SIGINT" } ) ) ,
84- SIGTERM : ( ) =>
85- scope . run ( ( ) => resolve ( { status : 143 , signal : "SIGTERM" } ) ) ,
86- } ;
87-
88- yield * withHost ( {
89- * deno ( ) {
90- hardexit = ( status ) => Deno . exit ( status ) ;
91- try {
92- Deno . addSignalListener ( "SIGINT" , interrupt . SIGINT ) ;
93- /**
94- * Windows only supports ctrl-c (SIGINT), ctrl-break (SIGBREAK), and ctrl-close (SIGUP)
95- */
96- if ( Deno . build . os !== "windows" ) {
97- Deno . addSignalListener ( "SIGTERM" , interrupt . SIGTERM ) ;
98- }
99- yield * body ( Deno . args . slice ( ) ) ;
100- } finally {
101- Deno . removeSignalListener ( "SIGINT" , interrupt . SIGINT ) ;
102- if ( Deno . build . os !== "windows" ) {
103- Deno . removeSignalListener ( "SIGTERM" , interrupt . SIGTERM ) ;
67+ return api . Main . invoke ( global , "main" , [ body ] ) ;
68+ }
69+
70+ global . around ( api . Main , {
71+ async main ( [ body ] ) {
72+ let hardexit = ( _status : number ) => { } ;
73+
74+ let result = await run ( ( ) =>
75+ callcc < Exit > ( function * ( resolve ) {
76+ // action will return shutdown immediately upon resolve, so stash
77+ // this function in the exit context so it can be called anywhere.
78+ yield * ExitContext . set ( resolve ) ;
79+
80+ // this will hold the event loop and prevent runtimes such as
81+ // Node and Deno from exiting prematurely.
82+ let interval = setInterval ( ( ) => { } , Math . pow ( 2 , 30 ) ) ;
83+
84+ let scope = yield * useScope ( ) ;
85+
86+ try {
87+ let interrupt = {
88+ SIGINT : ( ) =>
89+ scope . run ( ( ) => resolve ( { status : 130 , signal : "SIGINT" } ) ) ,
90+ SIGTERM : ( ) =>
91+ scope . run ( ( ) => resolve ( { status : 143 , signal : "SIGTERM" } ) ) ,
92+ } ;
93+
94+ yield * withHost ( {
95+ * deno ( ) {
96+ hardexit = ( status ) => Deno . exit ( status ) ;
97+ try {
98+ Deno . addSignalListener ( "SIGINT" , interrupt . SIGINT ) ;
99+ /**
100+ * Windows only supports ctrl-c (SIGINT), ctrl-break (SIGBREAK), and ctrl-close (SIGUP)
101+ */
102+ if ( Deno . build . os !== "windows" ) {
103+ Deno . addSignalListener ( "SIGTERM" , interrupt . SIGTERM ) ;
104+ }
105+ yield * body ( Deno . args . slice ( ) ) ;
106+ } finally {
107+ Deno . removeSignalListener ( "SIGINT" , interrupt . SIGINT ) ;
108+ if ( Deno . build . os !== "windows" ) {
109+ Deno . removeSignalListener ( "SIGTERM" , interrupt . SIGTERM ) ;
110+ }
104111 }
105- }
106- } ,
107- * node ( ) {
108- // Annotate dynamic import so that webpack ignores it.
109- // See https://webpack.js.org/api/module-methods/#webpackignore
110- let { default : process } = yield * call ( ( ) =>
111- import ( /* webpackIgnore: true */ "node:process" )
112- ) ;
113- hardexit = ( status ) => process . exit ( status ) ;
114- try {
115- process . on ( "SIGINT" , interrupt . SIGINT ) ;
116- if ( process . platform !== "win32" ) {
117- process . on ( "SIGTERM" , interrupt . SIGTERM ) ;
112+ } ,
113+ * node ( ) {
114+ // Annotate dynamic import so that webpack ignores it.
115+ // See https://webpack.js.org/api/module-methods/#webpackignore
116+ let { default : process } = yield * call ( ( ) =>
117+ import ( /* webpackIgnore: true */ "node:process" )
118+ ) ;
119+ hardexit = ( status ) => process . exit ( status ) ;
120+ try {
121+ process . on ( "SIGINT" , interrupt . SIGINT ) ;
122+ if ( process . platform !== "win32" ) {
123+ process . on ( "SIGTERM" , interrupt . SIGTERM ) ;
124+ }
125+ yield * body ( process . argv . slice ( 2 ) ) ;
126+ } finally {
127+ process . off ( "SIGINT" , interrupt . SIGINT ) ;
128+ if ( process . platform !== "win32" ) {
129+ process . off ( "SIGTERM" , interrupt . SIGINT ) ;
130+ }
118131 }
119- yield * body ( process . argv . slice ( 2 ) ) ;
120- } finally {
121- process . off ( "SIGINT" , interrupt . SIGINT ) ;
122- if ( process . platform !== "win32" ) {
123- process . off ( "SIGTERM" , interrupt . SIGINT ) ;
132+ } ,
133+ * browser ( ) {
134+ try {
135+ self . addEventListener ( "unload" , interrupt . SIGINT ) ;
136+ yield * body ( [ ] ) ;
137+ } finally {
138+ self . removeEventListener ( "unload" , interrupt . SIGINT ) ;
124139 }
125- }
126- } ,
127- * browser ( ) {
128- try {
129- self . addEventListener ( "unload" , interrupt . SIGINT ) ;
130- yield * body ( [ ] ) ;
131- } finally {
132- self . removeEventListener ( "unload" , interrupt . SIGINT ) ;
133- }
134- } ,
135- } ) ;
136-
137- yield * exit ( 0 ) ;
138- } catch ( error ) {
139- yield * resolve ( { status : 1 , error : error as Error } ) ;
140- } finally {
141- clearInterval ( interval ) ;
140+ } ,
141+ } ) ;
142+
143+ yield * exit ( 0 ) ;
144+ } catch ( error ) {
145+ yield * resolve ( { status : 1 , error : error as Error } ) ;
146+ } finally {
147+ clearInterval ( interval ) ;
148+ }
149+ } )
150+ ) ;
151+
152+ if ( result . message ) {
153+ if ( result . status === 0 ) {
154+ console . log ( result . message ) ;
155+ } else {
156+ console . error ( result . message ) ;
142157 }
143- } )
144- ) ;
145-
146- if ( result . message ) {
147- if ( result . status === 0 ) {
148- console . log ( result . message ) ;
149- } else {
150- console . error ( result . message ) ;
151158 }
152- }
153159
154- if ( result . error ) {
155- console . error ( result . error ) ;
156- }
160+ if ( result . error ) {
161+ console . error ( result . error ) ;
162+ }
157163
158- hardexit ( result . status ) ;
159- }
164+ hardexit ( result . status ) ;
165+ } ,
166+ } , { at : "min" } ) ;
160167
161168const ExitContext = createContext < ( exit : Exit ) => Operation < void > > ( "exit" ) ;
162169
0 commit comments