fix(javascript): ignore async exec stdio options (#7087)

Respect Node asynchronous exec/execFile method-default stdio instead of interpreting an ignored option. Remove the superseded callback-shape query while preserving caller input, Evidence, uncertainty, argv and fork controls. Independently validated on current main through actual Node pipe capture, matching real-app CLI/MCP facts, 81 targeted tests and static checking. Closes #7217.
This commit is contained in:
Wenyu Chiou authored and GitHub committed 2026-10-26 23:16:28 +08:00
1 parent a84e0cfcfe
commit 625e32744e
4 files changed
+76 -89

No files matched your search

@@ -23,7 +23,7 @@ import {
import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
import { javaScriptRuntimeContext } from "./javascriptSourceParser.js";
type Shape = "array" | "callback" | "unknown";
type Shape = "array" | "unknown";
/** Bounded argument-shape queries shared by call-signature owners. */
export type JavaScriptExpressionShapeResolver = ReturnType<
@@ -41,15 +41,6 @@ const commonJsWrapperParameterNames = new Set([
export const createSemanticExpressionShapeResolver = (
state: JavaScriptSemanticAnalysisState,
) => {
const hoistedFunction = (node: t.Node): boolean => {
const parent = state.parentsByNode.get(node);
return (
t.isFunctionDeclaration(node) &&
(t.isProgram(parent) ||
(t.isBlockStatement(parent) &&
t.isFunction(state.parentsByNode.get(parent))))
);
};
// Most modules have no named child arguments. Collect source-wide blockers
// only when a query actually needs a named binding or ambient undefined.
let blocked: boolean | undefined;
@@ -80,8 +71,6 @@ export const createSemanticExpressionShapeResolver = (
if (seen.has(node)) return "unknown";
seen.add(node);
if (t.isArrayExpression(node)) return "array";
if (t.isFunction(node) && !("declare" in node && node.declare))
return "callback";
if (!t.isIdentifier(node)) return "unknown";
const binding = resolveSemanticBindingState(state, node, node.name);
if (binding === undefined || binding.referenceInitializers.length > 0)
@@ -106,11 +95,7 @@ export const createSemanticExpressionShapeResolver = (
if (initializer === undefined || initializer.projection.length > 0)
return "unknown";
const read = semanticBindingAtRead(binding, node, state.parentsByNode);
// Hoisted function declarations are the only accepted unordered source.
if (
!hoistedFunction(initializer.node) &&
(read.status !== "ordered" || !read.hasDefiniteInitializer)
)
if (read.status !== "ordered" || !read.hasDefiniteInitializer)
return "unknown";
node = initializer.node;
depth++;
@@ -118,7 +103,6 @@ export const createSemanticExpressionShapeResolver = (
};
return {
isArray: (node: t.Node) => shape(node) === "array",
isCallback: (node: t.Node) => shape(node) === "callback",
isNullish: (input: t.Node) => {
const { node } = unwrapJavaScriptExpression(input);
return (