fix(javascript): preserve intrinsic projections and fresh target identity

Resolve known mutators through static binding projections and prove stable
identifier chains to fresh literals before widening unknown mutation targets.
Keep reassigned, uninitialized and member-projected targets conservative.
Cover both review regressions through source tests and inert CLI/MCP fixtures.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
N0zoM1z0
2026-10-11 15:22:12 +00:00
co-authored by factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> Kaoru0822
parent 47f8156efe
commit 5569e96162
6 changed files with 101 additions and 13 deletions
@@ -50,6 +50,7 @@ export function* collectJavaScriptIdentityWritesSteps(
kind: "binding" | "member" | "opaque-call",
) => readonly string[] | undefined,
intrinsic: (node: t.Node) => readonly string[] | undefined,
freshObject: (node: t.Node) => boolean,
retain: (node: t.Node, path: readonly (string | null)[]) => void,
): Generator<void> {
const objectMutators = new Set([
@@ -115,10 +116,7 @@ export function* collectJavaScriptIdentityWritesSteps(
? [stringValue(arguments_[1]) ?? null]
: [];
retain(node, [...exported, ...members, ...key]);
} else if (
!t.isObjectExpression(target) &&
!t.isArrayExpression(target)
) {
} else if (!freshObject(target)) {
const scope = origin(node, "opaque-call");
if (scope !== undefined) retain(node, scope);
}