From 45fe26f596d2e102c68f3180c488cde18824f691 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Fri, 17 Mar 2023 01:46:21 +0100 Subject: [PATCH] Fix missing option in `createFromFetch` (#47216) This PR makes sure that `callServer` is specified in all Flight response creation calls. Added a test to cover HMR. https://vercel.slack.com/archives/C03KAR5DCKC/p1678997184339409 --- .../next-core/js/src/entry/app/hydrate.tsx | 3 +- .../router-reducer/fetch-server-response.ts | 5 ++- test/e2e/app-dir/actions/app-action.test.ts | 31 ++++++++++++++++++- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx b/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx index 2be819e8ff67689..8bba2b6762bdf6e 100644 --- a/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx +++ b/packages/next-swc/crates/next-core/js/src/entry/app/hydrate.tsx @@ -4,6 +4,7 @@ import type { ReactElement } from "react"; // @ts-expect-error import { version } from "next/package.json"; import { createFromReadableStream } from "next/dist/compiled/react-server-dom-webpack/client"; +import { callServer } from 'next/dist/client/app-call-server'; import { HeadManagerContext } from "next/dist/shared/lib/head-manager-context"; @@ -109,7 +110,7 @@ function useInitialServerResponse(cacheKey: string) { }, }); - const newResponse = createFromReadableStream(readable); + const newResponse = createFromReadableStream(readable, { callServer }); rscCache.set(cacheKey, newResponse); return newResponse; diff --git a/packages/next/src/client/components/router-reducer/fetch-server-response.ts b/packages/next/src/client/components/router-reducer/fetch-server-response.ts index 8a1efbbae715023..ff6e079a73a8104 100644 --- a/packages/next/src/client/components/router-reducer/fetch-server-response.ts +++ b/packages/next/src/client/components/router-reducer/fetch-server-response.ts @@ -12,6 +12,7 @@ import { RSC_CONTENT_TYPE_HEADER, } from '../app-router-headers' import { urlToUrlWithoutFlightMarker } from '../app-router' +import { callServer } from '../../app-call-server' /** * Fetch the flight data for the provided url. Takes in the current router state to decide what to render server-side. @@ -75,7 +76,9 @@ export async function fetchServerResponse( } // Handle the `fetch` readable stream that can be unwrapped by `React.use`. - const flightData: FlightData = await createFromFetch(Promise.resolve(res)) + const flightData: FlightData = await createFromFetch(Promise.resolve(res), { + callServer, + }) return [flightData, canonicalUrl] } catch (err) { console.error( diff --git a/test/e2e/app-dir/actions/app-action.test.ts b/test/e2e/app-dir/actions/app-action.test.ts index d85a78e295ddcd1..804e425aaad38e3 100644 --- a/test/e2e/app-dir/actions/app-action.test.ts +++ b/test/e2e/app-dir/actions/app-action.test.ts @@ -7,7 +7,7 @@ createNextDescribe( files: __dirname, skipDeployment: true, }, - ({ next }) => { + ({ next, isNextDev }) => { it('should handle basic actions correctly', async () => { const browser = await next.browser('/server') @@ -83,5 +83,34 @@ createNextDescribe( await browser.elementByCss('#dec').click() await check(() => browser.elementByCss('h1').text(), '3') }) + + if (isNextDev) { + describe('HMR', () => { + it('should support updating the action', async () => { + const filePath = 'app/server/actions.js' + const origContent = await next.readFile(filePath) + + try { + const browser = await next.browser('/server') + + const cnt = await browser.elementByCss('h1').text() + expect(cnt).toBe('0') + + await browser.elementByCss('#inc').click() + await check(() => browser.elementByCss('h1').text(), '1') + + await next.patchFile( + filePath, + origContent.replace('return value + 1', 'return value + 1000') + ) + + await browser.elementByCss('#inc').click() + await check(() => browser.elementByCss('h1').text(), '1001') + } finally { + await next.patchFile(filePath, origContent) + } + }) + }) + } } )