mirror of
https://github.com/morluto/rea.git
synced 2026-11-06 06:46:10 +00: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:
1 parent
5a77acfbcd
commit
d72d856f58
20 files changed
+4544
-64
No files matched your search
@@ -0,0 +1,65 @@
|
||||
import * as t from "@babel/types";
|
||||
import { unwrapJavaScriptExpression } from "./javascriptAstValues.js";
|
||||
import { semanticBindingAtRead } from "./javascriptSemanticMutationInitializers.js";
|
||||
import {
|
||||
semanticStableInitializer,
|
||||
type JavaScriptBindingIndex,
|
||||
} from "./javascriptSemanticState.js";
|
||||
|
||||
/** Lexical candidates alone do not establish that object contents are intact. */
|
||||
const optionObjectCandidate = (
|
||||
input: t.Node | undefined,
|
||||
index: JavaScriptBindingIndex,
|
||||
):
|
||||
| {
|
||||
readonly object: t.ObjectExpression;
|
||||
readonly references: readonly t.Identifier[];
|
||||
}
|
||||
| undefined => {
|
||||
if (input === undefined) return undefined;
|
||||
let node = unwrapJavaScriptExpression(input).node;
|
||||
const seen = new Set<t.Node>();
|
||||
const references: t.Identifier[] = [];
|
||||
while (t.isIdentifier(node)) {
|
||||
if (seen.has(node)) return undefined;
|
||||
seen.add(node);
|
||||
const binding = index.bindingForReferenceAt(node);
|
||||
if (binding === undefined) return undefined;
|
||||
const initializer = semanticStableInitializer(binding, index.bindings);
|
||||
if (
|
||||
binding.mutable ||
|
||||
binding.declarationKinds.size !== 1 ||
|
||||
!binding.declarationKinds.has("const") ||
|
||||
initializer === undefined ||
|
||||
initializer.projection.length !== 0 ||
|
||||
!semanticBindingAtRead(binding, node, index.bindings.parentsByNode)
|
||||
.hasDefiniteInitializer
|
||||
)
|
||||
return undefined;
|
||||
references.push(node);
|
||||
node = unwrapJavaScriptExpression(initializer.node).node;
|
||||
}
|
||||
return t.isObjectExpression(node) ? { object: node, references } : undefined;
|
||||
};
|
||||
|
||||
/** Avoid building mutation facts for parameters, missing or unresolved objects. */
|
||||
export const hasElectronOptionObjectCandidate = (
|
||||
input: t.Node | undefined,
|
||||
index: JavaScriptBindingIndex,
|
||||
): boolean => optionObjectCandidate(input, index) !== undefined;
|
||||
|
||||
/** Select an inert const object using the shared lexical and mutation owner. */
|
||||
export const resolveElectronOptionObject = (
|
||||
input: t.Node | undefined,
|
||||
site: t.Node,
|
||||
index: JavaScriptBindingIndex,
|
||||
propertyPath: readonly string[] = [],
|
||||
): t.ObjectExpression | undefined => {
|
||||
const candidate = optionObjectCandidate(input, index);
|
||||
if (candidate === undefined) return undefined;
|
||||
for (const reference of candidate.references) {
|
||||
if (index.referenceMayHaveChangedAt(site, reference, propertyPath))
|
||||
return undefined;
|
||||
}
|
||||
return candidate.object;
|
||||
};
|
||||
Reference in new issue
Block a user