From 929f9639d9b855b850c5d4c5e98848740421e25a Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sun, 23 Feb 2020 16:56:22 -0600 Subject: [PATCH 01/11] Make sure to show error when url prop is returned for a page --- errors/reserved-page-prop.md | 9 +++++++ packages/next/next-server/server/render.tsx | 10 ++++++++ .../getserverprops/test/index.test.js | 24 +++++++++++++++++++ test/integration/prerender/test/index.test.js | 24 +++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 errors/reserved-page-prop.md diff --git a/errors/reserved-page-prop.md b/errors/reserved-page-prop.md new file mode 100644 index 000000000000..4dc2231737c1 --- /dev/null +++ b/errors/reserved-page-prop.md @@ -0,0 +1,9 @@ +# Reserved Page Prop + +#### Why This Error Occurred + +In a page's data method `getStaticProps`, `getServerProps`, or `getInitialProps` a reserved prop was returned. Currently the only reserved page prop is `url`. + +#### Possible Ways to Fix It + +Change the name of the prop returned from method to any other name. diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index f0e7a8b7c568..9d4cc0d7aeb8 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -545,6 +545,16 @@ export async function renderToHTML( props.pageProps = data.props ;(renderOpts as any).pageData = props } + + if ( + process.env.NODE_ENV !== 'production' && + Object.keys(props.pageProps).includes('url') + ) { + throw new Error( + 'The prop `url` can not be passed to pages as this is a reserved prop for Next.js. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' + ) + } + // We only need to do this if we want to support calling // _app's getInitialProps for getServerProps if not this can be removed if (isDataReq) return props diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 1c932da181e2..60d87b1b8254 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -322,6 +322,30 @@ const runTests = (dev = false) => { }) if (dev) { + it('should show error from url prop being returned', async () => { + const badPage = join(appDir, 'pages/bad.js') + await fs.writeFile( + badPage, + ` + export async function unstable_getServerProps() { + return { + props: { + url: 'something' + } + } + } + + export default () => 'hi' + ` + ) + + const html = await renderViaHTTP(appPort, '/bad') + await fs.remove(badPage) + expect(html).toMatch( + /The prop `url` can not be passed to pages as this is a reserved prop for Next.js/ + ) + }) + it('should show error for extra keys returned from getServerProps', async () => { const html = await renderViaHTTP(appPort, '/invalid-keys') expect(html).toContain( diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 1de888d0808e..53b99fda1e1e 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -413,6 +413,30 @@ const runTests = (dev = false) => { // ) // }) + it('should show error from url prop being returned', async () => { + const badPage = join(appDir, 'pages/bad.js') + await fs.writeFile( + badPage, + ` + export async function unstable_getStaticProps() { + return { + props: { + url: 'something' + } + } + } + + export default () => 'hi' + ` + ) + + const html = await renderViaHTTP(appPort, '/bad') + await fs.remove(badPage) + expect(html).toMatch( + /The prop `url` can not be passed to pages as this is a reserved prop for Next.js/ + ) + }) + it('should always call getStaticProps without caching in dev', async () => { const initialRes = await fetchViaHTTP(appPort, '/something') expect(initialRes.headers.get('cache-control')).toBeFalsy() From 9236547b22d1f10d8a849a1256e197c43fe60225 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sun, 23 Feb 2020 17:08:19 -0600 Subject: [PATCH 02/11] Update test and handle undefined pageProps --- packages/next/next-server/server/render.tsx | 2 +- test/integration/client-navigation/test/rendering.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index 9d4cc0d7aeb8..5873a6b7690b 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -548,7 +548,7 @@ export async function renderToHTML( if ( process.env.NODE_ENV !== 'production' && - Object.keys(props.pageProps).includes('url') + Object.keys(props.pageProps || {}).includes('url') ) { throw new Error( 'The prop `url` can not be passed to pages as this is a reserved prop for Next.js. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' diff --git a/test/integration/client-navigation/test/rendering.js b/test/integration/client-navigation/test/rendering.js index 4bc7ef238d89..078bb0a86e86 100644 --- a/test/integration/client-navigation/test/rendering.js +++ b/test/integration/client-navigation/test/rendering.js @@ -358,11 +358,11 @@ export default function(render, fetch) { expect($('#aspath').text()).toBe('/url-prop') }) - it('should override props.url, even when getInitialProps returns url as property', async () => { - const $ = await get$('/url-prop-override') - expect($('#pathname').text()).toBe('/url-prop-override') - expect($('#query').text()).toBe('0') - expect($('#aspath').text()).toBe('/url-prop-override') + it('should show error when url prop is passed', async () => { + const html = await render('/url-prop-override') + expect(html).toMatch( + /The prop `url` can not be passed to pages as this is a reserved prop for Next.js/ + ) }) }) From 7c0ae390439ecdfc2ecacd5002c7613d10b19ff0 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sun, 23 Feb 2020 17:10:08 -0600 Subject: [PATCH 03/11] Handle empty props --- packages/next/next-server/server/render.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index 5873a6b7690b..ceb885a50773 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -548,7 +548,7 @@ export async function renderToHTML( if ( process.env.NODE_ENV !== 'production' && - Object.keys(props.pageProps || {}).includes('url') + Object.keys(props?.pageProps || {}).includes('url') ) { throw new Error( 'The prop `url` can not be passed to pages as this is a reserved prop for Next.js. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' From 714db5d6dcdec079a5cb1b8eca7ae8dc04c7e96b Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 24 Feb 2020 10:17:17 -0600 Subject: [PATCH 04/11] Apply suggestions from code review Co-Authored-By: Tim Neutkens --- packages/next/next-server/server/render.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index ceb885a50773..4908cd8ab50a 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -551,7 +551,7 @@ export async function renderToHTML( Object.keys(props?.pageProps || {}).includes('url') ) { throw new Error( - 'The prop `url` can not be passed to pages as this is a reserved prop for Next.js. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' + 'The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' ) } From 41da9ecdfcb62dc0a4fde514af701ad6101b7922 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 24 Feb 2020 12:58:12 -0600 Subject: [PATCH 05/11] Update tests --- test/integration/client-navigation/test/rendering.js | 2 +- test/integration/getserverprops/test/index.test.js | 2 +- test/integration/prerender/test/index.test.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/client-navigation/test/rendering.js b/test/integration/client-navigation/test/rendering.js index 078bb0a86e86..7df06f5e68e9 100644 --- a/test/integration/client-navigation/test/rendering.js +++ b/test/integration/client-navigation/test/rendering.js @@ -361,7 +361,7 @@ export default function(render, fetch) { it('should show error when url prop is passed', async () => { const html = await render('/url-prop-override') expect(html).toMatch( - /The prop `url` can not be passed to pages as this is a reserved prop for Next.js/ + /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) }) }) diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 60d87b1b8254..2a8fd27bc0b0 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -342,7 +342,7 @@ const runTests = (dev = false) => { const html = await renderViaHTTP(appPort, '/bad') await fs.remove(badPage) expect(html).toMatch( - /The prop `url` can not be passed to pages as this is a reserved prop for Next.js/ + /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) }) diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 20fb26fbf0af..d41ef160f7a0 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -468,7 +468,7 @@ const runTests = (dev = false, looseMode = false) => { const html = await renderViaHTTP(appPort, '/bad') await fs.remove(badPage) expect(html).toMatch( - /The prop `url` can not be passed to pages as this is a reserved prop for Next.js/ + /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) }) From 4954648567c76644ba230f209f52a7d8b3bbf9a3 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 25 Feb 2020 10:01:42 -0600 Subject: [PATCH 06/11] Update to not add url prop for SSG/SSP pages --- .../build/babel/plugins/next-ssg-transform.ts | 10 ++-- packages/next/next-server/lib/constants.ts | 2 + .../next-server/server/load-components.ts | 51 +++++++++++++++++-- packages/next/next-server/server/render.tsx | 2 + packages/next/pages/_app.tsx | 15 +++++- .../getserverprops/test/index.test.js | 13 ++--- test/integration/prerender/test/index.test.js | 13 ++--- 7 files changed, 83 insertions(+), 23 deletions(-) diff --git a/packages/next/build/babel/plugins/next-ssg-transform.ts b/packages/next/build/babel/plugins/next-ssg-transform.ts index b4039bbe7616..2a7cea08e6b7 100644 --- a/packages/next/build/babel/plugins/next-ssg-transform.ts +++ b/packages/next/build/babel/plugins/next-ssg-transform.ts @@ -1,10 +1,12 @@ import { NodePath, PluginObj } from '@babel/core' import * as BabelTypes from '@babel/types' import { SERVER_PROPS_SSG_CONFLICT } from '../../../lib/constants' +import { + STATIC_PROPS_ID, + SERVER_PROPS_ID, +} from '../../../next-server/lib/constants' const pageComponentVar = '__NEXT_COMP' -const prerenderId = '__N_SSG' -const serverPropsId = '__N_SSP' export const EXPORT_NAME_GET_STATIC_PROPS = 'unstable_getStaticProps' export const EXPORT_NAME_GET_STATIC_PATHS = 'unstable_getStaticPaths' @@ -53,7 +55,7 @@ function decorateSsgExport( '=', t.memberExpression( t.identifier(pageComponentVar), - t.identifier(state.isPrerender ? prerenderId : serverPropsId) + t.identifier(state.isPrerender ? STATIC_PROPS_ID : SERVER_PROPS_ID) ), t.booleanLiteral(true) ), @@ -80,7 +82,7 @@ function decorateSsgExport( '=', t.memberExpression( t.identifier((defaultSpecifier as any).local.name), - t.identifier(state.isPrerender ? prerenderId : serverPropsId) + t.identifier(state.isPrerender ? STATIC_PROPS_ID : SERVER_PROPS_ID) ), t.booleanLiteral(true) ), diff --git a/packages/next/next-server/lib/constants.ts b/packages/next/next-server/lib/constants.ts index d52a40da605a..40f97db6f7b4 100644 --- a/packages/next/next-server/lib/constants.ts +++ b/packages/next/next-server/lib/constants.ts @@ -34,3 +34,5 @@ export const ROUTE_NAME_REGEX = /^static[/\\][^/\\]+[/\\]pages[/\\](.*)\.js$/ export const SERVERLESS_ROUTE_NAME_REGEX = /^pages[/\\](.*)\.js$/ export const TEMPORARY_REDIRECT_STATUS = 307 export const PERMANENT_REDIRECT_STATUS = 308 +export const STATIC_PROPS_ID = '__N_SSG' +export const SERVER_PROPS_ID = '__N_SSP' diff --git a/packages/next/next-server/server/load-components.ts b/packages/next/next-server/server/load-components.ts index e4852ab52676..b088480e485d 100644 --- a/packages/next/next-server/server/load-components.ts +++ b/packages/next/next-server/server/load-components.ts @@ -5,6 +5,8 @@ import { CLIENT_STATIC_FILES_PATH, REACT_LOADABLE_MANIFEST, SERVER_DIRECTORY, + STATIC_PROPS_ID, + SERVER_PROPS_ID, } from '../lib/constants' import { join } from 'path' import { requirePage } from './require' @@ -16,6 +18,20 @@ export function interopDefault(mod: any) { return mod.default || mod } +function addComponentPropsId( + Component: any, + getStaticProps: any, + getServerProps: any +) { + // Mark the component with the SSG or SSP id here since we don't run + // the SSG babel transform for server mode + if (getStaticProps) { + Component[STATIC_PROPS_ID] = true + } else if (getServerProps) { + Component[SERVER_PROPS_ID] = true + } +} + export type ManifestItem = { id: number | string name: string @@ -66,11 +82,24 @@ export async function loadComponents( ): Promise { if (serverless) { const Component = await requirePage(pathname, distDir, serverless) + const { + unstable_getStaticProps, + unstable_getStaticPaths, + unstable_getServerProps, + } = Component + + addComponentPropsId( + Component, + unstable_getStaticProps, + unstable_getServerProps + ) + return { Component, pageConfig: Component.config || {}, - unstable_getStaticProps: Component.unstable_getStaticProps, - unstable_getStaticPaths: Component.unstable_getStaticPaths, + unstable_getStaticProps, + unstable_getStaticPaths, + unstable_getServerProps, } as LoadComponentsReturnType } const documentPath = join( @@ -111,6 +140,18 @@ export async function loadComponents( interopDefault(AppMod), ]) + const { + unstable_getServerProps, + unstable_getStaticProps, + unstable_getStaticPaths, + } = ComponentMod + + addComponentPropsId( + Component, + unstable_getStaticProps, + unstable_getServerProps + ) + return { App, Document, @@ -119,8 +160,8 @@ export async function loadComponents( DocumentMiddleware, reactLoadableManifest, pageConfig: ComponentMod.config || {}, - unstable_getServerProps: ComponentMod.unstable_getServerProps, - unstable_getStaticProps: ComponentMod.unstable_getStaticProps, - unstable_getStaticPaths: ComponentMod.unstable_getStaticPaths, + unstable_getServerProps, + unstable_getStaticProps, + unstable_getStaticPaths, } } diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index f14abb0da107..faf806d1a582 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -548,6 +548,8 @@ export async function renderToHTML( } if ( + !isSpr && // we only show this error for legacy pages + !unstable_getServerProps && process.env.NODE_ENV !== 'production' && Object.keys(props?.pageProps || {}).includes('url') ) { diff --git a/packages/next/pages/_app.tsx b/packages/next/pages/_app.tsx index 3971441a2433..017f019cf180 100644 --- a/packages/next/pages/_app.tsx +++ b/packages/next/pages/_app.tsx @@ -42,8 +42,19 @@ export default class App

