Files
reverse-engineering-anything/src/domain/javascriptSemanticIr.ts
T

202 lines
6.4 KiB
TypeScript

import type { JavaScriptSourceRange } from "./javascriptStaticAnalysisTypes.js";
/** Hard bounds for one execution-free JavaScript semantic analysis. */
export interface JavaScriptSemanticLimits {
readonly maxScopes: number;
readonly maxBindings: number;
readonly maxCallables: number;
readonly maxReferences: number;
readonly maxModuleLinks: number;
readonly maxValueDepth: number;
readonly maxUnionValues: number;
readonly maxObjectProperties: number;
}
/** Conservative defaults for one source file. */
export const DEFAULT_JAVASCRIPT_SEMANTIC_LIMITS: JavaScriptSemanticLimits = {
maxScopes: 4_096,
maxBindings: 20_000,
maxCallables: 20_000,
maxReferences: 100_000,
maxModuleLinks: 20_000,
maxValueDepth: 16,
maxUnionValues: 32,
maxObjectProperties: 256,
};
/** Primitive values admitted into the bounded constant lattice. */
export type JavaScriptSemanticPrimitive = string | number | boolean | null;
/** Bounded, execution-free value lattice for JavaScript expressions. */
export type JavaScriptSemanticValue =
| {
readonly status: "literal";
readonly value: JavaScriptSemanticPrimitive;
}
| {
readonly status: "union";
readonly values: readonly JavaScriptSemanticPrimitive[];
}
| {
readonly status: "object";
readonly properties: readonly JavaScriptSemanticProperty[];
readonly unknownProperties: boolean;
}
| {
readonly status: "array";
readonly items: readonly JavaScriptSemanticValue[];
readonly unknownItems: boolean;
}
| {
readonly status: "unknown" | "ambiguous" | "cycle" | "limit-reached";
readonly reason: string;
};
/** One statically named object-literal property. */
export interface JavaScriptSemanticProperty {
readonly name: string;
readonly value: JavaScriptSemanticValue;
}
/** One exact module origin followed through imports, requires, or aliases. */
export interface JavaScriptModuleOrigin {
readonly specifier: string;
readonly importedPath: readonly string[];
}
/** Fail-closed provenance classification for one binding. */
export interface JavaScriptBindingProvenance {
readonly status:
| "module"
| "local"
| "unknown"
| "ambiguous"
| "cycle"
| "limit-reached";
readonly origins: readonly JavaScriptModuleOrigin[];
readonly reason: string | null;
}
/** One lexical scope recovered without executing source. */
export interface JavaScriptSemanticScope {
readonly scopeId: string;
readonly parentScopeId: string | null;
readonly kind: "program" | "function" | "block" | "class" | "catch";
readonly location: JavaScriptSourceRange;
readonly bindingsComplete: boolean;
readonly bindingIds: readonly string[];
}
/** One declaration or assignment contributing to a binding. */
export interface JavaScriptSemanticDefinition {
readonly kind:
| "import"
| "variable"
| "parameter"
| "function"
| "class"
| "catch"
| "assignment";
readonly location: JavaScriptSourceRange;
}
/** One resolved lexical binding plus bounded value and provenance. */
export interface JavaScriptSemanticBinding {
readonly bindingId: string;
readonly scopeId: string;
readonly name: string;
readonly kind: JavaScriptSemanticDefinition["kind"];
readonly mutable: boolean;
readonly definitions: readonly JavaScriptSemanticDefinition[];
readonly value: JavaScriptSemanticValue;
readonly provenance: JavaScriptBindingProvenance;
}
/** One identifier use and its fail-closed lexical resolution. */
export interface JavaScriptSemanticReference {
readonly name: string;
readonly role: "read" | "write" | "export";
readonly location: JavaScriptSourceRange;
readonly bindingId: string | null;
readonly resolution: "resolved" | "unbound" | "ambiguous" | "unknown";
}
/** Function, class, or method identity without pretending it is a binding. */
export interface JavaScriptSemanticCallable {
readonly callableId: string;
readonly kind: "function" | "class" | "method";
readonly name: string | null;
readonly containerScopeId: string;
readonly bodyScopeId: string | null;
readonly location: JavaScriptSourceRange;
}
/** Static import/export relationship retained for cross-file composition. */
export interface JavaScriptSemanticModuleLink {
readonly kind:
| "import"
| "require"
| "export"
| "re-export"
| "commonjs-export";
readonly specifier: string | null;
readonly importedName: string | null;
readonly localName: string | null;
readonly exportedName: string | null;
readonly location: JavaScriptSourceRange;
}
/** Coverage for bounded semantic recovery. */
interface JavaScriptSemanticCoverage {
readonly status: "complete" | "partial" | "truncated" | "failed";
readonly omittedCount: number | null;
readonly limitsReached: readonly (keyof JavaScriptSemanticLimits)[];
}
/** Provider-neutral JavaScript semantic IR v1. */
export interface JavaScriptSemanticIr {
readonly schema: "JavaScriptSemanticIR";
readonly schemaVersion: 1;
readonly scopes: readonly JavaScriptSemanticScope[];
readonly bindings: readonly JavaScriptSemanticBinding[];
readonly callables: readonly JavaScriptSemanticCallable[];
readonly references: readonly JavaScriptSemanticReference[];
readonly moduleLinks: readonly JavaScriptSemanticModuleLink[];
readonly coverage: JavaScriptSemanticCoverage;
readonly limitations: readonly string[];
}
/** Find the innermost resolved reference at one source coordinate. */
export const semanticReferenceAt = (
ir: JavaScriptSemanticIr,
line: number,
column: number,
): JavaScriptSemanticReference | undefined =>
ir.references.find(
({ location }) =>
location.start.line === line && location.start.column === column,
);
/** Read one binding by its deterministic semantic identifier. */
export const semanticBinding = (
ir: JavaScriptSemanticIr,
bindingId: string,
): JavaScriptSemanticBinding | undefined =>
ir.bindings.find(({ bindingId: candidate }) => candidate === bindingId);
/** Fail-closed result when Babel cannot produce an inert syntax tree. */
export const failedJavaScriptSemanticIr = (): JavaScriptSemanticIr => ({
schema: "JavaScriptSemanticIR",
schemaVersion: 1,
scopes: [],
bindings: [],
callables: [],
references: [],
moduleLinks: [],
coverage: { status: "failed", omittedCount: null, limitsReached: [] },
limitations: [
"JavaScript parsing failed; no semantic absence claim is available.",
"No JavaScript was executed.",
],
});