1- import { StdioOptions , spawn , ChildProcess } from 'child_process' ;
21import fs from 'fs' ;
32import path from 'path' ;
43import semver from 'semver' ;
@@ -7,11 +6,9 @@ import * as debugUtils from './debugUtil
76import * as folderUtils from './folderUtils' ;
87import * as fsUtils from './fsUtils' ;
98import * as httpUtils from './httpUtils' ;
10- import { Context } from './main ' ;
9+ import * as nodeUtils from './nodeUtils ' ;
1110import { RegistrySpec , Descriptor , Locator , PackageManagerSpec } from './types' ;
1211
13- declare const __non_webpack_require__ : unknown ;
14-
1512export async function fetchAvailableTags ( spec : RegistrySpec ) : Promise < Record < string , string > > {
1613 switch ( spec . type ) {
1714 case `npm` : {
@@ -133,7 +130,10 @@ export async function installVersion(installTarget: string, locator: Locator, {s
133130 return installFolder ;
134131}
135132
136- export async function runVersion ( installSpec : { location : string , spec : PackageManagerSpec } , locator : Locator , binName : string , args : Array < string > , context : Context ) {
133+ /**
134+ * Loads the binary, taking control of the current process.
135+ */
136+ export async function runVersion ( installSpec : { location : string , spec : PackageManagerSpec } , binName : string , args : Array < string > ) : Promise < void > {
137137 let binPath : string | null = null ;
138138 if ( Array . isArray ( installSpec . spec . bin ) ) {
139139 if ( installSpec . spec . bin . some ( bin => bin === binName ) ) {
@@ -155,82 +155,23 @@ export async function runVersion(installSpec: { location: string, spec: PackageM
155155 if ( ! binPath )
156156 throw new Error ( `Assertion failed: Unable to locate path for bin '${ binName } '` ) ;
157157
158- return new Promise < number > ( ( resolve , reject ) => {
159- process . on ( `SIGINT` , ( ) => {
160- // We don't want to exit the process before the child, so we just
161- // ignore SIGINT and wait for the regular exit to happen (the child
162- // will receive SIGINT too since it's part of the same process grp)
163- } ) ;
164-
165- const stdio : StdioOptions = [ `pipe` , `pipe` , `pipe` ] ;
166-
167- if ( context . stdin === process . stdin )
168- stdio [ 0 ] = `inherit` ;
169- if ( context . stdout === process . stdout )
170- stdio [ 1 ] = `inherit` ;
171- if ( context . stderr === process . stderr )
172- stdio [ 2 ] = `inherit` ;
173-
174- const v8CompileCache = typeof __non_webpack_require__ !== `undefined`
175- ? eval ( `require` ) . resolve ( `./vcc.js` )
176- : eval ( `require` ) . resolve ( `corepack/dist/vcc.js` ) ;
177-
178- const child = spawn ( process . execPath , [ `--require` , v8CompileCache , binPath ! , ...args ] , {
179- cwd : context . cwd ,
180- stdio,
181- env : {
182- ...process . env ,
183- COREPACK_ROOT : path . dirname ( eval ( `__dirname` ) ) ,
184- } ,
185- } ) ;
186-
187- activeChildren . add ( child ) ;
188-
189- if ( activeChildren . size === 1 ) {
190- process . on ( `SIGINT` , sigintHandler ) ;
191- process . on ( `SIGTERM` , sigtermHandler ) ;
192- }
193-
194- if ( context . stdin !== process . stdin )
195- context . stdin . pipe ( child . stdin ! ) ;
196- if ( context . stdout !== process . stdout )
197- child . stdout ! . pipe ( context . stdout ) ;
198- if ( context . stderr !== process . stderr )
199- child . stderr ! . pipe ( context . stderr ) ;
158+ nodeUtils . registerV8CompileCache ( ) ;
200159
201- child . on ( `error` , error => {
202- activeChildren . delete ( child ) ;
160+ // We load the binary into the current process,
161+ // while making it think it was spawned.
203162
204- if ( activeChildren . size === 0 ) {
205- process . off ( `SIGINT` , sigintHandler ) ;
206- process . off ( `SIGTERM` , sigtermHandler ) ;
207- }
163+ // Non-exhaustive list of requirements:
164+ // - Yarn uses process.argv[1] to determine its own path: https://github.com/yarnpkg/berry/blob/0da258120fc266b06f42aed67e4227e81a2a900f/packages/yarnpkg-cli/sources/main.ts#L80
165+ // - pnpm uses `require.main == null` to determine its own version: https://github.com/pnpm/pnpm/blob/e2866dee92991e979b2b0e960ddf5a74f6845d90/packages/cli-meta/src/index.ts#L14
208166
209- reject ( error ) ;
210- } ) ;
167+ process . env . COREPACK_ROOT = path . dirname ( eval ( `__dirname` ) ) ;
211168
212- child . on ( `exit` , exitCode => {
213- activeChildren . delete ( child ) ;
169+ process . argv = [
170+ process . execPath ,
171+ binPath ,
172+ ...args ,
173+ ] ;
174+ process . execArgv = [ ] ;
214175
215- if ( activeChildren . size === 0 ) {
216- process . off ( `SIGINT` , sigintHandler ) ;
217- process . off ( `SIGTERM` , sigtermHandler ) ;
218- }
219-
220- resolve ( exitCode !== null ? exitCode : 1 ) ;
221- } ) ;
222- } ) ;
223- }
224-
225- const activeChildren = new Set < ChildProcess > ( ) ;
226-
227- function sigintHandler ( ) {
228- // We don't want SIGINT to kill our process; we want it to kill the
229- // innermost process, whose end will cause our own to exit.
230- }
231-
232- function sigtermHandler ( ) {
233- for ( const child of activeChildren ) {
234- child . kill ( ) ;
235- }
176+ return nodeUtils . loadMainModule ( binPath ) ;
236177}
0 commit comments