mirror of
https://github.com/morluto/rea
synced 2026-10-27 22:45:19 -04:00
fix(javascript): derive loader references from lexical binding ownership
Use shared lexical bindings and recovered bundler identities for require and chunk references. Preserve uncertain writes as unresolved evidence; remove name-only loader aliases and repeated definition scans. Reviewed-PR: #2989 Co-authored-by: Hussnain Ahmad <ha7886899@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
resolveSemanticBindingState,
|
||||
type JavaScriptSemanticAnalysisState,
|
||||
} from "./javascriptSemanticState.js";
|
||||
import { semanticFactoryLoaderMemberAt } from "./javascriptSemanticRequireOrigin.js";
|
||||
|
||||
import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
|
||||
|
||||
@@ -46,7 +47,11 @@ export const inspectBundlerRegistration = (
|
||||
if (runtime === undefined || !t.isArrayExpression(entry)) return;
|
||||
const chunkIds = entry.elements[0];
|
||||
const table = entry.elements[1];
|
||||
const runtimeValue = runtimeMetadata(entry.elements[2]);
|
||||
const runtimeValue = runtimeMetadata(
|
||||
entry.elements[2],
|
||||
bindings,
|
||||
accumulator,
|
||||
);
|
||||
if (!t.isArrayExpression(chunkIds) || !t.isObjectExpression(table)) return;
|
||||
const recovered = recoverBundlerModules(source, table, accumulator, {
|
||||
runtime,
|
||||
@@ -253,7 +258,21 @@ const recoverBundlerModule = (
|
||||
const fingerprint = fingerprintJavaScriptAst(factory);
|
||||
const exportsValue = collectJavaScriptExports(factory, bindings);
|
||||
const requireName = factoryRequireName(factory);
|
||||
const asyncChunks = collectBundlerAsyncChunkKeys(factory, requireName);
|
||||
const requireParameter = runtimeFunctionParameters(factory)[2];
|
||||
const requireBindingId = t.isIdentifier(requireParameter)
|
||||
? (resolveSemanticBindingState(
|
||||
bindings,
|
||||
requireParameter,
|
||||
requireParameter.name,
|
||||
)?.bindingId ?? null)
|
||||
: null;
|
||||
if (requireBindingId !== null)
|
||||
accumulator.factoryRequireBindingIds.add(requireBindingId);
|
||||
const asyncChunks = collectBundlerAsyncChunkKeys(
|
||||
factory,
|
||||
requireBindingId,
|
||||
bindings,
|
||||
);
|
||||
if (typeof factory.start === "number" && typeof factory.end === "number") {
|
||||
const moduleRange = {
|
||||
start: factory.start,
|
||||
@@ -297,7 +316,11 @@ type BundlerFunction =
|
||||
| t.ArrowFunctionExpression
|
||||
| t.ObjectMethod;
|
||||
|
||||
const runtimeMetadata = (node: t.Node | null | undefined): RuntimeMetadata => {
|
||||
const runtimeMetadata = (
|
||||
node: t.Node | null | undefined,
|
||||
bindings: JavaScriptSemanticAnalysisState,
|
||||
accumulator: AnalysisAccumulator,
|
||||
): RuntimeMetadata => {
|
||||
if (!isBundlerFunction(node))
|
||||
return {
|
||||
requireName: null,
|
||||
@@ -308,6 +331,12 @@ const runtimeMetadata = (node: t.Node | null | undefined): RuntimeMetadata => {
|
||||
};
|
||||
const parameter = runtimeFunctionParameters(node)[0];
|
||||
const requireName = t.isIdentifier(parameter) ? parameter.name : null;
|
||||
const requireBindingId = t.isIdentifier(parameter)
|
||||
? (resolveSemanticBindingState(bindings, parameter, parameter.name)
|
||||
?.bindingId ?? null)
|
||||
: null;
|
||||
if (requireBindingId !== null)
|
||||
accumulator.factoryRequireBindingIds.add(requireBindingId);
|
||||
if (requireName === null)
|
||||
return {
|
||||
requireName,
|
||||
@@ -316,8 +345,18 @@ const runtimeMetadata = (node: t.Node | null | undefined): RuntimeMetadata => {
|
||||
asyncChunkKeys: [],
|
||||
unknownAsyncChunkKeys: 0,
|
||||
};
|
||||
const entries = collectBundlerCallArgumentValues(node, requireName);
|
||||
const asyncChunks = collectBundlerAsyncChunkKeys(node, requireName);
|
||||
const entries = collectBundlerCallArgumentValues(
|
||||
node,
|
||||
requireBindingId,
|
||||
bindings,
|
||||
null,
|
||||
);
|
||||
const asyncChunks = collectBundlerCallArgumentValues(
|
||||
node,
|
||||
requireBindingId,
|
||||
bindings,
|
||||
"e",
|
||||
);
|
||||
return {
|
||||
requireName,
|
||||
entryModuleKeys: entries.values,
|
||||
@@ -329,23 +368,43 @@ const runtimeMetadata = (node: t.Node | null | undefined): RuntimeMetadata => {
|
||||
|
||||
const collectBundlerAsyncChunkKeys = (
|
||||
factory: BundlerFunction,
|
||||
requireName: string | null,
|
||||
requireBindingId: string | null,
|
||||
bindings: JavaScriptSemanticAnalysisState,
|
||||
): StaticValues =>
|
||||
requireName === null
|
||||
requireBindingId === null
|
||||
? { values: [], unknown: 0 }
|
||||
: collectBundlerCallArgumentValues(factory, `${requireName}.e`);
|
||||
: collectBundlerCallArgumentValues(
|
||||
factory,
|
||||
requireBindingId,
|
||||
bindings,
|
||||
"e",
|
||||
);
|
||||
|
||||
const collectBundlerCallArgumentValues = (
|
||||
factory: BundlerFunction,
|
||||
callee: string,
|
||||
bindingId: string | null,
|
||||
bindings: JavaScriptSemanticAnalysisState,
|
||||
member: string | null,
|
||||
): StaticValues => {
|
||||
if (bindingId === null) return { values: [], unknown: 0 };
|
||||
const values: string[] = [];
|
||||
let unknown = 0;
|
||||
const bindingIds = new Set([bindingId]);
|
||||
traverseJavaScriptAst(factory, {
|
||||
enter: (node) => {
|
||||
if (!t.isCallExpression(node) && !t.isNewExpression(node))
|
||||
return undefined;
|
||||
if (calleeName(node.callee) !== callee) return undefined;
|
||||
const loader = semanticFactoryLoaderMemberAt(
|
||||
node,
|
||||
bindings,
|
||||
bindingIds,
|
||||
member,
|
||||
);
|
||||
if (loader === undefined) return undefined;
|
||||
if (loader === "unknown") {
|
||||
unknown += 1;
|
||||
return undefined;
|
||||
}
|
||||
const value = argumentValue(node.arguments[0]);
|
||||
if (value === undefined) unknown += 1;
|
||||
else values.push(value);
|
||||
|
||||
Reference in New Issue
Block a user