Fix global-error for nested routes (#60539)
## What This fixes when the deep nested routes throws a client side error, it can still be caught by the `global-error.js` ## How We should always resolve global-error from root app directory instead of current route's layout. Also fixed a bad test before where the gloabl-error.js is not located correctly Fixes #53756 Closes NEXT-1760
This commit is contained in:
parent
e07161a563
commit
98b99e408b
6 changed files with 47 additions and 10 deletions
|
@ -198,7 +198,7 @@ async function createTreeCodeFromPath(
|
||||||
const pages: string[] = []
|
const pages: string[] = []
|
||||||
|
|
||||||
let rootLayout: string | undefined
|
let rootLayout: string | undefined
|
||||||
let globalError: string = defaultGlobalErrorPath
|
let globalError: string | undefined
|
||||||
|
|
||||||
async function resolveAdjacentParallelSegments(
|
async function resolveAdjacentParallelSegments(
|
||||||
segmentPath: string
|
segmentPath: string
|
||||||
|
@ -356,18 +356,18 @@ async function createTreeCodeFromPath(
|
||||||
)?.[1]
|
)?.[1]
|
||||||
rootLayout = layoutPath
|
rootLayout = layoutPath
|
||||||
|
|
||||||
if (isDefaultNotFound && !layoutPath) {
|
if (isDefaultNotFound && !layoutPath && !rootLayout) {
|
||||||
rootLayout = defaultLayoutPath
|
rootLayout = defaultLayoutPath
|
||||||
definedFilePaths.push(['layout', rootLayout])
|
definedFilePaths.push(['layout', rootLayout])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (layoutPath) {
|
if (!globalError) {
|
||||||
const resolvedGlobalErrorPath = await resolver(
|
const resolvedGlobalErrorPath = await resolver(
|
||||||
`${path.dirname(layoutPath)}/${GLOBAL_ERROR_FILE_TYPE}`
|
`${appDirPrefix}/${GLOBAL_ERROR_FILE_TYPE}`
|
||||||
)
|
)
|
||||||
if (resolvedGlobalErrorPath) {
|
if (resolvedGlobalErrorPath) {
|
||||||
globalError = resolvedGlobalErrorPath
|
globalError = resolvedGlobalErrorPath
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ async function createTreeCodeFromPath(
|
||||||
treeCode: `${treeCode}.children;`,
|
treeCode: `${treeCode}.children;`,
|
||||||
pages: `${JSON.stringify(pages)};`,
|
pages: `${JSON.stringify(pages)};`,
|
||||||
rootLayout,
|
rootLayout,
|
||||||
globalError,
|
globalError: globalError ?? defaultGlobalErrorPath,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,6 @@ export default function GlobalError({ error }) {
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for inspecting purpose
|
||||||
|
GlobalError.displayName = 'GlobalError'
|
||||||
|
|
3
test/e2e/app-dir/global-error/basic/app/nested/layout.js
Normal file
3
test/e2e/app-dir/global-error/basic/app/nested/layout.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function NestedLayout({ children }) {
|
||||||
|
return <div>{children}</div>
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
export default function ClientPage() {
|
||||||
|
const [bad, setBad] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setBad(true)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (bad) {
|
||||||
|
throw Error('nested error')
|
||||||
|
}
|
||||||
|
|
||||||
|
return <p>client page</p>
|
||||||
|
}
|
|
@ -79,5 +79,17 @@ createNextDescribe(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should catch the client error thrown in the nested routes', async () => {
|
||||||
|
const browser = await next.browser('/nested/nested')
|
||||||
|
if (isNextDev) {
|
||||||
|
await testDev(browser, /Error: nested error/)
|
||||||
|
} else {
|
||||||
|
expect(await browser.elementByCss('h1').text()).toBe('Global Error')
|
||||||
|
expect(await browser.elementByCss('#error').text()).toBe(
|
||||||
|
'Global error: nested error'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue