diff --git a/packages/next/server/node-web-streams-helper.ts b/packages/next/server/node-web-streams-helper.ts index f854b4e675f3..c3e4eb636b04 100644 --- a/packages/next/server/node-web-streams-helper.ts +++ b/packages/next/server/node-web-streams-helper.ts @@ -111,8 +111,8 @@ export function encodeText(input: string) { return new TextEncoder().encode(input) } -export function decodeText(input?: Uint8Array) { - return new TextDecoder().decode(input) +export function decodeText(input?: Uint8Array, textDecoder?: TextDecoder) { + return textDecoder ? textDecoder.decode(input, { stream: true } ) : new TextDecoder().decode(input) } export function createTransformStream({ @@ -207,9 +207,11 @@ export function createBufferedTransformStream(): TransformStream< return pendingFlush } + const textDecoder = new TextDecoder(); + return createTransformStream({ transform(chunk, controller) { - bufferedString += decodeText(chunk) + bufferedString += decodeText(chunk, textDecoder) flushBuffer(controller) }, diff --git a/test/production/react-18-streaming-ssr/index.test.ts b/test/production/react-18-streaming-ssr/index.test.ts index 93a9a873051f..52aaaccc55aa 100644 --- a/test/production/react-18-streaming-ssr/index.test.ts +++ b/test/production/react-18-streaming-ssr/index.test.ts @@ -61,6 +61,15 @@ describe('react 18 streaming SSR with custom next configs', () => { return

hello nextjs

} `, + 'pages/multi-byte.js': ` + export default function Page() { + return ( +
+

{"マルチバイト".repeat(28)}

+
+ ); + } + `, }, nextConfig: { trailingSlash: true, @@ -98,4 +107,9 @@ describe('react 18 streaming SSR with custom next configs', () => { expect(res.status).toBe(200) expect(html).toContain('hello nextjs') }) + + it('should render multi-byte characters correctly in streaming', async () => { + const html = await renderViaHTTP(next.url, '/multi-byte') + expect(html).toContain('マルチバイト'.repeat(28)) + }) })