Skip to content

fix(pages-router): await Promise-shaped gssp props#1568

Open
james-elicx wants to merge 1 commit into
mainfrom
fix/gssp-promise-props
Open

fix(pages-router): await Promise-shaped gssp props#1568
james-elicx wants to merge 1 commit into
mainfrom
fix/gssp-promise-props

Conversation

@james-elicx
Copy link
Copy Markdown
Member

Closes #1459

Summary

  • Pages Router getServerSideProps returning { props: Promise.resolve(...) } now awaits the props value before serialising, matching Next.js.

Test plan

  • Test asserts Promise-shaped props render correctly
  • vp check passes

Next.js explicitly supports a Promise value for `getServerSideProps`
`props`. Pages returning `{ props: Promise.resolve(...) }` previously
rendered empty pageProps because vinext passed the unresolved Promise
straight through to the serializer. Match Next.js' `render.tsx` by
detecting a thenable `props` and awaiting it before continuing.

The fix is applied symmetrically to the dev server gssp dispatch
(`dev-server.ts`) and the prod page-data dispatch (`pages-page-data.ts`)
so the two stay in sync per AGENTS.md. Other return shapes (`notFound`,
`redirect`, `revalidate`, fallback) are untouched.

Closes #1459
@james-elicx
Copy link
Copy Markdown
Member Author

/bigbonk review

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 22, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@1568

commit: da7f304

@github-actions
Copy link
Copy Markdown

Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original
web preview production

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code is correct and focused. Both the dev server (dev-server.ts:532-540) and the shared prod helper (pages-page-data.ts:390-399) now correctly detect thenable props and await them before serialisation. The fixture page and test coverage (both dev and prod) are good.

Two observations:

1. Thenable detection vs instanceof Promise

Next.js uses (data as any).props instanceof Promise (see packages/next/src/server/render.tsx, line ~1145 on canary). This PR uses typeof result.props.then === "function", which is strictly more permissive (catches any thenable, not just native Promises). That's fine — it's defense-in-depth and won't cause false positives on normal objects. Just noting the difference for posterity.

2. getStaticProps props are not Promise-awaited — but that matches Next.js

I checked whether the same pattern applies to getStaticProps. In Next.js's render.tsx, the deferredContent / Promise-await logic is gated behind the getServerSideProps branch only — getStaticProps props are consumed synchronously via Object.assign({}, props.pageProps, 'props' in data ? data.props : undefined) without any Promise check. So vinext's getStaticProps code paths (4 locations across dev-server.ts and pages-page-data.ts) not handling Promise props is actually correct parity with Next.js. No action needed there.

LGTM — the fix matches Next.js semantics, the two code paths that needed fixing are fixed, and the test plan is solid.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 22, 2026

Review posted and approved on PR #1568.

Summary of findings:

  • The fix correctly awaits Promise-shaped props from getServerSideProps in both the dev server (dev-server.ts) and the shared prod helper (pages-page-data.ts), matching Next.js behavior.
  • The thenable detection (typeof .then === "function") is more permissive than Next.js's instanceof Promise check, which is a reasonable defense-in-depth approach.
  • I verified that getStaticProps does not need the same treatment — Next.js only applies the deferred-content pattern to getServerSideProps, so the 4 getStaticProps code paths that don't await are correct parity.
  • Test coverage is solid: fixture page, dev integration test, and prod integration test all verify the resolved values appear in both rendered HTML and the __NEXT_DATA__ payload.

github run

@james-elicx james-elicx marked this pull request as ready for review May 22, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pages Router: getServerSideProps Promise-shaped props not awaited

1 participant