fix(router-utils): cache a descriptor instead of the initializer AST node - #8296
fix(router-utils): cache a descriptor instead of the initializer AST node#8296sverrejoh wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe compiler now stores compact expression summaries instead of Babel expression nodes. Router utilities expose the summary type and helper. Start compiler kind resolution consumes summarized identifiers, members, and calls. ChangesExpression summary retention
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This change replaces retained initializer ASTs with compact summaries while preserving supported compiler kind resolution, reducing development-server memory retention without an identified current-head merge risk. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 4 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…AST nodes `extractModuleInfoFromAst` stored each `var` binding's initializer as the `t.Expression` node from the parsed file. `StartCompiler.moduleCache` keeps that module info for as long as the module is known, so in a dev server the node stays reachable for the process lifetime. `@babel/traverse` keys its `NodePath` and `Scope` caches on node identity (`WeakMap<node, ...>`), which is what normally lets a file's traversal state be collected once the AST is dropped. Holding one node from a file defeats that for the whole file: the cache entry chains through `NodePath.parentPath` up to the Program path and through `NodePath.scope` into every binding in the file. In a heap snapshot of our dev server these retained graphs survived a full GC. The only consumers, `resolveBindingKind` and `resolveExprKind`, read whether the expression is an identifier, a member access or a call, plus the names involved. They never read call arguments, source positions, scope or parent links. Store that projection instead of the node: - add `ExpressionSummary` and `summarizeExpression` to `@tanstack/router-utils` - change `ModuleInfoBinding['init']` to `ExpressionSummary | null` - resolve kinds from the summary in `StartCompiler` The summary is built with the same shape checks the resolvers used, so results are unchanged, and expressions the resolvers cannot act on summarize to `null`, which they already treat like an absent initializer. Resolving from a three-variant union also lets `resolveExprKind` drop its accumulator and its duplicated callee branches. Measured on our app: 11.6% less peak dev-server memory over four paired cold runs, with byte-identical build output.
eb9628e to
f37c22e
Compare
🎯 Changes
Alternative to #8215, which stops the same leak by cloning the node instead.
@babel/traversekeys itsNodePathandScopecaches on node identity, andthe Start compiler keeps the initializer node in its module cache for the life
of the dev server, so the file's traversal graph is never collected.
Rather than cloning the node, store only what the resolvers actually read. They
follow
callee,object, an identifierproperty, andname, never callarguments or source positions, so the cached shape can be a small descriptor:
✅ Checklist
🚀 Release Impact
Summary by CodeRabbit