next
Version:
The React Framework
156 lines (155 loc) • 8.83 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useMemo, useEffect, useRef, Suspense } from 'react';
import { Overlay } from '../components/overlay';
import { RuntimeError } from './runtime-error';
import { getErrorSource } from '../../../../../shared/lib/error-source';
import { HotlinkedText } from '../components/hot-linked-text';
import { PseudoHtmlDiff } from './runtime-error/component-stack-pseudo-html';
import { getHydrationWarningType } from '../../../errors/hydration-error-info';
import { getUnhandledErrorType, isUnhandledConsoleOrRejection } from '../../../errors/console-error';
import { extractNextErrorCode } from '../../../../../lib/error-telemetry-utils';
import { ErrorOverlayLayout } from '../components/errors/error-overlay-layout/error-overlay-layout';
import { NEXTJS_HYDRATION_ERROR_LINK } from '../../../is-hydration-error';
function isNextjsLink(text) {
return text.startsWith('https://nextjs.org');
}
function ErrorDescription(param) {
let { error, hydrationWarning } = param;
const isUnhandledOrReplayError = isUnhandledConsoleOrRejection(error);
const unhandledErrorType = isUnhandledOrReplayError ? getUnhandledErrorType(error) : null;
const isConsoleErrorStringMessage = unhandledErrorType === 'string';
// If the error is:
// - hydration warning
// - captured console error or unhandled rejection
// skip displaying the error name
const title = isUnhandledOrReplayError && isConsoleErrorStringMessage || hydrationWarning ? '' : error.name + ': ';
const environmentName = 'environmentName' in error ? error.environmentName : '';
const envPrefix = environmentName ? "[ " + environmentName + " ] " : '';
// The environment name will be displayed as a label, so remove it
// from the message (e.g. "[ Server ] hello world" -> "hello world").
let message = error.message;
if (message.startsWith(envPrefix)) {
message = message.slice(envPrefix.length);
}
return /*#__PURE__*/ _jsxs(_Fragment, {
children: [
title,
/*#__PURE__*/ _jsx(HotlinkedText, {
text: hydrationWarning || message,
matcher: isNextjsLink
})
]
});
}
export function Errors(param) {
let { runtimeErrors, debugInfo, onClose, ...props } = param;
var _activeError_componentStackFrames;
const dialogResizerRef = useRef(null);
useEffect(()=>{
// Close the error overlay when pressing escape
function handleKeyDown(event) {
if (event.key === 'Escape') {
onClose();
}
}
document.addEventListener('keydown', handleKeyDown);
return ()=>document.removeEventListener('keydown', handleKeyDown);
}, [
onClose
]);
const isLoading = useMemo(()=>{
return runtimeErrors.length < 1;
}, [
runtimeErrors.length
]);
const [activeIdx, setActiveIndex] = useState(0);
const activeError = useMemo(()=>{
var _runtimeErrors_activeIdx;
return (_runtimeErrors_activeIdx = runtimeErrors[activeIdx]) != null ? _runtimeErrors_activeIdx : null;
}, [
activeIdx,
runtimeErrors
]);
if (isLoading) {
// TODO: better loading state
return /*#__PURE__*/ _jsx(Overlay, {});
}
if (!activeError) {
return null;
}
const error = activeError.error;
const isServerError = [
'server',
'edge-server'
].includes(getErrorSource(error) || '');
const isUnhandledError = isUnhandledConsoleOrRejection(error);
const errorDetails = error.details || {};
const notes = errorDetails.notes || '';
const [warningTemplate, serverContent, clientContent] = errorDetails.warning || [
null,
'',
''
];
const hydrationErrorType = getHydrationWarningType(warningTemplate);
const hydrationWarning = warningTemplate ? warningTemplate.replace('%s', serverContent).replace('%s', clientContent).replace('%s', '') // remove the %s for stack
.replace(/%s$/, '') // If there's still a %s at the end, remove it
.replace(/^Warning: /, '').replace(/^Error: /, '') : null;
const errorCode = extractNextErrorCode(error);
const footerMessage = isServerError ? 'This error happened while generating the page. Any console logs will be displayed in the terminal window.' : undefined;
return /*#__PURE__*/ _jsxs(ErrorOverlayLayout, {
errorCode: errorCode,
errorType: isServerError ? 'Runtime Error' : isUnhandledError ? 'Console Error' : 'Unhandled Runtime Error',
errorMessage: /*#__PURE__*/ _jsx(ErrorDescription, {
error: error,
hydrationWarning: hydrationWarning
}),
onClose: isServerError ? undefined : onClose,
debugInfo: debugInfo,
error: error,
runtimeErrors: runtimeErrors,
activeIdx: activeIdx,
setActiveIndex: setActiveIndex,
footerMessage: footerMessage,
dialogResizerRef: dialogResizerRef,
...props,
children: [
/*#__PURE__*/ _jsxs("div", {
className: "error-overlay-notes-container",
children: [
notes ? /*#__PURE__*/ _jsx(_Fragment, {
children: /*#__PURE__*/ _jsx("p", {
id: "nextjs__container_errors__notes",
className: "nextjs__container_errors__notes",
children: notes
})
}) : null,
hydrationWarning ? /*#__PURE__*/ _jsx("p", {
id: "nextjs__container_errors__link",
className: "nextjs__container_errors__link",
children: /*#__PURE__*/ _jsx(HotlinkedText, {
text: "See more info here: " + NEXTJS_HYDRATION_ERROR_LINK
})
}) : null
]
}),
hydrationWarning && (((_activeError_componentStackFrames = activeError.componentStackFrames) == null ? void 0 : _activeError_componentStackFrames.length) || !!errorDetails.reactOutputComponentDiff) ? /*#__PURE__*/ _jsx(PseudoHtmlDiff, {
className: "nextjs__container_errors__component-stack",
hydrationMismatchType: hydrationErrorType,
firstContent: serverContent,
secondContent: clientContent,
reactOutputComponentDiff: errorDetails.reactOutputComponentDiff || ''
}) : null,
/*#__PURE__*/ _jsx(Suspense, {
fallback: /*#__PURE__*/ _jsx("div", {
"data-nextjs-error-suspended": true
}),
children: /*#__PURE__*/ _jsx(RuntimeError, {
error: activeError,
dialogResizerRef: dialogResizerRef
}, activeError.id.toString())
})
]
});
}
export const styles = "\n .nextjs-error-with-static {\n bottom: calc(16px * 4.5);\n }\n p.nextjs__container_errors__link {\n font-size: var(--size-14);\n }\n p.nextjs__container_errors__notes {\n color: var(--color-stack-notes);\n font-size: var(--size-14);\n line-height: 1.5;\n }\n .nextjs-container-errors-body > h2:not(:first-child) {\n margin-top: calc(16px + 8px);\n }\n .nextjs-container-errors-body > h2 {\n color: var(--color-title-color);\n margin-bottom: 8px;\n font-size: var(--size-20);\n }\n .nextjs-toast-errors-parent {\n cursor: pointer;\n transition: transform 0.2s ease;\n }\n .nextjs-toast-errors-parent:hover {\n transform: scale(1.1);\n }\n .nextjs-toast-errors {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n }\n .nextjs-toast-errors > svg {\n margin-right: 8px;\n }\n .nextjs-toast-hide-button {\n margin-left: 24px;\n border: none;\n background: none;\n color: var(--color-ansi-bright-white);\n padding: 0;\n transition: opacity 0.25s ease;\n opacity: 0.7;\n }\n .nextjs-toast-hide-button:hover {\n opacity: 1;\n }\n .nextjs__container_errors_inspect_copy_button {\n cursor: pointer;\n background: none;\n border: none;\n color: var(--color-ansi-bright-white);\n font-size: var(--size-24);\n padding: 0;\n margin: 0;\n margin-left: 8px;\n transition: opacity 0.25s ease;\n }\n .nextjs__container_errors__error_title {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 14px;\n }\n .error-overlay-notes-container {\n margin: 8px 2px;\n }\n .error-overlay-notes-container p {\n white-space: pre-wrap;\n }\n";
//# sourceMappingURL=errors.js.map