deno.land / x / deno@v1.28.2 / runtime / js / 40_spawn.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license."use strict";
((window) => { const core = window.Deno.core; const ops = core.ops; const { pathFromURL } = window.__bootstrap.util; const { illegalConstructorKey } = window.__bootstrap.webUtil; const { add, remove } = window.__bootstrap.abortSignal; const { ArrayPrototypeMap, ObjectEntries, String, TypeError, PromisePrototypeThen, SafePromiseAll, SymbolFor, } = window.__bootstrap.primordials; const { readableStreamCollectIntoUint8Array, readableStreamForRidUnrefable, readableStreamForRidUnrefableRef, readableStreamForRidUnrefableUnref, writableStreamForRid, } = window.__bootstrap.streams;
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
function spawnChildInner(opFn, command, apiName, { args = [], cwd = undefined, clearEnv = false, env = {}, uid = undefined, gid = undefined, stdin = "null", stdout = "piped", stderr = "piped", signal = undefined, windowsRawArguments = false, } = {}) { const child = opFn({ cmd: pathFromURL(command), args: ArrayPrototypeMap(args, String), cwd: pathFromURL(cwd), clearEnv, env: ObjectEntries(env), uid, gid, stdin, stdout, stderr, windowsRawArguments, }, apiName); return new Child(illegalConstructorKey, { ...child, signal, }); }
function createSpawnChild(opFn) { return function spawnChild(command, options = {}) { return spawnChildInner(opFn, command, "Deno.spawnChild()", options); }; }
function collectOutput(readableStream) { if (!(readableStream instanceof ReadableStream)) { return null; }
return readableStreamCollectIntoUint8Array(readableStream); }
class Child { #rid; #waitPromiseId; #unrefed = false;
#pid; get pid() { return this.#pid; }
#stdin = null; get stdin() { if (this.#stdin == null) { throw new TypeError("stdin is not piped"); } return this.#stdin; }
#stdoutPromiseId; #stdoutRid; #stdout = null; get stdout() { if (this.#stdout == null) { throw new TypeError("stdout is not piped"); } return this.#stdout; }
#stderrPromiseId; #stderrRid; #stderr = null; get stderr() { if (this.#stderr == null) { throw new TypeError("stderr is not piped"); } return this.#stderr; }
constructor(key = null, { signal, rid, pid, stdinRid, stdoutRid, stderrRid, } = null) { if (key !== illegalConstructorKey) { throw new TypeError("Illegal constructor."); }
this.#rid = rid; this.#pid = pid;
if (stdinRid !== null) { this.#stdin = writableStreamForRid(stdinRid); }
if (stdoutRid !== null) { this.#stdoutRid = stdoutRid; this.#stdout = readableStreamForRidUnrefable(stdoutRid); }
if (stderrRid !== null) { this.#stderrRid = stderrRid; this.#stderr = readableStreamForRidUnrefable(stderrRid); }
const onAbort = () => this.kill("SIGTERM"); signal?.[add](onAbort);
const waitPromise = core.opAsync("op_spawn_wait", this.#rid); this.#waitPromiseId = waitPromise[promiseIdSymbol]; this.#status = PromisePrototypeThen(waitPromise, (res) => { this.#rid = null; signal?.[remove](onAbort); return res; }); }
#status; get status() { return this.#status; }
async output() { if (this.#stdout?.locked) { throw new TypeError( "Can't collect output because stdout is locked", ); } if (this.#stderr?.locked) { throw new TypeError( "Can't collect output because stderr is locked", ); }
const [status, stdout, stderr] = await SafePromiseAll([ this.#status, collectOutput(this.#stdout), collectOutput(this.#stderr), ]);
return { success: status.success, code: status.code, signal: status.signal, get stdout() { if (stdout == null) { throw new TypeError("stdout is not piped"); } return stdout; }, get stderr() { if (stderr == null) { throw new TypeError("stderr is not piped"); } return stderr; }, }; }
kill(signo = "SIGTERM") { if (this.#rid === null) { throw new TypeError("Child process has already terminated."); } ops.op_kill(this.#pid, signo, "Deno.Child.kill()"); }
ref() { this.#unrefed = false; core.refOp(this.#waitPromiseId); if (this.#stdout) readableStreamForRidUnrefableRef(this.#stdout); if (this.#stderr) readableStreamForRidUnrefableRef(this.#stderr); }
unref() { this.#unrefed = true; core.unrefOp(this.#waitPromiseId); if (this.#stdout) readableStreamForRidUnrefableUnref(this.#stdout); if (this.#stderr) readableStreamForRidUnrefableUnref(this.#stderr); } }
function createSpawn(opFn) { return function spawn(command, options) { if (options?.stdin === "piped") { throw new TypeError( "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", ); } return spawnChildInner(opFn, command, "Deno.spawn()", options).output(); }; }
function createSpawnSync(opFn) { return function spawnSync(command, { args = [], cwd = undefined, clearEnv = false, env = {}, uid = undefined, gid = undefined, stdin = "null", stdout = "piped", stderr = "piped", windowsRawArguments = false, } = {}) { if (stdin === "piped") { throw new TypeError( "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", ); } const result = opFn({ cmd: pathFromURL(command), args: ArrayPrototypeMap(args, String), cwd: pathFromURL(cwd), clearEnv, env: ObjectEntries(env), uid, gid, stdin, stdout, stderr, windowsRawArguments, }); return { success: result.status.success, code: result.status.code, signal: result.status.signal, get stdout() { if (result.stdout == null) { throw new TypeError("stdout is not piped"); } return result.stdout; }, get stderr() { if (result.stderr == null) { throw new TypeError("stderr is not piped"); } return result.stderr; }, }; }; }
class Command { #command; #options;
#child;
#consumed;
constructor(command, options) { this.#command = command; this.#options = options; }
output() { if (this.#child) { return this.#child.output(); } else { if (this.#consumed) { throw new TypeError( "Command instance is being or has already been consumed.", ); } if (this.#options?.stdin === "piped") { throw new TypeError( "Piped stdin is not supported for this function, use 'Deno.Command.spawn()' instead", ); }
this.#consumed = true; return Deno.spawn(this.#command, this.#options); } }
outputSync() { if (this.#consumed) { throw new TypeError( "Command instance is being or has already been consumed.", ); } if (this.#child) { throw new TypeError("Was spawned"); } if (this.#options?.stdin === "piped") { throw new TypeError( "Piped stdin is not supported for this function, use 'Deno.Command.spawn()' instead", ); }
this.#consumed = true; return Deno.spawnSync(this.#command, this.#options); }
spawn() { if (this.#consumed) { throw new TypeError( "Command instance is being or has already been consumed.", ); }
this.#consumed = true; this.#child = Deno.spawnChild(this.#command, this.#options); }
get stdin() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
return this.#child.stdin; }
get stdout() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
return this.#child.stdout; }
get stderr() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
return this.#child.stderr; }
get status() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
return this.#child.status; }
get pid() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
return this.#child.pid; }
kill(signo = "SIGTERM") { if (!this.#child) { throw new TypeError("Wasn't spawned"); } this.#child.kill(signo); }
ref() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
this.#child.ref(); }
unref() { if (!this.#child) { throw new TypeError("Wasn't spawned"); }
this.#child.unref(); } }
window.__bootstrap.spawn = { Child, Command, createSpawn, createSpawnChild, createSpawnSync, };})(this);
Version Info