From 11494c30024c010523bdc7c27b772695c4c37c54 Mon Sep 17 00:00:00 2001 From: Vadzim Date: Tue, 28 Feb 2023 23:20:36 +0100 Subject: [PATCH] Fix usage of textDecoder to not break utf8 characters (#46564) Fix usage of textDecoder to prevent breaking utf8 characters fixes #46561 ## Bug - [x] Related issues linked using `fixes #number` // it's too hard to get a reproducible test // - Integration tests added // error links are not needed // - Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) --- packages/next/src/server/app-render.tsx | 6 ++++-- .../next/src/server/node-web-streams-helper.ts | 15 +++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/next/src/server/app-render.tsx b/packages/next/src/server/app-render.tsx index 29ce4aab089fb..30d394208a4ab 100644 --- a/packages/next/src/server/app-render.tsx +++ b/packages/next/src/server/app-render.tsx @@ -336,6 +336,7 @@ function useFlightResponse( const startScriptTag = nonce ? `` @@ -1476,10 +1477,11 @@ export async function renderToHTMLOrFlight( renderResult: RenderResult ): Promise => { const renderChunks: string[] = [] + const textDecoder = new TextDecoder() const writable = { write(chunk: any) { - renderChunks.push(decodeText(chunk)) + renderChunks.push(decodeText(chunk, textDecoder)) }, end() {}, destroy() {}, diff --git a/packages/next/src/server/node-web-streams-helper.ts b/packages/next/src/server/node-web-streams-helper.ts index 6138100f97899..6bc172bdcb742 100644 --- a/packages/next/src/server/node-web-streams-helper.ts +++ b/packages/next/src/server/node-web-streams-helper.ts @@ -14,10 +14,11 @@ export function encodeText(input: string) { return new TextEncoder().encode(input) } -export function decodeText(input?: Uint8Array, textDecoder?: TextDecoder) { - return textDecoder - ? textDecoder.decode(input, { stream: true }) - : new TextDecoder().decode(input) +export function decodeText( + input: Uint8Array | undefined, + textDecoder: TextDecoder +) { + return textDecoder.decode(input, { stream: true }) } export function readableStreamTee( @@ -161,6 +162,7 @@ function createHeadInsertionTransformStream( ): TransformStream { let inserted = false let freezing = false + const textDecoder = new TextDecoder() return new TransformStream({ async transform(chunk, controller) { @@ -176,7 +178,7 @@ function createHeadInsertionTransformStream( controller.enqueue(chunk) freezing = true } else { - const content = decodeText(chunk) + const content = decodeText(chunk, textDecoder) const index = content.indexOf('') if (index !== -1) { const insertedHeadContent = @@ -293,11 +295,12 @@ export function createRootLayoutValidatorStream( ): TransformStream { let foundHtml = false let foundBody = false + const textDecoder = new TextDecoder() return new TransformStream({ async transform(chunk, controller) { if (!foundHtml || !foundBody) { - const content = decodeText(chunk) + const content = decodeText(chunk, textDecoder) if (!foundHtml && content.includes('