mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(javascript): report fork's silent stdio as piped (#7083)
* fix(javascript): report fork's silent stdio as piped
Node's child_process.fork pipes stdin, stdout and stderr when options.silent is truthy and options.stdio is neither a string nor an array, and inherits them otherwise. REA never read silent, so fork("worker.js", { silent: true }) was reported with stdio_mode default (inherited). The unset-stdio case of fork now reads silent: truthy gives pipe, falsy or missing gives default, and an unresolved value gives dynamic.
* fix(javascript): apply fork's silent rule to other known stdio values
This commit is contained in:
1 parent
c74d302cc4
commit
80673b22a4
2 files changed
+58
-2
No files matched your search
@@ -52,6 +52,36 @@ describe("child-process options detection", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("reads fork's silent option when stdio is not a string or array", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
import { fork, spawn } from "node:child_process";
|
||||
|
||||
fork("piped.js", { silent: true });
|
||||
fork("inherited.js", [], { silent: false });
|
||||
fork("nullish-stdio.js", { silent: 1, stdio: null });
|
||||
fork("explicit-stdio.js", { silent: true, stdio: "inherit" });
|
||||
fork("dynamic.js", { silent: process.env.QUIET });
|
||||
spawn("tool", { silent: true });
|
||||
fork("boolean-stdio.js", { stdio: false, silent: true });
|
||||
fork("object-stdio.js", { stdio: {}, silent: false });
|
||||
fork("unresolved-stdio.js", { stdio: streams, silent: true });
|
||||
spawn("tool", { stdio: false });
|
||||
`);
|
||||
|
||||
expect(ir.childProcessSpawns.map(({ stdioMode }) => stdioMode)).toEqual([
|
||||
"pipe",
|
||||
"default",
|
||||
"pipe",
|
||||
"inherit",
|
||||
"dynamic",
|
||||
"default",
|
||||
"pipe",
|
||||
"default",
|
||||
"dynamic",
|
||||
"dynamic",
|
||||
]);
|
||||
});
|
||||
|
||||
it("preserves behavior with explicit args arrays", () => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
import { spawn, execFile, fork } from "node:child_process";
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from "./javascriptSemanticExpressionShapes.js";
|
||||
import {
|
||||
semanticStaticPropertyName,
|
||||
staticJavaScriptTruthiness,
|
||||
staticObjectProperty,
|
||||
unwrapJavaScriptExpression,
|
||||
} from "./javascriptAstValues.js";
|
||||
@@ -424,15 +425,40 @@ const stdioMode = (
|
||||
)
|
||||
return "default";
|
||||
const lookup = staticObjectProperty(expression, "stdio", context.isNullish);
|
||||
if (lookup.status === "missing") return "default";
|
||||
if (lookup.status === "missing")
|
||||
return unsetStdioMode(expression, method, context);
|
||||
if (lookup.status !== "explicit") return "dynamic";
|
||||
const value = unwrapJavaScriptExpression(lookup.property.value).node;
|
||||
if (context.isNullish(value)) return "default";
|
||||
if (context.isNullish(value))
|
||||
return unsetStdioMode(expression, method, context);
|
||||
if (t.isStringLiteral(value)) return value.value;
|
||||
if (t.isArrayExpression(value)) return "array";
|
||||
// fork ignores any other known stdio value and falls back to `silent`.
|
||||
if (method === "fork" && staticJavaScriptTruthiness(value) !== undefined)
|
||||
return unsetStdioMode(expression, method, context);
|
||||
return "dynamic";
|
||||
};
|
||||
|
||||
/**
|
||||
* Without a string or array `stdio`, Node's `fork` pipes the standard streams
|
||||
* when `silent` is truthy and inherits them otherwise.
|
||||
*/
|
||||
const unsetStdioMode = (
|
||||
options: t.Node,
|
||||
method: JavaScriptSemanticChildProcessSpawn["method"],
|
||||
context: ChildSpawnContext,
|
||||
): string => {
|
||||
if (method !== "fork") return "default";
|
||||
const silent = staticObjectProperty(options, "silent", context.isNullish);
|
||||
if (silent.status === "missing") return "default";
|
||||
if (silent.status !== "explicit") return "dynamic";
|
||||
const value = unwrapJavaScriptExpression(silent.property.value).node;
|
||||
if (context.isNullish(value)) return "default";
|
||||
const truthy = staticJavaScriptTruthiness(value);
|
||||
if (truthy === undefined) return "dynamic";
|
||||
return truthy ? "pipe" : "default";
|
||||
};
|
||||
|
||||
const objectBinding = (
|
||||
node: t.Expression | t.Super,
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
|
||||
Reference in new issue
Block a user