From 2ca072e5f1f737f4ddc76a75d1527259e6d25b89 Mon Sep 17 00:00:00 2001 From: Michael Ozeryansky Date: Thu, 2 Dec 2021 18:04:06 -0600 Subject: [PATCH] JSON.stringify generic errors --- packages/next/client/index.tsx | 2 +- packages/next/server/base-server.ts | 8 +++---- packages/next/server/dev/hot-reloader.ts | 2 +- packages/next/server/dev/next-dev-server.ts | 8 +++++-- .../acceptance/ReactRefreshLogBox.test.ts | 23 +++++++++++++++++++ 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/packages/next/client/index.tsx b/packages/next/client/index.tsx index 9ad4e7c63a0b..0caaaf778787 100644 --- a/packages/next/client/index.tsx +++ b/packages/next/client/index.tsx @@ -338,7 +338,7 @@ export async function initNext(opts: { webpackHMR?: any } = {}) { } } catch (error) { // This catches errors like throwing in the top level of a module - initialErr = isError(error) ? error : new Error(error + '') + initialErr = isError(error) ? error : new Error(JSON.stringify(error)) } if (process.env.NODE_ENV === 'development') { diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index e0feebf06e5b..7022005439a6 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -2292,7 +2292,7 @@ export default abstract class Server { } } } catch (error) { - const err = isError(error) ? error : error ? new Error(error + '') : null + const err = isError(error) ? error : error ? new Error(JSON.stringify(error)) : null if (err instanceof NoFallbackError && bubbleNoFallback) { throw err } @@ -2313,7 +2313,7 @@ export default abstract class Server { if (isError(err)) err.page = page throw err } - this.logError(err || new Error(error + '')) + this.logError(err || new Error(JSON.stringify(error))) } return response } @@ -2433,11 +2433,11 @@ export default abstract class Server { const renderToHtmlError = isError(error) ? error : error - ? new Error(error + '') + ? new Error(JSON.stringify(error)) : null const isWrappedError = renderToHtmlError instanceof WrappedBuildError if (!isWrappedError) { - this.logError(renderToHtmlError || new Error(error + '')) + this.logError(renderToHtmlError || new Error(JSON.stringify(error))) } res.statusCode = 500 const fallbackComponents = await this.getFallbackErrorComponents() diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index fb969a6707db..c4c94016fb6c 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -251,7 +251,7 @@ export default class HotReloader { } catch (error) { await renderScriptError( pageBundleRes, - isError(error) ? error : new Error(error + '') + isError(error) ? error : new Error(JSON.stringify(error)) ) return { finished: true } } diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index 52ef614ec907..5ceb07509382 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -538,7 +538,7 @@ export default class DevServer extends Server { return result } catch (error) { this.logErrorWithOriginalStack(error, undefined, 'client') - const err = isError(error) ? error : new Error(error + '') + const err = isError(error) ? error : new Error(JSON.stringify(error)) ;(err as any).middleware = true const { request, response, parsedUrl } = params this.renderError(err, request, response, parsedUrl.pathname) @@ -591,7 +591,11 @@ export default class DevServer extends Server { return await super.run(req, res, parsedUrl) } catch (error) { res.statusCode = 500 - const err = isError(error) ? error : error ? new Error(error + '') : null + const err = isError(error) + ? error + : error + ? new Error(JSON.stringify(error)) + : null try { this.logErrorWithOriginalStack(err).catch(() => {}) return await this.renderError(err, req, res, pathname!, { diff --git a/test/development/acceptance/ReactRefreshLogBox.test.ts b/test/development/acceptance/ReactRefreshLogBox.test.ts index 44ce8d9c6acd..b86ced0eb594 100644 --- a/test/development/acceptance/ReactRefreshLogBox.test.ts +++ b/test/development/acceptance/ReactRefreshLogBox.test.ts @@ -903,4 +903,27 @@ describe('ReactRefreshLogBox', () => { await cleanup() }) + + test('custom error prints JSON as string', async () => { + const { session, cleanup } = await sandbox(next) + + await session.patch( + 'index.js', + ` + export default () => { + throw {'a': 1, 'b': 'x'}; + return ( +
hello
+ ) + } + ` + ) + + expect(await session.hasRedbox(true)).toBe(true) + expect(await session.getRedboxDescription()).toMatchInlineSnapshot( + `"Error: {\\"a\\":1,\\"b\\":\\"x\\"}"` + ) + + await cleanup() + }) })