From 310407d331edb7fbec61ae21e752b51dd4f1d785 Mon Sep 17 00:00:00 2001 From: Jimmy Lai Date: Thu, 4 May 2023 15:17:59 +0200 Subject: [PATCH] action: add Readable.toWeb "polyfill" for node 16 (#49201) --- .../src/server/app-render/action-handler.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index 285132f4c8335..ed4552ed17c1c 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -22,6 +22,33 @@ import { FlightRenderResult } from './flight-render-result' import { ActionResult } from './types' import { ActionAsyncStorage } from '../../client/components/action-async-storage' +function nodeToWebReadableStream(nodeReadable: import('stream').Readable) { + if (process.env.NEXT_RUNTIME !== 'edge') { + const { Readable } = require('stream') + if ('toWeb' in Readable && typeof Readable.toWeb === 'function') { + return Readable.toWeb(nodeReadable) + } + + return new ReadableStream({ + start(controller) { + nodeReadable.on('data', (chunk) => { + controller.enqueue(chunk) + }) + + nodeReadable.on('end', () => { + controller.close() + }) + + nodeReadable.on('error', (error) => { + controller.error(error) + }) + }, + }) + } else { + throw new Error('Invalid runtime') + } +} + function formDataFromSearchQueryString(query: string) { const searchParams = new URLSearchParams(query) const formData = new FormData() @@ -266,12 +293,11 @@ export async function handleAction({ } else { // React doesn't yet publish a busboy version of decodeAction // so we polyfill the parsing of FormData. - const { Readable } = require('stream') const UndiciRequest = require('next/dist/compiled/undici').Request const fakeRequest = new UndiciRequest('http://localhost', { method: 'POST', headers: { 'Content-Type': req.headers['content-type'] }, - body: Readable.toWeb(req), + body: nodeToWebReadableStream(req), duplex: 'half', }) const formData = await fakeRequest.formData()