mirror of
https://github.com/morluto/rea
synced 2026-10-26 06:16:17 -04:00
b8fab74297
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.
151 lines
4.9 KiB
TypeScript
151 lines
4.9 KiB
TypeScript
import * as t from "@babel/types";
|
|
|
|
import { semanticStaticPropertyKey } from "./javascriptAstValues.js";
|
|
import { moduleFactory } from "./javascriptStaticAnalysisHelpers.js";
|
|
import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
|
|
import {
|
|
resolveSemanticBindingState,
|
|
semanticStableInitializer,
|
|
type JavaScriptSemanticAnalysisState,
|
|
} from "./javascriptSemanticState.js";
|
|
|
|
/** A literal module table dispatched by a standalone CommonJS-style runtime. */
|
|
interface JavaScriptBootstrap {
|
|
readonly body: t.BlockStatement;
|
|
readonly table: t.ObjectExpression;
|
|
readonly loaderName: string;
|
|
readonly loaderBindingId: string;
|
|
readonly tableBindingId: string;
|
|
}
|
|
|
|
/** Recognize syntax, never invoke a bootstrap or infer it from variable names. */
|
|
export const javascriptBootstrapAt = (
|
|
call: t.CallExpression,
|
|
state: JavaScriptSemanticAnalysisState,
|
|
): JavaScriptBootstrap | undefined => {
|
|
if (
|
|
(!t.isFunctionExpression(call.callee) &&
|
|
!t.isArrowFunctionExpression(call.callee)) ||
|
|
!t.isBlockStatement(call.callee.body) ||
|
|
call.callee.params.length !== 0 ||
|
|
call.arguments.length !== 0
|
|
)
|
|
return undefined;
|
|
const body = call.callee.body;
|
|
const tables = new Map<string, t.ObjectExpression>();
|
|
for (const statement of body.body) {
|
|
if (!t.isVariableDeclaration(statement)) continue;
|
|
for (const declaration of statement.declarations) {
|
|
if (
|
|
t.isIdentifier(declaration.id) &&
|
|
t.isObjectExpression(declaration.init) &&
|
|
declaration.init.properties.length > 0 &&
|
|
declaration.init.properties.every(
|
|
(property) => moduleFactory(property) !== undefined,
|
|
)
|
|
) {
|
|
const binding = resolveSemanticBindingState(
|
|
state,
|
|
declaration.id,
|
|
declaration.id.name,
|
|
);
|
|
if (
|
|
binding !== undefined &&
|
|
semanticStableInitializer(binding, state)?.node === declaration.init
|
|
)
|
|
tables.set(binding.bindingId, declaration.init);
|
|
}
|
|
}
|
|
}
|
|
if (tables.size === 0) return undefined;
|
|
for (const loader of body.body) {
|
|
if (
|
|
!t.isFunctionDeclaration(loader) ||
|
|
loader.id === null ||
|
|
loader.id === undefined ||
|
|
loader.params.length !== 1
|
|
)
|
|
continue;
|
|
const parameter = loader.params[0];
|
|
if (!t.isIdentifier(parameter)) continue;
|
|
const loaderName = loader.id.name;
|
|
const loaderBindingId = bindingId(state, loader.id);
|
|
const parameterBindingId = bindingId(state, parameter);
|
|
if (loaderBindingId === undefined || parameterBindingId === undefined)
|
|
continue;
|
|
let tableBindingId: string | undefined;
|
|
traverseJavaScriptAst(loader.body, {
|
|
enter: (node, _parent, ancestors) => {
|
|
if (
|
|
!t.isCallExpression(node) ||
|
|
ancestors().some((node) => t.isFunction(node))
|
|
)
|
|
return;
|
|
const candidate = dispatchedTableBinding(
|
|
node,
|
|
loaderBindingId,
|
|
parameterBindingId,
|
|
state,
|
|
);
|
|
if (candidate !== undefined && tables.has(candidate))
|
|
tableBindingId = candidate;
|
|
},
|
|
});
|
|
const table =
|
|
tableBindingId === undefined ? undefined : tables.get(tableBindingId);
|
|
if (table !== undefined && tableBindingId !== undefined)
|
|
return { body, table, loaderName, loaderBindingId, tableBindingId };
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
const dispatchedTableBinding = (
|
|
call: t.CallExpression,
|
|
loaderBindingId: string,
|
|
keyBindingId: string,
|
|
state: JavaScriptSemanticAnalysisState,
|
|
): string | undefined => {
|
|
const member = call.callee;
|
|
const viaCall =
|
|
t.isMemberExpression(member) &&
|
|
semanticStaticPropertyKey(member.property, member.computed) === "call";
|
|
const dispatch =
|
|
viaCall && t.isMemberExpression(member) ? member.object : member;
|
|
if (
|
|
!t.isMemberExpression(dispatch) ||
|
|
!dispatch.computed ||
|
|
!t.isIdentifier(dispatch.object) ||
|
|
!t.isIdentifier(dispatch.property) ||
|
|
bindingId(state, dispatch.property) !== keyBindingId
|
|
)
|
|
return undefined;
|
|
const args = viaCall ? call.arguments.slice(1) : call.arguments;
|
|
const [module, exports, require] = args;
|
|
if (
|
|
args.length !== 3 ||
|
|
!t.isIdentifier(module) ||
|
|
bindingId(state, module) === undefined ||
|
|
!t.isMemberExpression(exports) ||
|
|
!t.isIdentifier(exports.object) ||
|
|
bindingId(state, exports.object) !== bindingId(state, module) ||
|
|
semanticStaticPropertyKey(exports.property, exports.computed) !==
|
|
"exports" ||
|
|
!t.isIdentifier(require) ||
|
|
bindingId(state, require) !== loaderBindingId
|
|
)
|
|
return undefined;
|
|
if (
|
|
viaCall &&
|
|
(!t.isNode(call.arguments[0]) ||
|
|
!t.isNodesEquivalent(call.arguments[0], exports))
|
|
)
|
|
return undefined;
|
|
return bindingId(state, dispatch.object);
|
|
};
|
|
|
|
const bindingId = (
|
|
state: JavaScriptSemanticAnalysisState,
|
|
identifier: t.Identifier,
|
|
): string | undefined =>
|
|
resolveSemanticBindingState(state, identifier, identifier.name)?.bindingId;
|