Favor fallthrough switch instead of case statements for work tags (#17648)
* Favor fallthrough switch instead of case statements for work tags Currently we're inconsistently handling tags that are only relevant for certain flags. We should throw if the tag is not part of the built feature flags. This should also mean that the case statements can be eliminated. We can achieve this effect by putting the invariant outside of the switch and always early return in the switch. We already do this in beginWork. This PR makes this consistent in other places. * Fail if fundamental/scope tags are discovered without the flag on
Sebastian Markbåge committed
Dec 18, 2019 at 15:53 UTC
4c270375e931b133261495e3aa3f34407c5f79d8
3 files changed
+76
-93
packages/react-reconciler/src/ReactFiberBeginWork.js
+23
-26
@@ -1075,7 +1075,7 @@ function mountLazyComponent(
1075
resolvedProps,
1076
renderExpirationTime,
1077
);
1078
- break;
1078
+ return child;
1079
}
1080
case ClassComponent: {
1081
if (__DEV__) {
@@ -1090,7 +1090,7 @@ function mountLazyComponent(
1090
resolvedProps,
1091
renderExpirationTime,
1092
);
1093
- break;
1093
+ return child;
1094
}
1095
case ForwardRef: {
1096
if (__DEV__) {
@@ -1105,7 +1105,7 @@ function mountLazyComponent(
1105
resolvedProps,
1106
renderExpirationTime,
1107
);
1108
- break;
1108
+ return child;
1109
}
1110
case MemoComponent: {
1111
if (__DEV__) {
@@ -1130,32 +1130,29 @@ function mountLazyComponent(
1130
updateExpirationTime,
1131
renderExpirationTime,
1132
);
1133
- break;
1133
+ return child;
1134
}
1135
- default: {
1136
- let hint = '';
1137
- if (__DEV__) {
1138
- if (
1139
- Component !== null &&
1140
- typeof Component === 'object' &&
1141
- Component.$$typeof === REACT_LAZY_TYPE
1142
- ) {
1143
- hint = ' Did you wrap a component in React.lazy() more than once?';
1144
- }
1145
- }
1146
- // This message intentionally doesn't mention ForwardRef or MemoComponent
1147
- // because the fact that it's a separate type of work is an
1148
- // implementation detail.
1149
- invariant(
1150
- false,
1151
- 'Element type is invalid. Received a promise that resolves to: %s. ' +
1152
- 'Lazy element type must resolve to a class or function.%s',
1153
- Component,
1154
- hint,
1155
- );
1135
+ }
1136
+ let hint = '';
1137
+ if (__DEV__) {
1138
+ if (
1139
+ Component !== null &&
1140
+ typeof Component === 'object' &&
1141
+ Component.$$typeof === REACT_LAZY_TYPE
1142
+ ) {
1143
+ hint = ' Did you wrap a component in React.lazy() more than once?';
1144
}
1145
}
1158
- return child;
1146
+ // This message intentionally doesn't mention ForwardRef or MemoComponent
1147
+ // because the fact that it's a separate type of work is an
1148
+ // implementation detail.
1149
+ invariant(
1150
+ false,
1151
+ 'Element type is invalid. Received a promise that resolves to: %s. ' +
1152
+ 'Lazy element type must resolve to a class or function.%s',
1153
+ Component,
1154
+ hint,
1155
+ );
1156
}
1157
1158
function mountIncompleteClassComponent(
packages/react-reconciler/src/ReactFiberCommitWork.js
+27
-32
@@ -320,14 +320,12 @@ function commitBeforeMutationLifeCycles(
320
case IncompleteClassComponent:
321
// Nothing to do for these component types
322
return;
323
- default: {
324
- invariant(
325
- false,
326
- 'This unit of work tag should not have side-effects. This error is ' +
327
- 'likely caused by a bug in React. Please file an issue.',
328
- );
329
- }
323
}
324
+ invariant(
325
+ false,
326
+ 'This unit of work tag should not have side-effects. This error is ' +
327
+ 'likely caused by a bug in React. Please file an issue.',
328
+ );
329
}
330
331
function commitHookEffectList(
@@ -420,7 +418,7 @@ function commitLifeCycles(
418
case ForwardRef:
419
case SimpleMemoComponent: {
420
commitHookEffectList(UnmountLayout, MountLayout, finishedWork);
423
- break;
421
+ return;
422
}
423
case ClassComponent: {
424
const instance = finishedWork.stateNode;
@@ -629,14 +627,12 @@ function commitLifeCycles(
627
case FundamentalComponent:
628
case ScopeComponent:
629
return;
632
- default: {
633
- invariant(
634
- false,
635
- 'This unit of work tag should not have side-effects. This error is ' +
636
- 'likely caused by a bug in React. Please file an issue.',
637
- );
638
- }
630
}
631
+ invariant(
632
+ false,
633
+ 'This unit of work tag should not have side-effects. This error is ' +
634
+ 'likely caused by a bug in React. Please file an issue.',
635
+ );
636
}
637
638
function hideOrUnhideAllChildren(finishedWork, isHidden) {
@@ -785,7 +781,7 @@ function commitUnmount(
781
});
782
}
783
}
788
- break;
784
+ return;
785
}
786
case ClassComponent: {
787
safelyDetachRef(current);
@@ -843,6 +839,7 @@ function commitUnmount(
839
if (enableScopeAPI) {
840
safelyDetachRef(current);
841
}
842
+ return;
843
}
844
}
845
}
@@ -943,14 +940,12 @@ function commitContainer(finishedWork: Fiber) {
940
replaceContainerChildren(containerInfo, pendingChildren);
941
return;
942
}
946
- default: {
947
- invariant(
948
- false,
949
- 'This unit of work tag should not have side-effects. This error is ' +
950
- 'likely caused by a bug in React. Please file an issue.',
951
- );
952
- }
943
}
944
+ invariant(
945
+ false,
946
+ 'This unit of work tag should not have side-effects. This error is ' +
947
+ 'likely caused by a bug in React. Please file an issue.',
948
+ );
949
}
950
951
function getHostParentFiber(fiber: Fiber): Fiber {
@@ -1408,8 +1403,9 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1403
if (enableFundamentalAPI) {
1404
const fundamentalInstance = finishedWork.stateNode;
1405
updateFundamentalComponent(fundamentalInstance);
1406
+ return;
1407
}
1412
- return;
1408
+ break;
1409
}
1410
case ScopeComponent: {
1411
if (enableScopeAPI) {
@@ -1424,17 +1420,16 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1420
updateDeprecatedEventListeners(nextListeners, finishedWork, null);
1421
}
1422
}
1423
+ return;
1424
}
1428
- return;
1429
- }
1430
- default: {
1431
- invariant(
1432
- false,
1433
- 'This unit of work tag should not have side-effects. This error is ' +
1434
- 'likely caused by a bug in React. Please file an issue.',
1435
- );
1425
+ break;
1426
}
1427
}
1428
+ invariant(
1429
+ false,
1430
+ 'This unit of work tag should not have side-effects. This error is ' +
1431
+ 'likely caused by a bug in React. Please file an issue.',
1432
+ );
1433
}
1434
1435
function commitSuspenseComponent(finishedWork: Fiber) {
packages/react-reconciler/src/ReactFiberCompleteWork.js
+26
-35
@@ -638,18 +638,22 @@ function completeWork(
638
639
switch (workInProgress.tag) {
640
case IndeterminateComponent:
641
- break;
641
case LazyComponent:
643
- break;
642
case SimpleMemoComponent:
643
case FunctionComponent:
646
- break;
644
+ case ForwardRef:
645
+ case Fragment:
646
+ case Mode:
647
+ case Profiler:
648
+ case ContextConsumer:
649
+ case MemoComponent:
650
+ return null;
651
case ClassComponent: {
652
const Component = workInProgress.type;
653
if (isLegacyContextProvider(Component)) {
654
popLegacyContext(workInProgress);
655
}
652
- break;
656
+ return null;
657
}
658
case HostRoot: {
659
popHostContainer(workInProgress);
@@ -670,7 +674,7 @@ function completeWork(
674
}
675
}
676
updateHostContainer(workInProgress);
673
- break;
677
+ return null;
678
}
679
case HostComponent: {
680
popHostContext(workInProgress);
@@ -704,7 +708,7 @@ function completeWork(
708
'caused by a bug in React. Please file an issue.',
709
);
710
// This can happen when we abort work.
707
- break;
711
+ return null;
712
}
713
714
const currentHostContext = getHostContext();
@@ -783,7 +787,7 @@ function completeWork(
787
markRef(workInProgress);
788
}
789
}
786
- break;
790
+ return null;
791
}
792
case HostText: {
793
let newText = newProps;
@@ -817,10 +821,8 @@ function completeWork(
821
);
822
}
823
}
820
- break;
824
+ return null;
825
}
822
- case ForwardRef:
823
- break;
826
case SuspenseComponent: {
827
popSuspenseContext(workInProgress);
828
const nextState: null | SuspenseState = workInProgress.memoizedState;
@@ -961,26 +963,16 @@ function completeWork(
963
// Always notify the callback
964
workInProgress.effectTag |= Update;
965
}
964
- break;
966
+ return null;
967
}
966
- case Fragment:
967
- break;
968
- case Mode:
969
- break;
970
- case Profiler:
971
- break;
968
case HostPortal:
969
popHostContainer(workInProgress);
970
updateHostContainer(workInProgress);
975
- break;
971
+ return null;
972
case ContextProvider:
973
// Pop provider fiber
974
popProvider(workInProgress);
979
- break;
980
- case ContextConsumer:
981
- break;
982
- case MemoComponent:
983
- break;
975
+ return null;
976
case IncompleteClassComponent: {
977
// Same as class component case. I put it down here so that the tags are
978
// sequential to ensure this switch is compiled to a jump table.
@@ -988,7 +980,7 @@ function completeWork(
980
if (isLegacyContextProvider(Component)) {
981
popLegacyContext(workInProgress);
982
}
991
- break;
983
+ return null;
984
}
985
case SuspenseListComponent: {
986
popSuspenseContext(workInProgress);
@@ -999,7 +991,7 @@ function completeWork(
991
if (renderState === null) {
992
// We're running in the default, "independent" mode. We don't do anything
993
// in this mode.
1002
- break;
994
+ return null;
995
}
996
997
let didSuspendAlready =
@@ -1198,7 +1190,7 @@ function completeWork(
1190
// Do a pass over the next row.
1191
return next;
1192
}
1201
- break;
1193
+ return null;
1194
}
1195
case FundamentalComponent: {
1196
if (enableFundamentalAPI) {
@@ -1248,6 +1240,7 @@ function completeWork(
1240
markUpdate(workInProgress);
1241
}
1242
}
1243
+ return null;
1244
}
1245
break;
1246
}
@@ -1296,19 +1289,17 @@ function completeWork(
1289
markRef(workInProgress);
1290
}
1291
}
1292
+ return null;
1293
}
1294
break;
1295
}
1302
- default:
1303
- invariant(
1304
- false,
1305
- 'Unknown unit of work tag (%s). This error is likely caused by a bug in ' +
1306
- 'React. Please file an issue.',
1307
- workInProgress.tag,
1308
- );
1296
}
1310
-
1311
- return null;
1297
+ invariant(
1298
+ false,
1299
+ 'Unknown unit of work tag (%s). This error is likely caused by a bug in ' +
1300
+ 'React. Please file an issue.',
1301
+ workInProgress.tag,
1302
+ );
1303
}
1304
1305
export {completeWork};