Skip to content

Commit

Permalink
Enable owner stack in experimental build (#71716)
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi authored Oct 24, 2024
1 parent 4ae3fc3 commit dbc9452
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 13 deletions.
10 changes: 5 additions & 5 deletions packages/next/src/build/webpack/plugins/define-env-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ export function getDefineEnv({
const nextPublicEnv = getNextPublicEnvironmentVariables()
const nextConfigEnv = getNextConfigEnv(config)

const isPPREnabled = checkIsAppPPREnabled(config.experimental.ppr)
const isDynamicIOEnabled = !!config.experimental.dynamicIO

const defineEnv: DefineEnv = {
// internal field to identify the plugin config
__NEXT_DEFINE_ENV: true,
Expand Down Expand Up @@ -183,11 +186,8 @@ export function getDefineEnv({
'process.env.__NEXT_APP_ISR_INDICATOR': Boolean(
config.devIndicators.appIsrStatus
),
'process.env.__NEXT_PPR': checkIsAppPPREnabled(config.experimental.ppr),
'process.env.__NEXT_DYNAMIC_IO': !!config.experimental.dynamicIO,
'process.env.__NEXT_REACT_OWNER_STACK': Boolean(
config.experimental.reactOwnerStack
),
'process.env.__NEXT_PPR': isPPREnabled,
'process.env.__NEXT_DYNAMIC_IO': isDynamicIOEnabled,
'process.env.__NEXT_AFTER': config.experimental.after ?? false,
'process.env.NEXT_DEPLOYMENT_ID': config.deploymentId || false,
'process.env.__NEXT_FETCH_CACHE_KEY_PREFIX': fetchCacheKeyPrefix ?? '',
Expand Down
5 changes: 2 additions & 3 deletions packages/next/src/client/app-index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import { MissingSlotContext } from '../shared/lib/app-router-context.shared-runt

/// <reference types="react-dom/experimental" />

const isReactOwnerStackEnabled = !!process.env.__NEXT_REACT_OWNER_STACK

const appElement: HTMLElement | Document | null = document

const encoder = new TextEncoder()
Expand Down Expand Up @@ -234,7 +232,8 @@ export function hydrate() {
const hasMissingTags = !!rootLayoutMissingTags?.length

const errorCallbacks =
isReactOwnerStackEnabled && process.env.NODE_ENV !== 'production'
typeof (React as any).captureOwnerStack === 'function' &&
process.env.NODE_ENV !== 'production'
? {
onCaughtError,
onUncaughtError,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export const CallStackFrame: React.FC<{
// e.g. (app-pages-browser)/./app/page.tsx -> ./app/page.tsx
const formattedMethod = f.methodName.replace(/^\([\w-]+\)\//, '')

// Formatted file source could be empty. e.g. <anonymous> will be formatted to empty string,
// we'll skip rendering the frame in this case.
const fileSource = getFrameSource(f)
if (!fileSource) {
return null
}

return (
<div data-nextjs-call-stack-frame>
<h3 data-nextjs-frame-expanded={Boolean(frame.expanded)}>
Expand All @@ -40,7 +47,7 @@ export const CallStackFrame: React.FC<{
onClick={open}
title={hasSource ? 'Click to open in your editor' : undefined}
>
<span>{getFrameSource(f)}</span>
<span>{fileSource}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React from 'react'
import isError from '../../../../../lib/is-error'

const captureOwnerStack = (React as any).captureOwnerStack || (() => '')

const REACT_ERROR_STACK_BOTTOM_FRAME = 'react-stack-bottom-frame'
const REACT_ERROR_STACK_BOTTOM_FRAME_REGEX = new RegExp(
`(at ${REACT_ERROR_STACK_BOTTOM_FRAME} )|(${REACT_ERROR_STACK_BOTTOM_FRAME}\\@)`
)

export function getReactStitchedError<T = unknown>(err: T): Error | T {
if (!process.env.__NEXT_REACT_OWNER_STACK) {
if (typeof (React as any).captureOwnerStack !== 'function') {
return err
}

Expand All @@ -31,7 +29,7 @@ export function getReactStitchedError<T = unknown>(err: T): Error | T {
newError.stack = newStack

// Avoid duplicate overriding stack frames
const ownerStack = captureOwnerStack()
const ownerStack = (React as any).captureOwnerStack()
if (ownerStack && newStack.endsWith(ownerStack) === false) {
newStack += ownerStack
// Override stack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
waitForAndOpenRuntimeError,
} from 'next-test-utils'

const isReactExperimental = process.env.__NEXT_EXPERIMENTAL_PPR === 'true'

async function getRedboxResult(browser: any) {
const description = await getRedboxDescription(browser)
const callStacks = await getRedboxCallStack(browser)
Expand Down Expand Up @@ -44,6 +46,24 @@ describe('app-dir - capture-console-error', () => {
"description": "trigger an console <error>",
"source": "app/browser/event/page.js (7:17) @ onClick
5 | <button
6 | onClick={() => {
> 7 | console.error('trigger an console <%s>', 'error')
| ^
8 | }}
9 | >
10 | click to error",
}
`)
} else if (isReactExperimental) {
expect(result).toMatchInlineSnapshot(`
{
"callStacks": "button
app/browser/event/page.js (5:6)",
"count": 1,
"description": "trigger an console <error>",
"source": "app/browser/event/page.js (7:17) @ error
5 | <button
6 | onClick={() => {
> 7 | console.error('trigger an console <%s>', 'error')
Expand Down

0 comments on commit dbc9452

Please sign in to comment.