File tree Expand file tree Collapse file tree 2 files changed +65
-0
lines changed
Expand file tree Collapse file tree 2 files changed +65
-0
lines changed Original file line number Diff line number Diff line change @@ -1001,4 +1001,62 @@ describe('suspense hydration', () => {
10011001 } ) ;
10021002 } ) ;
10031003 } ) ;
1004+
1005+ it ( 'Should not crash when oldVNode._children is null during shouldComponentUpdate optimization' , ( ) => {
1006+ const originalHtml = '<div>Hello</div>' ;
1007+ scratch . innerHTML = originalHtml ;
1008+ clearLog ( ) ;
1009+
1010+ class ErrorBoundary extends React . Component {
1011+ constructor ( props ) {
1012+ super ( props ) ;
1013+ this . state = { hasError : false } ;
1014+ }
1015+
1016+ static getDerivedStateFromError ( ) {
1017+ return { hasError : true } ;
1018+ }
1019+
1020+ render ( ) {
1021+ return this . props . children ;
1022+ }
1023+ }
1024+
1025+ const [ Lazy , resolve ] = createLazy ( ) ;
1026+ function App ( ) {
1027+ return (
1028+ < Suspense >
1029+ < ErrorBoundary >
1030+ < Lazy />
1031+ </ ErrorBoundary >
1032+ </ Suspense >
1033+ ) ;
1034+ }
1035+
1036+ hydrate ( < App /> , scratch ) ;
1037+ rerender ( ) ; // Flush rerender queue to mimic what preact will really do
1038+ expect ( scratch . innerHTML ) . to . equal ( originalHtml ) ;
1039+ expect ( getLog ( ) ) . to . deep . equal ( [ ] ) ;
1040+ clearLog ( ) ;
1041+
1042+ let i = 0 ;
1043+ class ThrowOrRender extends React . Component {
1044+ shouldComponentUpdate ( ) {
1045+ return i === 0 ;
1046+ }
1047+ render ( ) {
1048+ if ( i === 0 ) {
1049+ i ++ ;
1050+ throw new Error ( 'Test error' ) ;
1051+ }
1052+ return < div > Hello</ div > ;
1053+ }
1054+ }
1055+
1056+ return resolve ( ThrowOrRender ) . then ( ( ) => {
1057+ rerender ( ) ;
1058+ expect ( scratch . innerHTML ) . to . equal ( originalHtml ) ;
1059+ clearLog ( ) ;
1060+ } ) ;
1061+ } ) ;
10041062} ) ;
Original file line number Diff line number Diff line change @@ -352,10 +352,12 @@ export function diff(
352352 for ( let i = excessDomChildren . length ; i -- ; ) {
353353 removeNode ( excessDomChildren [ i ] ) ;
354354 }
355+ markAsForce ( newVNode ) ;
355356 }
356357 } else {
357358 newVNode . _dom = oldVNode . _dom ;
358359 newVNode . _children = oldVNode . _children ;
360+ if ( e . then ) markAsForce ( newVNode ) ;
359361 }
360362 options . _catchError ( e , newVNode , oldVNode ) ;
361363 }
@@ -379,6 +381,11 @@ export function diff(
379381 return newVNode . _flags & MODE_SUSPENDED ? undefined : oldDom ;
380382}
381383
384+ function markAsForce ( vnode ) {
385+ if ( vnode && vnode . _component ) vnode . _component . _force = true ;
386+ if ( vnode && vnode . _children ) vnode . _children . forEach ( markAsForce ) ;
387+ }
388+
382389/**
383390 * @param {Array<Component> } commitQueue List of components
384391 * which have callbacks to invoke in commitRoot
You can’t perform that action at this time.
0 commit comments