fix(js): resolve literal URL from Request constructor in fetch calls (#6364)

* fix(js): resolve literal URL from Request constructor in fetch calls

* fix(js): gate Request URL extraction on fetch and require new operator
This commit is contained in:
Ahmed authored and GitHub committed 2026-10-23 05:38:17 +08:00
1 parent ee0ec027db
commit 3984d12a30
2 files changed
+153 -8

No files matched your search

@@ -434,6 +434,26 @@ export const indexVitePreloadDependencyTable = (
return escapedOrMutated ? dependencies.map(() => undefined) : dependencies;
};
const isFetchCall = (
node: t.Node,
bindings: JavaScriptSemanticAnalysisState,
): boolean =>
(t.isCallExpression(node) || t.isOptionalCallExpression(node)) &&
isUnmodifiedGlobalReference(node.callee, bindings, "fetch");
const requestConstructorUrl = (
node: t.Node,
bindings: JavaScriptSemanticAnalysisState,
): string | undefined => {
const target = unwrapJavaScriptExpression(node).node;
if (
t.isNewExpression(target) &&
isUnmodifiedGlobalReference(target.callee, bindings, "Request")
)
return stringValue(target.arguments[0]);
return undefined;
};
const inspectEndpointCall = (
node: JavaScriptCallLike,
name: string,
@@ -444,7 +464,11 @@ const inspectEndpointCall = (
if (isKnownNetworkRequest(node, bindings)) {
const target = argumentNode(node.arguments[0]);
if (target === undefined) return;
const literal = stringValue(target);
const literal =
stringValue(target) ??
(isFetchCall(node, bindings)
? requestConstructorUrl(target, bindings)
: undefined);
if (literal !== undefined) {
addEndpoint(context, {
node,
@@ -529,11 +553,7 @@ const isKnownNetworkRequest = (
node: JavaScriptCallLike,
bindings: JavaScriptSemanticAnalysisState,
): boolean => {
if (
(t.isCallExpression(node) || t.isOptionalCallExpression(node)) &&
isUnmodifiedGlobalReference(node.callee, bindings, "fetch")
)
return true;
if (isFetchCall(node, bindings)) return true;
if (
t.isNewExpression(node) &&
(isUnmodifiedGlobalReference(node.callee, bindings, "WebSocket") ||
@@ -655,6 +675,7 @@ const urlObjectRequestTarget = (
bindings: JavaScriptSemanticAnalysisState,
index: JavaScriptBindingIndex,
seen = new Set<string>(),
isToString = false,
): string | undefined => {
let target = unwrapJavaScriptExpression(node).node;
if (
@@ -666,8 +687,10 @@ const urlObjectRequestTarget = (
(t.isMemberExpression(callee) || t.isOptionalMemberExpression(callee)) &&
semanticStaticPropertyName(callee.property, callee.computed) ===
"toString"
)
) {
target = unwrapJavaScriptExpression(callee.object).node;
isToString = true;
}
}
if (!t.isIdentifier(target) || index.referenceMayHaveChangedAt(site, target))
return undefined;
@@ -688,7 +711,18 @@ const urlObjectRequestTarget = (
if (initializer === undefined) return undefined;
const initialized = unwrapJavaScriptExpression(initializer).node;
if (t.isIdentifier(initialized))
return urlObjectRequestTarget(initialized, site, bindings, index, seen);
return urlObjectRequestTarget(
initialized,
site,
bindings,
index,
seen,
isToString,
);
if (!isToString && isFetchCall(site, bindings)) {
const requestUrl = requestConstructorUrl(initialized, bindings);
if (requestUrl !== undefined) return requestUrl;
}
if (!t.isNewExpression(initialized)) return undefined;
if (!isUnmodifiedGlobalReference(initialized.callee, bindings, "URL"))
return undefined;