Skip to content

Commit

Permalink
Upgrade react@experimental (#40885)
Browse files Browse the repository at this point in the history
  • Loading branch information
timneutkens committed Sep 25, 2022
1 parent f6e37fd commit 3211b3f
Show file tree
Hide file tree
Showing 12 changed files with 182 additions and 115 deletions.
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -181,8 +181,8 @@
"react-17": "npm:react@17.0.2",
"react-dom": "18.2.0",
"react-dom-17": "npm:react-dom@17.0.2",
"react-dom-exp": "npm:react-dom@0.0.0-experimental-8951c5fc9-20220915",
"react-exp": "npm:react@0.0.0-experimental-8951c5fc9-20220915",
"react-dom-exp": "npm:react-dom@0.0.0-experimental-cb5084d1c-20220924",
"react-exp": "npm:react@0.0.0-experimental-cb5084d1c-20220924",
"react-ssr-prepass": "1.0.8",
"react-virtualized": "9.22.3",
"relay-compiler": "13.0.2",
Expand Down
12 changes: 3 additions & 9 deletions packages/next/client/components/hooks-server-context.ts
@@ -1,14 +1,8 @@
// @ts-expect-error createServerContext exists on experimental channel
import { createServerContext } from 'react'

// createServerContext exists in react@experimental + react-dom@experimental
if (typeof createServerContext === 'undefined') {
throw new Error(
'"app" directory requires React.createServerContext which is not available in the version of React you are using. Please update to react@experimental and react-dom@experimental.'
)
}
export const DYNAMIC_ERROR_CODE = 'DYNAMIC_SERVER_USAGE'

export class DynamicServerError extends Error {
digest: typeof DYNAMIC_ERROR_CODE = DYNAMIC_ERROR_CODE

constructor(type: string) {
super(`Dynamic server usage: ${type}`)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/next/client/components/layout-router.client.tsx
Expand Up @@ -309,7 +309,7 @@ class RedirectErrorBoundary extends React.Component<
}

static getDerivedStateFromError(error: any) {
if (error.code === 'NEXT_REDIRECT') {
if (error.digest === 'NEXT_REDIRECT') {
return { redirect: error.url }
}
// Re-throw if error is not for 404
Expand Down
2 changes: 1 addition & 1 deletion packages/next/client/components/redirect.ts
Expand Up @@ -4,6 +4,6 @@ export function redirect(url: string) {
// eslint-disable-next-line no-throw-literal
const error = new Error(REDIRECT_ERROR_CODE)
;(error as any).url = url
;(error as any).code = REDIRECT_ERROR_CODE
;(error as any).digest = REDIRECT_ERROR_CODE
throw error
}
Expand Up @@ -153,8 +153,22 @@ function serializeRowHeader(tag, id) {
return tag + id.toString(16) + ':';
}

function processErrorChunk(request, id, message, stack) {
function processErrorChunkProd(request, id, digest) {
{
// These errors should never make it into a build so we don't need to encode them in codes.json
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error('processErrorChunkProd should never be called while in development mode. Use processErrorChunkDev instead. This is a bug in React.');
}

var errorInfo = {
digest: digest
};
var row = serializeRowHeader('E', id) + stringify(errorInfo) + '\n';
}
function processErrorChunkDev(request, id, digest, message, stack) {

var errorInfo = {
digest: digest,
message: message,
stack: stack
};
Expand Down Expand Up @@ -1388,7 +1402,16 @@ function serializeModuleReference(request, parent, key, moduleReference) {
} catch (x) {
request.pendingChunks++;
var errorId = request.nextChunkId++;
emitErrorChunk(request, errorId, x);
var digest = logRecoverableError(request, x);

{
var _getErrorMessageAndSt = getErrorMessageAndStackDev(x),
message = _getErrorMessageAndSt.message,
stack = _getErrorMessageAndSt.stack;

emitErrorChunkDev(request, errorId, digest, message, stack);
}

return serializeByValueID(errorId);
}
}
Expand Down Expand Up @@ -1633,7 +1656,16 @@ function resolveModelToJSON(request, parent, key, value) {

request.pendingChunks++;
var errorId = request.nextChunkId++;
emitErrorChunk(request, errorId, x);
var digest = logRecoverableError(request, x);

{
var _getErrorMessageAndSt2 = getErrorMessageAndStackDev(x),
message = _getErrorMessageAndSt2.message,
stack = _getErrorMessageAndSt2.stack;

emitErrorChunkDev(request, errorId, digest, message, stack);
}

return serializeByRefID(errorId);
}
}
Expand Down Expand Up @@ -1744,7 +1776,39 @@ function resolveModelToJSON(request, parent, key, value) {

function logRecoverableError(request, error) {
var onError = request.onError;
onError(error);
var errorDigest = onError(error);

if (errorDigest != null && typeof errorDigest !== 'string') {
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error("onError returned something with a type other than \"string\". onError should return a string and may return null or undefined but must not return anything else. It received something of type \"" + typeof errorDigest + "\" instead");
}

return errorDigest || '';
}

function getErrorMessageAndStackDev(error) {
{
var message;
var stack = '';

try {
if (error instanceof Error) {
// eslint-disable-next-line react-internal/safe-string-coercion
message = String(error.message); // eslint-disable-next-line react-internal/safe-string-coercion

stack = String(error.stack);
} else {
message = 'Error: ' + error;
}
} catch (x) {
message = 'An error occurred but serializing the error message failed.';
}

return {
message: message,
stack: stack
};
}
}

function fatalError(request, error) {
Expand All @@ -1758,27 +1822,13 @@ function fatalError(request, error) {
}
}

function emitErrorChunk(request, id, error) {
// TODO: We should not leak error messages to the client in prod.
// Give this an error code instead and log on the server.
// We can serialize the error in DEV as a convenience.
var message;
var stack = '';

try {
if (error instanceof Error) {
// eslint-disable-next-line react-internal/safe-string-coercion
message = String(error.message); // eslint-disable-next-line react-internal/safe-string-coercion

stack = String(error.stack);
} else {
message = 'Error: ' + error;
}
} catch (x) {
message = 'An error occurred but serializing the error message failed.';
}
function emitErrorChunkProd(request, id, digest) {
var processedChunk = processErrorChunkProd(request, id, digest);
request.completedErrorChunks.push(processedChunk);
}

var processedChunk = processErrorChunk(request, id, message, stack);
function emitErrorChunkDev(request, id, digest, message, stack) {
var processedChunk = processErrorChunkDev(request, id, digest, message, stack);
request.completedErrorChunks.push(processedChunk);
}

Expand Down Expand Up @@ -1850,9 +1900,15 @@ function retryTask(request, task) {
} else {
request.abortableTasks.delete(task);
task.status = ERRORED;
logRecoverableError(request, x); // This errored, we need to serialize this error to the
var digest = logRecoverableError(request, x);

{
var _getErrorMessageAndSt3 = getErrorMessageAndStackDev(x),
message = _getErrorMessageAndSt3.message,
stack = _getErrorMessageAndSt3.stack;

emitErrorChunk(request, task.id, x);
emitErrorChunkDev(request, task.id, digest, message, stack);
}
}
}
}
Expand Down Expand Up @@ -2005,10 +2061,20 @@ function abort(request, reason) {
// to that row from every row that's still remaining.
var _error = reason === undefined ? new Error('The render was aborted by the server without a reason.') : reason;

logRecoverableError(request, _error);
var digest = logRecoverableError(request, _error);
request.pendingChunks++;
var errorId = request.nextChunkId++;
emitErrorChunk(request, errorId, _error);

if (true) {
var _getErrorMessageAndSt4 = getErrorMessageAndStackDev(_error),
message = _getErrorMessageAndSt4.message,
stack = _getErrorMessageAndSt4.stack;

emitErrorChunkDev(request, errorId, digest, message, stack);
} else {
emitErrorChunkProd(request, errorId, digest);
}

abortableTasks.forEach(function (task) {
return abortTask(task, request, errorId);
});
Expand Down

0 comments on commit 3211b3f

Please sign in to comment.