mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Fold navigator member reads under optional chains (#1954)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { isNavigatorGlobal } from "../builtins/navigator.js";
|
||||
import { isSafeToDiscard } from "./evaluation-safety.js";
|
||||
import { completeFuncValueArgs } from "../call-arguments.js";
|
||||
import { dynUndefinedExpr } from "../../../ir/build.js";
|
||||
@@ -223,6 +224,16 @@ export function lowerOptionalChain(
|
||||
// Native handle methods have no first-class value to guard; when the
|
||||
// method read itself has no lowering, re-dispatch the plain call (which
|
||||
// reports its own diagnostics) instead of failing on the value read.
|
||||
// `navigator?.userAgent`: Node's navigator global is never nullish and
|
||||
// has no value form, so the guarded step is the plain member read.
|
||||
if (isNavigatorGlobal(lowerer, recvNode)) {
|
||||
lowerer.chainHandled.add(dotNode);
|
||||
try {
|
||||
return lowerer.lowerExpr(expr);
|
||||
} finally {
|
||||
lowerer.chainHandled.delete(dotNode);
|
||||
}
|
||||
}
|
||||
let loweredReceiver: IrExpr | null;
|
||||
if (dotNode === expr && alwaysPresentStdlibMethod(lowerer, recvNode)) {
|
||||
loweredReceiver = tryLowerExpression(lowerer, recvNode);
|
||||
|
||||
@@ -306,10 +306,10 @@ export function lowerPropertyAccessExpr(
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!expr.questionDotToken) {
|
||||
const navigator = lowerNavigatorMember(lowerer, expr, NODE_COMPAT_VERSION);
|
||||
if (navigator) return navigator;
|
||||
}
|
||||
// Node's navigator is never nullish, so `navigator?.userAgent` (zod's
|
||||
// Cloudflare probe) folds like `navigator.userAgent`.
|
||||
const navigator = lowerNavigatorMember(lowerer, expr, NODE_COMPAT_VERSION);
|
||||
if (navigator) return navigator;
|
||||
// A dgram socket's method read as a value in JavaScript (`emit:
|
||||
// socket.emit.bind(socket)`): the socket crosses as its checked-dynamic
|
||||
// handle, whose methods are function values that dispatch on their
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/7600-navigator-optional-chain.js"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Node's navigator global read through optional chains (zod 4's
|
||||
// `navigator?.userAgent?.includes("Cloudflare")` probe): navigator is
|
||||
// never nullish, so each chain answers like the plain member read.
|
||||
const cloudflare = typeof navigator !== "undefined" && navigator?.userAgent?.includes("Cloudflare");
|
||||
console.log(cloudflare);
|
||||
console.log(navigator?.userAgent === navigator.userAgent, navigator?.userAgent?.startsWith("Node.js/"));
|
||||
console.log(navigator?.userAgent?.split("/")[0] ?? "none");
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 3000, "san": 22000 }
|
||||
Reference in New Issue
Block a user