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