diff --git a/.changeset/start-compiler-module-info-ast-retention.md b/.changeset/start-compiler-module-info-ast-retention.md new file mode 100644 index 00000000000..871e90b7f3f --- /dev/null +++ b/.changeset/start-compiler-module-info-ast-retention.md @@ -0,0 +1,5 @@ +--- +'@tanstack/router-utils': patch +--- + +Stop the Start compiler's module cache from retaining parsed ASTs. `extractModuleInfoFromAst` now stores a detached clone of each binding's initializer, so a cached module no longer keeps the `@babel/traverse` `NodePath` and `Scope` graph of the file it came from reachable. diff --git a/packages/router-utils/src/compiler-helpers.ts b/packages/router-utils/src/compiler-helpers.ts index 5460c349141..4b9bdd2641a 100644 --- a/packages/router-utils/src/compiler-helpers.ts +++ b/packages/router-utils/src/compiler-helpers.ts @@ -95,7 +95,9 @@ function addVariableDeclarationModuleInfo( for (const name of collectIdentifiersFromPattern(declarator.id)) { bindings.set(name, { type: 'var', - init: declarator.init ?? null, + // Detached: `@babel/traverse` keys its caches on node identity, so + // storing the original would pin this file's whole traversal graph. + init: declarator.init ? t.cloneNode(declarator.init, true, true) : null, }) exportMap?.set(name, name) } @@ -552,7 +554,9 @@ export function extractModuleInfoFromAst(ast: t.File): ExtractedModuleInfo { const synth = '__default_export__' bindings.set(synth, { type: 'var', - init: t.isExpression(declaration) ? declaration : null, + init: t.isExpression(declaration) + ? t.cloneNode(declaration, true, true) + : null, }) exportMap.set('default', synth) }