extends React.Component< render() { const { router, Component, pageProps } = this.props as AppProps - const url = createUrl(router) - return + + return ( + + ) } } diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 2a8fd27bc0b0..5a0be09e90aa 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -322,10 +322,10 @@ const runTests = (dev = false) => { }) if (dev) { - it('should show error from url prop being returned', async () => { - const badPage = join(appDir, 'pages/bad.js') + it('should not show error from url prop being returned', async () => { + const urlPropPage = join(appDir, 'pages/url-prop.js') await fs.writeFile( - badPage, + urlPropPage, ` export async function unstable_getServerProps() { return { @@ -339,11 +339,12 @@ const runTests = (dev = false) => { ` ) - const html = await renderViaHTTP(appPort, '/bad') - await fs.remove(badPage) - expect(html).toMatch( + const html = await renderViaHTTP(appPort, '/url-prop') + await fs.remove(urlPropPage) + expect(html).not.toMatch( /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) + expect(html).toContain('hi') }) it('should show error for extra keys returned from getServerProps', async () => { diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index e3d6857a2349..8f330908dd5d 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -428,10 +428,10 @@ const runTests = (dev = false, looseMode = false) => { // ) // }) - it('should show error from url prop being returned', async () => { - const badPage = join(appDir, 'pages/bad.js') + it('should not show error from url prop being returned', async () => { + const urlPropPage = join(appDir, 'pages/url-prop.js') await fs.writeFile( - badPage, + urlPropPage, ` export async function unstable_getStaticProps() { return { @@ -445,11 +445,12 @@ const runTests = (dev = false, looseMode = false) => { ` ) - const html = await renderViaHTTP(appPort, '/bad') - await fs.remove(badPage) - expect(html).toMatch( + const html = await renderViaHTTP(appPort, '/url-prop') + await fs.remove(urlPropPage) + expect(html).not.toMatch( /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) + expect(html).toContain('hi') }) it('should always show fallback for page not in getStaticPaths', async () => { From ed1d96f8a761f0d656e3535bcf3918820cf1f738 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 25 Feb 2020 10:08:06 -0600 Subject: [PATCH 07/11] Update errsh for reserved prop --- errors/reserved-page-prop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/errors/reserved-page-prop.md b/errors/reserved-page-prop.md index 4dc2231737c1..05eb65a64339 100644 --- a/errors/reserved-page-prop.md +++ b/errors/reserved-page-prop.md @@ -2,7 +2,7 @@ #### Why This Error Occurred -In a page's data method `getStaticProps`, `getServerProps`, or `getInitialProps` a reserved prop was returned. Currently the only reserved page prop is `url`. +In a page's `getInitialProps` a reserved prop was returned. Currently the only reserved page prop is `url`. #### Possible Ways to Fix It From 000838e1c979c5d9d8875bfe39b2aad4785a6462 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 25 Feb 2020 10:11:17 -0600 Subject: [PATCH 08/11] Update errsh wording some more --- errors/reserved-page-prop.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/errors/reserved-page-prop.md b/errors/reserved-page-prop.md index 05eb65a64339..ae83aaababfe 100644 --- a/errors/reserved-page-prop.md +++ b/errors/reserved-page-prop.md @@ -2,8 +2,8 @@ #### Why This Error Occurred -In a page's `getInitialProps` a reserved prop was returned. Currently the only reserved page prop is `url`. +In a page's `getInitialProps` a reserved prop was returned. Currently the only reserved page prop is `url` for legacy reasons. #### Possible Ways to Fix It -Change the name of the prop returned from method to any other name. +Change the name of the prop returned from `getInitialProps` to any other name. From 4b6b99ee2a9e6281014b04e5fd02c1f6c02dd092 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 26 Feb 2020 09:21:01 -0600 Subject: [PATCH 09/11] Update tests and to warn instead of error --- packages/next/next-server/server/render.tsx | 4 ++-- .../client-navigation/test/rendering.js | 10 ++++---- .../getserverprops/test/index.test.js | 23 ++++++++++++++----- test/integration/prerender/test/index.test.js | 8 +++---- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index faf806d1a582..6d035f078920 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -548,12 +548,12 @@ export async function renderToHTML( } if ( - !isSpr && // we only show this error for legacy pages + !isSpr && // we only show this warning for legacy pages !unstable_getServerProps && process.env.NODE_ENV !== 'production' && Object.keys(props?.pageProps || {}).includes('url') ) { - throw new Error( + console.warn( 'The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' ) } diff --git a/test/integration/client-navigation/test/rendering.js b/test/integration/client-navigation/test/rendering.js index 7df06f5e68e9..4bc7ef238d89 100644 --- a/test/integration/client-navigation/test/rendering.js +++ b/test/integration/client-navigation/test/rendering.js @@ -358,11 +358,11 @@ export default function(render, fetch) { expect($('#aspath').text()).toBe('/url-prop') }) - it('should show error when url prop is passed', async () => { - const html = await render('/url-prop-override') - expect(html).toMatch( - /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ - ) + it('should override props.url, even when getInitialProps returns url as property', async () => { + const $ = await get$('/url-prop-override') + expect($('#pathname').text()).toBe('/url-prop-override') + expect($('#query').text()).toBe('0') + expect($('#aspath').text()).toBe('/url-prop-override') }) }) diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 5a0be09e90aa..9be19f9da35b 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -23,6 +23,7 @@ const nextConfig = join(appDir, 'next.config.js') let app let appPort let buildId +let stderr const expectedManifestRoutes = () => ({ '/something': { @@ -322,7 +323,7 @@ const runTests = (dev = false) => { }) if (dev) { - it('should not show error from url prop being returned', async () => { + it('should not show warning from url prop being returned', async () => { const urlPropPage = join(appDir, 'pages/url-prop.js') await fs.writeFile( urlPropPage, @@ -335,16 +336,16 @@ const runTests = (dev = false) => { } } - export default () => 'hi' + export default ({ url }) =>

url: {url}

` ) const html = await renderViaHTTP(appPort, '/url-prop') await fs.remove(urlPropPage) - expect(html).not.toMatch( + expect(stderr).not.toMatch( /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) - expect(html).toContain('hi') + expect(html).toMatch(/url:.*?something/) }) it('should show error for extra keys returned from getServerProps', async () => { @@ -390,8 +391,13 @@ const runTests = (dev = false) => { describe('unstable_getServerProps', () => { describe('dev mode', () => { beforeAll(async () => { + stderr = '' appPort = await findPort() - app = await launchApp(appDir, appPort) + app = await launchApp(appDir, appPort, { + onStderr(msg) { + stderr += msg + }, + }) buildId = 'development' }) afterAll(() => killApp(app)) @@ -407,8 +413,13 @@ describe('unstable_getServerProps', () => { 'utf8' ) await nextBuild(appDir) + stderr = '' appPort = await findPort() - app = await nextStart(appDir, appPort) + app = await nextStart(appDir, appPort, { + onStderr(msg) { + stderr += msg + }, + }) buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') }) afterAll(() => killApp(app)) diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 8f330908dd5d..9281d2fbf9b3 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -428,7 +428,7 @@ const runTests = (dev = false, looseMode = false) => { // ) // }) - it('should not show error from url prop being returned', async () => { + it('should not show warning from url prop being returned', async () => { const urlPropPage = join(appDir, 'pages/url-prop.js') await fs.writeFile( urlPropPage, @@ -441,16 +441,16 @@ const runTests = (dev = false, looseMode = false) => { } } - export default () => 'hi' + export default ({ url }) =>

url: {url}

` ) const html = await renderViaHTTP(appPort, '/url-prop') await fs.remove(urlPropPage) - expect(html).not.toMatch( + expect(stderr).not.toMatch( /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ ) - expect(html).toContain('hi') + expect(html).toMatch(/url:.*?something/) }) it('should always show fallback for page not in getStaticPaths', async () => { From 2772c48382190077f7baa0d83722c92bc5fd8214 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 26 Feb 2020 09:23:34 -0600 Subject: [PATCH 10/11] Update reserved prop warning --- packages/next/next-server/server/render.tsx | 2 +- packages/next/pages/_app.tsx | 2 +- test/integration/getserverprops/test/index.test.js | 2 +- test/integration/prerender/test/index.test.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index 6d035f078920..5195874b57a1 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -554,7 +554,7 @@ export async function renderToHTML( Object.keys(props?.pageProps || {}).includes('url') ) { console.warn( - 'The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' + 'The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' ) } diff --git a/packages/next/pages/_app.tsx b/packages/next/pages/_app.tsx index 017f019cf180..0132f5ab4825 100644 --- a/packages/next/pages/_app.tsx +++ b/packages/next/pages/_app.tsx @@ -47,7 +47,7 @@ export default class App

extends React.Component< { const html = await renderViaHTTP(appPort, '/url-prop') await fs.remove(urlPropPage) expect(stderr).not.toMatch( - /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ + /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden/ ) expect(html).toMatch(/url:.*?something/) }) diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 9281d2fbf9b3..991c68004db9 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -448,7 +448,7 @@ const runTests = (dev = false, looseMode = false) => { const html = await renderViaHTTP(appPort, '/url-prop') await fs.remove(urlPropPage) expect(stderr).not.toMatch( - /The prop `url` can not be passed to pages as this is a reserved prop in Next.js for legacy reasons/ + /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden/ ) expect(html).toMatch(/url:.*?something/) }) From fbdb90a0512fffca4815daa7b6d27ace500e67ea Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 26 Feb 2020 09:46:01 -0600 Subject: [PATCH 11/11] Include page in url prop warning --- packages/next/next-server/server/render.tsx | 3 ++- test/integration/getserverprops/test/index.test.js | 2 +- test/integration/prerender/test/index.test.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/next/next-server/server/render.tsx b/packages/next/next-server/server/render.tsx index 5195874b57a1..8e848519c1c8 100644 --- a/packages/next/next-server/server/render.tsx +++ b/packages/next/next-server/server/render.tsx @@ -554,7 +554,8 @@ export async function renderToHTML( Object.keys(props?.pageProps || {}).includes('url') ) { console.warn( - 'The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden. See more info here: https://err.sh/zeit/next.js/reserved-page-prop' + `The prop \`url\` is a reserved prop in Next.js for legacy reasons and will be overridden on page ${pathname}\n` + + `See more info here: https://err.sh/zeit/next.js/reserved-page-prop` ) } diff --git a/test/integration/getserverprops/test/index.test.js b/test/integration/getserverprops/test/index.test.js index 6f16c339c49c..68a7215ce68b 100644 --- a/test/integration/getserverprops/test/index.test.js +++ b/test/integration/getserverprops/test/index.test.js @@ -343,7 +343,7 @@ const runTests = (dev = false) => { const html = await renderViaHTTP(appPort, '/url-prop') await fs.remove(urlPropPage) expect(stderr).not.toMatch( - /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden/ + /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden on page \/url-prop/ ) expect(html).toMatch(/url:.*?something/) }) diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 991c68004db9..309f06690be3 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -448,7 +448,7 @@ const runTests = (dev = false, looseMode = false) => { const html = await renderViaHTTP(appPort, '/url-prop') await fs.remove(urlPropPage) expect(stderr).not.toMatch( - /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden/ + /The prop `url` is a reserved prop in Next.js for legacy reasons and will be overridden on page \/url-prop/ ) expect(html).toMatch(/url:.*?something/) })