mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
feat(electron): resolve stable local constant window options
Resolve stable local constant BrowserWindow options with retained provenance and shared early-exit mutation queries. Preserve source ordering and unknown results for relevant mutations or escapes. Includes real Joplin correctness/cost receipts and regression coverage. Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
@@ -175,13 +175,16 @@ function* indexSemanticMemberMutationFactsSteps(
|
||||
indexedMemberMutationStates.add(state);
|
||||
}
|
||||
|
||||
/** Resolve one identifier or member use and summarize its source-site effects. */
|
||||
const semanticReferenceEffectsAtSite = (
|
||||
/** One owner projects source-site effects for complete reports or early exit. */
|
||||
const visitSemanticReferenceEffectsAtSite = (
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
site: t.Node,
|
||||
referenceNode: t.Node,
|
||||
visit: (
|
||||
effect: JavaScriptSemanticReferenceEffectsAtSite["effects"][number],
|
||||
) => boolean,
|
||||
requestedPath?: JavaScriptSemanticPropertyPath,
|
||||
): JavaScriptSemanticReferenceEffectsAtSite => {
|
||||
): Omit<JavaScriptSemanticReferenceEffectsAtSite, "effects"> => {
|
||||
const { root, path: inferredPath } = semanticReferenceRoot(referenceNode);
|
||||
const memberEffectsIndexed = indexedMemberMutationStates.has(state);
|
||||
if (!t.isIdentifier(root))
|
||||
@@ -189,7 +192,6 @@ const semanticReferenceEffectsAtSite = (
|
||||
bindingId: null,
|
||||
resolution: "unknown",
|
||||
memberEffectsIndexed,
|
||||
effects: [],
|
||||
};
|
||||
const lookup = semanticBindingLookupAt(state, root, root.name);
|
||||
const binding = "binding" in lookup ? lookup.binding : undefined;
|
||||
@@ -197,16 +199,19 @@ const semanticReferenceEffectsAtSite = (
|
||||
const resolution =
|
||||
lookup.kind === "binding" ? "resolved" : blocked ? "unknown" : "unbound";
|
||||
const path = requestedPath ?? inferredPath;
|
||||
const effects: JavaScriptSemanticReferenceEffectsAtSite["effects"][number][] =
|
||||
[];
|
||||
const metadata: Omit<JavaScriptSemanticReferenceEffectsAtSite, "effects"> = {
|
||||
bindingId: binding?.bindingId ?? null,
|
||||
resolution,
|
||||
memberEffectsIndexed,
|
||||
};
|
||||
const retain = (
|
||||
kind: JavaScriptSemanticReferenceEffectsAtSite["effects"][number]["kind"],
|
||||
node: t.Node | undefined,
|
||||
effectPath?: JavaScriptSemanticPropertyPath,
|
||||
): void => {
|
||||
): boolean => {
|
||||
if (effectPath !== undefined && !semanticPathsOverlap(path, effectPath))
|
||||
return;
|
||||
effects.push({
|
||||
return true;
|
||||
return visit({
|
||||
kind,
|
||||
...(effectPath === undefined ? {} : { path: effectPath }),
|
||||
timing: semanticEffectTiming(site, node, state),
|
||||
@@ -214,23 +219,40 @@ const semanticReferenceEffectsAtSite = (
|
||||
};
|
||||
if (binding !== undefined) {
|
||||
for (const node of state.bindingWrites.get(binding.bindingId) ?? [])
|
||||
retain("binding-write", node);
|
||||
if (!retain("binding-write", node)) return metadata;
|
||||
if (indexedMemberMutationStates.has(state)) {
|
||||
for (const effect of binding.memberWrites)
|
||||
retain("member-write", effect.node, effect.path);
|
||||
if (!retain("member-write", effect.node, effect.path)) return metadata;
|
||||
for (const effect of binding.escapedPaths)
|
||||
retain("escape", effect.node, effect.path);
|
||||
if (!retain("escape", effect.node, effect.path)) return metadata;
|
||||
}
|
||||
} else if (lookup.kind === "ambient" || lookup.kind === "uncertain-ambient") {
|
||||
for (const node of state.ambientBindingWrites.get(root.name) ?? [])
|
||||
retain("ambient-write", node);
|
||||
if (!retain("ambient-write", node)) return metadata;
|
||||
}
|
||||
return {
|
||||
bindingId: binding?.bindingId ?? null,
|
||||
resolution,
|
||||
memberEffectsIndexed,
|
||||
effects,
|
||||
};
|
||||
return metadata;
|
||||
};
|
||||
|
||||
/** Preserve the complete diagnostic contract for consumers needing every effect. */
|
||||
const semanticReferenceEffectsAtSite = (
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
site: t.Node,
|
||||
referenceNode: t.Node,
|
||||
requestedPath?: JavaScriptSemanticPropertyPath,
|
||||
): JavaScriptSemanticReferenceEffectsAtSite => {
|
||||
const effects: JavaScriptSemanticReferenceEffectsAtSite["effects"][number][] =
|
||||
[];
|
||||
const metadata = visitSemanticReferenceEffectsAtSite(
|
||||
state,
|
||||
site,
|
||||
referenceNode,
|
||||
(effect) => {
|
||||
effects.push(effect);
|
||||
return true;
|
||||
},
|
||||
requestedPath,
|
||||
);
|
||||
return { ...metadata, effects };
|
||||
};
|
||||
|
||||
const semanticReferenceRoot = (
|
||||
@@ -421,6 +443,12 @@ export function* indexJavaScriptBindingsWithReceiversSteps(
|
||||
*indexMemberMutationFactsSteps() {
|
||||
yield* indexSemanticMemberMutationFactsSteps(state);
|
||||
},
|
||||
bindingForReferenceAt(referenceNode) {
|
||||
const { root } = semanticReferenceRoot(referenceNode);
|
||||
return t.isIdentifier(root)
|
||||
? resolveSemanticBindingState(state, root, root.name)
|
||||
: undefined;
|
||||
},
|
||||
effectsForReferenceAt(site, referenceNode, propertyPath) {
|
||||
return semanticReferenceEffectsAtSite(
|
||||
state,
|
||||
@@ -429,6 +457,21 @@ export function* indexJavaScriptBindingsWithReceiversSteps(
|
||||
propertyPath,
|
||||
);
|
||||
},
|
||||
referenceMayHaveChangedAt(site, referenceNode, propertyPath) {
|
||||
if (!indexedMemberMutationStates.has(state)) return true;
|
||||
let changed = false;
|
||||
const metadata = visitSemanticReferenceEffectsAtSite(
|
||||
state,
|
||||
site,
|
||||
referenceNode,
|
||||
(effect) => {
|
||||
changed = effect.timing !== "after";
|
||||
return !changed;
|
||||
},
|
||||
propertyPath,
|
||||
);
|
||||
return metadata.resolution !== "resolved" || changed;
|
||||
},
|
||||
*referencesSteps() {
|
||||
references ??= yield* collectSemanticReferencesSteps(program, state);
|
||||
return references;
|
||||
|
||||
Reference in New Issue
Block a user