mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
* fix(javascript): resolve module-level Electron options in functions * fix(javascript): limit module option ancestry walk * fix(javascript): preserve uncertain captured argument ordering * fix(javascript): retain hoisted activation uncertainty * fix(javascript): retain function ownership through loops * fix(javascript): account for classic global activations * fix(javascript): bind first activations to lexical identities * fix(javascript): retain uncertain global activation timing * fix(javascript): isolate receiver facts and share computed reads * fix(javascript): retain projected and opaque global activations * fix(javascript): refresh activation bounds as opaque effects grow * fix(ci): format website watch directories without changing configuration * fix(javascript): share source reads across opaque-effect updates * fix(javascript): retain constructed-code global activation bounds * fix(javascript): share runtime activation and receiver facts * fix(javascript): reuse pattern reads and function positions * fix(javascript): isolate copied paths and preserve runtime reads * style(javascript): format migrated reference imports * fix(javascript): normalize constructor activation and receiver effects * fix(javascript): retain aliased receiver timing and lexical global this * fix(javascript): preserve effect-free receiver identity across activations * fix(javascript): retain outer activation and prototype effects * fix(javascript): index implicit reads without deep path rescans * fix(javascript): retain aliased prototype and parameter read uncertainty * fix(javascript): index reflected reads through intrinsic invocation facts * fix(javascript): retain unresolved global activation reads * chore: refresh PR branch after review fix publication * fix(javascript): retain projected receiver reads and cache method facts * fix(javascript): retain inherited and implicit activation reads * fix(javascript): retain caller-owned this uncertainty * fix(javascript): retain reflected reads with unresolved spread arguments * fix(javascript): preserve enclosing activation for decorators * fix(javascript): track intrinsic literal prototype effects * fix(javascript): retain catch activation from implicit reads * perf(javascript): reuse effective keys for projected reads * fix(javascript): retain possible caller-owned ambient effects
115 lines
4.0 KiB
TypeScript
115 lines
4.0 KiB
TypeScript
import { completeSemanticSteps } from "./javascriptSemanticTraversal.js";
|
|
import {
|
|
semanticStaticPropertyName,
|
|
unwrapJavaScriptExpression,
|
|
} from "./javascriptAstValues.js";
|
|
import { semanticBindingAtRead } from "./javascriptSemanticMutationInitializers.js";
|
|
import { semanticOpaqueGlobalMayHaveChanged } from "./javascriptSemanticOpaqueEffects.js";
|
|
import {
|
|
resolveSemanticBindingState,
|
|
semanticStableInitializer,
|
|
type JavaScriptBindingIndex,
|
|
type JavaScriptSemanticAnalysisState,
|
|
} from "./javascriptSemanticState.js";
|
|
import * as t from "@babel/types";
|
|
import { isUnmodifiedGlobalReference } from "./javascriptSemanticAmbientWrites.js";
|
|
|
|
export const isFetchCall = (
|
|
node: t.Node,
|
|
bindings: JavaScriptSemanticAnalysisState,
|
|
): boolean =>
|
|
(t.isCallExpression(node) || t.isOptionalCallExpression(node)) &&
|
|
isUnmodifiedGlobalReference(node.callee, bindings, "fetch");
|
|
|
|
/** Browser request identity requires an intact intrinsic, not a method spelling. */
|
|
export const isBrowserNetworkRequest = (
|
|
node: t.CallExpression | t.OptionalCallExpression | t.NewExpression,
|
|
bindings: JavaScriptSemanticAnalysisState,
|
|
): boolean =>
|
|
isFetchCall(node, bindings) ||
|
|
(t.isNewExpression(node) &&
|
|
(isUnmodifiedGlobalReference(node.callee, bindings, "WebSocket") ||
|
|
isUnmodifiedGlobalReference(node.callee, bindings, "EventSource"))) ||
|
|
((t.isCallExpression(node) || t.isOptionalCallExpression(node)) &&
|
|
isUnmodifiedGlobalReference(node.callee, bindings, [
|
|
"navigator",
|
|
"sendBeacon",
|
|
]));
|
|
|
|
const isXhrOpenRequest = (
|
|
node: t.Node,
|
|
bindings: JavaScriptSemanticAnalysisState,
|
|
index?: Pick<JavaScriptBindingIndex, "referenceMayHaveChangedAt">,
|
|
): boolean | undefined => {
|
|
if (!t.isCallExpression(node) && !t.isOptionalCallExpression(node))
|
|
return false;
|
|
const callee = unwrapJavaScriptExpression(node.callee).node;
|
|
if (
|
|
(!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) ||
|
|
semanticStaticPropertyName(callee.property, callee.computed) !== "open"
|
|
)
|
|
return false;
|
|
if (
|
|
["XMLHttpRequest", "Object"].some((owner) =>
|
|
["open", "__proto__"].some(
|
|
(member) =>
|
|
bindings.ambientWrites.covers([
|
|
"global",
|
|
owner,
|
|
"prototype",
|
|
member,
|
|
]) ||
|
|
bindings.ambientEscapes.covers([
|
|
"global",
|
|
owner,
|
|
"prototype",
|
|
member,
|
|
]),
|
|
),
|
|
)
|
|
)
|
|
return false;
|
|
let receiver = unwrapJavaScriptExpression(callee.object).node;
|
|
const seen = new Set<string>();
|
|
while (t.isIdentifier(receiver)) {
|
|
if (
|
|
index !== undefined &&
|
|
(index.referenceMayHaveChangedAt(node, receiver, ["open"]) ||
|
|
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).hasDefiniteInitializer
|
|
)
|
|
return false;
|
|
receiver = unwrapJavaScriptExpression(initializer.node).node;
|
|
}
|
|
if (
|
|
!t.isNewExpression(receiver) ||
|
|
!isUnmodifiedGlobalReference(receiver.callee, bindings, "XMLHttpRequest") ||
|
|
semanticOpaqueGlobalMayHaveChanged(callee, bindings)
|
|
)
|
|
return false;
|
|
return index === undefined && seen.size > 0 ? undefined : true;
|
|
};
|
|
|
|
/** Resolve once through the shared mutation index when lexical proof needs it. */
|
|
export const createXhrOpenRequestQuery =
|
|
(index: JavaScriptBindingIndex): ((node: t.Node) => boolean) =>
|
|
(node) => {
|
|
const proof = isXhrOpenRequest(node, index.bindings);
|
|
if (proof !== undefined) return proof;
|
|
completeSemanticSteps(index.indexMemberMutationFactsSteps());
|
|
return isXhrOpenRequest(node, index.bindings, index) === true;
|
|
};
|