Files
reverse-engineering-anything/src/domain/javascript/javascriptSemanticAliasSelections.ts
T
morluto cb4e5cfbff feat(analysis): make resource budgets recoverable across CLI and MCP (#9706)
* refactor(analysis): centralize resource budgets and recovery facts

* feat(analysis): expose ASAR and Ghidra runtime admission controls

* feat(artifacts): expose reader admission and preserve limited recognition

* feat(javascript): expose recoverable semantic precision budgets

* feat(web): add recoverable source-map budgets and compact retained views

* feat(web): make historical capture decoding budgets recoverable

* fix(desktop): enforce selected view policies across capture and export

* feat(runtime): make Frida and LLDB retention budgets selectable

* feat(native): expose diagnostic budgets and preserve exhaustion causes

* feat(managed): expose recoverable snapshot and representation budgets

* feat(metadata): make Go and Rust inspection budgets recoverable

* feat(wasm): expose representation and producer admissions

* feat(evm): expose per-call worker resource budgets

* feat(android): make resource and string-pool omissions recoverable

* feat(producers): expose command and recorded-capture budgets

* docs(analysis): record recovery contracts and integrated validation

* fix(docs): link calibration oracle from published verification pages

* fix(docs): restore desktop task anchors and receipt links

* test(analysis): align fixtures with selectable budget contracts

* fix(analysis): remove source-location projector dependency cycle

* test(analysis): refresh budget recovery and verifier regressions

* test(analysis): preserve format and publication recovery expectations

* test(windows): align conformance with owned runtime admission

* fix(desktop): preserve selected alias kinds in exported state

* test(analysis): align provider fixtures with recoverable budgets

* test(desktop): validate emitted alias metadata structurally

* fix(ghidra): classify bounded Windows endpoint refusals

* test(cli): assert selectable artifact admission recovery

* fix(cli): preserve capture provenance in environment builds
2026-11-10 05:11:20 -05:00

127 lines
4.0 KiB
TypeScript

import type { JavaScriptSemanticPropertyPath } from "./javascriptSemanticPropertyPaths.js";
import { JAVASCRIPT_SEMANTIC_PRECISION_DEFAULTS } from "./javascriptSemanticPrecision.js";
type PropertyKey = JavaScriptSemanticPropertyPath[number];
/** Finite alternatives retain selected keys without admitting unrelated slots. */
export type SemanticAliasSelection =
| PropertyKey
| { readonly alternatives: readonly PropertyKey[] };
export type SemanticAliasSelectionPath = readonly SemanticAliasSelection[];
export const semanticAliasSelectionChoices = (
key: SemanticAliasSelection,
): readonly PropertyKey[] =>
key !== null && typeof key === "object" && "alternatives" in key
? key.alternatives
: [key];
const selection = (choices: readonly PropertyKey[]): SemanticAliasSelection => {
if (choices.includes(null)) return null;
const alternatives = [
...new Map(choices.map((choice) => [JSON.stringify(choice), choice])),
]
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
.map(([, choice]) => choice);
return alternatives.length === 1 ? alternatives[0]! : { alternatives };
};
const selectionCovers = (
prior: SemanticAliasSelection,
next: SemanticAliasSelection,
): boolean => {
if (prior === null) return true;
const choices = new Set(
semanticAliasSelectionChoices(prior).map((key) => JSON.stringify(key)),
);
return semanticAliasSelectionChoices(next).every((key) =>
choices.has(JSON.stringify(key)),
);
};
const pathCovers = (
prior: SemanticAliasSelectionPath,
next: SemanticAliasSelectionPath,
): boolean =>
prior.every(
(key, index) =>
next[index] !== undefined && selectionCovers(key, next[index]!),
);
/** Only one differing selector can be joined without inventing crossed paths. */
const joinSelections = (
prior: SemanticAliasSelectionPath,
next: SemanticAliasSelectionPath,
): SemanticAliasSelectionPath | undefined => {
let changed = -1;
for (let index = 0; index < prior.length; index++) {
if (JSON.stringify(prior[index]) === JSON.stringify(next[index])) continue;
if (changed !== -1) return undefined;
changed = index;
}
return prior.map((key, index) =>
index === changed
? selection([
...semanticAliasSelectionChoices(key),
...semanticAliasSelectionChoices(next[index]!),
])
: key,
);
};
/** Preserve correlated selector alternatives while coalescing complete grids. */
export class SemanticAliasSelections {
#paths = new WeakMap<object, Map<number, SemanticAliasSelectionPath[]>>();
#calls = 0;
#limited = false;
constructor(
readonly onLimit: () => void,
readonly maxSelections: number = JAVASCRIPT_SEMANTIC_PRECISION_DEFAULTS.alias_selections,
) {}
get limited(): boolean {
return this.#limited;
}
normalize(
node: object,
next: SemanticAliasSelectionPath,
): SemanticAliasSelectionPath {
if (this.#limited) return next.map(() => null);
const existing = this.#paths.get(node);
const byDepth = existing ?? new Map<number, SemanticAliasSelectionPath[]>();
const paths = [...(byDepth.get(next.length) ?? [])];
let candidate = next.map((key) =>
selection(semanticAliasSelectionChoices(key)),
);
const covered = paths.find((prior) => pathCovers(prior, candidate));
if (covered !== undefined) return covered;
if (existing !== undefined && ++this.#calls > this.maxSelections) {
this.#limited = true;
this.#paths = new WeakMap();
this.onLimit();
return next.map(() => null);
}
for (let index = 0; index < paths.length;) {
const prior = paths[index]!;
if (pathCovers(prior, candidate)) return prior;
const joined = pathCovers(candidate, prior)
? candidate
: joinSelections(prior, candidate);
if (joined === undefined) {
index++;
continue;
}
candidate = [...joined];
paths.splice(index, 1);
index = 0;
}
paths.push(candidate);
byDepth.set(candidate.length, paths);
this.#paths.set(node, byDepth);
return candidate;
}
}