[PR #376] [MERGED] fix: pass parent promise to generateMetadata() for ancestor metadata access #523

Closed
opened 2026-05-06 13:08:31 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/376
Author: @james-elicx
Created: 3/9/2026
Status: Merged
Merged: 3/9/2026
Merged by: @james-elicx

Base: mainHead: fix/generatemetadata-parent-parameter


📝 Commits (7)

  • 98d70f9 fix: pass parent promise to generateMetadata() for ancestor metadata access
  • d2a91e8 regen snaps
  • bf6680e fix: address review comments — remove dead array, pass searchParams to generateMetadata
  • e41c0fb regen snaps
  • 2b7b2e9 regen snaps
  • 723b768 fix: pass actual route params to layout generateMetadata() in fallback render
  • 0147833 fix: forward params to resolveModuleViewport in renderHTTPAccessFallbackPage

📊 Changes

9 files changed (+765 additions, -156 deletions)

View changed files

📝 packages/vinext/src/server/app-dev-server.ts (+79 -22)
📝 packages/vinext/src/shims/metadata.tsx (+9 -2)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+474 -132)
📝 tests/fixtures/app-basic/app/nextjs-compat/layout-params-notfound/[slug]/layout.tsx (+26 -0)
tests/fixtures/app-basic/app/nextjs-compat/metadata-generate-searchparams/page.tsx (+17 -0)
tests/fixtures/app-basic/app/nextjs-compat/metadata-parent-generate/layout.tsx (+15 -0)
tests/fixtures/app-basic/app/nextjs-compat/metadata-parent-generate/page.tsx (+24 -0)
📝 tests/nextjs-compat/metadata.test.ts (+58 -0)
📝 tests/nextjs-compat/not-found.test.ts (+63 -0)

📄 Description

Summary

Fixes #375generateMetadata() was never passed the parent parameter, causing any app that uses await parent to throw a TypeError.

What changed

  • shims/metadata.tsxresolveModuleMetadata() now accepts a parent: Promise<Metadata> parameter (defaults to Promise.resolve({})) and passes it as the second argument to mod.generateMetadata().

  • server/app-dev-server.ts — Both call sites (buildPageElement and renderHTTPAccessFallbackPage) now build a serial parent promise chain matching Next.js's eager-execution-with-serial-resolution approach:

    • All generateMetadata() calls are kicked off concurrently (good for I/O-bound work).
    • Each segment's parent promise only resolves after the preceding segment's metadata is merged, so await parent gives the correct accumulated ancestor metadata.

Tests

Three new regression tests in tests/nextjs-compat/metadata.test.ts, backed by a new fixture at tests/fixtures/app-basic/app/nextjs-compat/metadata-parent-generate/:

  1. should pass parent metadata to generateMetadata via parent parameter — OG images from parent layout are visible to child
  2. should render page title from generateMetadata that uses parent — page title rendered correctly when using parent
  3. parent parameter should not be undefined (await parent must not throw)await parent never throws

Root cause of the previous crash (all tests 500ing)

The initial implementation accidentally included TypeScript type annotations (Promise<Metadata>[]) inside the template-literal string that generates the virtual RSC entry module. That virtual module is resolved as plain JavaScript (no .ts extension), so the generic syntax caused a parse error, crashing every page request. The fix was to remove the type annotations from the generated code (they're only needed in the outer .ts file, not in the emitted JS string).


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/376 **Author:** [@james-elicx](https://github.com/james-elicx) **Created:** 3/9/2026 **Status:** ✅ Merged **Merged:** 3/9/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `fix/generatemetadata-parent-parameter` --- ### 📝 Commits (7) - [`98d70f9`](https://github.com/cloudflare/vinext/commit/98d70f93c74513bd3f70fd77be22f15462ff71bf) fix: pass parent promise to generateMetadata() for ancestor metadata access - [`d2a91e8`](https://github.com/cloudflare/vinext/commit/d2a91e8c8c708a9a05b99b39481aefca55efeb42) regen snaps - [`bf6680e`](https://github.com/cloudflare/vinext/commit/bf6680e0bc89d126c3a64db5adefc177de712be9) fix: address review comments — remove dead array, pass searchParams to generateMetadata - [`e41c0fb`](https://github.com/cloudflare/vinext/commit/e41c0fb73bf204f2dcd1c8d9b8701242f6cbd621) regen snaps - [`2b7b2e9`](https://github.com/cloudflare/vinext/commit/2b7b2e98bc0d3ef89ee897ec4b20a4cade86d9de) regen snaps - [`723b768`](https://github.com/cloudflare/vinext/commit/723b7681115481febfb9f5bb7029d9c7d4d17aaf) fix: pass actual route params to layout generateMetadata() in fallback render - [`0147833`](https://github.com/cloudflare/vinext/commit/014783344704ecb50d42a1c9144485c098ad26b9) fix: forward params to resolveModuleViewport in renderHTTPAccessFallbackPage ### 📊 Changes **9 files changed** (+765 additions, -156 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/server/app-dev-server.ts` (+79 -22) 📝 `packages/vinext/src/shims/metadata.tsx` (+9 -2) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+474 -132) 📝 `tests/fixtures/app-basic/app/nextjs-compat/layout-params-notfound/[slug]/layout.tsx` (+26 -0) ➕ `tests/fixtures/app-basic/app/nextjs-compat/metadata-generate-searchparams/page.tsx` (+17 -0) ➕ `tests/fixtures/app-basic/app/nextjs-compat/metadata-parent-generate/layout.tsx` (+15 -0) ➕ `tests/fixtures/app-basic/app/nextjs-compat/metadata-parent-generate/page.tsx` (+24 -0) 📝 `tests/nextjs-compat/metadata.test.ts` (+58 -0) 📝 `tests/nextjs-compat/not-found.test.ts` (+63 -0) </details> ### 📄 Description ## Summary Fixes #375 — `generateMetadata()` was never passed the `parent` parameter, causing any app that uses `await parent` to throw a TypeError. ## What changed - **`shims/metadata.tsx`** — `resolveModuleMetadata()` now accepts a `parent: Promise<Metadata>` parameter (defaults to `Promise.resolve({})`) and passes it as the second argument to `mod.generateMetadata()`. - **`server/app-dev-server.ts`** — Both call sites (`buildPageElement` and `renderHTTPAccessFallbackPage`) now build a serial parent promise chain matching Next.js's eager-execution-with-serial-resolution approach: - All `generateMetadata()` calls are kicked off concurrently (good for I/O-bound work). - Each segment's `parent` promise only resolves after the preceding segment's metadata is merged, so `await parent` gives the correct accumulated ancestor metadata. ## Tests Three new regression tests in `tests/nextjs-compat/metadata.test.ts`, backed by a new fixture at `tests/fixtures/app-basic/app/nextjs-compat/metadata-parent-generate/`: 1. `should pass parent metadata to generateMetadata via parent parameter` — OG images from parent layout are visible to child 2. `should render page title from generateMetadata that uses parent` — page title rendered correctly when using parent 3. `parent parameter should not be undefined (await parent must not throw)` — `await parent` never throws ## Root cause of the previous crash (all tests 500ing) The initial implementation accidentally included TypeScript type annotations (`Promise<Metadata>[]`) inside the template-literal string that generates the virtual RSC entry module. That virtual module is resolved as plain JavaScript (no `.ts` extension), so the generic syntax caused a parse error, crashing every page request. The fix was to remove the type annotations from the generated code (they're only needed in the outer `.ts` file, not in the emitted JS string). --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:08:31 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#523
No description provided.