@@ -90,46 +90,28 @@ describe('ReactDOMFizzServer', () => {
9090 } ) ; 
9191
9292 function  expectErrors ( errorsArr ,  toBeDevArr ,  toBeProdArr )  { 
93-  const  mappedErrows  =  errorsArr . map ( error  =>  { 
94-  if  ( error . componentStack )  { 
95-  return  [ 
96-  error . message , 
97-  error . hash , 
98-  normalizeCodeLocInfo ( error . componentStack ) , 
99-  ] ; 
100-  }  else  if  ( error . hash )  { 
101-  return  [ error . message ,  error . hash ] ; 
93+  const  mappedErrows  =  errorsArr . map ( ( { error,  errorInfo} )  =>  { 
94+  const  stack  =  errorInfo  &&  errorInfo . componentStack ; 
95+  const  digest  =  errorInfo  &&  errorInfo . digest ; 
96+  if  ( stack )  { 
97+  return  [ error . message ,  digest ,  normalizeCodeLocInfo ( stack ) ] ; 
98+  }  else  if  ( digest )  { 
99+  return  [ error . message ,  digest ] ; 
102100 } 
103101 return  error . message ; 
104102 } ) ; 
105103 if  ( __DEV__ )  { 
106-  expect ( mappedErrows ) . toEqual ( 
107-  toBeDevArr , 
108-  // .map(([errorMessage, errorHash, errorComponentStack]) => { 
109-  // if (typeof error === 'string' || error instanceof String) { 
110-  // return error; 
111-  // } 
112-  // let str = JSON.stringify(error).replace(/\\n/g, '\n'); 
113-  // // this gets stripped away by normalizeCodeLocInfo... 
114-  // // Kind of hacky but lets strip it away here too just so they match... 
115-  // // easier than fixing the regex to account for this edge case 
116-  // if (str.endsWith('at **)" }')) { 
117-  // str = str.replace(/at \*\*\)\" }$/, 'at **)'); 
118-  // } 
119-  // return str; 
120-  // }), 
121-  ) ; 
104+  expect ( mappedErrows ) . toEqual ( toBeDevArr ) ; 
122105 }  else  { 
123106 expect ( mappedErrows ) . toEqual ( toBeProdArr ) ; 
124107 } 
125108 } 
126109
127-  // @TODO  we will use this in a followup change once we start exposing componentStacks from server errors 
128-  // function componentStack(components) { 
129-  // return components 
130-  // .map(component => `\n in ${component} (at **)`) 
131-  // .join(''); 
132-  // } 
110+  function  componentStack ( components )  { 
111+  return  components 
112+  . map ( component  =>  `\n in ${ component }  ) 
113+  . join ( '' ) ; 
114+  } 
133115
134116 async  function  act ( callback )  { 
135117 await  callback ( ) ; 
@@ -471,8 +453,8 @@ describe('ReactDOMFizzServer', () => {
471453 bootstrapped  =  true ; 
472454 // Attempt to hydrate the content. 
473455 ReactDOMClient . hydrateRoot ( container ,  < App  isClient = { true }  /> ,  { 
474-  onRecoverableError ( error )  { 
475-  errors . push ( error ) ; 
456+  onRecoverableError ( error ,   errorInfo )  { 
457+  errors . push ( { error,  errorInfo } ) ; 
476458 } , 
477459 } ) ; 
478460 } ; 
@@ -483,8 +465,8 @@ describe('ReactDOMFizzServer', () => {
483465 loggedErrors . push ( x ) ; 
484466 return  'Hash of ('  +  x . message  +  ')' ; 
485467 } 
486-  //  const expectedHash  = onError(theError);
487-  //  loggedErrors.length = 0;
468+  const  expectedDigest  =  onError ( theError ) ; 
469+  loggedErrors . length  =  0 ; 
488470
489471 await  act ( async  ( )  =>  { 
490472 const  { pipe}  =  ReactDOMFizzServer . renderToPipeableStream ( 
@@ -519,9 +501,18 @@ describe('ReactDOMFizzServer', () => {
519501 expect ( Scheduler ) . toFlushAndYield ( [ ] ) ; 
520502 expectErrors ( 
521503 errors , 
522-  [ theError . message ] , 
523504 [ 
524-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
505+  [ 
506+  theError . message , 
507+  expectedDigest , 
508+  componentStack ( [ 'Lazy' ,  'Suspense' ,  'div' ,  'App' ] ) , 
509+  ] , 
510+  ] , 
511+  [ 
512+  [ 
513+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
514+  expectedDigest , 
515+  ] , 
525516 ] , 
526517 ) ; 
527518
@@ -577,8 +568,8 @@ describe('ReactDOMFizzServer', () => {
577568 loggedErrors . push ( x ) ; 
578569 return  'hash of ('  +  x . message  +  ')' ; 
579570 } 
580-  //  const expectedHash  = onError(theError);
581-  //  loggedErrors.length = 0;
571+  const  expectedDigest  =  onError ( theError ) ; 
572+  loggedErrors . length  =  0 ; 
582573
583574 function  App ( { isClient} )  { 
584575 return  ( 
@@ -605,8 +596,8 @@ describe('ReactDOMFizzServer', () => {
605596 const  errors  =  [ ] ; 
606597 // Attempt to hydrate the content. 
607598 ReactDOMClient . hydrateRoot ( container ,  < App  isClient = { true }  /> ,  { 
608-  onRecoverableError ( error )  { 
609-  errors . push ( error ) ; 
599+  onRecoverableError ( error ,   errorInfo )  { 
600+  errors . push ( { error,  errorInfo } ) ; 
610601 } , 
611602 } ) ; 
612603 Scheduler . unstable_flushAll ( ) ; 
@@ -630,9 +621,18 @@ describe('ReactDOMFizzServer', () => {
630621
631622 expectErrors ( 
632623 errors , 
633-  [ theError . message ] , 
634624 [ 
635-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
625+  [ 
626+  theError . message , 
627+  expectedDigest , 
628+  componentStack ( [ 'Suspense' ,  'div' ,  'App' ] ) , 
629+  ] , 
630+  ] , 
631+  [ 
632+  [ 
633+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
634+  expectedDigest , 
635+  ] , 
636636 ] , 
637637 ) ; 
638638
@@ -675,8 +675,8 @@ describe('ReactDOMFizzServer', () => {
675675 loggedErrors . push ( x ) ; 
676676 return  'hash('  +  x . message  +  ')' ; 
677677 } 
678-  //  const expectedHash  = onError(theError);
679-  //  loggedErrors.length = 0;
678+  const  expectedDigest  =  onError ( theError ) ; 
679+  loggedErrors . length  =  0 ; 
680680
681681 await  act ( async  ( )  =>  { 
682682 const  { pipe}  =  ReactDOMFizzServer . renderToPipeableStream ( 
@@ -693,8 +693,8 @@ describe('ReactDOMFizzServer', () => {
693693 const  errors  =  [ ] ; 
694694 // Attempt to hydrate the content. 
695695 ReactDOMClient . hydrateRoot ( container ,  < App  isClient = { true }  /> ,  { 
696-  onRecoverableError ( error )  { 
697-  errors . push ( error ) ; 
696+  onRecoverableError ( error ,   errorInfo )  { 
697+  errors . push ( { error,  errorInfo } ) ; 
698698 } , 
699699 } ) ; 
700700 Scheduler . unstable_flushAll ( ) ; 
@@ -703,9 +703,18 @@ describe('ReactDOMFizzServer', () => {
703703
704704 expectErrors ( 
705705 errors , 
706-  [ theError . message ] , 
707706 [ 
708-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
707+  [ 
708+  theError . message , 
709+  expectedDigest , 
710+  componentStack ( [ 'Erroring' ,  'Suspense' ,  'div' ,  'App' ] ) , 
711+  ] , 
712+  ] , 
713+  [ 
714+  [ 
715+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
716+  expectedDigest , 
717+  ] , 
709718 ] , 
710719 ) ; 
711720 } ) ; 
@@ -735,8 +744,8 @@ describe('ReactDOMFizzServer', () => {
735744 loggedErrors . push ( x ) ; 
736745 return  'hash('  +  x . message  +  ')' ; 
737746 } 
738-  //  const expectedHash  = onError(theError);
739-  //  loggedErrors.length = 0;
747+  const  expectedDigest  =  onError ( theError ) ; 
748+  loggedErrors . length  =  0 ; 
740749
741750 await  act ( async  ( )  =>  { 
742751 const  { pipe}  =  ReactDOMFizzServer . renderToPipeableStream ( 
@@ -753,8 +762,8 @@ describe('ReactDOMFizzServer', () => {
753762 const  errors  =  [ ] ; 
754763 // Attempt to hydrate the content. 
755764 ReactDOMClient . hydrateRoot ( container ,  < App  isClient = { true }  /> ,  { 
756-  onRecoverableError ( error )  { 
757-  errors . push ( error ) ; 
765+  onRecoverableError ( error ,   errorInfo )  { 
766+  errors . push ( { error,  errorInfo } ) ; 
758767 } , 
759768 } ) ; 
760769 Scheduler . unstable_flushAll ( ) ; 
@@ -773,9 +782,18 @@ describe('ReactDOMFizzServer', () => {
773782
774783 expectErrors ( 
775784 errors , 
776-  [ theError . message ] , 
777785 [ 
778-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
786+  [ 
787+  theError . message , 
788+  expectedDigest , 
789+  componentStack ( [ 'Lazy' ,  'Suspense' ,  'div' ,  'App' ] ) , 
790+  ] , 
791+  ] , 
792+  [ 
793+  [ 
794+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
795+  expectedDigest , 
796+  ] , 
779797 ] , 
780798 ) ; 
781799
@@ -1053,9 +1071,10 @@ describe('ReactDOMFizzServer', () => {
10531071 } 
10541072
10551073 const  loggedErrors  =  [ ] ; 
1074+  const  expectedDigest  =  'Hash for Abort' ; 
10561075 function  onError ( error )  { 
10571076 loggedErrors . push ( error ) ; 
1058-  return  `Hash of ( ${ error . message } )` ; 
1077+  return  expectedDigest ; 
10591078 } 
10601079
10611080 let  controls ; 
@@ -1069,8 +1088,8 @@ describe('ReactDOMFizzServer', () => {
10691088 const  errors  =  [ ] ; 
10701089 // Attempt to hydrate the content. 
10711090 ReactDOMClient . hydrateRoot ( container ,  < App  /> ,  { 
1072-  onRecoverableError ( error )  { 
1073-  errors . push ( error ) ; 
1091+  onRecoverableError ( error ,   errorInfo )  { 
1092+  errors . push ( { error,  errorInfo } ) ; 
10741093 } , 
10751094 } ) ; 
10761095 Scheduler . unstable_flushAll ( ) ; 
@@ -1087,9 +1106,12 @@ describe('ReactDOMFizzServer', () => {
10871106 expect ( Scheduler ) . toFlushAndYield ( [ ] ) ; 
10881107 expectErrors ( 
10891108 errors , 
1090-  [ 'This Suspense boundary was aborted by the server'  ] , 
1109+  [ [ 'This Suspense boundary was aborted by the server.'  ,   expectedDigest ] ] , 
10911110 [ 
1092-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
1111+  [ 
1112+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
1113+  expectedDigest , 
1114+  ] , 
10931115 ] , 
10941116 ) ; 
10951117 expect ( getVisibleChildren ( container ) ) . toEqual ( < div > Loading...</ div > ) ; 
@@ -1755,8 +1777,8 @@ describe('ReactDOMFizzServer', () => {
17551777 loggedErrors . push ( x ) ; 
17561778 return  `hash of (${ x . message }  ; 
17571779 } 
1758-  //  const expectedHash  = onError(theError);
1759-  //  loggedErrors.length = 0;
1780+  const  expectedDigest  =  onError ( theError ) ; 
1781+  loggedErrors . length  =  0 ; 
17601782
17611783 let  controls ; 
17621784 await  act ( async  ( )  =>  { 
@@ -1775,8 +1797,8 @@ describe('ReactDOMFizzServer', () => {
17751797 const  errors  =  [ ] ; 
17761798 // Attempt to hydrate the content. 
17771799 ReactDOMClient . hydrateRoot ( container ,  < App  isClient = { true }  /> ,  { 
1778-  onRecoverableError ( error )  { 
1779-  errors . push ( error ) ; 
1800+  onRecoverableError ( error ,   errorInfo )  { 
1801+  errors . push ( { error,  errorInfo } ) ; 
17801802 } , 
17811803 } ) ; 
17821804 Scheduler . unstable_flushAll ( ) ; 
@@ -1809,9 +1831,25 @@ describe('ReactDOMFizzServer', () => {
18091831 expect ( Scheduler ) . toFlushAndYield ( [ ] ) ; 
18101832 expectErrors ( 
18111833 errors , 
1812-  [ theError . message ] , 
18131834 [ 
1814-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
1835+  [ 
1836+  theError . message , 
1837+  expectedDigest , 
1838+  componentStack ( [ 
1839+  'AsyncText' , 
1840+  'h1' , 
1841+  'Suspense' , 
1842+  'div' , 
1843+  'Suspense' , 
1844+  'App' , 
1845+  ] ) , 
1846+  ] , 
1847+  ] , 
1848+  [ 
1849+  [ 
1850+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
1851+  expectedDigest , 
1852+  ] , 
18151853 ] , 
18161854 ) ; 
18171855
@@ -3142,8 +3180,8 @@ describe('ReactDOMFizzServer', () => {
31423180 loggedErrors . push ( x ) ; 
31433181 return  x . message . replace ( 'bad message' ,  'bad hash' ) ; 
31443182 } 
3145-  //  const expectedHash  = onError(theError);
3146-  //  loggedErrors.length = 0;
3183+  const  expectedDigest  =  onError ( theError ) ; 
3184+  loggedErrors . length  =  0 ; 
31473185
31483186 await  act ( async  ( )  =>  { 
31493187 const  { pipe}  =  ReactDOMFizzServer . renderToPipeableStream ( < App  /> ,  { 
@@ -3156,18 +3194,27 @@ describe('ReactDOMFizzServer', () => {
31563194
31573195 const  errors  =  [ ] ; 
31583196 ReactDOMClient . hydrateRoot ( container ,  < App  isClient = { true }  /> ,  { 
3159-  onRecoverableError ( error )  { 
3160-  errors . push ( error ) ; 
3197+  onRecoverableError ( error ,   errorInfo )  { 
3198+  errors . push ( { error,  errorInfo } ) ; 
31613199 } , 
31623200 } ) ; 
31633201 expect ( Scheduler ) . toFlushAndYield ( [ ] ) ; 
31643202
31653203 // If escaping were not done we would get a message that says "bad hash" 
31663204 expectErrors ( 
31673205 errors , 
3168-  [ theError . message ] , 
31693206 [ 
3170-  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
3207+  [ 
3208+  theError . message , 
3209+  expectedDigest , 
3210+  componentStack ( [ 'Erroring' ,  'Suspense' ,  'div' ,  'App' ] ) , 
3211+  ] , 
3212+  ] , 
3213+  [ 
3214+  [ 
3215+  'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.' , 
3216+  expectedDigest , 
3217+  ] , 
31713218 ] , 
31723219 ) ; 
31733220 } ) ; 
0 commit comments