Files
rea/src/domain/javascript/javascriptSymbolicValues.ts
T
morluto b8fab74297 fix(javascript): preserve execution and invocation provenance
Keep direct empty bridge objects observed, reject unexecuted initializers,
invalidate modified bootstrap tables and Electron identities, and retain
selection predicates through symbolic values and wrapper paths. Track lexical
binding identity and completed activation boundaries without leaking analysis
order into earlier reads.

Separate wrapper invocation provenance from the underlying IPC source range
so repeated registrations remain ambiguous through transfer and graph joins.
Use the same offered transfer budget for module preflight and final writing.

Index static literal properties once instead of rescanning every member. Keep
the original 10,001-member capacity fixture; Flameox confirmed the repeated
lookup cost and the optimized fixture completes in under one second locally.
Prune the stale compact-schema tool inventory assertion and update the public
call-graph registration expectation to its declared result envelope.

Validation: build, check, docs:check, 83 focused tests, 10 Electron identity
acceptance cases, 2 full-scale finding-capacity cases, and 7 compact-schema
transport tests. No real Electron runtime execution is claimed.
2026-10-12 10:03:17 +08:00

119 lines
3.9 KiB
TypeScript

import type * as t from "@babel/types";
/** A lexical substitution environment, never a JavaScript execution context. */
export interface SymbolicEnvironment {
readonly values: ReadonlyMap<string, SymbolicValue>;
readonly parent?: SymbolicEnvironment;
/** Source point at which the current function is being symbolically executed. */
readonly point?: t.Node;
/** Lexical function scope for point-sensitive local initializer checks. */
readonly scopeId?: string;
/** Function activation captured by this environment, when one exists. */
readonly scopeNode?: t.Function;
/** Completion boundary proven for this captured activation. */
readonly completedAt?: t.Node;
}
export interface SymbolicCondition {
readonly node: t.Node;
readonly positive: boolean | "nullish" | "not-nullish";
}
export interface SymbolicMetadata {
/** Predicates required for this value to be selected. */
readonly conditions?: readonly SymbolicCondition[];
/** A control-flow join prevented a sound predicate from being retained. */
readonly conditionUnresolved?: true;
}
export interface SymbolicFunction extends SymbolicMetadata {
readonly kind: "function";
readonly node: t.Function;
readonly environment: SymbolicEnvironment;
readonly origins: readonly t.Node[];
/** Return statement completing the activation that produced this value. */
readonly returnPoint?: t.Node;
}
export type SymbolicValue = (
| { readonly kind: "unknown"; readonly reason: string }
| {
readonly kind: "literal";
readonly value: string | number | boolean | null | undefined;
}
| { readonly kind: "external"; readonly path: readonly string[] }
| {
readonly kind: "object";
readonly node: t.ObjectExpression;
readonly environment: SymbolicEnvironment;
}
| {
readonly kind: "namespace";
readonly bindingId: string;
readonly environment: SymbolicEnvironment;
}
| {
readonly kind: "loader";
readonly modules: ReadonlyMap<string, SymbolicValue>;
}
| { readonly kind: "array"; readonly values: readonly SymbolicValue[] }
| {
readonly kind: "record";
readonly values: ReadonlyMap<string, SymbolicValue>;
}
| { readonly kind: "union"; readonly values: readonly SymbolicValue[] }
| SymbolicFunction
) &
SymbolicMetadata;
export const symbolicUnknown = (reason: string): SymbolicValue => ({
kind: "unknown",
reason,
});
export const symbolicVariants = (
value: SymbolicValue,
): readonly SymbolicValue[] =>
value.kind === "union" ? value.values : [value];
export const symbolicUnion = (
values: readonly SymbolicValue[],
): SymbolicValue => {
const unique = [...new Set(values.flatMap(symbolicVariants))];
return unique.length === 1 ? unique[0]! : { kind: "union", values: unique };
};
export const symbolicTruth = (value: SymbolicValue): boolean | undefined => {
if (value.kind === "union") {
const choices = value.values.map(symbolicTruth);
return choices.length > 0 &&
choices.every((choice) => choice === choices[0])
? choices[0]
: undefined;
}
return value.kind === "literal"
? Boolean(value.value)
: ["function", "object", "namespace", "array", "record", "loader"].includes(
value.kind,
)
? true
: undefined;
};
/** Attach selection predicates to values while preserving their representation. */
export const symbolicCondition = (
value: SymbolicValue,
condition: SymbolicCondition,
): SymbolicValue => {
if (value.kind === "union")
return symbolicUnion(
value.values.map((variant) => symbolicCondition(variant, condition)),
);
return { ...value, conditions: [...(value.conditions ?? []), condition] };
};
export const symbolicConditionsUnresolved = (
value: SymbolicValue,
): SymbolicValue => {
if (value.kind === "union")
return symbolicUnion(value.values.map(symbolicConditionsUnresolved));
return { ...value, conditionUnresolved: true };
};