Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions packages/next/src/lib/is-error.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isPlainObject } from '../shared/lib/is-plain-object'
import safeStringify from 'next/dist/compiled/safe-stable-stringify'

// We allow some additional attached properties for Next.js errors
export interface NextError extends Error {
Expand All @@ -19,24 +20,6 @@ export default function isError(err: unknown): err is NextError {
)
}

/**
* This is a safe stringify function that handles circular references.
*/
export function safeStringify(obj: any) {
const seen = new WeakSet()

return JSON.stringify(obj, (_key, value) => {
// If value is an object and already seen, replace with "[Circular]"
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return '[Circular]'
}
seen.add(value)
}
return value
})
}

export function getProperError(err: unknown): Error {
if (isError(err)) {
return err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const maximumBreadth =
? terminalLoggingConfig.edgeLimit
: 100

const stringify = configure({
export const safeStringifyWithDepth = configure({
maximumDepth,
maximumBreadth,
})
Expand Down Expand Up @@ -80,7 +80,7 @@ export function preLogSerializationClone<T>(
// only safe if passed safeClone data
export const logStringify = (data: unknown): string => {
try {
const result = stringify(data)
const result = safeStringifyWithDepth(data)
return result ?? `"${UNAVAILABLE_MARKER}"`
} catch {
return `"${UNAVAILABLE_MARKER}"`
Expand Down
9 changes: 6 additions & 3 deletions packages/next/src/next-devtools/userspace/app/forward-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import {
type LogMethod,
patchConsoleMethod,
} from '../../shared/forward-logs-shared'
import { preLogSerializationClone, logStringify } from './forward-logs-utils'
import { safeStringify } from '../../../lib/is-error'
import {
preLogSerializationClone,
logStringify,
safeStringifyWithDepth,
} from './forward-logs-utils'

// Client-side file logger for browser logs
class ClientFileLogger {
Expand Down Expand Up @@ -46,7 +49,7 @@ class ClientFileLogger {
return String(arg)
if (arg === null) return 'null'
if (arg === undefined) return 'undefined'
return safeStringify(arg)
return safeStringifyWithDepth(arg)
})
.join(' ')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('serialize-circular-error', () => {
`)
const output = next.cliOutput
expect(output).toContain(
'Error: {"objA":{"other":{"a":"[Circular]"}},"objB":"[Circular]"}'
'Error: {"objA":{"other":{"a":"[Circular]"}},"objB":{"a":{"other":"[Circular]"}}}'
)
})

Expand All @@ -44,7 +44,7 @@ describe('serialize-circular-error', () => {

const output = next.cliOutput
expect(output).toContain(
'Error: {"objC":{"other":{"a":"[Circular]"}},"objD":"[Circular]"}'
'Error: {"objC":{"other":{"a":"[Circular]"}},"objD":{"a":{"other":"[Circular]"}}}'
)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ export default function ClientPage() {
console.warn('Client: This is a warning message from client component')
}, [])

console.error('globalThis', globalThis)

return <p>client page with logging</p>
}
2 changes: 1 addition & 1 deletion test/e2e/app-dir/log-file/log-file.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('log-file', () => {
await retry(async () => {
const newLogContent = getNewLogContent()
expect(newLogContent).toMatchInlineSnapshot(`
"[xx:xx:xx.xxx] Browser LOG Client: Complex circular object: {"name":"test","data":{"nested":{"value":42,"items":[1,2,3]},"parent":"[Circular]"},"metadata":{"name":"safe stringify","version":"1.0.0"}}
"[xx:xx:xx.xxx] Browser LOG Client: Complex circular object: {"data":{"nested":{"items":[1,2,3],"value":42},"parent":"[Circular]"},"metadata":{"name":"safe stringify","version":"1.0.0"},"name":"test"}
[xx:xx:xx.xxx] Browser ERROR Client: This is an error message from client component
[xx:xx:xx.xxx] Browser WARN Client: This is a warning message from client component
"
Expand Down
Loading