mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
fix(javascript): converge cyclic aliases with explicit projection widening
Replace initializer-history and full-path enumeration with a finite projection join at each source read. Retain conservative local returned-reference effects and disclose precision loss through static, semantic and captured-web results. Close full-binding callback cycles while preserving narrowed read semantics. Fixes #4348 Fixes #5138 Refs #4349 Refs #4364 Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Fuxuan-CN <3072252442@qq.com>
This commit is contained in:
@@ -33,6 +33,8 @@ interface CallResolutionContext {
|
||||
readonly state: JavaScriptSemanticAnalysisState;
|
||||
readonly callableById: ReadonlyMap<string, JavaScriptSemanticCallable>;
|
||||
readonly seenInitializers: ReadonlySet<JavaScriptSemanticInitializer>;
|
||||
/** Bindings on the active chain whose read selected every initializer. */
|
||||
readonly seenBindings: ReadonlySet<JavaScriptSemanticBindingState>;
|
||||
readonly bindingCache: WeakMap<t.Identifier, LocalCallableResolution>;
|
||||
}
|
||||
|
||||
@@ -53,6 +55,7 @@ export const resolveLocalCallables = (
|
||||
state: input.state,
|
||||
callableById: input.callableById,
|
||||
seenInitializers: input.seenInitializers,
|
||||
seenBindings: new Set(),
|
||||
bindingCache: input.bindingCache,
|
||||
});
|
||||
|
||||
@@ -103,7 +106,26 @@ const resolveIdentifier = (
|
||||
node,
|
||||
context.state.parentsByNode,
|
||||
);
|
||||
const candidates = resolveBindingCallables(read.binding, context);
|
||||
// A full read re-enters the same candidate set wherever the chain returns
|
||||
// to this binding. Close that cycle at the binding; position-narrowed reads
|
||||
// keep their per-initializer cycle handling.
|
||||
const selectsAll = read.binding === binding;
|
||||
if (selectsAll && context.seenBindings.has(binding))
|
||||
return {
|
||||
callableIds: [],
|
||||
complete: false,
|
||||
cycleDependent: true,
|
||||
reason: `Call target initializer cycle at ${binding.name}.`,
|
||||
};
|
||||
const candidates = resolveBindingCallables(
|
||||
read.binding,
|
||||
selectsAll
|
||||
? {
|
||||
...context,
|
||||
seenBindings: new Set(context.seenBindings).add(binding),
|
||||
}
|
||||
: context,
|
||||
);
|
||||
// Knowing every local candidate does not prove that any write replaced the
|
||||
// incoming value, or that a write in another activation precedes this read.
|
||||
const covered =
|
||||
|
||||
Reference in New Issue
Block a user