Skip to content

Commit 16e5fd6

Browse files
authored
Remove .cancel() method (#711)
1 parent 472c065 commit 16e5fd6

File tree

6 files changed

+43
-112
lines changed

6 files changed

+43
-112
lines changed

index.d.ts

+1-8
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,7 @@ type ExecaCommonReturnValue<IsSync extends boolean = boolean, OptionsType extend
670670
cwd: string;
671671

672672
/**
673-
Whether the process was canceled.
674-
675-
You can cancel the spawned process using the [`signal`](https://github.com/sindresorhus/execa#signal-1) option.
673+
Whether the process was canceled using the [`signal`](https://github.com/sindresorhus/execa#signal-1) option.
676674
*/
677675
isCanceled: boolean;
678676

@@ -783,11 +781,6 @@ export type ExecaChildPromise<OptionsType extends Options = Options> = {
783781
*/
784782
kill(signal?: string, options?: KillOptions): void;
785783

786-
/**
787-
Similar to [`childProcess.kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal). This used to be preferred when cancelling the child process execution as the error is more descriptive and [`childProcessResult.isCanceled`](#iscanceled) is set to `true`. But now this is deprecated and you should either use `.kill()` or the `signal` option when creating the child process.
788-
*/
789-
cancel(): void;
790-
791784
/**
792785
[Pipe](https://nodejs.org/api/stream.html#readablepipedestination-options) the child process's `stdout` to `target`, which can be:
793786
- Another `execa()` return value

index.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {makeError} from './lib/error.js';
1010
import {handleInputAsync, pipeOutputAsync} from './lib/stdio/async.js';
1111
import {handleInputSync, pipeOutputSync} from './lib/stdio/sync.js';
1212
import {normalizeStdioNode} from './lib/stdio/normalize.js';
13-
import {spawnedKill, spawnedCancel, validateTimeout} from './lib/kill.js';
13+
import {spawnedKill, validateTimeout} from './lib/kill.js';
1414
import {addPipeMethods} from './lib/pipe.js';
1515
import {getSpawnedResult, makeAllStream} from './lib/stream.js';
1616
import {mergePromise} from './lib/promise.js';
@@ -142,20 +142,19 @@ export function execa(rawFile, rawArgs, rawOptions) {
142142

143143
pipeOutputAsync(spawned, stdioStreamsGroups);
144144

145-
const context = {isCanceled: false, timedOut: false};
146-
147145
spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned));
148-
spawned.cancel = spawnedCancel.bind(null, spawned, context);
149146
spawned.all = makeAllStream(spawned, options);
150147

151148
addPipeMethods(spawned);
152149

153-
const promise = handlePromise({spawned, options, context, stdioStreamsGroups, command, escapedCommand});
150+
const promise = handlePromise({spawned, options, stdioStreamsGroups, command, escapedCommand});
154151
mergePromise(spawned, promise);
155152
return spawned;
156153
}
157154

158-
const handlePromise = async ({spawned, options, context, stdioStreamsGroups, command, escapedCommand}) => {
155+
const handlePromise = async ({spawned, options, stdioStreamsGroups, command, escapedCommand}) => {
156+
const context = {timedOut: false};
157+
159158
const [
160159
[exitCode, signal, error],
161160
stdioResults,
@@ -165,7 +164,7 @@ const handlePromise = async ({spawned, options, context, stdioStreamsGroups, com
165164
const all = handleOutput(options, allResult);
166165

167166
if (error || exitCode !== 0 || signal !== null) {
168-
const isCanceled = context.isCanceled || Boolean(options.signal?.aborted);
167+
const isCanceled = options.signal?.aborted === true;
169168
const returnedError = makeError({
170169
error,
171170
exitCode,

index.test-d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ const syncGenerator = function * (lines: Iterable<string>) {
7676

7777
try {
7878
const execaPromise = execa('unicorns', {all: true});
79-
execaPromise.cancel();
8079

8180
const execaBufferPromise = execa('unicorns', {encoding: 'buffer', all: true});
8281
const writeStream = createWriteStream('output.txt');

lib/kill.js

-9
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,6 @@ const getForceKillAfterTimeout = (signal, forceKillAfterTimeout, killResult) =>
4242
return forceKillAfterTimeout;
4343
};
4444

45-
// `childProcess.cancel()`
46-
export const spawnedCancel = (spawned, context) => {
47-
const killResult = spawned.kill();
48-
49-
if (killResult) {
50-
context.isCanceled = true;
51-
}
52-
};
53-
5445
const killAfterTimeout = async ({spawned, timeout, killSignal, context, controller}) => {
5546
await pSetTimeout(timeout, undefined, {ref: false, signal: controller.signal});
5647
spawned.kill(killSignal);

readme.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,7 @@ Whether the process timed out.
461461

462462
Type: `boolean`
463463

464-
Whether the process was canceled.
465-
466-
You can cancel the spawned process using the [`signal`](#signal-1) option.
464+
Whether the process was canceled using the [`signal`](#signal-1) option.
467465

468466
#### isTerminated
469467

test/kill.js

+35-84
Original file line numberDiff line numberDiff line change
@@ -182,122 +182,73 @@ test('removes exit handler on exit', async t => {
182182
t.false(exitListeners.includes(listener));
183183
});
184184

185-
test('cancel method kills the subprocess', async t => {
186-
const subprocess = execa('node');
187-
subprocess.cancel();
188-
t.true(subprocess.killed);
189-
const {isTerminated} = await t.throwsAsync(subprocess);
190-
t.true(isTerminated);
191-
});
192-
193-
test('result.isCanceled is false when spawned.cancel() isn\'t called (success)', async t => {
185+
test('result.isCanceled is false when abort isn\'t called (success)', async t => {
194186
const {isCanceled} = await execa('noop.js');
195187
t.false(isCanceled);
196188
});
197189

198-
test('result.isCanceled is false when spawned.cancel() isn\'t called (failure)', async t => {
190+
test('result.isCanceled is false when abort isn\'t called (failure)', async t => {
199191
const {isCanceled} = await t.throwsAsync(execa('fail.js'));
200192
t.false(isCanceled);
201193
});
202194

203-
test('result.isCanceled is false when spawned.cancel() isn\'t called in sync mode (success)', t => {
195+
test('result.isCanceled is false when abort isn\'t called in sync mode (success)', t => {
204196
const {isCanceled} = execaSync('noop.js');
205197
t.false(isCanceled);
206198
});
207199

208-
test('result.isCanceled is false when spawned.cancel() isn\'t called in sync mode (failure)', t => {
200+
test('result.isCanceled is false when abort isn\'t called in sync mode (failure)', t => {
209201
const {isCanceled} = t.throws(() => {
210202
execaSync('fail.js');
211203
});
212204
t.false(isCanceled);
213205
});
214206

215-
test('calling cancel method throws an error with message "Command was canceled"', async t => {
216-
const subprocess = execa('noop.js');
217-
subprocess.cancel();
218-
await t.throwsAsync(subprocess, {message: /Command was canceled/});
207+
test('calling abort is not considered a signal termination', async t => {
208+
const abortController = new AbortController();
209+
const subprocess = execa('noop.js', {signal: abortController.signal});
210+
abortController.abort();
211+
const {isTerminated, signal} = await t.throwsAsync(subprocess);
212+
t.false(isTerminated);
213+
t.is(signal, undefined);
219214
});
220215

221-
test('error.isCanceled is true when cancel method is used', async t => {
222-
const subprocess = execa('noop.js');
223-
subprocess.cancel();
216+
test('error.isCanceled is true when abort is used', async t => {
217+
const abortController = new AbortController();
218+
const subprocess = execa('noop.js', {signal: abortController.signal});
219+
abortController.abort();
224220
const {isCanceled} = await t.throwsAsync(subprocess);
225221
t.true(isCanceled);
226222
});
227223

228224
test('error.isCanceled is false when kill method is used', async t => {
229-
const subprocess = execa('noop.js');
225+
const abortController = new AbortController();
226+
const subprocess = execa('noop.js', {signal: abortController.signal});
230227
subprocess.kill();
231228
const {isCanceled} = await t.throwsAsync(subprocess);
232229
t.false(isCanceled);
233230
});
234231

235-
test('calling cancel method twice should show the same behaviour as calling it once', async t => {
236-
const subprocess = execa('noop.js');
237-
subprocess.cancel();
238-
subprocess.cancel();
239-
const {isCanceled} = await t.throwsAsync(subprocess);
240-
t.true(isCanceled);
241-
t.true(subprocess.killed);
242-
});
243-
244-
test('calling cancel method on a successfully completed process does not make result.isCanceled true', async t => {
245-
const subprocess = execa('noop.js');
246-
const {isCanceled} = await subprocess;
247-
subprocess.cancel();
248-
t.false(isCanceled);
232+
test('calling abort throws an error with message "Command was canceled"', async t => {
233+
const abortController = new AbortController();
234+
const subprocess = execa('noop.js', {signal: abortController.signal});
235+
abortController.abort();
236+
await t.throwsAsync(subprocess, {message: /Command was canceled/});
249237
});
250238

251-
test('calling cancel method on a process which has been killed does not make error.isCanceled true', async t => {
252-
const subprocess = execa('noop.js');
253-
subprocess.kill();
239+
test('calling abort twice should show the same behaviour as calling it once', async t => {
240+
const abortController = new AbortController();
241+
const subprocess = execa('noop.js', {signal: abortController.signal});
242+
abortController.abort();
243+
abortController.abort();
254244
const {isCanceled} = await t.throwsAsync(subprocess);
255-
t.false(isCanceled);
245+
t.true(isCanceled);
256246
});
257247

258-
if (globalThis.AbortController !== undefined) {
259-
test('calling abort throws an error with message "Command was canceled"', async t => {
260-
const abortController = new AbortController();
261-
const subprocess = execa('noop.js', [], {signal: abortController.signal});
262-
abortController.abort();
263-
await t.throwsAsync(subprocess, {message: /Command was canceled/});
264-
});
265-
266-
test('calling abort twice should show the same behaviour as calling it once', async t => {
267-
const abortController = new AbortController();
268-
const subprocess = execa('noop.js', [], {signal: abortController.signal});
269-
abortController.abort();
270-
abortController.abort();
271-
const {isCanceled} = await t.throwsAsync(subprocess);
272-
t.true(isCanceled);
273-
t.true(subprocess.killed);
274-
});
275-
276-
test('calling abort on a successfully completed process does not make result.isCanceled true', async t => {
277-
const abortController = new AbortController();
278-
const subprocess = execa('noop.js', [], {signal: abortController.signal});
279-
const {isCanceled} = await subprocess;
280-
abortController.abort();
281-
t.false(isCanceled);
282-
});
283-
284-
test('calling cancel after abort should show the same behaviour as only calling cancel', async t => {
285-
const abortController = new AbortController();
286-
const subprocess = execa('noop.js', [], {signal: abortController.signal});
287-
abortController.abort();
288-
subprocess.cancel();
289-
const {isCanceled} = await t.throwsAsync(subprocess);
290-
t.true(isCanceled);
291-
t.true(subprocess.killed);
292-
});
293-
294-
test('calling abort after cancel should show the same behaviour as only calling cancel', async t => {
295-
const abortController = new AbortController();
296-
const subprocess = execa('noop.js', [], {signal: abortController.signal});
297-
subprocess.cancel();
298-
abortController.abort();
299-
const {isCanceled} = await t.throwsAsync(subprocess);
300-
t.true(isCanceled);
301-
t.true(subprocess.killed);
302-
});
303-
}
248+
test('calling abort on a successfully completed process does not make result.isCanceled true', async t => {
249+
const abortController = new AbortController();
250+
const subprocess = execa('noop.js', {signal: abortController.signal});
251+
const result = await subprocess;
252+
abortController.abort();
253+
t.false(result.isCanceled);
254+
});

0 commit comments

Comments
 (0)