From 1a51b803f37f1b6bfe4075b9be6ef7d8fff8916b Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 3 Jun 2026 14:37:58 +0200 Subject: [PATCH 1/3] Revert #7524 --- .changeset/solid-symbols-sink.md | 5 ++ packages/router-core/src/ssr/tsrScript.ts | 13 +---- .../tests/tsr-script-teardown.test.ts | 56 +++++++++++++++++++ 3 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 .changeset/solid-symbols-sink.md create mode 100644 packages/router-core/tests/tsr-script-teardown.test.ts diff --git a/.changeset/solid-symbols-sink.md b/.changeset/solid-symbols-sink.md new file mode 100644 index 0000000000..81200c60ec --- /dev/null +++ b/.changeset/solid-symbols-sink.md @@ -0,0 +1,5 @@ +--- +'@tanstack/router-core': patch +--- + +delete $\_TSR immediately on stream end diff --git a/packages/router-core/src/ssr/tsrScript.ts b/packages/router-core/src/ssr/tsrScript.ts index 0c4b8f703b..69c9abe05d 100644 --- a/packages/router-core/src/ssr/tsrScript.ts +++ b/packages/router-core/src/ssr/tsrScript.ts @@ -9,17 +9,8 @@ self.$_TSR = { }, c() { if (this.hydrated && this.streamEnded) { - const cleanup = () => { - if (self.$_TSR?.hydrated && self.$_TSR?.streamEnded) { - delete self.$_TSR - delete self.$R['tsr'] - } - } - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', cleanup, { once: true }) - } else { - cleanup() - } + delete self.$_TSR + delete self.$R['tsr'] } }, p(script) { diff --git a/packages/router-core/tests/tsr-script-teardown.test.ts b/packages/router-core/tests/tsr-script-teardown.test.ts new file mode 100644 index 0000000000..2a60271e5a --- /dev/null +++ b/packages/router-core/tests/tsr-script-teardown.test.ts @@ -0,0 +1,56 @@ +import { afterEach, beforeEach, describe, expect, test } from 'vitest' +import minifiedTsrBootStrapScript from '../src/ssr/tsrScript?script-string' + +type TsrBootstrap = { + h: () => void + e: () => void + c: () => void +} + +// Assign `self.$_TSR`. +function installBootstrap(): TsrBootstrap { + new Function(minifiedTsrBootStrapScript)() + return (window as any).$_TSR +} + +function setReadyState(value: DocumentReadyState) { + Object.defineProperty(document, 'readyState', { + configurable: true, + get: () => value, + }) +} + +describe('$_TSR client teardown', () => { + beforeEach(() => { + ;(window as any).$R = { tsr: [] } + delete (window as any).$_TSR + }) + + afterEach(() => { + delete (window as any).$_TSR + delete (window as any).$R + setReadyState('complete') + }) + + test('does not tear down until both hydrated and streamEnded', () => { + setReadyState('complete') + const tsr = installBootstrap() + + tsr.h() + expect((window as any).$_TSR).toBeDefined() + + tsr.e() + expect((window as any).$_TSR).toBeUndefined() + }) + + test('tears down immediately when the document is already parsed', () => { + setReadyState('complete') + const tsr = installBootstrap() + + tsr.h() + tsr.e() + + expect((window as any).$_TSR).toBeUndefined() + expect((window as any).$R.tsr).toBeUndefined() + }) +}) \ No newline at end of file From 574e19ae33b7c633a0e8a3c69d93d6f8c16ee186 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 12:39:35 +0000 Subject: [PATCH 2/3] ci: apply automated fixes --- packages/router-core/tests/tsr-script-teardown.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/router-core/tests/tsr-script-teardown.test.ts b/packages/router-core/tests/tsr-script-teardown.test.ts index 2a60271e5a..432e2350fb 100644 --- a/packages/router-core/tests/tsr-script-teardown.test.ts +++ b/packages/router-core/tests/tsr-script-teardown.test.ts @@ -53,4 +53,4 @@ describe('$_TSR client teardown', () => { expect((window as any).$_TSR).toBeUndefined() expect((window as any).$R.tsr).toBeUndefined() }) -}) \ No newline at end of file +}) From 00b5045f3ab3db40d0571ee32cedc61aa1fb9276 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Thu, 4 Jun 2026 12:53:14 +0200 Subject: [PATCH 3/3] remove readyState --- .../router-core/tests/tsr-script-teardown.test.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/router-core/tests/tsr-script-teardown.test.ts b/packages/router-core/tests/tsr-script-teardown.test.ts index 432e2350fb..2355e1c99a 100644 --- a/packages/router-core/tests/tsr-script-teardown.test.ts +++ b/packages/router-core/tests/tsr-script-teardown.test.ts @@ -13,13 +13,6 @@ function installBootstrap(): TsrBootstrap { return (window as any).$_TSR } -function setReadyState(value: DocumentReadyState) { - Object.defineProperty(document, 'readyState', { - configurable: true, - get: () => value, - }) -} - describe('$_TSR client teardown', () => { beforeEach(() => { ;(window as any).$R = { tsr: [] } @@ -29,11 +22,9 @@ describe('$_TSR client teardown', () => { afterEach(() => { delete (window as any).$_TSR delete (window as any).$R - setReadyState('complete') }) test('does not tear down until both hydrated and streamEnded', () => { - setReadyState('complete') const tsr = installBootstrap() tsr.h() @@ -43,8 +34,7 @@ describe('$_TSR client teardown', () => { expect((window as any).$_TSR).toBeUndefined() }) - test('tears down immediately when the document is already parsed', () => { - setReadyState('complete') + test('removes both $_TSR and $R[tsr] on teardown', () => { const tsr = installBootstrap() tsr.h()