加入了node_modules
添加了新的功能项
This commit is contained in:
15
node_modules/execa/lib/convert/add.js
generated
vendored
Normal file
15
node_modules/execa/lib/convert/add.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import {initializeConcurrentStreams} from './concurrent.js';
|
||||
import {createReadable} from './readable.js';
|
||||
import {createWritable} from './writable.js';
|
||||
import {createDuplex} from './duplex.js';
|
||||
import {createIterable} from './iterable.js';
|
||||
|
||||
// Add methods to convert the subprocess to a stream or iterable
|
||||
export const addConvertedStreams = (subprocess, {encoding}) => {
|
||||
const concurrentStreams = initializeConcurrentStreams();
|
||||
subprocess.readable = createReadable.bind(undefined, {subprocess, concurrentStreams, encoding});
|
||||
subprocess.writable = createWritable.bind(undefined, {subprocess, concurrentStreams});
|
||||
subprocess.duplex = createDuplex.bind(undefined, {subprocess, concurrentStreams, encoding});
|
||||
subprocess.iterable = createIterable.bind(undefined, subprocess, encoding);
|
||||
subprocess[Symbol.asyncIterator] = createIterable.bind(undefined, subprocess, encoding, {});
|
||||
};
|
||||
33
node_modules/execa/lib/convert/concurrent.js
generated
vendored
Normal file
33
node_modules/execa/lib/convert/concurrent.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import {createDeferred} from '../utils/deferred.js';
|
||||
|
||||
// When using multiple `.readable()`/`.writable()`/`.duplex()`, `final` and `destroy` should wait for other streams
|
||||
export const initializeConcurrentStreams = () => ({
|
||||
readableDestroy: new WeakMap(),
|
||||
writableFinal: new WeakMap(),
|
||||
writableDestroy: new WeakMap(),
|
||||
});
|
||||
|
||||
// Each file descriptor + `waitName` has its own array of promises.
|
||||
// Each promise is a single `.readable()`/`.writable()`/`.duplex()` call.
|
||||
export const addConcurrentStream = (concurrentStreams, stream, waitName) => {
|
||||
const weakMap = concurrentStreams[waitName];
|
||||
if (!weakMap.has(stream)) {
|
||||
weakMap.set(stream, []);
|
||||
}
|
||||
|
||||
const promises = weakMap.get(stream);
|
||||
const promise = createDeferred();
|
||||
promises.push(promise);
|
||||
const resolve = promise.resolve.bind(promise);
|
||||
return {resolve, promises};
|
||||
};
|
||||
|
||||
// Wait for other streams, but stop waiting when subprocess ends
|
||||
export const waitForConcurrentStreams = async ({resolve, promises}, subprocess) => {
|
||||
resolve();
|
||||
const [isSubprocessExit] = await Promise.race([
|
||||
Promise.allSettled([true, subprocess]),
|
||||
Promise.all([false, ...promises]),
|
||||
]);
|
||||
return !isSubprocessExit;
|
||||
};
|
||||
69
node_modules/execa/lib/convert/duplex.js
generated
vendored
Normal file
69
node_modules/execa/lib/convert/duplex.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
import {Duplex} from 'node:stream';
|
||||
import {callbackify} from 'node:util';
|
||||
import {BINARY_ENCODINGS} from '../arguments/encoding-option.js';
|
||||
import {
|
||||
getSubprocessStdout,
|
||||
getReadableOptions,
|
||||
getReadableMethods,
|
||||
onStdoutFinished,
|
||||
onReadableDestroy,
|
||||
} from './readable.js';
|
||||
import {
|
||||
getSubprocessStdin,
|
||||
getWritableMethods,
|
||||
onStdinFinished,
|
||||
onWritableDestroy,
|
||||
} from './writable.js';
|
||||
|
||||
// Create a `Duplex` stream combining both `subprocess.readable()` and `subprocess.writable()`
|
||||
export const createDuplex = ({subprocess, concurrentStreams, encoding}, {from, to, binary: binaryOption = true, preserveNewlines = true} = {}) => {
|
||||
const binary = binaryOption || BINARY_ENCODINGS.has(encoding);
|
||||
const {subprocessStdout, waitReadableDestroy} = getSubprocessStdout(subprocess, from, concurrentStreams);
|
||||
const {subprocessStdin, waitWritableFinal, waitWritableDestroy} = getSubprocessStdin(subprocess, to, concurrentStreams);
|
||||
const {readableEncoding, readableObjectMode, readableHighWaterMark} = getReadableOptions(subprocessStdout, binary);
|
||||
const {read, onStdoutDataDone} = getReadableMethods({
|
||||
subprocessStdout,
|
||||
subprocess,
|
||||
binary,
|
||||
encoding,
|
||||
preserveNewlines,
|
||||
});
|
||||
const duplex = new Duplex({
|
||||
read,
|
||||
...getWritableMethods(subprocessStdin, subprocess, waitWritableFinal),
|
||||
destroy: callbackify(onDuplexDestroy.bind(undefined, {
|
||||
subprocessStdout,
|
||||
subprocessStdin,
|
||||
subprocess,
|
||||
waitReadableDestroy,
|
||||
waitWritableFinal,
|
||||
waitWritableDestroy,
|
||||
})),
|
||||
readableHighWaterMark,
|
||||
writableHighWaterMark: subprocessStdin.writableHighWaterMark,
|
||||
readableObjectMode,
|
||||
writableObjectMode: subprocessStdin.writableObjectMode,
|
||||
encoding: readableEncoding,
|
||||
});
|
||||
onStdoutFinished({
|
||||
subprocessStdout,
|
||||
onStdoutDataDone,
|
||||
readable: duplex,
|
||||
subprocess,
|
||||
subprocessStdin,
|
||||
});
|
||||
onStdinFinished(subprocessStdin, duplex, subprocessStdout);
|
||||
return duplex;
|
||||
};
|
||||
|
||||
const onDuplexDestroy = async ({subprocessStdout, subprocessStdin, subprocess, waitReadableDestroy, waitWritableFinal, waitWritableDestroy}, error) => {
|
||||
await Promise.all([
|
||||
onReadableDestroy({subprocessStdout, subprocess, waitReadableDestroy}, error),
|
||||
onWritableDestroy({
|
||||
subprocessStdin,
|
||||
subprocess,
|
||||
waitWritableFinal,
|
||||
waitWritableDestroy,
|
||||
}, error),
|
||||
]);
|
||||
};
|
||||
34
node_modules/execa/lib/convert/iterable.js
generated
vendored
Normal file
34
node_modules/execa/lib/convert/iterable.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import {BINARY_ENCODINGS} from '../arguments/encoding-option.js';
|
||||
import {getFromStream} from '../arguments/fd-options.js';
|
||||
import {iterateOnSubprocessStream} from '../io/iterate.js';
|
||||
|
||||
// Convert the subprocess to an async iterable
|
||||
export const createIterable = (subprocess, encoding, {
|
||||
from,
|
||||
binary: binaryOption = false,
|
||||
preserveNewlines = false,
|
||||
} = {}) => {
|
||||
const binary = binaryOption || BINARY_ENCODINGS.has(encoding);
|
||||
const subprocessStdout = getFromStream(subprocess, from);
|
||||
const onStdoutData = iterateOnSubprocessStream({
|
||||
subprocessStdout,
|
||||
subprocess,
|
||||
binary,
|
||||
shouldEncode: true,
|
||||
encoding,
|
||||
preserveNewlines,
|
||||
});
|
||||
return iterateOnStdoutData(onStdoutData, subprocessStdout, subprocess);
|
||||
};
|
||||
|
||||
const iterateOnStdoutData = async function * (onStdoutData, subprocessStdout, subprocess) {
|
||||
try {
|
||||
yield * onStdoutData;
|
||||
} finally {
|
||||
if (subprocessStdout.readable) {
|
||||
subprocessStdout.destroy();
|
||||
}
|
||||
|
||||
await subprocess;
|
||||
}
|
||||
};
|
||||
113
node_modules/execa/lib/convert/readable.js
generated
vendored
Normal file
113
node_modules/execa/lib/convert/readable.js
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
import {Readable} from 'node:stream';
|
||||
import {callbackify} from 'node:util';
|
||||
import {BINARY_ENCODINGS} from '../arguments/encoding-option.js';
|
||||
import {getFromStream} from '../arguments/fd-options.js';
|
||||
import {iterateOnSubprocessStream, DEFAULT_OBJECT_HIGH_WATER_MARK} from '../io/iterate.js';
|
||||
import {createDeferred} from '../utils/deferred.js';
|
||||
import {addConcurrentStream, waitForConcurrentStreams} from './concurrent.js';
|
||||
import {
|
||||
safeWaitForSubprocessStdin,
|
||||
waitForSubprocessStdout,
|
||||
waitForSubprocess,
|
||||
destroyOtherStream,
|
||||
} from './shared.js';
|
||||
|
||||
// Create a `Readable` stream that forwards from `stdout` and awaits the subprocess
|
||||
export const createReadable = ({subprocess, concurrentStreams, encoding}, {from, binary: binaryOption = true, preserveNewlines = true} = {}) => {
|
||||
const binary = binaryOption || BINARY_ENCODINGS.has(encoding);
|
||||
const {subprocessStdout, waitReadableDestroy} = getSubprocessStdout(subprocess, from, concurrentStreams);
|
||||
const {readableEncoding, readableObjectMode, readableHighWaterMark} = getReadableOptions(subprocessStdout, binary);
|
||||
const {read, onStdoutDataDone} = getReadableMethods({
|
||||
subprocessStdout,
|
||||
subprocess,
|
||||
binary,
|
||||
encoding,
|
||||
preserveNewlines,
|
||||
});
|
||||
const readable = new Readable({
|
||||
read,
|
||||
destroy: callbackify(onReadableDestroy.bind(undefined, {subprocessStdout, subprocess, waitReadableDestroy})),
|
||||
highWaterMark: readableHighWaterMark,
|
||||
objectMode: readableObjectMode,
|
||||
encoding: readableEncoding,
|
||||
});
|
||||
onStdoutFinished({
|
||||
subprocessStdout,
|
||||
onStdoutDataDone,
|
||||
readable,
|
||||
subprocess,
|
||||
});
|
||||
return readable;
|
||||
};
|
||||
|
||||
// Retrieve `stdout` (or other stream depending on `from`)
|
||||
export const getSubprocessStdout = (subprocess, from, concurrentStreams) => {
|
||||
const subprocessStdout = getFromStream(subprocess, from);
|
||||
const waitReadableDestroy = addConcurrentStream(concurrentStreams, subprocessStdout, 'readableDestroy');
|
||||
return {subprocessStdout, waitReadableDestroy};
|
||||
};
|
||||
|
||||
export const getReadableOptions = ({readableEncoding, readableObjectMode, readableHighWaterMark}, binary) => binary
|
||||
? {readableEncoding, readableObjectMode, readableHighWaterMark}
|
||||
: {readableEncoding, readableObjectMode: true, readableHighWaterMark: DEFAULT_OBJECT_HIGH_WATER_MARK};
|
||||
|
||||
export const getReadableMethods = ({subprocessStdout, subprocess, binary, encoding, preserveNewlines}) => {
|
||||
const onStdoutDataDone = createDeferred();
|
||||
const onStdoutData = iterateOnSubprocessStream({
|
||||
subprocessStdout,
|
||||
subprocess,
|
||||
binary,
|
||||
shouldEncode: !binary,
|
||||
encoding,
|
||||
preserveNewlines,
|
||||
});
|
||||
|
||||
return {
|
||||
read() {
|
||||
onRead(this, onStdoutData, onStdoutDataDone);
|
||||
},
|
||||
onStdoutDataDone,
|
||||
};
|
||||
};
|
||||
|
||||
// Forwards data from `stdout` to `readable`
|
||||
const onRead = async (readable, onStdoutData, onStdoutDataDone) => {
|
||||
try {
|
||||
const {value, done} = await onStdoutData.next();
|
||||
if (done) {
|
||||
onStdoutDataDone.resolve();
|
||||
} else {
|
||||
readable.push(value);
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
|
||||
// When `subprocess.stdout` ends/aborts/errors, do the same on `readable`.
|
||||
// Await the subprocess, for the same reason as above.
|
||||
export const onStdoutFinished = async ({subprocessStdout, onStdoutDataDone, readable, subprocess, subprocessStdin}) => {
|
||||
try {
|
||||
await waitForSubprocessStdout(subprocessStdout);
|
||||
await subprocess;
|
||||
await safeWaitForSubprocessStdin(subprocessStdin);
|
||||
await onStdoutDataDone;
|
||||
|
||||
if (readable.readable) {
|
||||
readable.push(null);
|
||||
}
|
||||
} catch (error) {
|
||||
await safeWaitForSubprocessStdin(subprocessStdin);
|
||||
destroyOtherReadable(readable, error);
|
||||
}
|
||||
};
|
||||
|
||||
// When `readable` aborts/errors, do the same on `subprocess.stdout`
|
||||
export const onReadableDestroy = async ({subprocessStdout, subprocess, waitReadableDestroy}, error) => {
|
||||
if (await waitForConcurrentStreams(waitReadableDestroy, subprocess)) {
|
||||
destroyOtherReadable(subprocessStdout, error);
|
||||
await waitForSubprocess(subprocess, error);
|
||||
}
|
||||
};
|
||||
|
||||
const destroyOtherReadable = (stream, error) => {
|
||||
destroyOtherStream(stream, stream.readable, error);
|
||||
};
|
||||
46
node_modules/execa/lib/convert/shared.js
generated
vendored
Normal file
46
node_modules/execa/lib/convert/shared.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import {finished} from 'node:stream/promises';
|
||||
import {isStreamAbort} from '../resolve/wait-stream.js';
|
||||
|
||||
export const safeWaitForSubprocessStdin = async subprocessStdin => {
|
||||
if (subprocessStdin === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await waitForSubprocessStdin(subprocessStdin);
|
||||
} catch {}
|
||||
};
|
||||
|
||||
export const safeWaitForSubprocessStdout = async subprocessStdout => {
|
||||
if (subprocessStdout === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await waitForSubprocessStdout(subprocessStdout);
|
||||
} catch {}
|
||||
};
|
||||
|
||||
export const waitForSubprocessStdin = async subprocessStdin => {
|
||||
await finished(subprocessStdin, {cleanup: true, readable: false, writable: true});
|
||||
};
|
||||
|
||||
export const waitForSubprocessStdout = async subprocessStdout => {
|
||||
await finished(subprocessStdout, {cleanup: true, readable: true, writable: false});
|
||||
};
|
||||
|
||||
// When `readable` or `writable` aborts/errors, awaits the subprocess, for the reason mentioned above
|
||||
export const waitForSubprocess = async (subprocess, error) => {
|
||||
await subprocess;
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const destroyOtherStream = (stream, isOpen, error) => {
|
||||
if (error && !isStreamAbort(error)) {
|
||||
stream.destroy(error);
|
||||
} else if (isOpen) {
|
||||
stream.destroy();
|
||||
}
|
||||
};
|
||||
90
node_modules/execa/lib/convert/writable.js
generated
vendored
Normal file
90
node_modules/execa/lib/convert/writable.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import {Writable} from 'node:stream';
|
||||
import {callbackify} from 'node:util';
|
||||
import {getToStream} from '../arguments/fd-options.js';
|
||||
import {addConcurrentStream, waitForConcurrentStreams} from './concurrent.js';
|
||||
import {
|
||||
safeWaitForSubprocessStdout,
|
||||
waitForSubprocessStdin,
|
||||
waitForSubprocess,
|
||||
destroyOtherStream,
|
||||
} from './shared.js';
|
||||
|
||||
// Create a `Writable` stream that forwards to `stdin` and awaits the subprocess
|
||||
export const createWritable = ({subprocess, concurrentStreams}, {to} = {}) => {
|
||||
const {subprocessStdin, waitWritableFinal, waitWritableDestroy} = getSubprocessStdin(subprocess, to, concurrentStreams);
|
||||
const writable = new Writable({
|
||||
...getWritableMethods(subprocessStdin, subprocess, waitWritableFinal),
|
||||
destroy: callbackify(onWritableDestroy.bind(undefined, {
|
||||
subprocessStdin,
|
||||
subprocess,
|
||||
waitWritableFinal,
|
||||
waitWritableDestroy,
|
||||
})),
|
||||
highWaterMark: subprocessStdin.writableHighWaterMark,
|
||||
objectMode: subprocessStdin.writableObjectMode,
|
||||
});
|
||||
onStdinFinished(subprocessStdin, writable);
|
||||
return writable;
|
||||
};
|
||||
|
||||
// Retrieve `stdin` (or other stream depending on `to`)
|
||||
export const getSubprocessStdin = (subprocess, to, concurrentStreams) => {
|
||||
const subprocessStdin = getToStream(subprocess, to);
|
||||
const waitWritableFinal = addConcurrentStream(concurrentStreams, subprocessStdin, 'writableFinal');
|
||||
const waitWritableDestroy = addConcurrentStream(concurrentStreams, subprocessStdin, 'writableDestroy');
|
||||
return {subprocessStdin, waitWritableFinal, waitWritableDestroy};
|
||||
};
|
||||
|
||||
export const getWritableMethods = (subprocessStdin, subprocess, waitWritableFinal) => ({
|
||||
write: onWrite.bind(undefined, subprocessStdin),
|
||||
final: callbackify(onWritableFinal.bind(undefined, subprocessStdin, subprocess, waitWritableFinal)),
|
||||
});
|
||||
|
||||
// Forwards data from `writable` to `stdin`
|
||||
const onWrite = (subprocessStdin, chunk, encoding, done) => {
|
||||
if (subprocessStdin.write(chunk, encoding)) {
|
||||
done();
|
||||
} else {
|
||||
subprocessStdin.once('drain', done);
|
||||
}
|
||||
};
|
||||
|
||||
// Ensures that the writable `final` and readable `end` events awaits the subprocess.
|
||||
// Like this, any subprocess failure is propagated as a stream `error` event, instead of being lost.
|
||||
// The user does not need to `await` the subprocess anymore, but now needs to await the stream completion or error.
|
||||
// When multiple writables are targeting the same stream, they wait for each other, unless the subprocess ends first.
|
||||
const onWritableFinal = async (subprocessStdin, subprocess, waitWritableFinal) => {
|
||||
if (await waitForConcurrentStreams(waitWritableFinal, subprocess)) {
|
||||
if (subprocessStdin.writable) {
|
||||
subprocessStdin.end();
|
||||
}
|
||||
|
||||
await subprocess;
|
||||
}
|
||||
};
|
||||
|
||||
// When `subprocess.stdin` ends/aborts/errors, do the same on `writable`.
|
||||
export const onStdinFinished = async (subprocessStdin, writable, subprocessStdout) => {
|
||||
try {
|
||||
await waitForSubprocessStdin(subprocessStdin);
|
||||
if (writable.writable) {
|
||||
writable.end();
|
||||
}
|
||||
} catch (error) {
|
||||
await safeWaitForSubprocessStdout(subprocessStdout);
|
||||
destroyOtherWritable(writable, error);
|
||||
}
|
||||
};
|
||||
|
||||
// When `writable` aborts/errors, do the same on `subprocess.stdin`
|
||||
export const onWritableDestroy = async ({subprocessStdin, subprocess, waitWritableFinal, waitWritableDestroy}, error) => {
|
||||
await waitForConcurrentStreams(waitWritableFinal, subprocess);
|
||||
if (await waitForConcurrentStreams(waitWritableDestroy, subprocess)) {
|
||||
destroyOtherWritable(subprocessStdin, error);
|
||||
await waitForSubprocess(subprocess, error);
|
||||
}
|
||||
};
|
||||
|
||||
const destroyOtherWritable = (stream, error) => {
|
||||
destroyOtherStream(stream, stream.writable, error);
|
||||
};
|
||||
Reference in New Issue
Block a user