Socket
Socket
Sign inDemoInstall

@tracerbench/spawn

Package Overview
Dependencies
4
Maintainers
3
Versions
13
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.2 to 1.0.3

dist/execa.d.ts

2

dist/newProcess.d.ts
import * as t from "../types";
export default function newProcess(child: import("execa").ExecaChildProcess): t.Process;
export default function newProcess(child: import("execa").ExecaChildProcess, command: string, debugCallback: (formatter: any, ...args: any[]) => void): t.Process;
//# sourceMappingURL=newProcess.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const debug = require("debug");
const events_1 = require("events");
const race_cancellation_1 = require("race-cancellation");
const debugCallback = debug("@tracerbench/spawn");
function newProcess(child) {
function newProcess(child, command, debugCallback) {
let hasExited = false;

@@ -14,8 +12,8 @@ let lastError;

lastError = error;
debugCallback("child process error %O", error);
onExit(error);
debugCallback("%o (pid: %o) 'error' event: %O", command, child.pid, error);
onErrorOrExit(error);
});
child.on("exit", () => {
debugCallback("child process exit");
onExit();
debugCallback("%o (pid: %o) 'exit' event", command, child.pid);
onErrorOrExit();
});

@@ -34,3 +32,9 @@ return {

};
function onExit(error) {
/*
https://nodejs.org/api/child_process.html#child_process_event_exit
The 'exit' event may or may not fire after an error has occurred.
When listening to both the 'exit' and 'error' events, it is important to guard against accidentally invoking handler functions multiple times.
*/
function onErrorOrExit(error) {
if (hasExited) {

@@ -74,15 +78,8 @@ return;

async function kill(timeout, raceCancellation) {
if (hasExited) {
return;
if (!child.killed && child.pid) {
child.kill();
}
if (child.killed || !child.pid) {
return;
}
child.kill();
await waitForExit(timeout, raceCancellation);
}
async function dispose() {
if (hasExited) {
return;
}
try {

@@ -95,3 +92,3 @@ await kill();

// just output for debugging
debugCallback("dispose error %O", e);
debugCallback("%o (pid: %o) dispose error: %O", command, child.pid, e);
}

@@ -98,0 +95,0 @@ }

@@ -1,3 +0,3 @@

import { ProcessWithPipeMessageTransport } from "../types";
export default function newProcessWithPipeMessageTransport(child: import("execa").ExecaChildProcess): ProcessWithPipeMessageTransport;
import { ProcessWithPipeMessageTransport, Stdio } from "../types";
export default function newProcessWithPipeMessageTransport(command: string, args: string[], stdio: Stdio, debugCallback: (formatter: any, ...args: any[]) => void): ProcessWithPipeMessageTransport;
//# sourceMappingURL=newProcessWithPipeMessageTransport.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const debug = require("debug");
const execa_1 = require("./execa");
const newPipeMessageTransport_1 = require("./newPipeMessageTransport");
const newProcess_1 = require("./newProcess");
const debugCallback = debug("@tracerbench/spawn");
function newProcessWithPipeMessageTransport(child) {
const process = newProcess_1.default(child);
const [, , , writeStream, readStream] = streamsForPipe(child);
return Object.assign(process, {
attach: newPipeMessageTransport_1.default((onRead, onReadEnd, onClose) => {
child.on("error", onClose);
child.on("exit", onClose);
readStream.on("data", onRead);
readStream.on("end", () => {
debugCallback("read pipe end");
onReadEnd();
});
readStream.on("error", error => {
debugCallback("read pipe error %O", error);
});
writeStream.on("close", () => {
debugCallback("write pipe close");
onClose();
});
writeStream.on("error", (error) => {
debugCallback("write pipe error %O", error);
// writes while the other side is closing can cause EPIPE
// just wait for close to actually happen and ignore it.
if (error && "code" in error && error.code === "EPIPE") {
return;
}
onClose(error);
});
return [data => writeStream.write(data), () => writeStream.end()];
}),
function newProcessWithPipeMessageTransport(command, args, stdio, debugCallback) {
const child = execa_1.default(command, args, {
// disable buffer, pipe or drain
buffer: false,
stdio: [stdio, stdio, stdio, "pipe", "pipe"],
}, debugCallback);
const process = newProcess_1.default(child, command, debugCallback);
const [, , , writeStream, readStream] = child.stdio;
const attach = newPipeMessageTransport_1.default((onRead, onReadEnd, onClose) => {
child.on("error", onClose);
child.on("exit", onClose);
readStream.on("data", handleReadData);
readStream.on("end", handleReadEnd);
readStream.on("error", handleReadError);
writeStream.on("close", handleWriteClose);
writeStream.on("error", handleWriteError);
return [data => writeStream.write(data), () => writeStream.end()];
function handleReadData(buffer) {
debugEvent("read", "data", buffer.byteLength);
onRead(buffer);
}
function handleReadEnd() {
debugEvent("read", "end");
onReadEnd();
}
function handleReadError(error) {
debugEvent("read", "error", error);
}
function handleWriteError(error) {
debugEvent("write", "error", error);
// writes while the other side is closing can cause EPIPE
// just wait for close to actually happen and ignore it.
if (error && "code" in error && error.code === "EPIPE") {
return;
}
onClose(error);
}
function handleWriteClose() {
debugEvent("write", "close");
onClose();
}
function debugEvent(pipe, event, arg) {
if (arg === undefined) {
debugCallback("%s pipe (pid: %o) %o event", pipe, child.pid, event);
}
else {
debugCallback("%s pipe (pid: %o) %o event: %O", pipe, child.pid, event, arg);
}
}
});
return Object.assign(process, { attach });
}
exports.default = newProcessWithPipeMessageTransport;
function streamsForPipe(child) {
const stdio = child.stdio;
if (stdio.length === 5) {
return stdio;
}
throw new Error("expected process to have 5 stdio streams");
}
//# sourceMappingURL=newProcessWithPipeMessageTransport.js.map
import { ProcessWithWebSocketUrl, Stdio } from "../types";
export default function newProcessWithWebSocketUrl(child: import("execa").ExecaChildProcess, stdio: Stdio): ProcessWithWebSocketUrl;
export default function newProcessWithWebSocketUrl(command: string, args: string[], stdio: Stdio, debugCallback: (formatter: any, ...args: any[]) => void): ProcessWithWebSocketUrl;
//# sourceMappingURL=newProcessWithWebSocketUrl.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const race_cancellation_1 = require("race-cancellation");
const execa_1 = require("./execa");
const newProcess_1 = require("./newProcess");
const newWebSocketUrlParser_1 = require("./newWebSocketUrlParser");
function newProcessWithWebSocketUrl(child, stdio) {
const process = newProcess_1.default(child);
function newProcessWithWebSocketUrl(command, args, stdio, debugCallback) {
const child = execa_1.default(command, args, {
// disable buffer, pipe or drain
buffer: false,
stdio: [stdio, stdio, "pipe"],
}, debugCallback);
const process = newProcess_1.default(child, command, debugCallback);
return Object.assign(process, {

@@ -9,0 +15,0 @@ url: createUrl(child.stderr, stdio, process.raceExit),

@@ -1,4 +0,4 @@

import * as t from "../types";
export default function spawn<T extends t.Transport>(executable: string, args: string[], stdio: t.Stdio | undefined, transport: T): t.TransportMapping[T];
export default function spawn<T extends t.Transport>(executable: string, args: string[], stdio?: t.Stdio): t.ProcessWithPipeMessageTransport;
import { DebugCallback, ProcessWithPipeMessageTransport, ProcessWithWebSocketUrl, Stdio } from "../types";
export default function spawn(executable: string, args: string[], stderr: Stdio | undefined, transport: "websocket", debugCallback?: DebugCallback): ProcessWithWebSocketUrl;
export default function spawn(executable: string, args: string[], stderr?: Stdio, transport?: "pipe", debugCallback?: DebugCallback): ProcessWithPipeMessageTransport;
//# sourceMappingURL=spawn.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = require("debug");
const execa = require("execa");
const newProcessWithPipeMessageTransport_1 = require("./newProcessWithPipeMessageTransport");
const newProcessWithWebSocketUrl_1 = require("./newProcessWithWebSocketUrl");
const debugCallback = debug_1.default("@tracerbench/spawn");
function spawn(executable, args, stdio = "ignore", transport = "pipe") {
const opts = {
// disable buffer, pipe or drain
buffer: false,
stdio: stdioFor(stdio, transport),
};
debugCallback("execa(%o, %O, %O)", executable, args, opts);
const child = execa(executable, args, opts);
// even though the child promise is a promise of exit
// it rejects on being signalled
child.catch(() => {
// ignore unhandled rejection from sending signal
});
function spawn(executable, args, stderr = "ignore", transport = "pipe", debugCallback = debug_1.default("@tracerbench/spawn")) {
switch (transport) {
case "pipe":
return newProcessWithPipeMessageTransport_1.default(child);
return newProcessWithPipeMessageTransport_1.default(executable, args, stderr, debugCallback);
case "websocket":
return newProcessWithWebSocketUrl_1.default(child, stdio);
return newProcessWithWebSocketUrl_1.default(executable, args, stderr, debugCallback);
default:

@@ -31,11 +17,2 @@ throw invalidTransport(transport);

exports.default = spawn;
function stdioFor(stdio, transport) {
if (transport === "pipe") {
return [stdio, stdio, stdio, "pipe", "pipe"];
}
if (transport === "websocket") {
return [stdio, stdio, "pipe"];
}
throw new Error(`invalid transport argument ${transport}`);
}
function invalidTransport(transport) {

@@ -42,0 +19,0 @@ return new Error(`invalid transport argument "${transport}"`);

{
"name": "@tracerbench/spawn",
"version": "1.0.2",
"version": "1.0.3",
"description": "High level spawn API for spawning process with a connection to the DevTools protocol.",

@@ -34,3 +34,3 @@ "license": "BSD-2-Clause",

},
"gitHead": "a63772e4ffbab7f3c273970f3fa176bb2544405b"
"gitHead": "707c39013bbab664521045c17fcdc96d68bc2516"
}

@@ -1,2 +0,1 @@

import debug = require("debug");
import { EventEmitter } from "events";

@@ -14,6 +13,6 @@ import {

const debugCallback = debug("@tracerbench/spawn");
export default function newProcess(
child: import("execa").ExecaChildProcess,
command: string,
debugCallback: (formatter: any, ...args: any[]) => void,
): t.Process {

@@ -28,8 +27,9 @@ let hasExited = false;

lastError = error;
debugCallback("child process error %O", error);
onExit(error);
debugCallback("%o (pid: %o) 'error' event: %O", command, child.pid, error);
onErrorOrExit(error);
});
child.on("exit", () => {
debugCallback("child process exit");
onExit();
debugCallback("%o (pid: %o) 'exit' event", command, child.pid);
onErrorOrExit();
});

@@ -50,3 +50,9 @@

function onExit(error?: Error) {
/*
https://nodejs.org/api/child_process.html#child_process_event_exit
The 'exit' event may or may not fire after an error has occurred.
When listening to both the 'exit' and 'error' events, it is important to guard against accidentally invoking handler functions multiple times.
*/
function onErrorOrExit(error?: Error) {
if (hasExited) {

@@ -103,12 +109,6 @@ return;

async function kill(timeout?: number, raceCancellation?: RaceCancellation) {
if (hasExited) {
return;
if (!child.killed && child.pid) {
child.kill();
}
if (child.killed || !child.pid) {
return;
}
child.kill();
await waitForExit(timeout, raceCancellation);

@@ -118,6 +118,2 @@ }

async function dispose(): Promise<void> {
if (hasExited) {
return;
}
try {

@@ -129,5 +125,5 @@ await kill();

// just output for debugging
debugCallback("dispose error %O", e);
debugCallback("%o (pid: %o) dispose error: %O", command, child.pid, e);
}
}
}

@@ -1,60 +0,91 @@

import debug = require("debug");
import { ProcessWithPipeMessageTransport, Stdio } from "../types";
import { ProcessWithPipeMessageTransport } from "../types";
import execa from "./execa";
import createPipeMessageTransport from "./newPipeMessageTransport";
import newProcess from "./newProcess";
const debugCallback = debug("@tracerbench/spawn");
export default function newProcessWithPipeMessageTransport(
child: import("execa").ExecaChildProcess,
command: string,
args: string[],
stdio: Stdio,
debugCallback: (formatter: any, ...args: any[]) => void,
): ProcessWithPipeMessageTransport {
const process = newProcess(child);
const [, , , writeStream, readStream] = streamsForPipe(child);
return Object.assign(process, {
attach: createPipeMessageTransport((onRead, onReadEnd, onClose) => {
child.on("error", onClose);
child.on("exit", onClose);
const child = execa(
command,
args,
{
// disable buffer, pipe or drain
buffer: false,
stdio: [stdio, stdio, stdio, "pipe", "pipe"],
},
debugCallback,
);
readStream.on("data", onRead);
readStream.on("end", () => {
debugCallback("read pipe end");
onReadEnd();
});
readStream.on("error", error => {
debugCallback("read pipe error %O", error);
});
const process = newProcess(child, command, debugCallback);
const [, , , writeStream, readStream] = child.stdio as [
NodeJS.WritableStream,
NodeJS.ReadableStream,
NodeJS.ReadableStream,
NodeJS.WritableStream,
NodeJS.ReadableStream,
];
writeStream.on("close", () => {
debugCallback("write pipe close");
onClose();
});
writeStream.on("error", (error: Error | NodeJS.ErrnoException) => {
debugCallback("write pipe error %O", error);
// writes while the other side is closing can cause EPIPE
// just wait for close to actually happen and ignore it.
if (error && "code" in error && error.code === "EPIPE") {
return;
}
onClose(error);
});
const attach = createPipeMessageTransport((onRead, onReadEnd, onClose) => {
child.on("error", onClose);
child.on("exit", onClose);
return [data => writeStream.write(data), () => writeStream.end()];
}),
readStream.on("data", handleReadData);
readStream.on("end", handleReadEnd);
readStream.on("error", handleReadError);
writeStream.on("close", handleWriteClose);
writeStream.on("error", handleWriteError);
return [data => writeStream.write(data), () => writeStream.end()];
function handleReadData(buffer: Buffer) {
debugEvent("read", "data", buffer.byteLength);
onRead(buffer);
}
function handleReadEnd() {
debugEvent("read", "end");
onReadEnd();
}
function handleReadError(error: Error) {
debugEvent("read", "error", error);
}
function handleWriteError(error: Error | NodeJS.ErrnoException) {
debugEvent("write", "error", error);
// writes while the other side is closing can cause EPIPE
// just wait for close to actually happen and ignore it.
if (error && "code" in error && error.code === "EPIPE") {
return;
}
onClose(error);
}
function handleWriteClose() {
debugEvent("write", "close");
onClose();
}
function debugEvent(pipe: "read" | "write", event: string, arg?: any) {
if (arg === undefined) {
debugCallback("%s pipe (pid: %o) %o event", pipe, child.pid, event);
} else {
debugCallback(
"%s pipe (pid: %o) %o event: %O",
pipe,
child.pid,
event,
arg,
);
}
}
});
}
function streamsForPipe(child: import("execa").ExecaChildProcess) {
const stdio: unknown[] = child.stdio;
if (stdio.length === 5) {
return stdio as [
NodeJS.WritableStream,
NodeJS.ReadableStream,
NodeJS.ReadableStream,
NodeJS.WritableStream,
NodeJS.ReadableStream,
];
}
throw new Error("expected process to have 5 stdio streams");
return Object.assign(process, { attach });
}

@@ -9,2 +9,3 @@ import {

import execa from "./execa";
import newProcess from "./newProcess";

@@ -14,6 +15,19 @@ import newWebSocketUrlParser from "./newWebSocketUrlParser";

export default function newProcessWithWebSocketUrl(
child: import("execa").ExecaChildProcess,
command: string,
args: string[],
stdio: Stdio,
debugCallback: (formatter: any, ...args: any[]) => void,
): ProcessWithWebSocketUrl {
const process = newProcess(child);
const child = execa(
command,
args,
{
// disable buffer, pipe or drain
buffer: false,
stdio: [stdio, stdio, "pipe"],
},
debugCallback,
);
const process = newProcess(child, command, debugCallback);
return Object.assign(process, {

@@ -20,0 +34,0 @@ url: createUrl(child.stderr!, stdio, process.raceExit),

import debug from "debug";
import execa = require("execa");
import * as t from "../types";
import {
DebugCallback,
ProcessWithPipeMessageTransport,
ProcessWithWebSocketUrl,
Stdio,
Transport,
} from "../types";

@@ -9,41 +14,38 @@ import newProcessWithPipeMessageTransport from "./newProcessWithPipeMessageTransport";

const debugCallback = debug("@tracerbench/spawn");
export default function spawn<T extends t.Transport>(
export default function spawn(
executable: string,
args: string[],
stdio: t.Stdio | undefined,
transport: T,
): t.TransportMapping[T];
export default function spawn<T extends t.Transport>(
stderr: Stdio | undefined,
transport: "websocket",
debugCallback?: DebugCallback,
): ProcessWithWebSocketUrl;
export default function spawn(
executable: string,
args: string[],
stdio?: t.Stdio,
): t.ProcessWithPipeMessageTransport;
stderr?: Stdio,
transport?: "pipe",
debugCallback?: DebugCallback,
): ProcessWithPipeMessageTransport;
export default function spawn(
executable: string,
args: string[],
stdio: t.Stdio = "ignore",
transport: t.Transport = "pipe",
): t.TransportMapping[t.Transport] {
const opts: execa.Options = {
// disable buffer, pipe or drain
buffer: false,
stdio: stdioFor(stdio, transport),
};
debugCallback("execa(%o, %O, %O)", executable, args, opts);
const child = execa(executable, args, opts);
// even though the child promise is a promise of exit
// it rejects on being signalled
child.catch(() => {
// ignore unhandled rejection from sending signal
});
stderr: Stdio = "ignore",
transport: Transport = "pipe",
debugCallback: DebugCallback = debug("@tracerbench/spawn"),
): ProcessWithPipeMessageTransport | ProcessWithWebSocketUrl {
switch (transport) {
case "pipe":
return newProcessWithPipeMessageTransport(child);
return newProcessWithPipeMessageTransport(
executable,
args,
stderr,
debugCallback,
);
case "websocket":
return newProcessWithWebSocketUrl(child, stdio);
return newProcessWithWebSocketUrl(
executable,
args,
stderr,
debugCallback,
);
default:

@@ -54,17 +56,4 @@ throw invalidTransport(transport);

function stdioFor(
stdio: "ignore" | "inherit",
transport: "pipe" | "websocket",
): readonly execa.StdioOption[] {
if (transport === "pipe") {
return [stdio, stdio, stdio, "pipe", "pipe"];
}
if (transport === "websocket") {
return [stdio, stdio, "pipe"];
}
throw new Error(`invalid transport argument ${transport}`);
}
function invalidTransport(transport: never) {
return new Error(`invalid transport argument "${transport}"`);
}
import { AttachMessageTransport } from "@tracerbench/message-transport";
import { RaceCancellation } from "race-cancellation";
export type DebugCallback = (formatter: any, ...args: any[]) => void;
export interface Process {

@@ -5,0 +7,0 @@ /**

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc