Skip to content

Commit a3ee6cd

Browse files
committedOct 4, 2023
Lets avoid spawn.sync
1 parent 3df3708 commit a3ee6cd

File tree

3 files changed

+75
-102
lines changed

3 files changed

+75
-102
lines changed
 

‎lib/run-task.js

+73-68
Original file line numberDiff line numberDiff line change
@@ -139,83 +139,86 @@ function cleanTaskArg (arg) {
139139
*/
140140
module.exports = function runTask (task, options) {
141141
let cp = null
142-
const promise = new Promise((resolve, reject) => {
143-
ansiStylesPromise.then(({ default: ansiStyles }) => {
144-
const stdin = options.stdin
145-
const stdout = wrapLabeling(task, options.stdout, options.labelState, ansiStyles)
146-
const stderr = wrapLabeling(task, options.stderr, options.labelState, ansiStyles)
147-
const stdinKind = detectStreamKind(stdin, process.stdin)
148-
const stdoutKind = detectStreamKind(stdout, process.stdout)
149-
const stderrKind = detectStreamKind(stderr, process.stderr)
150-
const spawnOptions = { stdio: [stdinKind, stdoutKind, stderrKind] }
151-
152-
// Print task name.
153-
if (options.printName && stdout != null) {
154-
stdout.write(createHeader(
155-
task,
156-
options.packageInfo,
157-
options.stdout.isTTY,
158-
ansiStyles
159-
))
160-
}
161142

162-
// Execute.
163-
let npmPath = options.npmPath
164-
if (!npmPath && process.env.npm_execpath) {
165-
const basename = path.basename(process.env.npm_execpath)
166-
let newBasename = basename
167-
if (basename.startsWith('npx')) {
168-
newBasename = basename.replace('npx', 'npm') // eslint-disable-line no-process-env
169-
} else if (basename.startsWith('pnpx')) {
170-
newBasename = basename.replace('pnpx', 'pnpm') // eslint-disable-line no-process-env
171-
}
172-
173-
npmPath = newBasename === basename
174-
? path.join(path.dirname(process.env.npm_execpath), newBasename)
175-
: process.env.npm_execpath // eslint-disable-line no-process-env
143+
async function asyncRunTask () {
144+
const { default: ansiStyles } = await ansiStylesPromise
145+
146+
const stdin = options.stdin
147+
const stdout = wrapLabeling(task, options.stdout, options.labelState, ansiStyles)
148+
const stderr = wrapLabeling(task, options.stderr, options.labelState, ansiStyles)
149+
const stdinKind = detectStreamKind(stdin, process.stdin)
150+
const stdoutKind = detectStreamKind(stdout, process.stdout)
151+
const stderrKind = detectStreamKind(stderr, process.stderr)
152+
const spawnOptions = { stdio: [stdinKind, stdoutKind, stderrKind] }
153+
154+
// Print task name.
155+
if (options.printName && stdout != null) {
156+
stdout.write(createHeader(
157+
task,
158+
options.packageInfo,
159+
options.stdout.isTTY,
160+
ansiStyles
161+
))
162+
}
163+
164+
// Execute.
165+
let npmPath = options.npmPath
166+
if (!npmPath && process.env.npm_execpath) {
167+
const basename = path.basename(process.env.npm_execpath)
168+
let newBasename = basename
169+
if (basename.startsWith('npx')) {
170+
newBasename = basename.replace('npx', 'npm') // eslint-disable-line no-process-env
171+
} else if (basename.startsWith('pnpx')) {
172+
newBasename = basename.replace('pnpx', 'pnpm') // eslint-disable-line no-process-env
176173
}
177174

178-
const npmPathIsJs = typeof npmPath === 'string' && /\.(c|m)?js/.test(path.extname(npmPath))
179-
let execPath = (npmPathIsJs ? process.execPath : npmPath || 'npm')
180-
181-
if (!npmPath && !process.env.npm_execpath) {
182-
// When a script is being run via pnpm, npmPath and npm_execpath will be null or undefined
183-
// Attempt to figure out whether we're running via pnpm
184-
const projectRoot = path.dirname(options.packageInfo.path)
185-
const hasPnpmLockfile = fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml'))
186-
const { status: pnpmFound, output } = spawn.sync('which', 'pnpm', { silent: true })
187-
if (hasPnpmLockfile && __dirname.split(path.delimiter).includes('.pnpm') && pnpmFound) {
188-
execPath = output
189-
}
175+
npmPath = newBasename === basename
176+
? path.join(path.dirname(process.env.npm_execpath), newBasename)
177+
: process.env.npm_execpath // eslint-disable-line no-process-env
178+
}
179+
180+
const npmPathIsJs = typeof npmPath === 'string' && /\.(c|m)?js/.test(path.extname(npmPath))
181+
let execPath = (npmPathIsJs ? process.execPath : npmPath || 'npm')
182+
183+
if (!npmPath && !process.env.npm_execpath) {
184+
// When a script is being run via pnpm, npmPath and npm_execpath will be null or undefined
185+
// Attempt to figure out whether we're running via pnpm
186+
const projectRoot = path.dirname(options.packageInfo.path)
187+
const hasPnpmLockfile = fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml'))
188+
const { status: pnpmFound, output: pnpmWhichOutput } = await spawn('which', 'pnpm', { silent: true })
189+
if (hasPnpmLockfile && __dirname.split(path.delimiter).includes('.pnpm') && pnpmFound) {
190+
execPath = pnpmWhichOutput
190191
}
192+
}
191193

192-
const isYarn = process.env.npm_config_user_agent && process.env.npm_config_user_agent.startsWith('yarn') // eslint-disable-line no-process-env
194+
const isYarn = process.env.npm_config_user_agent && process.env.npm_config_user_agent.startsWith('yarn') // eslint-disable-line no-process-env
193195

194-
const spawnArgs = ['run']
196+
const spawnArgs = ['run']
195197

196-
if (npmPathIsJs) {
197-
spawnArgs.unshift(npmPath)
198-
}
199-
if (!isYarn) {
200-
Array.prototype.push.apply(spawnArgs, options.prefixOptions)
201-
} else if (options.prefixOptions.indexOf('--silent') !== -1) {
202-
spawnArgs.push('--silent')
203-
}
204-
Array.prototype.push.apply(spawnArgs, parseArgs(task).map(cleanTaskArg))
198+
if (npmPathIsJs) {
199+
spawnArgs.unshift(npmPath)
200+
}
201+
if (!isYarn) {
202+
Array.prototype.push.apply(spawnArgs, options.prefixOptions)
203+
} else if (options.prefixOptions.indexOf('--silent') !== -1) {
204+
spawnArgs.push('--silent')
205+
}
206+
Array.prototype.push.apply(spawnArgs, parseArgs(task).map(cleanTaskArg))
205207

206-
cp = spawn(execPath, spawnArgs, spawnOptions)
208+
cp = spawn(execPath, spawnArgs, spawnOptions)
207209

208-
// Piping stdio.
209-
if (stdinKind === 'pipe') {
210-
stdin.pipe(cp.stdin)
211-
}
212-
if (stdoutKind === 'pipe') {
213-
cp.stdout.pipe(stdout, { end: false })
214-
}
215-
if (stderrKind === 'pipe') {
216-
cp.stderr.pipe(stderr, { end: false })
217-
}
210+
// Piping stdio.
211+
if (stdinKind === 'pipe') {
212+
stdin.pipe(cp.stdin)
213+
}
214+
if (stdoutKind === 'pipe') {
215+
cp.stdout.pipe(stdout, { end: false })
216+
}
217+
if (stderrKind === 'pipe') {
218+
cp.stderr.pipe(stderr, { end: false })
219+
}
218220

221+
return new Promise((resolve, reject) => {
219222
// Register
220223
cp.on('error', (err) => {
221224
cp = null
@@ -226,7 +229,9 @@ module.exports = function runTask (task, options) {
226229
resolve({ task, code, signal })
227230
})
228231
})
229-
})
232+
}
233+
234+
const promise = asyncRunTask()
230235

231236
promise.abort = function abort () {
232237
if (cp != null) {

‎lib/spawn-posix.js

+1-17
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,9 @@ function kill () {
5555
* @returns {ChildProcess} A ChildProcess instance of new process.
5656
* @private
5757
*/
58-
function spawn (command, args, options) {
58+
module.exports = function spawn (command, args, options) {
5959
const child = crossSpawn(command, args, options)
6060
child.kill = kill
6161

6262
return child
6363
}
64-
65-
/**
66-
* Launches a new process synchronously with the given command.
67-
* This is almost same as `child_process.spawnSync`.
68-
*
69-
* This returns a `SpawnSyncReturns` object.
70-
*
71-
* @param {string} command - The command to run.
72-
* @param {string[]} args - List of string arguments.
73-
* @param {object} options - Options.
74-
* @returns {SpawnSyncReturns} A ChildProcess instance of new process.
75-
* @private
76-
*/
77-
spawn.sync = crossSpawn.sync
78-
79-
module.exports = spawn

‎lib/spawn-win32.js

+1-17
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,9 @@ function kill () {
4242
* @returns {ChildProcess} A ChildProcess instance of new process.
4343
* @private
4444
*/
45-
function spawn (command, args, options) {
45+
module.exports = function spawn (command, args, options) {
4646
const child = crossSpawn(command, args, options)
4747
child.kill = kill
4848

4949
return child
5050
}
51-
52-
/**
53-
* Launches a new process synchronously with the given command.
54-
* This is almost same as `child_process.spawnSync`.
55-
*
56-
* This returns a `SpawnSyncReturns` object.
57-
*
58-
* @param {string} command - The command to run.
59-
* @param {string[]} args - List of string arguments.
60-
* @param {object} options - Options.
61-
* @returns {SpawnSyncReturns} A ChildProcess instance of new process.
62-
* @private
63-
*/
64-
spawn.sync = crossSpawn.sync
65-
66-
module.exports = spawn

0 commit comments

Comments
 (0)
Please sign in to comment.