mirror of
https://github.com/morluto/rea.git
synced 2026-11-04 05:46:17 +00:00
fix(javascript): distinguish Map lookups from network endpoints
Resolve unchanged Map operations through shared binding, capture, mutation, and ambient escape facts. Reuse that proof in application and captured bundle analysis; unresolved get/delete receivers remain inferred candidates. Preserve repeated native operations without manufacturing receiver escapes. Retain uncertainty for real escapes, opaque eval, and changed constructor adder hooks. Converge stored aliases at the producing boundary. Adapt the JavaScript changes from #4863, excluding its Linux resource fix. Add captured-bundle parity, repeated-operation and constructor-hook coverage. Fixes #4853 Co-authored-by: abdooo2235 <abdalrhmantheiv15@gmail.com>
This commit is contained in:
1 parent
e6c487799b
commit
fbfdb6abe9
16 files changed
+1021
-73
No files matched your search
@@ -0,0 +1,74 @@
|
||||
import * as t from "@babel/types";
|
||||
|
||||
import {
|
||||
semanticStaticPropertyName,
|
||||
unwrapJavaScriptExpression,
|
||||
} from "./javascriptAstValues.js";
|
||||
import { isUnmodifiedGlobalReference } from "./javascriptSemanticAmbientWrites.js";
|
||||
import { semanticOpaqueGlobalMayHaveChanged } from "./javascriptSemanticOpaqueEffects.js";
|
||||
import { semanticBindingAtRead } from "./javascriptSemanticMutationInitializers.js";
|
||||
import {
|
||||
resolveSemanticBindingState,
|
||||
semanticStableInitializer,
|
||||
type JavaScriptBindingIndex,
|
||||
type JavaScriptSemanticAnalysisState,
|
||||
} from "./javascriptSemanticState.js";
|
||||
|
||||
/** Prove an unchanged Map operation; undefined requests shared member-mutation facts. */
|
||||
export const isIntrinsicMapLookup = (
|
||||
node: t.CallExpression | t.OptionalCallExpression | t.NewExpression,
|
||||
bindings: JavaScriptSemanticAnalysisState,
|
||||
index?: Pick<JavaScriptBindingIndex, "referenceMayHaveChangedAt">,
|
||||
): boolean | undefined => {
|
||||
const callee = unwrapJavaScriptExpression(node.callee).node;
|
||||
if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee))
|
||||
return false;
|
||||
const method = semanticStaticPropertyName(callee.property, callee.computed);
|
||||
if (method !== "get" && method !== "delete") return false;
|
||||
const prototypeMemberMayHaveChanged = (member: string): boolean =>
|
||||
["Map", "Object"].some((owner) => {
|
||||
const path = ["global", owner, "prototype", member];
|
||||
return (
|
||||
bindings.ambientWrites.covers(path) ||
|
||||
bindings.ambientEscapes.covers(path)
|
||||
);
|
||||
});
|
||||
if (prototypeMemberMayHaveChanged(method)) return false;
|
||||
let receiver = unwrapJavaScriptExpression(callee.object).node;
|
||||
const seen = new Set<string>();
|
||||
while (t.isIdentifier(receiver)) {
|
||||
if (
|
||||
index !== undefined &&
|
||||
(index.referenceMayHaveChangedAt(node, receiver, [method]) ||
|
||||
index.referenceMayHaveChangedAt(node, receiver, ["__proto__"]))
|
||||
)
|
||||
return false;
|
||||
const binding = resolveSemanticBindingState(
|
||||
bindings,
|
||||
receiver,
|
||||
receiver.name,
|
||||
);
|
||||
if (binding === undefined || seen.has(binding.bindingId)) return false;
|
||||
seen.add(binding.bindingId);
|
||||
const initializer = semanticStableInitializer(binding, bindings);
|
||||
if (
|
||||
initializer === undefined ||
|
||||
initializer.projection.length !== 0 ||
|
||||
!semanticBindingAtRead(binding, receiver, bindings.parentsByNode)
|
||||
.hasDefiniteInitializer
|
||||
)
|
||||
return false;
|
||||
receiver = unwrapJavaScriptExpression(initializer.node).node;
|
||||
}
|
||||
if (
|
||||
!t.isNewExpression(receiver) ||
|
||||
!isUnmodifiedGlobalReference(receiver.callee, bindings, "Map")
|
||||
)
|
||||
return false;
|
||||
// Iterable construction reads and invokes the instance's set hook. A changed
|
||||
// adder can install its own get/delete before the constructed value is read.
|
||||
if (receiver.arguments.length > 0 && prototypeMemberMayHaveChanged("set"))
|
||||
return false;
|
||||
if (semanticOpaqueGlobalMayHaveChanged(callee, bindings)) return false;
|
||||
return index === undefined && seen.size > 0 ? undefined : true;
|
||||
};
|
||||
Reference in new issue
Block a user