From 09de11920c77d28f1faaf166fec5a9133a47b2e8 Mon Sep 17 00:00:00 2001 From: Malte Ubl Date: Sun, 25 Oct 2026 15:15:13 -0700 Subject: [PATCH] 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 --- .../src/frontend/lowering/lower-functions.ts | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/packages/compiler/src/frontend/lowering/lower-functions.ts b/packages/compiler/src/frontend/lowering/lower-functions.ts index 444134203..bd9b5f55d 100644 --- a/packages/compiler/src/frontend/lowering/lower-functions.ts +++ b/packages/compiler/src/frontend/lowering/lower-functions.ts @@ -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);