fix(javascript): unify loader binding and mutation ownership

Model the CommonJS wrapper binding and query shared lexical identity, mutation, and evaluation timing at each call. Remove duplicate importer interpretation and preserve uncertainty for with scopes, prototypes, repeated writes, and opaque object escapes.

Validate generated fixtures against bounded Node oracles; no analyzed target execution is added.

Refs: #3982, #4072

Co-authored-by: Geronimo <varungore1@gmail.com>
This commit is contained in:
morlutoandGeronimo committed 2026-10-16 08:14:52 +08:00
1 parent b67baede2e
commit 1b9b725c4c
8 files changed
+1089 -295

No files matched your search

@@ -1146,7 +1146,11 @@ const observableMutationPaths = (
const hasParsedRequireOrigin = binding.initializers.some(
({ node }) => semanticRequireOrigin(node, state) !== undefined,
);
if (binding.directOrigins.length > 0 || hasParsedRequireOrigin)
if (
binding.directOrigins.length > 0 ||
hasParsedRequireOrigin ||
binding.hostOrigin !== undefined
)
(observer.origins ??= new Set()).add("opaque");
for (const initializer of binding.initializers) {
link(
@@ -1176,6 +1180,11 @@ const observableMutationPaths = (
// Keep class/getter projections distinct so cycle pruning does not
// discard observable escapes through a shared getter result.
if (
t.isNewExpression(expression) &&
semanticClassCandidates(expression.callee, state).length === 0
)
(observer.origins ??= new Set()).add("opaque");
else if (
t.isObjectExpression(expression) ||
t.isArrayExpression(expression) ||
t.isClass(expression) ||