Keep the receiver read in every JavaScript function for now

Skipping it in functions without `this` missed methods that read the
receiver through super (8302-class-super-method-values,
prototype-method-overrides) and changes the default build's dynamic-tier
counts. It changes the default JavaScript lowering, so it gets its own PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Malte Ubl
2026-10-25 15:15:13 -07:00
co-authored by Claude Opus 5.5
parent f10f7c42b4
commit 09de11920c
@@ -62,29 +62,6 @@ function declareCallReceiver(
};
}
/** Whether a JavaScript function's own `this` can be read: a `this` in its
* parameters or body, outside nested non-arrow functions (which bind their
* own). Conservative inside classes and object literal methods. A function
* that never reads it skips the ambient receiver read at entry. */
function readsOwnThis(node: ts.FunctionLikeDeclaration): boolean {
let found = false;
const visit = (n: ts.Node): void => {
if (found) return;
if (n.kind === ts.SyntaxKind.ThisKeyword) {
found = true;
return;
}
if (ts.isFunctionDeclaration(n) || ts.isFunctionExpression(n)) return;
ts.forEachChild(n, (c) => {
visit(c);
return undefined;
});
};
for (const p of node.parameters.nodes) visit(p);
if (node.body !== undefined) visit(node.body);
return found;
}
/** True when the identifier resolves (through import aliases) to a
* top-level function declaration of ANY program file (not merely a
* same-named local shadowing one). Functions declared directly in a
@@ -359,7 +336,7 @@ export function lowerLambda(
try {
const receiver =
(checkedReceiver ||
(isJsSourceFile(ts.getSourceFileOfNode(node)) && readsOwnThis(node)) ||
isJsSourceFile(ts.getSourceFileOfNode(node)) ||
node.parameters.nodes.some(isThisParameter)) &&
!ts.isArrowFunction(node)
? declareCallReceiver(lowerer, node, isGenerator)
@@ -564,8 +541,7 @@ export function lowerFunction(lowerer: Lowerer, decl: ts.FunctionDeclaration): I
const argumentCount: IrStmt[] = [];
declareArgumentCount(lowerer, decl, argumentCount);
const receiver =
decl.parameters.nodes.some(isThisParameter) ||
(isJsSourceFile(ts.getSourceFileOfNode(decl)) && readsOwnThis(decl))
decl.parameters.nodes.some(isThisParameter) || isJsSourceFile(ts.getSourceFileOfNode(decl))
? declareCallReceiver(lowerer, decl, sig.generator !== undefined)
: null;
const { params, prologue } = lowerer.declareParams(decl.parameters.nodes, sig.params);