@@ -2188,6 +2188,129 @@ describe('suspense', () => {
21882188 } ) ;
21892189 } ) ;
21902190
2191+ it ( 'should not crash when suspended child updates after unmount' , ( ) => {
2192+ let childInstance = null ;
2193+ const neverResolvingPromise = new Promise ( ( ) => { } ) ;
2194+
2195+ class ThrowingChild extends Component {
2196+ constructor ( props ) {
2197+ super ( props ) ;
2198+ this . state = { suspend : false , value : 0 } ;
2199+ childInstance = this ;
2200+ }
2201+
2202+ render ( props , state ) {
2203+ if ( state . suspend ) {
2204+ throw neverResolvingPromise ;
2205+ }
2206+ return < div > value:{ state . value } </ div > ;
2207+ }
2208+ }
2209+
2210+ render (
2211+ < Suspense fallback = { < div > Suspended...</ div > } >
2212+ < ThrowingChild />
2213+ </ Suspense > ,
2214+ scratch
2215+ ) ;
2216+
2217+ expect ( scratch . innerHTML ) . to . equal ( '<div>value:0</div>' ) ;
2218+
2219+ childInstance . setState ( { suspend : true } ) ;
2220+ rerender ( ) ;
2221+ expect ( scratch . innerHTML ) . to . equal ( '<div>Suspended...</div>' ) ;
2222+
2223+ render ( null , scratch ) ;
2224+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
2225+
2226+ childInstance . setState ( { value : 1 } ) ;
2227+ rerender ( ) ;
2228+
2229+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
2230+ } ) ;
2231+
2232+ it ( 'should not crash when suspense promise resolves after unmount' , ( ) => {
2233+ let resolve ;
2234+ const promise = new Promise ( r => {
2235+ resolve = r ;
2236+ } ) ;
2237+
2238+ class ThrowingChild extends Component {
2239+ render ( ) {
2240+ throw promise ;
2241+ }
2242+ }
2243+
2244+ render (
2245+ < Suspense fallback = { < div > Suspended...</ div > } >
2246+ < ThrowingChild />
2247+ </ Suspense > ,
2248+ scratch
2249+ ) ;
2250+ rerender ( ) ;
2251+
2252+ expect ( scratch . innerHTML ) . to . equal ( '<div>Suspended...</div>' ) ;
2253+
2254+ render ( null , scratch ) ;
2255+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
2256+
2257+ resolve ( ) ;
2258+
2259+ return promise . then ( ( ) => {
2260+ rerender ( ) ;
2261+ expect ( scratch . innerHTML ) . to . equal ( '' ) ;
2262+ } ) ;
2263+ } ) ;
2264+
2265+ it ( 'should not crash when useContext is used in a suspending component' , ( ) => {
2266+ const TestContext = createContext ( 'default' ) ;
2267+ let resolve ;
2268+ let shouldSuspend = false ;
2269+ const promise = new Promise ( r => {
2270+ resolve = r ;
2271+ } ) ;
2272+
2273+ function ContextUser ( ) {
2274+ const value = React . useContext ( TestContext ) ;
2275+ if ( shouldSuspend ) {
2276+ throw promise ;
2277+ }
2278+ return < div > Context: { value } </ div > ;
2279+ }
2280+
2281+ render (
2282+ < TestContext . Provider value = "test-value" >
2283+ < Suspense fallback = { < div > Suspended...</ div > } >
2284+ < ContextUser />
2285+ </ Suspense >
2286+ </ TestContext . Provider > ,
2287+ scratch
2288+ ) ;
2289+
2290+ expect ( scratch . innerHTML ) . to . equal ( '<div>Context: test-value</div>' ) ;
2291+
2292+ shouldSuspend = true ;
2293+ render (
2294+ < TestContext . Provider value = "test-value" >
2295+ < Suspense fallback = { < div > Suspended...</ div > } >
2296+ < ContextUser />
2297+ </ Suspense >
2298+ </ TestContext . Provider > ,
2299+ scratch
2300+ ) ;
2301+ rerender ( ) ;
2302+
2303+ expect ( scratch . innerHTML ) . to . equal ( '<div>Suspended...</div>' ) ;
2304+
2305+ shouldSuspend = false ;
2306+ resolve ( ) ;
2307+
2308+ return promise . then ( ( ) => {
2309+ rerender ( ) ;
2310+ expect ( scratch . innerHTML ) . to . equal ( '<div>Context: test-value</div>' ) ;
2311+ } ) ;
2312+ } ) ;
2313+
21912314 it ( 'should not crash if fallback has same DOM as suspended nodes' , ( ) => {
21922315 const [ Lazy , resolveLazy ] = createLazy ( ) ;
21932316
0 commit comments