From 1ccda45f7dcef77db7727a6a929ecf71ceea03d4 Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Tue, 20 Oct 2026 03:59:25 -0500 Subject: [PATCH] Decode an AST list's position only when it is read Every read of an AST list field built an AstNodeList whose pos and end were decoded from the wire first, though most readers only use `nodes`. The list now keeps the wire file and the list's index, and pos and end decode when they are read. The allocation per read stays the same size, and a decoded file still holds no list objects. --- packages/compiler/src/frontend/ts7/ast-node.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/compiler/src/frontend/ts7/ast-node.ts b/packages/compiler/src/frontend/ts7/ast-node.ts index 92ab5e4b8..3760fff8d 100644 --- a/packages/compiler/src/frontend/ts7/ast-node.ts +++ b/packages/compiler/src/frontend/ts7/ast-node.ts @@ -19,13 +19,22 @@ import { SyntaxKind, NodeFlags } from "./enums.js"; /** A list of child nodes with the list's own position, the shape of tsc-ts's * NodeList. The file keeps the nodes array, not this object: each read of a * list field returns a new AstNodeList over the same array, so `nodes` keeps - * its identity and a decoded file holds no list objects. */ + * its identity and a decoded file holds no list objects. The position is + * decoded from the wire when it is read; most readers only use `nodes`. */ export class AstNodeList { constructor( - readonly pos: number, - readonly end: number, + private readonly wire: AstWireFile, + private readonly index: number, readonly nodes: readonly T[], ) {} + + get pos(): number { + return this.wire.pos(this.index) >>> 0; + } + + get end(): number { + return this.wire.end(this.index) >>> 0; + } } /** One immutable AST response owns one object per node and one array per @@ -83,7 +92,7 @@ export class AstFile { this.lists[index] = nodes; this.materialized?.(); } - return new AstNodeList(this.wire.pos(index) >>> 0, this.wire.end(index) >>> 0, nodes); + return new AstNodeList(this.wire, index, nodes); } namedChild(node: AstNode, name: string): number {