[PR #1083] [MERGED] refactor(server): dedupe TextDecoder stream consumption #1080

Closed
opened 2026-05-06 13:11:52 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/1083
Author: @james-elicx
Created: 5/5/2026
Status: Merged
Merged: 5/5/2026
Merged by: @james-elicx

Base: mainHead: refactor/dedupe-textdecoder-stream


📝 Commits (2)

  • df69ae4 refactor(server): dedupe TextDecoder stream consumption
  • d9c7350 refactor(server): address review feedback from #1083

📊 Changes

8 files changed (+94 additions, -97 deletions)

View changed files

📝 packages/vinext/src/server/app-page-cache.ts (+3 -12)
📝 packages/vinext/src/server/app-page-dispatch.ts (+2 -2)
📝 packages/vinext/src/server/app-page-execution.ts (+0 -17)
📝 packages/vinext/src/server/app-server-action-execution.ts (+4 -20)
📝 packages/vinext/src/server/pages-node-compat.ts (+4 -22)
📝 packages/vinext/src/server/pages-page-response.ts (+2 -21)
packages/vinext/src/utils/text-stream.ts (+76 -0)
📝 tests/app-page-execution.test.ts (+3 -3)

📄 Description

Summary

Follow-up to the dedupe round (#1058, #1069-#1081). Extracts the repeated new TextDecoder() + ReadableStream chunk-loop into two helpers in packages/vinext/src/utils/text-stream.ts:

  • readStreamAsText(stream) for the consume-to-single-string shape
  • readStreamAsTextWithLimit(stream, maxBytes, onLimitExceeded) for the size-limited shape (callback throws so each caller keeps its own error type)

Files changed

Deduped:

  • packages/vinext/src/server/app-page-cache.ts (ISR HTML cache write)
  • packages/vinext/src/server/pages-page-response.ts (recordStreamToString removed; was only called once)
  • packages/vinext/src/server/app-server-action-execution.ts (readActionBodyWithLimit)
  • packages/vinext/src/server/pages-node-compat.ts (readPagesRequestBodyWithLimit)

New helper:

  • packages/vinext/src/utils/text-stream.ts

Intentionally left inline

These five sites have load-bearing differences that don't fit either helper:

  • rsc-stream-hints.ts - line-buffered TransformStream with carry for partial Flight lines
  • app-ssr-stream.ts (createRscEmbedTransform) - interleaves raw-byte accumulation with fixFlightHints
  • app-ssr-stream.ts (createTickBufferedTransform) - HTML transform applying fixPreloadAs
  • shims/fetch-cache.ts - mixed string/Uint8Array stream, tee handling, custom BodyTooLargeForCacheKeyError, decoder also reused for non-stream Uint8Array body

So 4 of 9 sites cleanly deduped; 5 left alone. Pure refactor; no behaviour change at the deduped sites except a minor robustness improvement: readStreamAsText releases the reader lock in finally (the inline copy in app-page-cache.ts did not). The streams there are wholly consumed and not reused, so this is observably equivalent.

Test plan

  • pnpm vp test run tests/app-router.test.ts tests/pages-router.test.ts (508 tests pass; the only failure is a pre-existing flaky afterAll cleanup hook in Pages Router allowedDevOrigins config that does not run any deduped code path)
  • pnpm fmt --write
  • pnpm knip (clean)
  • CI required checks

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/1083 **Author:** [@james-elicx](https://github.com/james-elicx) **Created:** 5/5/2026 **Status:** ✅ Merged **Merged:** 5/5/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `refactor/dedupe-textdecoder-stream` --- ### 📝 Commits (2) - [`df69ae4`](https://github.com/cloudflare/vinext/commit/df69ae41411cc8a3f09aafc880c753582aa98bfa) refactor(server): dedupe TextDecoder stream consumption - [`d9c7350`](https://github.com/cloudflare/vinext/commit/d9c73502d47b1bc12d555e97381bce4d38101659) refactor(server): address review feedback from #1083 ### 📊 Changes **8 files changed** (+94 additions, -97 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/server/app-page-cache.ts` (+3 -12) 📝 `packages/vinext/src/server/app-page-dispatch.ts` (+2 -2) 📝 `packages/vinext/src/server/app-page-execution.ts` (+0 -17) 📝 `packages/vinext/src/server/app-server-action-execution.ts` (+4 -20) 📝 `packages/vinext/src/server/pages-node-compat.ts` (+4 -22) 📝 `packages/vinext/src/server/pages-page-response.ts` (+2 -21) ➕ `packages/vinext/src/utils/text-stream.ts` (+76 -0) 📝 `tests/app-page-execution.test.ts` (+3 -3) </details> ### 📄 Description ## Summary Follow-up to the dedupe round (#1058, #1069-#1081). Extracts the repeated `new TextDecoder()` + `ReadableStream` chunk-loop into two helpers in `packages/vinext/src/utils/text-stream.ts`: - `readStreamAsText(stream)` for the consume-to-single-string shape - `readStreamAsTextWithLimit(stream, maxBytes, onLimitExceeded)` for the size-limited shape (callback throws so each caller keeps its own error type) ## Files changed Deduped: - `packages/vinext/src/server/app-page-cache.ts` (ISR HTML cache write) - `packages/vinext/src/server/pages-page-response.ts` (`recordStreamToString` removed; was only called once) - `packages/vinext/src/server/app-server-action-execution.ts` (`readActionBodyWithLimit`) - `packages/vinext/src/server/pages-node-compat.ts` (`readPagesRequestBodyWithLimit`) New helper: - `packages/vinext/src/utils/text-stream.ts` ## Intentionally left inline These five sites have load-bearing differences that don't fit either helper: - `rsc-stream-hints.ts` - line-buffered `TransformStream` with `carry` for partial Flight lines - `app-ssr-stream.ts` (`createRscEmbedTransform`) - interleaves raw-byte accumulation with `fixFlightHints` - `app-ssr-stream.ts` (`createTickBufferedTransform`) - HTML transform applying `fixPreloadAs` - `shims/fetch-cache.ts` - mixed string/Uint8Array stream, tee handling, custom `BodyTooLargeForCacheKeyError`, decoder also reused for non-stream `Uint8Array` body So 4 of 9 sites cleanly deduped; 5 left alone. Pure refactor; no behaviour change at the deduped sites except a minor robustness improvement: `readStreamAsText` releases the reader lock in `finally` (the inline copy in `app-page-cache.ts` did not). The streams there are wholly consumed and not reused, so this is observably equivalent. ## Test plan - [x] `pnpm vp test run tests/app-router.test.ts tests/pages-router.test.ts` (508 tests pass; the only failure is a pre-existing flaky `afterAll` cleanup hook in `Pages Router allowedDevOrigins config` that does not run any deduped code path) - [x] `pnpm fmt --write` - [x] `pnpm knip` (clean) - [ ] CI required checks 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:11:52 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#1080
No description provided.