Skip to content

Commit

Permalink
fix(turbopack): allow page segments that don't alter the path after c…
Browse files Browse the repository at this point in the history
…atchall (#67713)

### What?

Parallel routes and groups were not allowed after a catch-all segment on
the turbopack side previously.

Closes PACK-2975
Fixes #64600
  • Loading branch information
ForsakenHarmony committed Jul 13, 2024
1 parent 005a776 commit 29af5dc
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 5 deletions.
22 changes: 17 additions & 5 deletions packages/next-swc/crates/next-core/src/next_app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,25 @@ impl AppPage {
}

pub fn push(&mut self, segment: PageSegment) -> Result<()> {
if matches!(
self.0.last(),
Some(PageSegment::CatchAll(..) | PageSegment::OptionalCatchAll(..))
) && !matches!(segment, PageSegment::PageType(..))
let has_catchall = self.0.iter().any(|segment| {
matches!(
segment,
PageSegment::CatchAll(..) | PageSegment::OptionalCatchAll(..)
)
});

if has_catchall
&& matches!(
segment,
PageSegment::Static(..)
| PageSegment::Dynamic(..)
| PageSegment::CatchAll(..)
| PageSegment::OptionalCatchAll(..)
)
{
bail!(
"Invalid segment {:?}, catch all segment must be the last segment (segments: {:?})",
"Invalid segment {:?}, catch all segment must be the last segment modifying the \
path (segments: {:?})",
segment,
self.0
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return <h4 id="catch-all-slot-group-page">Catch-all Slot Group Page</h4>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ReactNode } from 'react'

export default function Layout({ children }: { children: ReactNode }) {
return (
<div>
<h3 id="catch-all-slot-layout">Catch-all Slot Layout</h3>
{children}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ReactNode } from 'react'

export default function Layout({
children,
slot,
}: {
children: ReactNode
slot: ReactNode
}) {
return (
<div id="catch-all-layout">
<h2>Catch-all Layout</h2>
{slot}
{children}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return <h3 id="catch-all-page">Catch-all Page</h3>
}
14 changes: 14 additions & 0 deletions test/e2e/app-dir/catchall-parallel-routes-group/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ReactNode } from 'react'

export default function Root({ children }: { children: ReactNode }) {
return (
<html>
<body>
<div id="root-layout">
<h1>Root Layout</h1>
{children}
</div>
</body>
</html>
)
}
12 changes: 12 additions & 0 deletions test/e2e/app-dir/catchall-parallel-routes-group/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Link from 'next/link'

export default function Page() {
return (
<div id="root-page">
<h2>Root Page</h2>
<div>
<Link href="/foobar">To /foobar (catchall)</Link>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { nextTestSetup } from 'e2e-utils'
import { check } from 'next-test-utils'

describe('catchall-parallel-routes-group', () => {
const { next } = nextTestSetup({
files: __dirname,
})

it('should work without throwing any errors about invalid pages', async () => {
const browser = await next.browser('/')

await check(() => browser.elementByCss('body').text(), /Root Page/)
await browser.elementByCss('[href="/foobar"]').click()

// catch all matches page, but also slot with layout and group
await check(() => browser.elementByCss('body').text(), /Catch-all Page/)
await check(
() => browser.elementByCss('body').text(),
/Catch-all Slot Group Page/
)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {}

module.exports = nextConfig

0 comments on commit 29af5dc

Please sign in to comment.