From 553420e763a7a62356927d9120554b19f40e76f5 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Thu, 2 Jun 2022 01:47:41 -0400 Subject: [PATCH] refactor hash to digest --- .../src/__tests__/ReactDOMFizzServer-test.js | 8 +-- .../src/client/ReactDOMHostConfig.js | 43 +++++++++++---- .../src/server/ReactDOMServerFormatConfig.js | 54 +++++++++---------- .../ReactDOMServerLegacyFormatConfig.js | 2 +- .../server/ReactNativeServerFormatConfig.js | 4 +- .../src/ReactCapturedValue.js | 10 ++-- .../src/ReactFiberBeginWork.new.js | 14 +++-- .../src/ReactFiberBeginWork.old.js | 14 +++-- .../src/ReactFiberWorkLoop.new.js | 4 +- .../src/ReactFiberWorkLoop.old.js | 4 +- .../src/ReactInternalTypes.js | 2 +- packages/react-server/src/ReactFizzServer.js | 24 ++++----- 12 files changed, 107 insertions(+), 76 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index bba82732a7c9b..f78e69ae7c945 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -92,11 +92,11 @@ describe('ReactDOMFizzServer', () => { function expectErrors(errorsArr, toBeDevArr, toBeProdArr) { const mappedErrows = errorsArr.map(({error, errorInfo}) => { const stack = errorInfo && errorInfo.componentStack; - const errorHash = errorInfo && errorInfo.errorHash; + const digest = errorInfo && errorInfo.digest; if (stack) { - return [error.message, errorHash, normalizeCodeLocInfo(stack)]; - } else if (errorHash) { - return [error.message, errorHash]; + return [error.message, digest, normalizeCodeLocInfo(stack)]; + } else if (digest) { + return [error.message, digest]; } return error.message; }); diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js index 58dab0f150889..662abd8a69c33 100644 --- a/packages/react-dom/src/client/ReactDOMHostConfig.js +++ b/packages/react-dom/src/client/ReactDOMHostConfig.js @@ -729,22 +729,43 @@ export function isSuspenseInstancePending(instance: SuspenseInstance) { export function isSuspenseInstanceFallback(instance: SuspenseInstance) { return instance.data === SUSPENSE_FALLBACK_START_DATA; } + export function getSuspenseInstanceFallbackErrorDetails( instance: SuspenseInstance, -): {message?: string, stack?: string, hash?: string} { - const nextSibling = instance.nextSibling; - if ( - nextSibling && - nextSibling.nodeType === ELEMENT_NODE && - nextSibling.nodeName.toLowerCase() === 'template' - ) { +): {digest: ?string, message?: string, stack?: string} { + const dataset = + instance.nextSibling && ((instance.nextSibling: any): HTMLElement).dataset; + let digest, message, stack; + if (dataset) { + digest = dataset.dgst; + if (__DEV__) { + message = dataset.msg; + stack = dataset.stck; + } + } + if (__DEV__) { return { - message: ((nextSibling: any): HTMLTemplateElement).dataset.msg, - stack: ((nextSibling: any): HTMLTemplateElement).dataset.stack, - hash: ((nextSibling: any): HTMLTemplateElement).dataset.hash, + message, + digest, + stack, + }; + } else { + return { + digest, }; } - return {}; + + // let value = {message: undefined, hash: undefined}; + // const nextSibling = instance.nextSibling; + // if (nextSibling) { + // const dataset = ((nextSibling: any): HTMLTemplateElement).dataset; + // value.message = dataset.msg; + // value.hash = dataset.hash; + // if (__DEV__) { + // value.stack = dataset.stack; + // } + // } + // return value; } export function registerSuspenseInstanceRetry( diff --git a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js index f006477c4b0a3..8ec0683ec6084 100644 --- a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js +++ b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js @@ -1527,13 +1527,13 @@ const startClientRenderedSuspenseBoundary = stringToPrecomputedChunk( const endSuspenseBoundary = stringToPrecomputedChunk(''); const clientRenderedSuspenseBoundaryError1 = stringToPrecomputedChunk( - '', @@ -1576,7 +1576,7 @@ export function writeStartPendingSuspenseBoundary( export function writeStartClientRenderedSuspenseBoundary( destination: Destination, responseState: ResponseState, - errorHash: ?string, + errorDigest: ?string, errorMesssage: ?string, errorComponentStack: ?string, ): boolean { @@ -1585,11 +1585,12 @@ export function writeStartClientRenderedSuspenseBoundary( destination, startClientRenderedSuspenseBoundary, ); - if (errorHash) { - writeChunk(destination, clientRenderedSuspenseBoundaryError1); - writeChunk(destination, stringToChunk(escapeTextForBrowser(errorHash))); - // In prod errorMessage will usually be nullish but there is one case where - // it is used (currently when the server aborts the task) so we leave it ungated. + writeChunk(destination, clientRenderedSuspenseBoundaryError1); + writeChunk( + destination, + stringToChunk(escapeTextForBrowser(errorDigest || '')), + ); + if (__DEV__) { if (errorMesssage) { writeChunk(destination, clientRenderedSuspenseBoundaryError1A); writeChunk( @@ -1597,21 +1598,18 @@ export function writeStartClientRenderedSuspenseBoundary( stringToChunk(escapeTextForBrowser(errorMesssage)), ); } - if (__DEV__) { - // Component stacks are currently only captured in dev - if (errorComponentStack) { - writeChunk(destination, clientRenderedSuspenseBoundaryError1B); - writeChunk( - destination, - stringToChunk(escapeTextForBrowser(errorComponentStack)), - ); - } + if (errorComponentStack) { + writeChunk(destination, clientRenderedSuspenseBoundaryError1B); + writeChunk( + destination, + stringToChunk(escapeTextForBrowser(errorComponentStack)), + ); } - result = writeChunkAndReturn( - destination, - clientRenderedSuspenseBoundaryError2, - ); } + result = writeChunkAndReturn( + destination, + clientRenderedSuspenseBoundaryError2, + ); return result; } export function writeEndCompletedSuspenseBoundary( @@ -1772,7 +1770,7 @@ export function writeEndSegment( // const SUSPENSE_PENDING_START_DATA = '$?'; // const SUSPENSE_FALLBACK_START_DATA = '$!'; // -// function clientRenderBoundary(suspenseBoundaryID, errorHash, errorMsg, errorComponentStack) { +// function clientRenderBoundary(suspenseBoundaryID, errorDigest, errorMsg, errorComponentStack) { // // Find the fallback's first element. // const suspenseIdNode = document.getElementById(suspenseBoundaryID); // if (!suspenseIdNode) { @@ -1786,9 +1784,9 @@ export function writeEndSegment( // suspenseNode.data = SUSPENSE_FALLBACK_START_DATA; // // assign error metadata to first sibling // let dataset = suspenseIdNode.dataset; -// if (errorHash) dataset.hash = errorHash; +// if (errorDigest) dataset.dgst = errorDigest; // if (errorMsg) dataset.msg = errorMsg; -// if (errorComponentStack) dataset.stack = errorComponentStack; +// if (errorComponentStack) dataset.stck = errorComponentStack; // // Tell React to retry it if the parent already hydrated. // if (suspenseNode._reactRetry) { // suspenseNode._reactRetry(); @@ -1876,7 +1874,7 @@ const completeSegmentFunction = const completeBoundaryFunction = 'function $RC(a,b){a=document.getElementById(a);b=document.getElementById(b);b.parentNode.removeChild(b);if(a){a=a.previousSibling;var f=a.parentNode,c=a.nextSibling,e=0;do{if(c&&8===c.nodeType){var d=c.data;if("/$"===d)if(0===e)break;else e--;else"$"!==d&&"$?"!==d&&"$!"!==d||e++}d=c.nextSibling;f.removeChild(c);c=d}while(c);for(;b.firstChild;)f.insertBefore(b.firstChild,c);a.data="$";a._reactRetry&&a._reactRetry()}}'; const clientRenderFunction = - 'function $RX(b,c,d,e){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.hash=c),d&&(a.msg=d),e&&(a.stack=e),b._reactRetry&&b._reactRetry())}'; + 'function $RX(b,c,d,e){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),b._reactRetry&&b._reactRetry())}'; const completeSegmentScript1Full = stringToPrecomputedChunk( completeSegmentFunction + ';$RS("', @@ -1957,7 +1955,7 @@ export function writeClientRenderBoundaryInstruction( destination: Destination, responseState: ResponseState, boundaryID: SuspenseBoundaryID, - errorHash: ?string, + errorDigest: ?string, errorMessage?: string, errorComponentStack?: string, ): boolean { @@ -1979,11 +1977,11 @@ export function writeClientRenderBoundaryInstruction( writeChunk(destination, boundaryID); writeChunk(destination, clientRenderScript1A); - if (errorHash || errorMessage || errorComponentStack) { + if (errorDigest || errorMessage || errorComponentStack) { writeChunk(destination, clientRenderErrorScriptArgInterstitial); writeChunk( destination, - stringToChunk(escapeJSStringsForInstructionScripts(errorHash || '')), + stringToChunk(escapeJSStringsForInstructionScripts(errorDigest || '')), ); } if (errorMessage || errorComponentStack) { diff --git a/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js index 71716d7b71f28..4dff9651858b7 100644 --- a/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js +++ b/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js @@ -149,7 +149,7 @@ export function writeStartClientRenderedSuspenseBoundary( destination: Destination, responseState: ResponseState, // flushing these error arguments are not currently supported in this legacy streaming format. - errorHash: ?string, + errorDigest: ?string, errorMessage?: string, errorComponentStack?: string, ): boolean { diff --git a/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js b/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js index d65a30180a4db..3c2c23c911faf 100644 --- a/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js +++ b/packages/react-native-renderer/src/server/ReactNativeServerFormatConfig.js @@ -226,7 +226,7 @@ export function writeStartClientRenderedSuspenseBoundary( destination: Destination, responseState: ResponseState, // TODO: encode error for native - errorHash: ?string, + errorDigest: ?string, errorMessage: ?string, errorComponentStack: ?string, ): boolean { @@ -300,7 +300,7 @@ export function writeClientRenderBoundaryInstruction( responseState: ResponseState, boundaryID: SuspenseBoundaryID, // TODO: encode error for native - errorHash: ?string, + errorDigest: ?string, errorMessage: ?string, errorComponentStack: ?string, ): boolean { diff --git a/packages/react-reconciler/src/ReactCapturedValue.js b/packages/react-reconciler/src/ReactCapturedValue.js index 82425f09e2556..64b1f18515d5a 100644 --- a/packages/react-reconciler/src/ReactCapturedValue.js +++ b/packages/react-reconciler/src/ReactCapturedValue.js @@ -15,7 +15,7 @@ export type CapturedValue = {| value: T, source: Fiber | null, stack: string | null, - hash: string | null, + digest: string | null, |}; export function createCapturedValueAtFiber( @@ -28,19 +28,19 @@ export function createCapturedValueAtFiber( value, source, stack: getStackByFiberInDevAndProd(source), - hash: null, + digest: null, }; } export function createCapturedValue( value: T, - hash?: string, - stack?: string, + digest: ?string, + stack: ?string, ): CapturedValue { return { value, source: null, stack: stack != null ? stack : null, - hash: hash != null ? hash : null, + digest: digest != null ? digest : null, }; } diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index 5c9579599384e..ed6456cfc96df 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -2583,9 +2583,15 @@ function updateDehydratedSuspenseComponent( // This boundary is in a permanent fallback state. In this case, we'll never // get an update and we'll never be able to hydrate the final content. Let's just try the // client side render instead. - const {message, hash, stack} = getSuspenseInstanceFallbackErrorDetails( - suspenseInstance, - ); + let digest, message, stack; + if (__DEV__) { + ({digest, message, stack} = getSuspenseInstanceFallbackErrorDetails( + suspenseInstance, + )); + } else { + ({digest} = getSuspenseInstanceFallbackErrorDetails(suspenseInstance)); + } + const error = message ? // eslint-disable-next-line react-internal/prod-error-codes new Error(message) @@ -2594,7 +2600,7 @@ function updateDehydratedSuspenseComponent( 'due to an error during server rendering. Switched to ' + 'client rendering.', ); - const capturedValue = createCapturedValue(error, hash, stack); + const capturedValue = createCapturedValue(error, digest, stack); return retrySuspenseComponentWithoutHydrating( current, workInProgress, diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index d1de936825229..c67896853f90e 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -2583,9 +2583,15 @@ function updateDehydratedSuspenseComponent( // This boundary is in a permanent fallback state. In this case, we'll never // get an update and we'll never be able to hydrate the final content. Let's just try the // client side render instead. - const {message, hash, stack} = getSuspenseInstanceFallbackErrorDetails( - suspenseInstance, - ); + let digest, message, stack; + if (__DEV__) { + ({digest, message, stack} = getSuspenseInstanceFallbackErrorDetails( + suspenseInstance, + )); + } else { + ({digest} = getSuspenseInstanceFallbackErrorDetails(suspenseInstance)); + } + const error = message ? // eslint-disable-next-line react-internal/prod-error-codes new Error(message) @@ -2594,7 +2600,7 @@ function updateDehydratedSuspenseComponent( 'due to an error during server rendering. Switched to ' + 'client rendering.', ); - const capturedValue = createCapturedValue(error, hash, stack); + const capturedValue = createCapturedValue(error, digest, stack); return retrySuspenseComponentWithoutHydrating( current, workInProgress, diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index 8b6fff00626a3..80f1ac281b834 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -2343,8 +2343,8 @@ function commitRootImpl( for (let i = 0; i < recoverableErrors.length; i++) { const recoverableError = recoverableErrors[i]; const componentStack = recoverableError.stack; - const errorHash = recoverableError.hash; - onRecoverableError(recoverableError.value, {componentStack, errorHash}); + const digest = recoverableError.digest; + onRecoverableError(recoverableError.value, {componentStack, digest}); } } diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index 3f930d8b41b83..8ced93396ab3d 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -2343,8 +2343,8 @@ function commitRootImpl( for (let i = 0; i < recoverableErrors.length; i++) { const recoverableError = recoverableErrors[i]; const componentStack = recoverableError.stack; - const errorHash = recoverableError.hash; - onRecoverableError(recoverableError.value, {componentStack, errorHash}); + const digest = recoverableError.digest; + onRecoverableError(recoverableError.value, {componentStack, digest}); } } diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 8e552aaf4c046..90eaf94474461 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -249,7 +249,7 @@ type BaseFiberRootProperties = {| onRecoverableError: ( error: mixed, - errorInfo: {errorHash?: ?string, componentStack?: ?string}, + errorInfo: {errorDigest?: ?string, componentStack?: ?string}, ) => void, |}; diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index 5376ca2764ff2..31a22f132ecaf 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -131,7 +131,7 @@ type LegacyContext = { type SuspenseBoundary = { id: SuspenseBoundaryID, rootSegmentID: number, - errorHash: ?string, // the error hash if it errors + errorDigest: ?string, // the error hash if it errors errorMessage?: string, // the error string if it errors errorComponentStack?: string, // the error component stack if it errors forceClientRender: boolean, // if it errors or infinitely suspends @@ -323,7 +323,7 @@ function createSuspenseBoundary( completedSegments: [], byteSize: 0, fallbackAbortableTasks, - errorHash: null, + errorDigest: null, }; } @@ -463,14 +463,14 @@ function captureBoundaryErrorDetailsDev( function logRecoverableError(request: Request, error: any): ?string { // If this callback errors, we intentionally let that error bubble up to become a fatal error // so that someone fixes the error reporting instead of hiding it. - const errorHash = request.onError(error); - if (errorHash != null && typeof errorHash !== 'string') { + const errorDigest = request.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 errorHash}" instead`, + `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 errorHash; + return errorDigest; } function fatalError(request: Request, error: mixed): void { @@ -568,7 +568,7 @@ function renderSuspenseBoundary( } catch (error) { contentRootSegment.status = ERRORED; newBoundary.forceClientRender = true; - newBoundary.errorHash = logRecoverableError(request, error); + newBoundary.errorDigest = logRecoverableError(request, error); if (__DEV__) { captureBoundaryErrorDetailsDev(newBoundary, error); } @@ -1488,14 +1488,14 @@ function erroredTask( error: mixed, ) { // Report the error to a global handler. - const errorHash = logRecoverableError(request, error); + const errorDigest = logRecoverableError(request, error); if (boundary === null) { fatalError(request, error); } else { boundary.pendingTasks--; if (!boundary.forceClientRender) { boundary.forceClientRender = true; - boundary.errorHash = errorHash; + boundary.errorDigest = errorDigest; if (__DEV__) { captureBoundaryErrorDetailsDev(boundary, error); } @@ -1556,7 +1556,7 @@ function abortTask(task: Task): void { const error = new Error( 'This Suspense boundary was aborted by the server', ); - boundary.errorHash = request.onError(error); + boundary.errorDigest = request.onError(error); if (__DEV__) { captureBoundaryErrorDetailsDev(boundary, error); } @@ -1838,7 +1838,7 @@ function flushSegment( writeStartClientRenderedSuspenseBoundary( destination, request.responseState, - boundary.errorHash, + boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack, ); @@ -1921,7 +1921,7 @@ function flushClientRenderedBoundary( destination, request.responseState, boundary.id, - boundary.errorHash, + boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack, );