@samitouri / QOS-React / commits / 350d736361

Use `T | null` instead of `?T` types

Flow maybe types accept both null and undefined. When the final parameter of a function accepts a maybe type, passing nothing (undefined) successfully typechecks, which can lead to bugs if the omission is accidental. Being forced to pass null is harder to screw up. Explicit null checks are also faster.

Andrew Clark committed Feb 10, 2017 at 17:30 UTC 350d736361f5a86d94960cfd230ff7f77a21785b
12 files changed +263 -271
src/renderers/shared/fiber/ReactChildFiber.js
+82 -86
@@ -73,9 +73,9 @@ const {
73 Deletion,
74 } = ReactTypeOfSideEffect;
75
76 -function coerceRef(current: ?Fiber, element: ReactElement) {
76 +function coerceRef(current: Fiber | null, element: ReactElement) {
77 let mixedRef = element.ref;
78 - if (mixedRef != null && typeof mixedRef !== 'function') {
78 + if (mixedRef !== null && typeof mixedRef !== 'function') {
79 if (element._owner) {
80 const owner : ?(Fiber | ReactInstance) = (element._owner : any);
81 let inst;
@@ -97,7 +97,7 @@ function coerceRef(current: ?Fiber, element: ReactElement) {
97 );
98 const stringRef = String(mixedRef);
99 // Check if previous string ref matches new string ref
100 - if (current && current.ref && current.ref._stringRef === stringRef) {
100 + if (current !== null && current.ref !== null && current.ref._stringRef === stringRef) {
101 return current.ref;
102 }
103 const ref = function(value) {
@@ -161,14 +161,14 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
161 // When we're reconciling in place we have a work in progress copy. We
162 // actually want the current copy. If there is no current copy, then we
163 // don't need to track deletion side-effects.
164 - if (!childToDelete.alternate) {
164 + if (childToDelete.alternate === null) {
165 return;
166 }
167 childToDelete = childToDelete.alternate;
168 }
169 // Deletions are added in reversed order so we add it to the front.
170 const last = returnFiber.progressedLastDeletion;
171 - if (last) {
171 + if (last !== null) {
172 last.nextEffect = childToDelete;
173 returnFiber.progressedLastDeletion = childToDelete;
174 } else {
@@ -182,7 +182,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
182
183 function deleteRemainingChildren(
184 returnFiber : Fiber,
185 - currentFirstChild : ?Fiber
185 + currentFirstChild : Fiber | null
186 ) : null {
187 if (!shouldTrackSideEffects) {
188 // Noop.
@@ -192,7 +192,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
192 // TODO: For the shouldClone case, this could be micro-optimized a bit by
193 // assuming that after the first child we've already added everything.
194 let childToDelete = currentFirstChild;
195 - while (childToDelete) {
195 + while (childToDelete !== null) {
196 deleteChild(returnFiber, childToDelete);
197 childToDelete = childToDelete.sibling;
198 }
@@ -209,7 +209,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
209 const existingChildren : Map<string | number, Fiber> = new Map();
210
211 let existingChild = currentFirstChild;
212 - while (existingChild) {
212 + while (existingChild !== null) {
213 if (existingChild.key !== null) {
214 existingChildren.set(existingChild.key, existingChild);
215 } else {
@@ -247,7 +247,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
247 return lastPlacedIndex;
248 }
249 const current = newFiber.alternate;
250 - if (current) {
250 + if (current !== null) {
251 const oldIndex = current.index;
252 if (oldIndex < lastPlacedIndex) {
253 // This is a move.
@@ -267,7 +267,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
267 function placeSingleChild(newFiber : Fiber) : Fiber {
268 // This is simpler for the single child case. We only need to do a
269 // placement for inserting new children.
270 - if (shouldTrackSideEffects && !newFiber.alternate) {
270 + if (shouldTrackSideEffects && newFiber.alternate === null) {
271 newFiber.effectTag = Placement;
272 }
273 return newFiber;
@@ -275,11 +275,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
275
276 function updateTextNode(
277 returnFiber : Fiber,
278 - current : ?Fiber,
278 + current : Fiber | null,
279 textContent : string,
280 priority : PriorityLevel
281 ) {
282 - if (current == null || current.tag !== HostText) {
282 + if (current === null || current.tag !== HostText) {
283 // Insert
284 const created = createFiberFromText(textContent, priority);
285 created.return = returnFiber;
@@ -295,11 +295,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
295
296 function updateElement(
297 returnFiber : Fiber,
298 - current : ?Fiber,
298 + current : Fiber | null,
299 element : ReactElement,
300 priority : PriorityLevel
301 ) : Fiber {
302 - if (current == null || current.type !== element.type) {
302 + if (current === null || current.type !== element.type) {
303 // Insert
304 const created = createFiberFromElement(element, priority);
305 created.ref = coerceRef(current, element);
@@ -321,12 +321,12 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
321
322 function updateCoroutine(
323 returnFiber : Fiber,
324 - current : ?Fiber,
324 + current : Fiber | null,
325 coroutine : ReactCoroutine,
326 priority : PriorityLevel
327 ) : Fiber {
328 // TODO: Should this also compare handler to determine whether to reuse?
329 - if (current == null || current.tag !== CoroutineComponent) {
329 + if (current === null || current.tag !== CoroutineComponent) {
330 // Insert
331 const created = createFiberFromCoroutine(coroutine, priority);
332 created.return = returnFiber;
@@ -342,11 +342,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
342
343 function updateYield(
344 returnFiber : Fiber,
345 - current : ?Fiber,
345 + current : Fiber | null,
346 yieldNode : ReactYield,
347 priority : PriorityLevel
348 ) : Fiber {
349 - if (current == null || current.tag !== YieldComponent) {
349 + if (current === null || current.tag !== YieldComponent) {
350 // Insert
351 const created = createFiberFromYield(yieldNode, priority);
352 created.type = yieldNode.value;
@@ -363,12 +363,12 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
363
364 function updatePortal(
365 returnFiber : Fiber,
366 - current : ?Fiber,
366 + current : Fiber | null,
367 portal : ReactPortal,
368 priority : PriorityLevel
369 ) : Fiber {
370 if (
371 - current == null ||
371 + current === null ||
372 current.tag !== HostPortal ||
373 current.stateNode.containerInfo !== portal.containerInfo ||
374 current.stateNode.implementation !== portal.implementation
@@ -388,11 +388,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
388
389 function updateFragment(
390 returnFiber : Fiber,
391 - current : ?Fiber,
391 + current : Fiber | null,
392 fragment : Iterable<*>,
393 priority : PriorityLevel
394 ) : Fiber {
395 - if (current == null || current.tag !== Fragment) {
395 + if (current === null || current.tag !== Fragment) {
396 // Insert
397 const created = createFiberFromFragment(fragment, priority);
398 created.return = returnFiber;
@@ -410,7 +410,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
410 returnFiber : Fiber,
411 newChild : any,
412 priority : PriorityLevel
413 - ) : ?Fiber {
413 + ) : Fiber | null {
414 if (typeof newChild === 'string' || typeof newChild === 'number') {
415 // Text nodes doesn't have keys. If the previous node is implicitly keyed
416 // we can continue to replace it without aborting even if it is not a text
@@ -463,13 +463,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
463
464 function updateSlot(
465 returnFiber : Fiber,
466 - oldFiber : ?Fiber,
466 + oldFiber : Fiber | null,
467 newChild : any,
468 priority : PriorityLevel
469 - ) : ?Fiber {
469 + ) : Fiber | null {
470 // Update the fiber if the keys match, otherwise return null.
471
472 - const key = oldFiber ? oldFiber.key : null;
472 + const key = oldFiber !== null ? oldFiber.key : null;
473
474 if (typeof newChild === 'string' || typeof newChild === 'number') {
475 // Text nodes doesn't have keys. If the previous node is implicitly keyed
@@ -540,7 +540,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
540 newIdx : number,
541 newChild : any,
542 priority : PriorityLevel
543 - ) : ?Fiber {
543 + ) : Fiber | null {
544
545 if (typeof newChild === 'string' || typeof newChild === 'number') {
546 // Text nodes doesn't have keys, so we neither have to check the old nor
@@ -596,7 +596,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
596 knownKeys : Set<string> | null
597 ) : Set<string> | null {
598 if (__DEV__) {
599 - if (typeof child !== 'object' || child == null) {
599 + if (typeof child !== 'object' || child === null) {
600 return knownKeys;
601 }
602 switch (child.$$typeof) {
@@ -607,7 +607,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
607 if (typeof key !== 'string') {
608 break;
609 }
610 - if (knownKeys == null) {
610 + if (knownKeys === null) {
611 knownKeys = new Set();
612 knownKeys.add(key);
613 break;
@@ -634,9 +634,9 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
634
635 function reconcileChildrenArray(
636 returnFiber : Fiber,
637 - currentFirstChild : ?Fiber,
637 + currentFirstChild : Fiber | null,
638 newChildren : Array<*>,
639 - priority : PriorityLevel) : ?Fiber {
639 + priority : PriorityLevel) : Fiber | null {
640
641 // This algorithm can't optimize by searching from boths ends since we
642 // don't have backpointers on fibers. I'm trying to see how far we can get
@@ -666,21 +666,19 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
666 }
667 }
668
669 - let resultingFirstChild : ?Fiber = null;
670 - let previousNewFiber : ?Fiber = null;
669 + let resultingFirstChild : Fiber | null = null;
670 + let previousNewFiber : Fiber | null = null;
671
672 let oldFiber = currentFirstChild;
673 let lastPlacedIndex = 0;
674 let newIdx = 0;
675 let nextOldFiber = null;
676 - for (; oldFiber && newIdx < newChildren.length; newIdx++) {
677 - if (oldFiber) {
678 - if (oldFiber.index > newIdx) {
679 - nextOldFiber = oldFiber;
680 - oldFiber = null;
681 - } else {
682 - nextOldFiber = oldFiber.sibling;
683 - }
676 + for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
677 + if (oldFiber.index > newIdx) {
678 + nextOldFiber = oldFiber;
679 + oldFiber = null;
680 + } else {
681 + nextOldFiber = oldFiber.sibling;
682 }
683 const newFiber = updateSlot(
684 returnFiber,
@@ -688,25 +686,25 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
686 newChildren[newIdx],
687 priority
688 );
691 - if (!newFiber) {
689 + if (newFiber === null) {
690 // TODO: This breaks on empty slots like null children. That's
691 // unfortunate because it triggers the slow path all the time. We need
692 // a better way to communicate whether this was a miss or null,
693 // boolean, undefined, etc.
696 - if (!oldFiber) {
694 + if (oldFiber === null) {
695 oldFiber = nextOldFiber;
696 }
697 break;
698 }
699 if (shouldTrackSideEffects) {
702 - if (oldFiber && !newFiber.alternate) {
700 + if (oldFiber && newFiber.alternate === null) {
701 // We matched the slot, but we didn't reuse the existing fiber, so we
702 // need to delete the existing child.
703 deleteChild(returnFiber, oldFiber);
704 }
705 }
706 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
709 - if (!previousNewFiber) {
707 + if (previousNewFiber === null) {
708 // TODO: Move out of the loop. This only happens for the first run.
709 resultingFirstChild = newFiber;
710 } else {
@@ -726,7 +724,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
724 return resultingFirstChild;
725 }
726
729 - if (!oldFiber) {
727 + if (oldFiber === null) {
728 // If we don't have any more existing children we can choose a fast path
729 // since the rest will all be insertions.
730 for (; newIdx < newChildren.length; newIdx++) {
@@ -739,7 +737,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
737 continue;
738 }
739 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
742 - if (!previousNewFiber) {
740 + if (previousNewFiber === null) {
741 // TODO: Move out of the loop. This only happens for the first run.
742 resultingFirstChild = newFiber;
743 } else {
@@ -764,7 +762,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
762 );
763 if (newFiber) {
764 if (shouldTrackSideEffects) {
767 - if (newFiber.alternate) {
765 + if (newFiber.alternate !== null) {
766 // The new fiber is a work in progress, but if there exists a
767 // current, that means that we reused the fiber. We need to delete
768 // it from the child list so that we don't add it to the deletion
@@ -775,7 +773,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
773 }
774 }
775 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
778 - if (!previousNewFiber) {
776 + if (previousNewFiber === null) {
777 resultingFirstChild = newFiber;
778 } else {
779 previousNewFiber.sibling = newFiber;
@@ -795,9 +793,9 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
793
794 function reconcileChildrenIterator(
795 returnFiber : Fiber,
798 - currentFirstChild : ?Fiber,
796 + currentFirstChild : Fiber | null,
797 newChildrenIterable : Iterable<*>,
800 - priority : PriorityLevel) : ?Fiber {
798 + priority : PriorityLevel) : Fiber | null {
799
800 // This is the same implementation as reconcileChildrenArray(),
801 // but using the iterator instead.
@@ -852,8 +850,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
850 'An iterable object provided no iterator.',
851 );
852
855 - let resultingFirstChild : ?Fiber = null;
856 - let previousNewFiber : ?Fiber = null;
853 + let resultingFirstChild : Fiber | null = null;
854 + let previousNewFiber : Fiber | null = null;
855
856 let oldFiber = currentFirstChild;
857 let lastPlacedIndex = 0;
@@ -861,14 +859,12 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
859 let nextOldFiber = null;
860
861 let step = newChildren.next();
864 - for (; oldFiber && !step.done; newIdx++, step = newChildren.next()) {
865 - if (oldFiber) {
866 - if (oldFiber.index > newIdx) {
867 - nextOldFiber = oldFiber;
868 - oldFiber = null;
869 - } else {
870 - nextOldFiber = oldFiber.sibling;
871 - }
862 + for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) {
863 + if (oldFiber.index > newIdx) {
864 + nextOldFiber = oldFiber;
865 + oldFiber = null;
866 + } else {
867 + nextOldFiber = oldFiber.sibling;
868 }
869 const newFiber = updateSlot(
870 returnFiber,
@@ -876,7 +872,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
872 step.value,
873 priority
874 );
879 - if (!newFiber) {
875 + if (newFiber === null) {
876 // TODO: This breaks on empty slots like null children. That's
877 // unfortunate because it triggers the slow path all the time. We need
878 // a better way to communicate whether this was a miss or null,
@@ -887,14 +883,14 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
883 break;
884 }
885 if (shouldTrackSideEffects) {
890 - if (oldFiber && !newFiber.alternate) {
886 + if (oldFiber && newFiber.alternate === null) {
887 // We matched the slot, but we didn't reuse the existing fiber, so we
888 // need to delete the existing child.
889 deleteChild(returnFiber, oldFiber);
890 }
891 }
892 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
897 - if (!previousNewFiber) {
893 + if (previousNewFiber === null) {
894 // TODO: Move out of the loop. This only happens for the first run.
895 resultingFirstChild = newFiber;
896 } else {
@@ -914,7 +910,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
910 return resultingFirstChild;
911 }
912
917 - if (!oldFiber) {
913 + if (oldFiber === null) {
914 // If we don't have any more existing children we can choose a fast path
915 // since the rest will all be insertions.
916 for (; !step.done; newIdx++, step = newChildren.next()) {
@@ -923,11 +919,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
919 step.value,
920 priority
921 );
926 - if (!newFiber) {
922 + if (newFiber === null) {
923 continue;
924 }
925 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
930 - if (!previousNewFiber) {
926 + if (previousNewFiber === null) {
927 // TODO: Move out of the loop. This only happens for the first run.
928 resultingFirstChild = newFiber;
929 } else {
@@ -950,9 +946,9 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
946 step.value,
947 priority
948 );
953 - if (newFiber) {
949 + if (newFiber !== null) {
950 if (shouldTrackSideEffects) {
955 - if (newFiber.alternate) {
951 + if (newFiber.alternate !== null) {
952 // The new fiber is a work in progress, but if there exists a
953 // current, that means that we reused the fiber. We need to delete
954 // it from the child list so that we don't add it to the deletion
@@ -963,7 +959,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
959 }
960 }
961 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
966 - if (!previousNewFiber) {
962 + if (previousNewFiber === null) {
963 resultingFirstChild = newFiber;
964 } else {
965 previousNewFiber.sibling = newFiber;
@@ -983,13 +979,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
979
980 function reconcileSingleTextNode(
981 returnFiber : Fiber,
986 - currentFirstChild : ?Fiber,
982 + currentFirstChild : Fiber | null,
983 textContent : string,
984 priority : PriorityLevel
985 ) : Fiber {
986 // There's no need to check for keys on text nodes since we don't have a
987 // way to define them.
992 - if (currentFirstChild && currentFirstChild.tag === HostText) {
988 + if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
989 // We already have an existing node so let's just update it and delete
990 // the rest.
991 deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
@@ -1008,13 +1004,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1004
1005 function reconcileSingleElement(
1006 returnFiber : Fiber,
1011 - currentFirstChild : ?Fiber,
1007 + currentFirstChild : Fiber | null,
1008 element : ReactElement,
1009 priority : PriorityLevel
1010 ) : Fiber {
1011 const key = element.key;
1012 let child = currentFirstChild;
1017 - while (child) {
1013 + while (child !== null) {
1014 // TODO: If key === null and child.key === null, then this only applies to
1015 // the first item in the list.
1016 if (child.key === key) {
@@ -1047,13 +1043,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1043
1044 function reconcileSingleCoroutine(
1045 returnFiber : Fiber,
1050 - currentFirstChild : ?Fiber,
1046 + currentFirstChild : Fiber | null,
1047 coroutine : ReactCoroutine,
1048 priority : PriorityLevel
1049 ) : Fiber {
1050 const key = coroutine.key;
1051 let child = currentFirstChild;
1056 - while (child) {
1052 + while (child !== null) {
1053 // TODO: If key === null and child.key === null, then this only applies to
1054 // the first item in the list.
1055 if (child.key === key) {
@@ -1080,13 +1076,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1076
1077 function reconcileSingleYield(
1078 returnFiber : Fiber,
1083 - currentFirstChild : ?Fiber,
1079 + currentFirstChild : Fiber | null,
1080 yieldNode : ReactYield,
1081 priority : PriorityLevel
1082 ) : Fiber {
1083 // There's no need to check for keys on yields since they're stateless.
1084 let child = currentFirstChild;
1089 - if (child) {
1085 + if (child !== null) {
1086 if (child.tag === YieldComponent) {
1087 deleteRemainingChildren(returnFiber, child.sibling);
1088 const existing = useFiber(child, priority);
@@ -1106,13 +1102,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1102
1103 function reconcileSinglePortal(
1104 returnFiber : Fiber,
1109 - currentFirstChild : ?Fiber,
1105 + currentFirstChild : Fiber | null,
1106 portal : ReactPortal,
1107 priority : PriorityLevel
1108 ) : Fiber {
1109 const key = portal.key;
1110 let child = currentFirstChild;
1115 - while (child) {
1111 + while (child !== null) {
1112 // TODO: If key === null and child.key === null, then this only applies to
1113 // the first item in the list.
1114 if (child.key === key) {
@@ -1146,10 +1142,10 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1142 // children and the parent.
1143 function reconcileChildFibers(
1144 returnFiber : Fiber,
1149 - currentFirstChild : ?Fiber,
1145 + currentFirstChild : Fiber | null,
1146 newChild : any,
1147 priority : PriorityLevel
1152 - ) : ?Fiber {
1148 + ) : Fiber | null {
1149 // This function is not recursive.
1150 // If the top level item is an array, we treat it as a set of children,
1151 // not as a fragment. Nested arrays on the other hand will be treated as
@@ -1329,11 +1325,11 @@ exports.reconcileChildFibersInPlace = ChildReconciler(false, true);
1325
1326 exports.mountChildFibersInPlace = ChildReconciler(false, false);
1327
1332 -exports.cloneChildFibers = function(current : ?Fiber, workInProgress : Fiber) : void {
1328 +exports.cloneChildFibers = function(current : Fiber | null, workInProgress : Fiber) : void {
1329 if (!workInProgress.child) {
1330 return;
1331 }
1336 - if (current && workInProgress.child === current.child) {
1332 + if (current !== null && workInProgress.child === current.child) {
1333 // We use workInProgress.child since that lets Flow know that it can't be
1334 // null since we validated that already. However, as the line above suggests
1335 // they're actually the same thing.
@@ -1349,7 +1345,7 @@ exports.cloneChildFibers = function(current : ?Fiber, workInProgress : Fiber) :
1345 workInProgress.child = newChild;
1346
1347 newChild.return = workInProgress;
1352 - while (currentChild.sibling) {
1348 + while (currentChild.sibling !== null) {
1349 currentChild = currentChild.sibling;
1350 newChild = newChild.sibling = cloneFiber(
1351 currentChild,
@@ -1365,7 +1361,7 @@ exports.cloneChildFibers = function(current : ?Fiber, workInProgress : Fiber) :
1361 // need to clone. We need to reset the return fiber though since we'll
1362 // traverse down into them.
1363 let child = workInProgress.child;
1368 - while (child) {
1364 + while (child !== null) {
1365 child.return = workInProgress;
1366 child = child.sibling;
1367 }
src/renderers/shared/fiber/ReactDebugCurrentFiber.js
+2 -2
@@ -22,7 +22,7 @@ if (__DEV__) {
22 function getCurrentFiberOwnerName() : string | null {
23 if (__DEV__) {
24 const fiber = ReactDebugCurrentFiber.current;
25 - if (fiber == null) {
25 + if (fiber === null) {
26 return null;
27 }
28 if (fiber._debugOwner != null) {
@@ -35,7 +35,7 @@ function getCurrentFiberOwnerName() : string | null {
35 function getCurrentFiberStackAddendum() : string | null {
36 if (__DEV__) {
37 const fiber = ReactDebugCurrentFiber.current;
38 - if (fiber == null) {
38 + if (fiber === null) {
39 return null;
40 }
41 // Safe because if current fiber exists, we are reconciling,
src/renderers/shared/fiber/ReactFiber.js
+11 -11
@@ -93,11 +93,11 @@ export type Fiber = {
93 // This is effectively the parent, but there can be multiple parents (two)
94 // so this is only the parent of the thing we're currently processing.
95 // It is conceptually the same as the return address of a stack frame.
96 - return: ?Fiber,
96 + return: Fiber | null,
97
98 // Singly Linked List Tree Structure.
99 - child: ?Fiber,
100 - sibling: ?Fiber,
99 + child: Fiber | null,
100 + sibling: Fiber | null,
101 index: number,
102
103 // The ref last used to attach this node.
@@ -119,13 +119,13 @@ export type Fiber = {
119 effectTag: TypeOfSideEffect,
120
121 // Singly linked list fast path to the next fiber with side-effects.
122 - nextEffect: ?Fiber,
122 + nextEffect: Fiber | null,
123
124 // The first and last fiber with side-effect within this subtree. This allows
125 // us to reuse a slice of the linked list when we reuse the work done within
126 // this fiber.
127 - firstEffect: ?Fiber,
128 - lastEffect: ?Fiber,
127 + firstEffect: Fiber | null,
128 + lastEffect: Fiber | null,
129
130 // This will be used to quickly determine if a subtree has no pending changes.
131 pendingWorkPriority: PriorityLevel,
@@ -139,19 +139,19 @@ export type Fiber = {
139 // priority, then we need to store the progressed work somewhere. This holds
140 // the started child set until we need to get back to working on it. It may
141 // or may not be the same as the "current" child.
142 - progressedChild: ?Fiber,
142 + progressedChild: Fiber | null,
143
144 // When we reconcile children onto progressedChild it is possible that we have
145 // to delete some child fibers. We need to keep track of this side-effects so
146 // that if we continue later on, we have to include those effects. Deletions
147 // are added in the reverse order from sibling pointers.
148 - progressedFirstDeletion: ?Fiber,
149 - progressedLastDeletion: ?Fiber,
148 + progressedFirstDeletion: Fiber | null,
149 + progressedLastDeletion: Fiber | null,
150
151 // This is a pooled version of a Fiber. Every fiber that gets updated will
152 // eventually have a pair. There are cases when we can clean up pairs to save
153 // memory if we need to.
154 - alternate: ?Fiber,
154 + alternate: Fiber | null,
155
156 // Conceptual aliases
157 // workInProgress : Fiber -> alternate The alternate used for reuse happens
@@ -249,7 +249,7 @@ exports.cloneFiber = function(fiber : Fiber, priorityLevel : PriorityLevel) : Fi
249 // objects for things that are never updated. It also allow us to reclaim the
250 // extra memory if needed.
251 let alt = fiber.alternate;
252 - if (alt) {
252 + if (alt !== null) {
253 // If we clone, then we do so from the "current" state. The current state
254 // can't have any side-effects that are still valid so we reset just to be
255 // sure.
src/renderers/shared/fiber/ReactFiberBeginWork.js
+22 -22
@@ -102,7 +102,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
102 // We now have clones. Let's store them as the currently progressed work.
103 workInProgress.progressedChild = workInProgress.child;
104 workInProgress.progressedPriority = priorityLevel;
105 - if (current) {
105 + if (current !== null) {
106 // We also store it on the current. When the alternate swaps in we can
107 // continue from this point.
108 current.progressedChild = workInProgress.progressedChild;
@@ -131,7 +131,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
131 // At this point any memoization is no longer valid since we'll have changed
132 // the children.
133 workInProgress.memoizedProps = null;
134 - if (!current) {
134 + if (current === null) {
135 // If this is a fresh new component that hasn't been rendered yet, we
136 // won't update its child set by applying minimal side-effects. Instead,
137 // we will add them all to the child before it gets rendered. That means
@@ -191,9 +191,9 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
191 return workInProgress.child;
192 }
193
194 - function markRef(current : ?Fiber, workInProgress : Fiber) {
194 + function markRef(current : Fiber | null, workInProgress : Fiber) {
195 const ref = workInProgress.ref;
196 - if (ref && (!current || current.ref !== ref)) {
196 + if (ref !== null && (!current || current.ref !== ref)) {
197 // Schedule a Ref effect
198 workInProgress.effectTag |= Ref;
199 }
@@ -211,7 +211,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
211 nextProps = memoizedProps;
212 }
213 } else {
214 - if (nextProps == null || memoizedProps === nextProps) {
214 + if (nextProps === null || memoizedProps === nextProps) {
215 return bailoutOnAlreadyFinishedWork(current, workInProgress);
216 }
217 // TODO: Disable this before release, since it is not part of the public API
@@ -240,14 +240,14 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
240 return workInProgress.child;
241 }
242
243 - function updateClassComponent(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) {
243 + function updateClassComponent(current : Fiber | null, workInProgress : Fiber, priorityLevel : PriorityLevel) {
244 // Push context providers early to prevent context stack mismatches.
245 // During mounting we don't know the child context yet as the instance doesn't exist.
246 // We will invalidate the child context in finishClassComponent() right after rendering.
247 const hasContext = pushContextProvider(workInProgress);
248
249 let shouldUpdate;
250 - if (!current) {
250 + if (current === null) {
251 if (!workInProgress.stateNode) {
252 // In the initial pass we might need to construct the instance.
253 constructClassInstance(workInProgress);
@@ -264,7 +264,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
264 }
265
266 function finishClassComponent(
267 - current : ?Fiber,
267 + current : Fiber | null,
268 workInProgress : Fiber,
269 shouldUpdate : boolean,
270 hasContext : boolean,
@@ -314,7 +314,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
314 pushHostContainer(workInProgress, root.containerInfo);
315
316 const updateQueue = workInProgress.updateQueue;
317 - if (updateQueue) {
317 + if (updateQueue !== null) {
318 const prevState = workInProgress.memoizedState;
319 const state = beginUpdateQueue(workInProgress, updateQueue, null, prevState, null, priorityLevel);
320 if (prevState === state) {
@@ -335,7 +335,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
335 pushHostContext(workInProgress);
336
337 let nextProps = workInProgress.pendingProps;
338 - const prevProps = current ? current.memoizedProps : null;
338 + const prevProps = current !== null ? current.memoizedProps : null;
339 const memoizedProps = workInProgress.memoizedProps;
340 if (hasContextChanged()) {
341 // Normally we can bail out on props equality but if context has changed
@@ -359,7 +359,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
359 // that is a bit tricky since workInProgress and current can have
360 // different "hidden" settings.
361 let child = workInProgress.progressedChild;
362 - while (child) {
362 + while (child !== null) {
363 // To ensure that this subtree gets its priority reset, the children
364 // need to be reset.
365 child.pendingWorkPriority = OffscreenPriority;
@@ -409,16 +409,16 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
409 // Reconcile the children and stash them for later work.
410 reconcileChildrenAtPriority(current, workInProgress, nextChildren, OffscreenPriority);
411 memoizeProps(workInProgress, nextProps);
412 - workInProgress.child = current ? current.child : null;
412 + workInProgress.child = current !== null ? current.child : null;
413
414 - if (!current) {
414 + if (current === null) {
415 // If this doesn't have a current we won't track it for placement
416 // effects. However, when we come back around to this we have already
417 // inserted the parent which means that we'll infact need to make this a
418 // placement.
419 // TODO: There has to be a better solution to this problem.
420 let child = workInProgress.progressedChild;
421 - while (child) {
421 + while (child !== null) {
422 child.effectTag = Placement;
423 child = child.sibling;
424 }
@@ -464,7 +464,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
464 value = fn(props, context);
465 }
466
467 - if (typeof value === 'object' && value && typeof value.render === 'function') {
467 + if (typeof value === 'object' && value !== null && typeof value.render === 'function') {
468 // Proceed under the assumption that this is a class instance
469 workInProgress.tag = ClassComponent;
470
@@ -479,7 +479,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
479 // Proceed under the assumption that this is a functional component
480 workInProgress.tag = FunctionalComponent;
481 if (__DEV__) {
482 - if (workInProgress.ref != null) {
482 + if (workInProgress.ref !== null) {
483 let info = '';
484 const ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
485 if (ownerName) {
@@ -517,7 +517,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
517 if (nextCoroutine === null) {
518 nextCoroutine = current && current.memoizedProps;
519 invariant(
520 - nextCoroutine != null,
520 + nextCoroutine !== null,
521 'We should always have pending or current props. This error is ' +
522 'likely caused by a bug in React. Please file an issue.'
523 );
@@ -538,7 +538,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
538 // At this point any memoization is no longer valid since we'll have changed
539 // the children.
540 workInProgress.memoizedProps = null;
541 - if (!current) {
541 + if (current === null) {
542 workInProgress.stateNode = mountChildFibersInPlace(
543 workInProgress,
544 workInProgress.stateNode,
@@ -592,7 +592,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
592 return bailoutOnAlreadyFinishedWork(current, workInProgress);
593 }
594
595 - if (!current) {
595 + if (current === null) {
596 // Portals are special because we don't append the children during mount
597 // but at commit. Therefore we need to track insertions which the normal
598 // flow doesn't do during mount. This doesn't happen at the root because
@@ -632,7 +632,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
632 }
633 */
634
635 - function bailoutOnAlreadyFinishedWork(current, workInProgress : Fiber) : ?Fiber {
635 + function bailoutOnAlreadyFinishedWork(current, workInProgress : Fiber) : Fiber | null {
636 const priorityLevel = workInProgress.pendingWorkPriority;
637 // TODO: We should ideally be able to bail out early if the children have no
638 // more work to do. However, since we don't have a separation of this
@@ -687,7 +687,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
687 // is handled by beginUpdateQueue.
688 }
689
690 - function beginWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) : ?Fiber {
690 + function beginWork(current : Fiber | null, workInProgress : Fiber, priorityLevel : PriorityLevel) : Fiber | null {
691 if (workInProgress.pendingWorkPriority === NoWork ||
692 workInProgress.pendingWorkPriority > priorityLevel) {
693 return bailoutOnLowPriority(current, workInProgress);
@@ -744,7 +744,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
744 }
745 }
746
747 - function beginFailedWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) {
747 + function beginFailedWork(current : Fiber | null, workInProgress : Fiber, priorityLevel : PriorityLevel) {
748 invariant(
749 workInProgress.tag === ClassComponent ||
750 workInProgress.tag === HostRoot,
src/renderers/shared/fiber/ReactFiberClassComponent.js
+7 -7
@@ -71,7 +71,7 @@ module.exports = function(
71 };
72
73 function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) {
74 - if (oldProps === null || (workInProgress.updateQueue && workInProgress.updateQueue.hasForceUpdate)) {
74 + if (oldProps === null || (workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate)) {
75 // If the workInProgress already has an Update effect, return true
76 return true;
77 }
@@ -208,10 +208,10 @@ module.exports = function(
208 workInProgress.effectTag |= Update;
209 }
210
211 - function markUpdateIfAlreadyInProgress(current: ?Fiber, workInProgress : Fiber) {
211 + function markUpdateIfAlreadyInProgress(current: Fiber | null, workInProgress : Fiber) {
212 // If an update was already in progress, we should schedule an Update
213 // effect even though we're bailing out, so that cWU/cDU are called.
214 - if (current) {
214 + if (current !== null) {
215 if (workInProgress.memoizedProps !== current.memoizedProps ||
216 workInProgress.memoizedState !== current.memoizedState) {
217 markUpdate(workInProgress);
@@ -274,7 +274,7 @@ module.exports = function(
274 // If we had additional state updates during this life-cycle, let's
275 // process them now.
276 const updateQueue = workInProgress.updateQueue;
277 - if (updateQueue) {
277 + if (updateQueue !== null) {
278 instance.state = beginUpdateQueue(
279 workInProgress,
280 updateQueue,
@@ -343,7 +343,7 @@ module.exports = function(
343 // They may be from componentWillMount() or from error boundary's setState()
344 // during initial mounting.
345 const newUpdateQueue = workInProgress.updateQueue;
346 - if (newUpdateQueue) {
346 + if (newUpdateQueue !== null) {
347 newInstance.state = beginUpdateQueue(
348 workInProgress,
349 newUpdateQueue,
@@ -392,7 +392,7 @@ module.exports = function(
392 const oldState = workInProgress.memoizedState;
393 // TODO: Previous state can be null.
394 let newState;
395 - if (updateQueue) {
395 + if (updateQueue !== null) {
396 newState = beginUpdateQueue(
397 workInProgress,
398 updateQueue,
@@ -408,7 +408,7 @@ module.exports = function(
408 if (oldProps === newProps &&
409 oldState === newState &&
410 !hasContextChanged() &&
411 - !(updateQueue && updateQueue.hasForceUpdate)) {
411 + !(updateQueue !== null && updateQueue.hasForceUpdate)) {
412 markUpdateIfAlreadyInProgress(current, workInProgress);
413 return false;
414 }
src/renderers/shared/fiber/ReactFiberCommitWork.js
+29 -29
@@ -38,7 +38,7 @@ var invariant = require('invariant');
38
39 module.exports = function<T, P, I, TI, PI, C, CX, PL>(
40 config : HostConfig<T, P, I, TI, PI, C, CX, PL>,
41 - captureError : (failedFiber : Fiber, error: Error) => ?Fiber
41 + captureError : (failedFiber : Fiber, error: Error) => Fiber | null
42 ) {
43
44 const {
@@ -65,7 +65,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
65 function safelyDetachRef(current : Fiber) {
66 try {
67 const ref = current.ref;
68 - if (ref) {
68 + if (ref !== null) {
69 ref(null);
70 }
71 } catch (error) {
@@ -74,10 +74,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
74 }
75
76 // Only called during update. It's ok to throw.
77 - function detachRefIfNeeded(current : ?Fiber, finishedWork : Fiber) {
77 + function detachRefIfNeeded(current : Fiber | null, finishedWork : Fiber) {
78 if (current) {
79 const currentRef = current.ref;
80 - if (currentRef && currentRef !== finishedWork.ref) {
80 + if (currentRef !== null && currentRef !== finishedWork.ref) {
81 currentRef(null);
82 }
83 }
@@ -85,7 +85,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
85
86 function getHostParent(fiber : Fiber) : I | C {
87 let parent = fiber.return;
88 - while (parent) {
88 + while (parent !== null) {
89 switch (parent.tag) {
90 case HostComponent:
91 return parent.stateNode;
@@ -105,7 +105,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
105
106 function getHostParentFiber(fiber : Fiber) : Fiber {
107 let parent = fiber.return;
108 - while (parent) {
108 + while (parent !== null) {
109 if (isHostParent(parent)) {
110 return parent;
111 }
@@ -134,8 +134,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
134 let node : Fiber = fiber;
135 siblings: while (true) {
136 // If we didn't find anything, let's try the next sibling.
137 - while (!node.sibling) {
138 - if (!node.return || isHostParent(node.return)) {
137 + while (node.sibling === null) {
138 + if (node.return === null || isHostParent(node.return)) {
139 // If we pop out of the root or hit the parent the fiber we are the
140 // last sibling.
141 return null;
@@ -153,7 +153,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
153 }
154 // If we don't have a child, try the siblings instead.
155 // We also skip portals because they are not part of this host tree.
156 - if (!node.child || node.tag === HostPortal) {
156 + if (node.child === null || node.tag === HostPortal) {
157 continue siblings;
158 } else {
159 node.child.return = node;
@@ -211,7 +211,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
211 // If the insertion itself is a portal, then we don't want to traverse
212 // down its children. Instead, we'll get insertions from each child in
213 // the portal directly.
214 - } else if (node.child) {
214 + } else if (node.child !== null) {
215 node.child.return = node;
216 node = node.child;
217 continue;
@@ -219,8 +219,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
219 if (node === finishedWork) {
220 return;
221 }
222 - while (!node.sibling) {
223 - if (!node.return || node.return === finishedWork) {
222 + while (node.sibling === null) {
223 + if (node.return === null || node.return === finishedWork) {
224 return;
225 }
226 node = node.return;
@@ -241,7 +241,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
241 commitUnmount(node);
242 // Visit children because they may contain more composite or host nodes.
243 // Skip portals because commitUnmount() currently visits them recursively.
244 - if (node.child && node.tag !== HostPortal) {
244 + if (node.child !== null && node.tag !== HostPortal) {
245 node.child.return = node;
246 node = node.child;
247 continue;
@@ -249,8 +249,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
249 if (node === root) {
250 return;
251 }
252 - while (!node.sibling) {
253 - if (!node.return || node.return === root) {
252 + while (node.sibling === null) {
253 + if (node.return === null || node.return === root) {
254 return;
255 }
256 node = node.return;
@@ -276,7 +276,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
276 // We will reassign it back when we pop the portal on the way up.
277 parent = node.stateNode.containerInfo;
278 // Visit children because portals might contain host components.
279 - if (node.child) {
279 + if (node.child !== null) {
280 node.child.return = node;
281 node = node.child;
282 continue;
@@ -284,7 +284,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
284 } else {
285 commitUnmount(node);
286 // Visit children because we may find more host components below.
287 - if (node.child) {
287 + if (node.child !== null) {
288 node.child.return = node;
289 node = node.child;
290 continue;
@@ -293,8 +293,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
293 if (node === current) {
294 return;
295 }
296 - while (!node.sibling) {
297 - if (!node.return || node.return === current) {
296 + while (node.sibling === null) {
297 + if (node.return === null || node.return === current) {
298 return;
299 }
300 node = node.return;
@@ -364,7 +364,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
364 }
365 }
366
367 - function commitWork(current : ?Fiber, finishedWork : Fiber) : void {
367 + function commitWork(current : Fiber | null, finishedWork : Fiber) : void {
368 switch (finishedWork.tag) {
369 case ClassComponent: {
370 detachRefIfNeeded(current, finishedWork);
@@ -372,7 +372,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
372 }
373 case HostComponent: {
374 const instance : I = finishedWork.stateNode;
375 - if (instance != null && current) {
375 + if (instance != null && current !== null) {
376 // Commit the work prepared earlier.
377 const newProps = finishedWork.memoizedProps;
378 const oldProps = current.memoizedProps;
@@ -380,7 +380,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
380 // TODO: Type the updateQueue to be specific to host components.
381 const updatePayload : null | PL = (finishedWork.updateQueue : any);
382 finishedWork.updateQueue = null;
383 - if (updatePayload) {
383 + if (updatePayload !== null) {
384 commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork);
385 }
386 }
@@ -389,7 +389,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
389 }
390 case HostText: {
391 invariant(
392 - finishedWork.stateNode !== null && current != null,
392 + finishedWork.stateNode !== null && current !== null,
393 'This should only be done during updates. This error is likely ' +
394 'caused by a bug in React. Please file an issue.'
395 );
@@ -415,12 +415,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
415 }
416 }
417
418 - function commitLifeCycles(current : ?Fiber, finishedWork : Fiber) : void {
418 + function commitLifeCycles(current : Fiber | null, finishedWork : Fiber) : void {
419 switch (finishedWork.tag) {
420 case ClassComponent: {
421 const instance = finishedWork.stateNode;
422 if (finishedWork.effectTag & Update) {
423 - if (!current) {
423 + if (current === null) {
424 if (typeof instance.componentDidMount === 'function') {
425 instance.componentDidMount();
426 }
@@ -432,14 +432,14 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
432 }
433 }
434 }
435 - if ((finishedWork.effectTag & Callback) && finishedWork.updateQueue) {
435 + if ((finishedWork.effectTag & Callback) && finishedWork.updateQueue !== null) {
436 commitCallbacks(finishedWork, finishedWork.updateQueue, instance);
437 }
438 return;
439 }
440 case HostRoot: {
441 const updateQueue = finishedWork.updateQueue;
442 - if (updateQueue) {
442 + if (updateQueue !== null) {
443 const instance = finishedWork.child && finishedWork.child.stateNode;
444 commitCallbacks(finishedWork, updateQueue, instance);
445 }
@@ -453,7 +453,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
453 // These effects should only be committed when components are first mounted,
454 // aka when there is no current/alternate.
455 if (
456 - !current &&
456 + current === null &&
457 finishedWork.effectTag & Update
458 ) {
459 const type = finishedWork.type;
@@ -486,7 +486,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
486 return;
487 }
488 const ref = finishedWork.ref;
489 - if (ref) {
489 + if (ref !== null) {
490 const instance = getPublicInstance(finishedWork.stateNode);
491 ref(instance);
492 }
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+14 -14
@@ -71,7 +71,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
71 // We now have clones. Let's store them as the currently progressed work.
72 workInProgress.progressedChild = workInProgress.child;
73 workInProgress.progressedPriority = priorityLevel;
74 - if (current) {
74 + if (current !== null) {
75 // We also store it on the current. When the alternate swaps in we can
76 // continue from this point.
77 current.progressedChild = workInProgress.progressedChild;
@@ -90,7 +90,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
90 if (node) {
91 node.return = workInProgress;
92 }
93 - while (node) {
93 + while (node !== null) {
94 if (node.tag === HostComponent || node.tag === HostText ||
95 node.tag === HostPortal) {
96 invariant(
@@ -99,13 +99,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
99 );
100 } else if (node.tag === YieldComponent) {
101 yields.push(node.type);
102 - } else if (node.child) {
102 + } else if (node.child !== null) {
103 node.child.return = node;
104 node = node.child;
105 continue;
106 }
107 - while (!node.sibling) {
108 - if (!node.return || node.return === workInProgress) {
107 + while (node.sibling === null) {
108 + if (node.return === null || node.return === workInProgress) {
109 return;
110 }
111 node = node.return;
@@ -115,7 +115,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
115 }
116 }
117
118 - function moveCoroutineToHandlerPhase(current : ?Fiber, workInProgress : Fiber) {
118 + function moveCoroutineToHandlerPhase(current : Fiber | null, workInProgress : Fiber) {
119 var coroutine = (workInProgress.memoizedProps : ?ReactCoroutine);
120 invariant(
121 coroutine,
@@ -140,7 +140,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
140 var props = coroutine.props;
141 var nextChildren = fn(props, yields);
142
143 - var currentFirstChild = current ? current.child : null;
143 + var currentFirstChild = current !== null ? current.child : null;
144 // Inherit the priority of the returnFiber.
145 const priority = workInProgress.pendingWorkPriority;
146 workInProgress.child = reconcileChildFibers(
@@ -157,22 +157,22 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
157 // We only have the top Fiber that was created but we need recurse down its
158 // children to find all the terminal nodes.
159 let node = workInProgress.child;
160 - while (node) {
160 + while (node !== null) {
161 if (node.tag === HostComponent || node.tag === HostText) {
162 appendInitialChild(parent, node.stateNode);
163 } else if (node.tag === HostPortal) {
164 // If we have a portal child, then we don't want to traverse
165 // down its children. Instead, we'll get insertions from each child in
166 // the portal directly.
167 - } else if (node.child) {
167 + } else if (node.child !== null) {
168 node = node.child;
169 continue;
170 }
171 if (node === workInProgress) {
172 return;
173 }
174 - while (!node.sibling) {
175 - if (!node.return || node.return === workInProgress) {
174 + while (node.sibling === null) {
175 + if (node.return === null || node.return === workInProgress) {
176 return;
177 }
178 node = node.return;
@@ -181,7 +181,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
181 }
182 }
183
184 - function completeWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
184 + function completeWork(current : Fiber | null, workInProgress : Fiber) : Fiber | null {
185 if (__DEV__) {
186 ReactDebugCurrentFiber.current = workInProgress;
187 }
@@ -208,7 +208,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
208 const rootContainerInstance = getRootHostContainer();
209 const type = workInProgress.type;
210 const newProps = workInProgress.memoizedProps;
211 - if (current && workInProgress.stateNode != null) {
211 + if (current !== null && workInProgress.stateNode != null) {
212 // If we have an alternate, that means this is an update and we need to
213 // schedule a side-effect to do the updates.
214 const oldProps = current.memoizedProps;
@@ -268,7 +268,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
268 }
269
270 workInProgress.stateNode = instance;
271 - if (workInProgress.ref) {
271 + if (workInProgress.ref !== null) {
272 // If there is a ref on a host node we need to schedule a callback
273 workInProgress.effectTag |= Ref;
274 }
src/renderers/shared/fiber/ReactFiberContext.js
+1 -1
@@ -149,7 +149,7 @@ function processChildContext(fiber : Fiber, parentContext : Object, isReconcilin
149 if (typeof instance.getChildContext !== 'function') {
150 if (__DEV__) {
151 const componentName = getComponentName(fiber);
152 -
152 +
153 if (!warnedAboutMissingGetChildContext[componentName]) {
154 warnedAboutMissingGetChildContext[componentName] = true;
155 warning(
src/renderers/shared/fiber/ReactFiberHostContext.js
+7 -5
@@ -44,14 +44,14 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
44 getRootHostContext,
45 } = config;
46
47 - let contextStackCursor : StackCursor<?CX> = createCursor((null: ?CX));
48 - let contextFiberStackCursor : StackCursor<?Fiber> = createCursor((null: ?Fiber));
49 - let rootInstanceStackCursor : StackCursor<?C> = createCursor((null: ?C));
47 + let contextStackCursor : StackCursor<CX | null> = createCursor((null: ?CX));
48 + let contextFiberStackCursor : StackCursor<Fiber | null> = createCursor((null: Fiber | null));
49 + let rootInstanceStackCursor : StackCursor<C | null> = createCursor((null: ?C));
50
51 function getRootHostContainer() : C {
52 const rootInstance = rootInstanceStackCursor.current;
53 invariant(
54 - rootInstance != null,
54 + rootInstance !== null,
55 'Expected root container to exist. This error is likely caused by a ' +
56 'bug in React. Please file an issue.'
57 );
@@ -95,7 +95,9 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
95 'a bug in React. Please file an issue.'
96 );
97
98 - const context = contextStackCursor.current || emptyObject;
98 + const context = contextStackCursor.current !== null ?
99 + contextStackCursor.current :
100 + emptyObject;
101 const nextContext = getChildHostContext(context, fiber.type, rootInstance);
102
103 // Don't push this Fiber's context unless it's unique.
src/renderers/shared/fiber/ReactFiberReconciler.js
+1 -1
@@ -206,7 +206,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
206
207 findHostInstance(fiber : Fiber) : I | TI | null {
208 const hostFiber = findCurrentHostFiber(fiber);
209 - if (!hostFiber) {
209 + if (hostFiber === null) {
210 return null;
211 }
212 return hostFiber.stateNode;
src/renderers/shared/fiber/ReactFiberRoot.js
+3 -3
@@ -24,10 +24,10 @@ export type FiberRoot = {
24 // Determines if this root has already been added to the schedule for work.
25 isScheduled: boolean,
26 // The work schedule is a linked list.
27 - nextScheduledRoot: ?FiberRoot,
27 + nextScheduledRoot: FiberRoot | null,
28 // Top context object, used by renderSubtreeIntoContainer
29 - context: ?Object,
30 - pendingContext: ?Object,
29 + context: Object | null,
30 + pendingContext: Object | null,
31 };
32
33 exports.createFiberRoot = function(containerInfo : any) : FiberRoot {
src/renderers/shared/fiber/ReactFiberScheduler.js
+84 -90
@@ -22,7 +22,7 @@ export type CapturedError = {
22 componentStack : string,
23 error : Error,
24 errorBoundaryFound : boolean,
25 - errorBoundaryName : ?string,
25 + errorBoundaryName : string | null,
26 willRetry : boolean,
27 };
28
@@ -134,17 +134,17 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
134 let isBatchingUpdates : boolean = false;
135
136 // The next work in progress fiber that we're currently working on.
137 - let nextUnitOfWork : ?Fiber = null;
137 + let nextUnitOfWork : Fiber | null = null;
138 let nextPriorityLevel : PriorityLevel = NoWork;
139
140 // The next fiber with an effect that we're currently committing.
141 - let nextEffect : ?Fiber = null;
141 + let nextEffect : Fiber | null = null;
142
143 - let pendingCommit : ?Fiber = null;
143 + let pendingCommit : Fiber | null = null;
144
145 // Linked list of roots with scheduled work on them.
146 - let nextScheduledRoot : ?FiberRoot = null;
147 - let lastScheduledRoot : ?FiberRoot = null;
146 + let nextScheduledRoot : FiberRoot | null = null;
147 + let lastScheduledRoot : FiberRoot | null = null;
148
149 // Keep track of which host environment callbacks are scheduled.
150 let isAnimationCallbackScheduled : boolean = false;
@@ -193,7 +193,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
193 // the work loop.
194 function findNextUnitOfWork() {
195 // Clear out roots with no more work on them, or if they have uncaught errors
196 - while (nextScheduledRoot && nextScheduledRoot.current.pendingWorkPriority === NoWork) {
196 + while (nextScheduledRoot !== null && nextScheduledRoot.current.pendingWorkPriority === NoWork) {
197 // Unschedule this root.
198 nextScheduledRoot.isScheduled = false;
199 // Read the next pointer now.
@@ -215,7 +215,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
215 let root = nextScheduledRoot;
216 let highestPriorityRoot = null;
217 let highestPriorityLevel = NoWork;
218 - while (root) {
218 + while (root !== null) {
219 if (root.current.pendingWorkPriority !== NoWork && (
220 highestPriorityLevel === NoWork ||
221 highestPriorityLevel > root.current.pendingWorkPriority)) {
@@ -225,7 +225,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
225 // We didn't find anything to do in this root, so let's try the next one.
226 root = root.nextScheduledRoot;
227 }
228 - if (highestPriorityRoot) {
228 + if (highestPriorityRoot !== null) {
229 nextPriorityLevel = highestPriorityLevel;
230 priorityContext = nextPriorityLevel;
231
@@ -247,7 +247,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
247 }
248
249 function commitAllHostEffects() {
250 - while (nextEffect) {
250 + while (nextEffect !== null) {
251 if (__DEV__) {
252 ReactDebugCurrentFiber.current = nextEffect;
253 }
@@ -306,7 +306,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
306 }
307
308 function commitAllLifeCycles() {
309 - while (nextEffect) {
309 + while (nextEffect !== null) {
310 const current = nextEffect.alternate;
311 // Use Task priority for lifecycle updates
312 if (nextEffect.effectTag & (Update | Callback)) {
@@ -359,7 +359,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
359 // the root has an effect, we need to add it to the end of the list. The
360 // resulting list is the set that would belong to the root's parent, if
361 // it had one; that is, all the effects in the tree including the root.
362 - if (finishedWork.lastEffect) {
362 + if (finishedWork.lastEffect !== null) {
363 finishedWork.lastEffect.nextEffect = finishedWork;
364 firstEffect = finishedWork.firstEffect;
365 } else {
@@ -376,18 +376,18 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
376 // The first pass performs all the host insertions, updates, deletions and
377 // ref unmounts.
378 nextEffect = firstEffect;
379 - while (nextEffect) {
379 + while (nextEffect !== null) {
380 try {
381 commitAllHostEffects(finishedWork);
382 } catch (error) {
383 invariant(
384 - nextEffect != null,
384 + nextEffect !== null,
385 'Should have next effect. This error is likely caused by a bug ' +
386 'in React. Please file an issue.'
387 );
388 captureError(nextEffect, error);
389 // Clean-up
390 - if (nextEffect) {
390 + if (nextEffect !== null) {
391 nextEffect = nextEffect.nextEffect;
392 }
393 }
@@ -406,17 +406,17 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
406 // and deletions in the entire tree have already been invoked.
407 // This pass also triggers any renderer-specific initial effects.
408 nextEffect = firstEffect;
409 - while (nextEffect) {
409 + while (nextEffect !== null) {
410 try {
411 commitAllLifeCycles(finishedWork, nextEffect);
412 } catch (error) {
413 invariant(
414 - nextEffect != null,
414 + nextEffect !== null,
415 'Should have next effect. This error is likely caused by a bug ' +
416 'in React. Please file an issue.'
417 );
418 captureError(nextEffect, error);
419 - if (nextEffect) {
419 + if (nextEffect !== null) {
420 nextEffect = nextEffect.nextEffect;
421 }
422 }
@@ -446,7 +446,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
446 // Check for pending update priority. This is usually null so it shouldn't
447 // be a perf issue.
448 const queue = workInProgress.updateQueue;
449 - if (queue) {
449 + if (queue !== null) {
450 newPriority = getPendingPriority(queue);
451 }
452
@@ -456,7 +456,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
456 // Either it is the same as child, or it just bailed out because it choose
457 // not to do the work.
458 let child = workInProgress.progressedChild;
459 - while (child) {
459 + while (child !== null) {
460 // Ensure that remaining work priority bubbles up.
461 if (child.pendingWorkPriority !== NoWork &&
462 (newPriority === NoWork ||
@@ -468,7 +468,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
468 workInProgress.pendingWorkPriority = newPriority;
469 }
470
471 - function completeUnitOfWork(workInProgress : Fiber) : ?Fiber {
471 + function completeUnitOfWork(workInProgress : Fiber) : Fiber | null {
472 while (true) {
473 // The current, flushed, state of this fiber is the alternate.
474 // Ideally nothing should rely on this, but relying on it here
@@ -482,7 +482,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
482
483 resetWorkPriority(workInProgress);
484
485 - if (next) {
485 + if (next !== null) {
486 if (__DEV__ && ReactFiberInstrumentation.debugTool) {
487 ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);
488 }
@@ -491,15 +491,15 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
491 return next;
492 }
493
494 - if (returnFiber) {
494 + if (returnFiber !== null) {
495 // Append all the effects of the subtree and this fiber onto the effect
496 // list of the parent. The completion order of the children affects the
497 // side-effect order.
498 - if (!returnFiber.firstEffect) {
498 + if (returnFiber.firstEffect === null) {
499 returnFiber.firstEffect = workInProgress.firstEffect;
500 }
501 - if (workInProgress.lastEffect) {
502 - if (returnFiber.lastEffect) {
501 + if (workInProgress.lastEffect !== null) {
502 + if (returnFiber.lastEffect !== null) {
503 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
504 }
505 returnFiber.lastEffect = workInProgress.lastEffect;
@@ -512,7 +512,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
512 // reusing children we'll schedule this effect onto itself since we're
513 // at the end.
514 if (workInProgress.effectTag !== NoEffect) {
515 - if (returnFiber.lastEffect) {
515 + if (returnFiber.lastEffect !== null) {
516 returnFiber.lastEffect.nextEffect = workInProgress;
517 } else {
518 returnFiber.firstEffect = workInProgress;
@@ -525,10 +525,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
525 ReactFiberInstrumentation.debugTool.onCompleteWork(workInProgress);
526 }
527
528 - if (siblingFiber) {
528 + if (siblingFiber !== null) {
529 // If there is more work to do in this returnFiber, do that next.
530 return siblingFiber;
531 - } else if (returnFiber) {
531 + } else if (returnFiber !== null) {
532 // If there's no more work in this returnFiber. Complete the returnFiber.
533 workInProgress = returnFiber;
534 continue;
@@ -548,7 +548,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
548 }
549 }
550
551 - function performUnitOfWork(workInProgress : Fiber) : ?Fiber {
551 + function performUnitOfWork(workInProgress : Fiber) : Fiber | null {
552 // The current, flushed, state of this fiber is the alternate.
553 // Ideally nothing should rely on this, but relying on it here
554 // means that we don't need an additional field on the work in
@@ -561,7 +561,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
561 ReactFiberInstrumentation.debugTool.onBeginWork(workInProgress);
562 }
563
564 - if (!next) {
564 + if (next === null) {
565 // If this doesn't spawn new work, complete the current work.
566 next = completeUnitOfWork(workInProgress);
567 }
@@ -574,7 +574,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
574 return next;
575 }
576
577 - function performFailedUnitOfWork(workInProgress : Fiber) : ?Fiber {
577 + function performFailedUnitOfWork(workInProgress : Fiber) : Fiber | null {
578
579 // The current, flushed, state of this fiber is the alternate.
580 // Ideally nothing should rely on this, but relying on it here
@@ -588,7 +588,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
588 ReactFiberInstrumentation.debugTool.onBeginWork(workInProgress);
589 }
590
591 - if (!next) {
591 + if (next === null) {
592 // If this doesn't spawn new work, complete the current work.
593 next = completeUnitOfWork(workInProgress);
594 }
@@ -610,16 +610,16 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
610
611 function performAnimationWork() {
612 isAnimationCallbackScheduled = false;
613 - performWork(AnimationPriority);
613 + performWork(AnimationPriority, null);
614 }
615
616 function clearErrors() {
617 - if (!nextUnitOfWork) {
617 + if (nextUnitOfWork === null) {
618 nextUnitOfWork = findNextUnitOfWork();
619 }
620 // Keep performing work until there are no more errors
621 - while (capturedErrors && capturedErrors.size &&
622 - nextUnitOfWork &&
621 + while (capturedErrors !== null && capturedErrors.size &&
622 + nextUnitOfWork !== null &&
623 nextPriorityLevel !== NoWork &&
624 nextPriorityLevel <= TaskPriority) {
625 if (hasCapturedError(nextUnitOfWork)) {
@@ -628,7 +628,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
628 } else {
629 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
630 }
631 - if (!nextUnitOfWork) {
631 + if (nextUnitOfWork === null) {
632 // If performUnitOfWork returns null, that means we just comitted
633 // a root. Normally we'd need to clear any errors that were scheduled
634 // during the commit phase. But we're already clearing errors, so
@@ -642,16 +642,16 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
642 // Clear any errors.
643 clearErrors();
644
645 - if (!nextUnitOfWork) {
645 + if (nextUnitOfWork === null) {
646 nextUnitOfWork = findNextUnitOfWork();
647 }
648
649 let hostRootTimeMarker;
650 if (
651 ReactFeatureFlags.logTopLevelRenders &&
652 - nextUnitOfWork &&
652 + nextUnitOfWork !== null &&
653 nextUnitOfWork.tag === HostRoot &&
654 - nextUnitOfWork.child
654 + nextUnitOfWork.child !== null
655 ) {
656 const componentName = getComponentName(nextUnitOfWork.child) || '';
657 hostRootTimeMarker = 'React update: ' + componentName;
@@ -660,17 +660,17 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
660
661 // If there's a deadline, and we're not performing Task work, perform work
662 // using this loop that checks the deadline on every iteration.
663 - if (deadline && priorityLevel > TaskPriority) {
663 + if (deadline !== null && priorityLevel > TaskPriority) {
664 // The deferred work loop will run until there's no time left in
665 // the current frame.
666 - while (nextUnitOfWork && !deadlineHasExpired) {
666 + while (nextUnitOfWork !== null && !deadlineHasExpired) {
667 if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
668 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
669 // In a deferred work batch, iff nextUnitOfWork returns null, we just
670 // completed a root and a pendingCommit exists. Logically, we could
671 // omit either of the checks in the following condition, but we need
672 // both to satisfy Flow.
673 - if (!nextUnitOfWork && pendingCommit) {
673 + if (nextUnitOfWork === null && pendingCommit !== null) {
674 // If we have time, we should commit the work now.
675 if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
676 commitAllWork(pendingCommit);
@@ -690,11 +690,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
690 // If there's no deadline, or if we're performing Task work, use this loop
691 // that doesn't check how much time is remaining. It will keep running
692 // until we run out of work at this priority level.
693 - while (nextUnitOfWork &&
693 + while (nextUnitOfWork !== null &&
694 nextPriorityLevel !== NoWork &&
695 nextPriorityLevel <= priorityLevel) {
696 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
697 - if (!nextUnitOfWork) {
697 + if (nextUnitOfWork === null) {
698 nextUnitOfWork = findNextUnitOfWork();
699 // performUnitOfWork returned null, which means we just comitted a
700 // root. Clear any errors that were scheduled during the commit phase.
@@ -725,14 +725,14 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
725 // deferred batch.
726 while (priorityLevel !== NoWork && !fatalError) {
727 invariant(
728 - deadline || (priorityLevel < HighPriority),
728 + deadline !== null || (priorityLevel < HighPriority),
729 'Cannot perform deferred work without a deadline. This error is ' +
730 'likely caused by a bug in React. Please file an issue.'
731 );
732
733 // Before starting any work, check to see if there are any pending
734 // commits from the previous frame.
735 - if (pendingCommit && !deadlineHasExpired) {
735 + if (pendingCommit !== null && !deadlineHasExpired) {
736 commitAllWork(pendingCommit);
737 }
738
@@ -746,7 +746,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
746 } catch (error) {
747 // We caught an error during either the begin or complete phases.
748 const failedWork = nextUnitOfWork;
749 - if (failedWork) {
749 + if (failedWork !== null) {
750 // Reset the priority context to its value before reconcilation.
751 priorityContext = priorityContextBeforeReconciliation;
752
@@ -754,7 +754,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
754 // error boundary, the nearest host container acts as one. If
755 // captureError returns null, the error was intentionally ignored.
756 const maybeBoundary = captureError(failedWork, error);
757 - if (maybeBoundary) {
757 + if (maybeBoundary !== null) {
758 const boundary = maybeBoundary;
759
760 // Complete the boundary as if it rendered null. This will unmount
@@ -774,7 +774,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
774 }
775 // Continue performing work
776 continue;
777 - } else if (!fatalError) {
777 + } else if (fatalError === null) {
778 // There is no current unit of work. This is a worst-case scenario
779 // and should only be possible if there's a bug in the renderer, e.g.
780 // inside resetAfterCommit.
@@ -830,13 +830,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
830 failedBoundaries = null;
831
832 // It's safe to throw any unhandled errors.
833 - if (errorToThrow) {
833 + if (errorToThrow !== null) {
834 throw errorToThrow;
835 }
836 }
837
838 // Returns the boundary that captured the error, or null if the error is ignored
839 - function captureError(failedWork : Fiber, error : Error) : ?Fiber {
839 + function captureError(failedWork : Fiber, error : Error) : Fiber | null {
840 // It is no longer valid because we exited the user code.
841 ReactCurrentOwner.current = null;
842 if (__DEV__) {
@@ -846,12 +846,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
846 nextUnitOfWork = null;
847
848 // Search for the nearest error boundary.
849 - let boundary : ?Fiber = null;
849 + let boundary : Fiber | null = null;
850
851 // Passed to logCapturedError()
852 let errorBoundaryFound : boolean = false;
853 let willRetry : boolean = false;
854 - let errorBoundaryName : ?string = null;
854 + let errorBoundaryName : string | null = null;
855
856 // Host containers are a special case. If the failed work itself is a host
857 // container, then it acts as its own boundary. In all other cases, we
@@ -867,7 +867,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
867 }
868 } else {
869 let node = failedWork.return;
870 - while (node && !boundary) {
870 + while (node !== null && boundary === null) {
871 if (node.tag === ClassComponent) {
872 const instance = node.stateNode;
873 if (typeof instance.unstable_handleError === 'function') {
@@ -897,9 +897,9 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
897 // this boundary already captured an error during this commit.
898 // This case exists because multiple errors can be thrown during
899 // a single commit without interruption.
900 - if (commitPhaseBoundaries && (
900 + if (commitPhaseBoundaries !== null && (
901 commitPhaseBoundaries.has(node) ||
902 - (node.alternate) && commitPhaseBoundaries.has(node.alternate)
902 + (node.alternate !== null && commitPhaseBoundaries.has(node.alternate))
903 )) {
904 // If so, we should ignore this error.
905 return null;
@@ -914,10 +914,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
914 }
915 }
916
917 - if (boundary) {
917 + if (boundary !== null) {
918 // Add to the collection of failed boundaries. This lets us know that
919 // subsequent errors in this subtree should propagate to the next boundary.
920 - if (!failedBoundaries) {
920 + if (failedBoundaries === null) {
921 failedBoundaries = new Set();
922 }
923 failedBoundaries.add(boundary);
@@ -933,7 +933,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
933 // map of errors and their component stack location keyed by the boundaries
934 // that capture them. We mostly use this Map as a Set; it's a Map only to
935 // avoid adding a field to Fiber to store the error.
936 - if (!capturedErrors) {
936 + if (capturedErrors === null) {
937 capturedErrors = new Map();
938 }
939 capturedErrors.set(boundary, {
@@ -948,7 +948,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
948 // If we're in the commit phase, defer scheduling an update on the
949 // boundary until after the commit is complete
950 if (isCommitting) {
951 - if (!commitPhaseBoundaries) {
951 + if (commitPhaseBoundaries === null) {
952 commitPhaseBoundaries = new Set();
953 }
954 commitPhaseBoundaries.add(boundary);
@@ -957,7 +957,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
957 scheduleErrorRecovery(boundary);
958 }
959 return boundary;
960 - } else if (!firstUncaughtError) {
960 + } else if (firstUncaughtError === null) {
961 // If no boundary is found, we'll need to throw the error
962 firstUncaughtError = error;
963 }
@@ -968,8 +968,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
968 // TODO: capturedErrors should store the boundary instance, to avoid needing
969 // to check the alternate.
970 return Boolean(
971 - capturedErrors &&
972 - (capturedErrors.has(fiber) || (fiber.alternate && capturedErrors.has(fiber.alternate)))
971 + capturedErrors !== null &&
972 + (capturedErrors.has(fiber) || (fiber.alternate !== null && capturedErrors.has(fiber.alternate)))
973 );
974 }
975
@@ -977,18 +977,18 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
977 // TODO: failedBoundaries should store the boundary instance, to avoid
978 // needing to check the alternate.
979 return Boolean(
980 - failedBoundaries &&
981 - (failedBoundaries.has(fiber) || (fiber.alternate && failedBoundaries.has(fiber.alternate)))
980 + failedBoundaries !== null &&
981 + (failedBoundaries.has(fiber) || (fiber.alternate !== null && failedBoundaries.has(fiber.alternate)))
982 );
983 }
984
985 function commitErrorHandling(effectfulFiber : Fiber) {
986 let capturedError;
987 - if (capturedErrors) {
987 + if (capturedErrors !== null) {
988 capturedError = capturedErrors.get(effectfulFiber);
989 capturedErrors.delete(effectfulFiber);
990 - if (!capturedError) {
991 - if (effectfulFiber.alternate) {
990 + if (capturedError == null) {
991 + if (effectfulFiber.alternate !== null) {
992 effectfulFiber = effectfulFiber.alternate;
993 capturedError = capturedErrors.get(effectfulFiber);
994 capturedErrors.delete(effectfulFiber);
@@ -1002,19 +1002,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1002 'bug in React. Please file an issue.'
1003 );
1004
1005 - let error;
1006 -
1007 - // Conditional required to satisfy Flow
1008 - if (capturedError) {
1009 - error = capturedError.error;
1010 -
1011 - try {
1012 - logCapturedError(capturedError);
1013 - } catch (e) {
1014 - // Prevent cycle if logCapturedError() throws.
1015 - // A cycle may still occur if logCapturedError renders a component that throws.
1016 - console.error(e);
1017 - }
1005 + const error = capturedError.error;
1006 + try {
1007 + logCapturedError(capturedError);
1008 + } catch (e) {
1009 + // Prevent cycle if logCapturedError() throws.
1010 + // A cycle may still occur if logCapturedError renders a component that throws.
1011 + console.error(e);
1012 }
1013
1014 switch (effectfulFiber.tag) {
@@ -1025,7 +1019,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1019 instance.unstable_handleError(error);
1020 return;
1021 case HostRoot:
1028 - if (!firstUncaughtError) {
1022 + if (firstUncaughtError === null) {
1023 // If this is the host container, we treat it as a no-op error
1024 // boundary. We'll throw the first uncaught error once it's safe to
1025 // do so, at the end of the batch.
@@ -1043,7 +1037,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1037
1038 function unwindContexts(from : Fiber, to: Fiber) {
1039 let node = from;
1046 - while (node && (node !== to) && (node.alternate !== to)) {
1040 + while (node !== null && (node !== to) && (node.alternate !== to)) {
1041 switch (node.tag) {
1042 case ClassComponent:
1043 popContextProvider(node);
@@ -1091,7 +1085,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1085
1086 let node = fiber;
1087 let shouldContinue = true;
1094 - while (node && shouldContinue) {
1088 + while (node !== null && shouldContinue) {
1089 // Walk the parent path to the root and update each node's priority. Once
1090 // we reach a node whose priority matches (and whose alternate's priority
1091 // matches) we can exit safely knowing that the rest of the path is correct.
@@ -1102,7 +1096,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1096 shouldContinue = true;
1097 node.pendingWorkPriority = priorityLevel;
1098 }
1105 - if (node.alternate) {
1099 + if (node.alternate !== null) {
1100 if (node.alternate.pendingWorkPriority === NoWork ||
1101 node.alternate.pendingWorkPriority > priorityLevel) {
1102 // Priority did not match. Update and keep going.
@@ -1110,7 +1104,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1104 node.alternate.pendingWorkPriority = priorityLevel;
1105 }
1106 }
1113 - if (!node.return) {
1107 + if (node.return === null) {
1108 if (node.tag === HostRoot) {
1109 const root : FiberRoot = (node.stateNode : any);
1110 scheduleRoot(root, priorityLevel);
@@ -1118,7 +1112,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1112 // schedule a callback to perform work later.
1113 switch (priorityLevel) {
1114 case SynchronousPriority:
1121 - performWork(SynchronousPriority);
1115 + performWork(SynchronousPriority, null);
1116 return;
1117 case TaskPriority:
1118 // TODO: If we're not already performing work, schedule a
@@ -1175,7 +1169,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1169 // If we're not already inside a batch, we need to flush any task work
1170 // that was created by the user-provided function.
1171 if (!isPerformingWork && !isBatchingUpdates) {
1178 - performWork(TaskPriority);
1172 + performWork(TaskPriority, null);
1173 }
1174 }
1175 }