71
return Component;
72
}
73
74
- function patch(version) {
74
+ async function patch(version) {
75
+ const Component = version();
76
+ await act(() => {
77
+ ReactFreshRuntime.performReactRefresh();
78
+ });
79
+ return Component;
80
+ }
81
+
82
+ function patchSync(version) {
83
const Component = version();
84
ReactFreshRuntime.performReactRefresh();
85
return Component;
132
expect(el.textContent).toBe('1');
133
134
// Perform a hot update.
127
- const HelloV2 = patch(() => {
135
+ const HelloV2 = await patch(() => {
136
function Hello() {
137
const [val, setVal] = React.useState(0);
138
return (
225
expect(el.textContent).toBe('1');
226
227
// Perform a hot update.
220
- const OuterV2 = patch(() => {
228
+ const OuterV2 = await patch(() => {
229
function Hello() {
230
const [val, setVal] = React.useState(0);
231
return (
356
expect(el.textContent).toBe('1');
357
358
// Patch to change the color.
351
- const ParentV2 = patch(() => {
359
+ const ParentV2 = await patch(() => {
360
function Hello() {
361
const [val, setVal] = React.useState(0);
362
return (
443
expect(el.textContent).toBe('1');
444
445
// Perform a hot update.
438
- patch(() => {
446
+ await patch(() => {
447
function Hello({color}) {
448
const [val, setVal] = React.useState(0);
449
return (
497
expect(el.textContent).toBe('1');
498
499
// Perform a hot update of just the rendering function.
492
- patch(() => {
500
+ await patch(() => {
501
function Hello({color}) {
502
const [val, setVal] = React.useState(0);
503
return (
551
expect(el.textContent).toBe('1');
552
553
// Perform a hot update.
546
- const OuterV2 = patch(() => {
554
+ const OuterV2 = await patch(() => {
555
function Hello() {
556
const [val, setVal] = React.useState(0);
557
return (
640
expect(el.textContent).toBe('1');
641
642
// Perform a hot update.
635
- const OuterV2 = patch(() => {
643
+ const OuterV2 = await patch(() => {
644
function Hello() {
645
const [val, setVal] = React.useState(0);
646
return (
727
expect(el.textContent).toBe('1');
728
729
// Perform a hot update of just the rendering function.
722
- patch(() => {
730
+ await patch(() => {
731
function Hello() {
732
const [val, setVal] = React.useState(0);
733
return (
776
expect(el.textContent).toBe('1');
777
778
// Perform a hot update.
771
- const OuterV2 = patch(() => {
779
+ const OuterV2 = await patch(() => {
780
function Hello() {
781
const [val, setVal] = React.useState(0);
782
return (
888
expect(el.textContent).toBe('1');
889
890
// Perform a hot update.
883
- const AppV2 = patch(() => {
891
+ const AppV2 = await patch(() => {
892
function Hello() {
893
const [val, setVal] = React.useState(0);
894
return (
1011
expect(container.textContent).toBe('Loading');
1012
1013
// Perform a hot update.
1006
- patch(() => {
1014
+ await patch(() => {
1015
function Hello() {
1016
const [val, setVal] = React.useState(0);
1017
return (
1041
expect(el.style.color).toBe('red');
1042
1043
// Test another reload.
1036
- patch(() => {
1044
+ await patch(() => {
1045
function Hello() {
1046
const [val, setVal] = React.useState(0);
1047
return (
1095
expect(container.textContent).toBe('Loading');
1096
1097
// Perform a hot update.
1090
- patch(() => {
1098
+ await patch(() => {
1099
function renderHello() {
1100
const [val, setVal] = React.useState(0);
1101
return (
1126
expect(el.style.color).toBe('red');
1127
1128
// Test another reload.
1121
- patch(() => {
1129
+ await patch(() => {
1130
function renderHello() {
1131
const [val, setVal] = React.useState(0);
1132
return (
1181
expect(container.textContent).toBe('Loading');
1182
1183
// Perform a hot update.
1176
- patch(() => {
1184
+ await patch(() => {
1185
function renderHello() {
1186
const [val, setVal] = React.useState(0);
1187
return (
1212
expect(el.style.color).toBe('red');
1213
1214
// Test another reload.
1207
- patch(() => {
1215
+ await patch(() => {
1216
function renderHello() {
1217
const [val, setVal] = React.useState(0);
1218
return (
1267
expect(container.textContent).toBe('Loading');
1268
1269
// Perform a hot update.
1262
- patch(() => {
1270
+ await patch(() => {
1271
function renderHello() {
1272
const [val, setVal] = React.useState(0);
1273
return (
1298
expect(el.style.color).toBe('red');
1299
1300
// Test another reload.
1293
- patch(() => {
1301
+ await patch(() => {
1302
function renderHello() {
1303
const [val, setVal] = React.useState(0);
1304
return (
1366
expect(primaryChild.style.display).toBe('');
1367
1368
// Perform a hot update.
1361
- patch(() => {
1369
+ await patch(() => {
1370
function Hello({children}) {
1371
const [val, setVal] = React.useState(0);
1372
return (
1412
expect(fallbackChild.style.display).toBe('');
1413
1414
// Perform a hot update.
1407
- patch(() => {
1415
+ await patch(() => {
1416
function Hello({children}) {
1417
const [val, setVal] = React.useState(0);
1418
return (
1444
expect(primaryChild.style.display).toBe('');
1445
1446
// Perform a hot update.
1439
- patch(() => {
1447
+ await patch(() => {
1448
function Hello({children}) {
1449
const [val, setVal] = React.useState(0);
1450
return (
1500
expect(appRenders).toBe(1);
1501
1502
// Perform a hot update for Hello only.
1495
- patch(() => {
1503
+ await patch(() => {
1504
function Hello() {
1505
const [val, setVal] = React.useState(0);
1506
return (
1560
expect(container.textContent).toBe('XXXXXXXXXX');
1561
helloRenders = 0;
1562
1555
- patch(() => {
1563
+ await patch(() => {
1564
function Hello({children}) {
1565
helloRenders++;
1566
return <div>O{children}O</div>;
1627
expect(el2.textContent).toBe('1');
1628
1629
// Perform a hot update for both inner components.
1622
- patch(() => {
1630
+ await patch(() => {
1631
function Hello1() {
1632
const [val, setVal] = React.useState(0);
1633
return (
1689
expect(el.textContent).toBe('1');
1690
1691
// Perform a hot update.
1684
- const HelloV2 = patch(() => {
1692
+ const HelloV2 = await patch(() => {
1693
function Hello() {
1694
const [val, setVal] = React.useState(0);
1695
return (
1710
expect(el.style.color).toBe('red');
1711
1712
// Perform a hot update.
1705
- const HelloV3 = patch(() => {
1713
+ const HelloV3 = await patch(() => {
1714
function Hello() {
1715
const [val, setVal] = React.useState(0);
1716
return (
1751
expect(newEl.style.color).toBe('yellow');
1752
1753
// Verify we can patch again while preserving the signature.
1746
- patch(() => {
1754
+ await patch(() => {
1755
function Hello() {
1756
const [val, setVal] = React.useState(0);
1757
return (
1771
expect(newEl.style.color).toBe('purple');
1772
1773
// Check removing the signature also causes a remount.
1766
- patch(() => {
1774
+ await patch(() => {
1775
function Hello() {
1776
const [val, setVal] = React.useState(0);
1777
return (
1948
}, 10000);
1949
1950
async function runRemountingStressTest(tree) {
1943
- patch(() => {
1951
+ await patch(() => {
1952
function Hello({children}) {
1953
return <section data-color="blue">{children}</section>;
1954
}
1969
});
1970
1971
// Patch color without changing the signature.
1964
- patch(() => {
1972
+ await patch(() => {
1973
function Hello({children}) {
1974
return <section data-color="red">{children}</section>;
1975
}
1988
});
1989
1990
// Patch color *and* change the signature.
1983
- patch(() => {
1991
+ await patch(() => {
1992
function Hello({children}) {
1993
return <section data-color="orange">{children}</section>;
1994
}
2007
});
2008
2009
// Now patch color but *don't* change the signature.
2002
- patch(() => {
2010
+ await patch(() => {
2011
function Hello({children}) {
2012
return <section data-color="black">{children}</section>;
2013
}
2237
expect(el.textContent).toBe('1');
2238
2239
// Perform a hot update that doesn't remount.
2232
- patch(() => {
2240
+ await patch(() => {
2241
function Hello() {
2242
const [val, setVal] = React.useState(0);
2243
return (
2258
expect(el.style.color).toBe('red');
2259
2260
// Perform a hot update that remounts.
2253
- patch(() => {
2261
+ await patch(() => {
2262
function Hello() {
2263
const [val, setVal] = React.useState(0);
2264
return (
2287
expect(newEl.style.color).toBe('yellow');
2288
2289
// Verify we can patch again while preserving the signature.
2282
- patch(() => {
2290
+ await patch(() => {
2291
function Hello() {
2292
const [val, setVal] = React.useState(0);
2293
return (
2307
expect(newEl.style.color).toBe('purple');
2308
2309
// Check removing the signature also causes a remount.
2302
- patch(() => {
2310
+ await patch(() => {
2311
function Hello() {
2312
const [val, setVal] = React.useState(0);
2313
return (
2364
expect(useEffectWithEmptyArrayCalls).toBe(1); // useEffect didn't re-run
2365
2366
// Perform a hot update.
2359
- patch(() => {
2367
+ await patch(() => {
2368
function Hello() {
2369
const [val, setVal] = React.useState(0);
2370
const tranformed = React.useMemo(() => val * 10, [val]);
2421
expect(el.style.color).toBe('blue');
2422
2423
// Perform a hot update.
2416
- patch(() => {
2424
+ await patch(() => {
2425
function Hello() {
2426
const source = React.useMemo(() => ({value: 20}), []);
2427
const [state, setState] = React.useState({value: null});
2476
expect(el.firstChild).toBe(null); // Offscreen content not flushed yet.
2477
2478
// Perform a hot update.
2471
- patch(() => {
2479
+ patchSync(() => {
2480
function Hello() {
2481
React.useLayoutEffect(() => {
2482
Scheduler.log('Hello#layout');
2515
expect(el.firstChild.style.color).toBe('red');
2516
2517
// Hot reload while we're offscreen.
2510
- patch(() => {
2518
+ patchSync(() => {
2519
function Hello() {
2520
React.useLayoutEffect(() => {
2521
Scheduler.log('Hello#layout');
2583
const secondP = firstP.nextSibling.nextSibling;
2584
2585
// Perform a hot update that fails.
2578
- patch(() => {
2586
+ await patch(() => {
2587
function Hello() {
2588
throw new Error('No');
2589
}
2595
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
2596
2597
// Perform a hot update that fixes the error.
2590
- patch(() => {
2598
+ await patch(() => {
2599
function Hello() {
2600
return <h1>Fixed!</h1>;
2601
}
2609
2610
// Verify next hot reload doesn't remount anything.
2611
const helloNode = container.firstChild.nextSibling;
2604
- patch(() => {
2612
+ await patch(() => {
2613
function Hello() {
2614
return <h1>Nice.</h1>;
2615
}
2661
const secondP = firstP.nextSibling.nextSibling;
2662
2663
// Perform a hot update that fails.
2656
- patch(() => {
2664
+ await patch(() => {
2665
function Hello() {
2666
throw new Error('No');
2667
}
2673
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
2674
2675
// Perform a hot update that fixes the error.
2668
- patch(() => {
2676
+ await patch(() => {
2677
function Hello() {
2678
return <h1>Fixed!</h1>;
2679
}
2687
2688
// Verify next hot reload doesn't remount anything.
2689
const helloNode = container.firstChild.nextSibling;
2682
- patch(() => {
2690
+ await patch(() => {
2691
function Hello() {
2692
return <h1>Nice.</h1>;
2693
}
2743
2744
// Perform a hot update that fails.
2745
let crash;
2738
- patch(() => {
2746
+ await patch(() => {
2747
function Hello() {
2748
const [x, setX] = React.useState('');
2749
React.useEffect(() => {
2769
expect(container.firstChild.nextSibling.nextSibling).toBe(secondP);
2770
2771
// Perform a hot update that fixes the error.
2764
- patch(() => {
2772
+ await patch(() => {
2773
function Hello() {
2774
const [x] = React.useState('');
2775
React.useEffect(() => {}, []); // Removes the bad effect code.
2786
2787
// Verify next hot reload doesn't remount anything.
2788
const helloNode = container.firstChild.nextSibling;
2781
- patch(() => {
2789
+ await patch(() => {
2790
function Hello() {
2791
const [x] = React.useState('');
2792
React.useEffect(() => {}, []);
2816
expect(container.innerHTML).toBe('');
2817
2818
// A bad retry
2811
- expect(() => {
2812
- patch(() => {
2819
+ await expect(async () => {
2820
+ await patch(() => {
2821
function Hello() {
2822
throw new Error('Not yet');
2823
}
2824
$RefreshReg$(Hello, 'Hello');
2825
});
2818
- }).toThrow('Not yet');
2826
+ }).rejects.toThrow('Not yet');
2827
expect(container.innerHTML).toBe('');
2828
2829
// Perform a hot update that fixes the error.
2822
- patch(() => {
2830
+ await patch(() => {
2831
function Hello() {
2832
return <h1>Fixed!</h1>;
2833
}
2837
expect(container.innerHTML).toBe('<h1>Fixed!</h1>');
2838
2839
// Ensure we can keep failing and recovering later.
2832
- expect(() => {
2833
- patch(() => {
2840
+ await expect(async () => {
2841
+ await patch(() => {
2842
function Hello() {
2843
throw new Error('No 2');
2844
}
2845
$RefreshReg$(Hello, 'Hello');
2846
});
2839
- }).toThrow('No 2');
2847
+ }).rejects.toThrow('No 2');
2848
expect(container.innerHTML).toBe('');
2841
- expect(() => {
2842
- patch(() => {
2849
+ await expect(async () => {
2850
+ await patch(() => {
2851
function Hello() {
2852
throw new Error('Not yet 2');
2853
}
2854
$RefreshReg$(Hello, 'Hello');
2855
});
2848
- }).toThrow('Not yet 2');
2856
+ }).rejects.toThrow('Not yet 2');
2857
expect(container.innerHTML).toBe('');
2850
- patch(() => {
2858
+ await patch(() => {
2859
function Hello() {
2860
return <h1>Fixed 2!</h1>;
2861
}
2867
await act(() => {
2868
root.unmount();
2869
});
2862
- patch(() => {
2870
+ await patch(() => {
2871
function Hello() {
2872
throw new Error('Ignored');
2873
}
2874
$RefreshReg$(Hello, 'Hello');
2875
});
2876
expect(container.innerHTML).toBe('');
2869
- patch(() => {
2877
+ await patch(() => {
2878
function Hello() {
2879
return <h1>Ignored</h1>;
2880
}
2904
});
2905
2906
// Perform a hot update that fixes the error.
2899
- patch(() => {
2907
+ await patch(() => {
2908
function Hello() {
2909
return <h1>Fixed!</h1>;
2910
}
2929
2930
// Perform a hot update that fails.
2931
// This removes the root.
2924
- expect(() => {
2925
- patch(() => {
2932
+ await expect(async () => {
2933
+ await patch(() => {
2934
function Hello() {
2935
throw new Error('No');
2936
}
2937
$RefreshReg$(Hello, 'Hello');
2938
});
2931
- }).toThrow('No');
2939
+ }).rejects.toThrow('No');
2940
expect(container.innerHTML).toBe('');
2941
2942
// A bad retry
2935
- expect(() => {
2936
- patch(() => {
2943
+ await expect(async () => {
2944
+ await patch(() => {
2945
function Hello() {
2946
throw new Error('Not yet');
2947
}
2948
$RefreshReg$(Hello, 'Hello');
2949
});
2942
- }).toThrow('Not yet');
2950
+ }).rejects.toThrow('Not yet');
2951
expect(container.innerHTML).toBe('');
2952
2953
// Perform a hot update that fixes the error.
2946
- patch(() => {
2954
+ await patch(() => {
2955
function Hello() {
2956
return <h1>Fixed!</h1>;
2957
}
2962
2963
// Verify next hot reload doesn't remount anything.
2964
const helloNode = container.firstChild;
2957
- patch(() => {
2965
+ await patch(() => {
2966
function Hello() {
2967
return <h1>Nice.</h1>;
2968
}
2972
expect(helloNode.textContent).toBe('Nice.');
2973
2974
// Break again.
2967
- expect(() => {
2968
- patch(() => {
2975
+ await expect(async () => {
2976
+ await patch(() => {
2977
function Hello() {
2978
throw new Error('Oops');
2979
}
2980
$RefreshReg$(Hello, 'Hello');
2981
});
2974
- }).toThrow('Oops');
2982
+ }).rejects.toThrow('Oops');
2983
expect(container.innerHTML).toBe('');
2984
2985
// Perform a hot update that fixes the error.
2978
- patch(() => {
2986
+ await patch(() => {
2987
function Hello() {
2988
return <h1>At last.</h1>;
2989
}
2997
root.unmount();
2998
});
2999
expect(container.innerHTML).toBe('');
2992
- patch(() => {
3000
+ await patch(() => {
3001
function Hello() {
3002
return <h1>Never mind me!</h1>;
3003
}
3018
expect(container.innerHTML).toBe('<h1>Hi</h1>');
3019
3020
// Break again.
3013
- expect(() => {
3014
- patch(() => {
3021
+ await expect(async () => {
3022
+ await patch(() => {
3023
function Hello() {
3024
throw new Error('Oops');
3025
}
3026
$RefreshReg$(Hello, 'Hello');
3027
});
3020
- }).toThrow('Oops');
3028
+ }).rejects.toThrow('Oops');
3029
expect(container.innerHTML).toBe('');
3030
3031
// Check we don't attempt to reverse an intentional unmount, even after an error.
3033
root.unmount();
3034
});
3035
expect(container.innerHTML).toBe('');
3028
- patch(() => {
3036
+ await patch(() => {
3037
function Hello() {
3038
return <h1>Never mind me!</h1>;
3039
}
3147
expect(el.textContent).toBe('1');
3148
3149
// Perform a hot update.
3142
- const HelloV2 = patch(() => {
3150
+ const HelloV2 = await patch(() => {
3151
class Hello extends React.Component {
3152
state = {count: 0};
3153
handleClick = () => {
3184
expect(newEl.style.color).toBe('red');
3185
expect(newEl.textContent).toBe('1');
3186
3179
- const HelloV3 = patch(() => {
3187
+ const HelloV3 = await patch(() => {
3188
class Hello extends React.Component {
3189
state = {count: 0};
3190
handleClick = () => {
3243
);
3244
expect(testRef.current.getColor()).toBe('green');
3245
3238
- patch(() => {
3246
+ await patch(() => {
3247
class Hello extends React.Component {
3248
getColor() {
3249
return 'orange';
3256
});
3257
expect(testRef.current.getColor()).toBe('orange');
3258
3251
- patch(() => {
3259
+ await patch(() => {
3260
const Hello = React.forwardRef((props, ref) => {
3261
React.useImperativeHandle(ref, () => ({
3262
getColor() {
3269
});
3270
expect(testRef.current.getColor()).toBe('pink');
3271
3264
- patch(() => {
3272
+ await patch(() => {
3273
const Hello = React.forwardRef((props, ref) => {
3274
React.useImperativeHandle(ref, () => ({
3275
getColor() {
3282
});
3283
expect(testRef.current.getColor()).toBe('yellow');
3284
3277
- patch(() => {
3285
+ await patch(() => {
3286
const Hello = React.forwardRef((props, ref) => {
3287
React.useImperativeHandle(ref, () => ({
3288
getColor() {
3322
expect(el.textContent).toBe('1');
3323
3324
// Perform a hot update that turns it into a class.
3317
- const HelloV2 = patch(() => {
3325
+ const HelloV2 = await patch(() => {
3326
class Hello extends React.Component {
3327
state = {count: 0};
3328
handleClick = () => {
3360
expect(newEl.textContent).toBe('1');
3361
3362
// Now convert it back to a function.
3355
- const HelloV3 = patch(() => {
3363
+ const HelloV3 = await patch(() => {
3364
function Hello() {
3365
const [val, setVal] = React.useState(0);
3366
return (
3391
expect(finalEl.textContent).toBe('1');
3392
3393
// Now that it's a function, verify edits keep state.
3386
- patch(() => {
3394
+ await patch(() => {
3395
function Hello() {
3396
const [val, setVal] = React.useState(0);
3397
return (
3880
expect(el.textContent).toBe('1');
3881
3882
// Perform a hot update.
3875
- patch(() => {
3883
+ await patch(() => {
3884
function Hello() {
3885
const [val, setVal] = React.useState(0);
3886
return (