@@ -529,4 +529,74 @@ describe('hydrate()', () => {
529529 rerender ( ) ;
530530 expect ( scratch . innerHTML ) . to . equal ( '<div>Error!</div>' ) ;
531531 } ) ;
532+
533+ it ( 'should not crash when hydrating a suspending component without excess DOM children' , ( ) => {
534+ const promise = Promise . resolve ( ) ;
535+ let caught ;
536+
537+ class Boundary extends Component {
538+ componentDidCatch ( error ) {
539+ caught = error ;
540+ this . setState ( { error } ) ;
541+ }
542+
543+ render ( ) {
544+ return this . state && this . state . error ? (
545+ < div > Loading</ div >
546+ ) : (
547+ < textarea defaultValue = "" >
548+ < Suspender />
549+ </ textarea >
550+ ) ;
551+ }
552+ }
553+
554+ function Suspender ( ) {
555+ throw promise ;
556+ }
557+
558+ scratch . innerHTML = '<textarea></textarea>' ;
559+
560+ expect ( ( ) => {
561+ hydrate ( < Boundary /> , scratch ) ;
562+ } ) . to . not . throw ( ) ;
563+
564+ expect ( caught ) . to . equal ( promise ) ;
565+ } ) ;
566+
567+ it ( 'should pass the original error to boundaries when hydrating without excess DOM children' , ( ) => {
568+ let caught ;
569+ const error = new Error ( 'real error' ) ;
570+
571+ class Boundary extends Component {
572+ componentDidCatch ( error ) {
573+ caught = error ;
574+ this . setState ( { error } ) ;
575+ }
576+
577+ render ( ) {
578+ return this . state && this . state . error ? < div > Error!</ div > : < Wrapper /> ;
579+ }
580+ }
581+
582+ function Wrapper ( ) {
583+ return (
584+ < textarea defaultValue = "" >
585+ < Boom />
586+ </ textarea >
587+ ) ;
588+ }
589+
590+ function Boom ( ) {
591+ throw error ;
592+ }
593+
594+ scratch . innerHTML = '<textarea></textarea>' ;
595+
596+ hydrate ( < Boundary /> , scratch ) ;
597+ rerender ( ) ;
598+
599+ expect ( caught ) . to . equal ( error ) ;
600+ expect ( caught . message ) . to . equal ( 'real error' ) ;
601+ } ) ;
532602} ) ;
0 commit comments