Replace `throw new Error` with invariant module
Andrew Clark committed
Feb 3, 2017 at 13:32 UTC
a1ef4c43913c2febcb0eef5d6070b666e81aa233
7 files changed
+154
-97
src/renderers/shared/fiber/ReactChildFiber.js
+12
-9
@@ -797,17 +797,19 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
797
// but using the iterator instead.
798
799
const iteratorFn = getIteratorFn(newChildrenIterable);
800
- if (typeof iteratorFn !== 'function') {
801
- throw new Error('An object is not an iterable.');
802
- }
800
+ invariant(
801
+ typeof iteratorFn === 'function',
802
+ 'An object is not an iterable.'
803
+ );
804
805
if (__DEV__) {
806
// First, validate keys.
807
// We'll get a different iterator later for the main pass.
808
const newChildren = iteratorFn.call(newChildrenIterable);
808
- if (newChildren == null) {
809
- throw new Error('An iterable object provided no iterator.');
810
- }
809
+ invariant(
810
+ newChildren != null,
811
+ 'An iterable object provided no iterator.'
812
+ );
813
let knownKeys = null;
814
let step = newChildren.next();
815
for (; !step.done; step = newChildren.next()) {
@@ -817,9 +819,10 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
819
}
820
821
const newChildren = iteratorFn.call(newChildrenIterable);
820
- if (newChildren == null) {
821
- throw new Error('An iterable object provided no iterator.');
822
- }
822
+ invariant(
823
+ newChildren != null,
824
+ 'An iterable object provided no iterator.'
825
+ );
826
827
let resultingFirstChild : ?Fiber = null;
828
let previousNewFiber : ?Fiber = null;
src/renderers/shared/fiber/ReactFiberBeginWork.js
+24
-18
@@ -62,10 +62,11 @@ var {
62
} = require('ReactTypeOfSideEffect');
63
var ReactCurrentOwner = require('ReactCurrentOwner');
64
var ReactFiberClassComponent = require('ReactFiberClassComponent');
65
-var warning = require('warning');
65
+var invariant = require('invariant');
66
67
if (__DEV__) {
68
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
69
+ var warning = require('warning');
70
71
var warnedAboutStatelessRefs = {};
72
}
@@ -341,9 +342,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
342
// we don't do the bailout and we have to reuse existing props instead.
343
if (nextProps === null) {
344
nextProps = memoizedProps;
344
- if (!nextProps) {
345
- throw new Error('We should always have pending or current props.');
346
- }
345
+ invariant(
346
+ nextProps !== null,
347
+ 'We should always have pending or current props.'
348
+ );
349
}
350
} else if (nextProps === null || memoizedProps === nextProps) {
351
if (memoizedProps.hidden &&
@@ -442,9 +444,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
444
}
445
446
function mountIndeterminateComponent(current, workInProgress, priorityLevel) {
445
- if (current) {
446
- throw new Error('An indeterminate component should never have mounted.');
447
- }
447
+ invariant(
448
+ current === null,
449
+ 'An indeterminate component should never have mounted'
450
+ );
451
var fn = workInProgress.type;
452
var props = workInProgress.pendingProps;
453
var unmaskedContext = getUnmaskedContext(workInProgress);
@@ -511,9 +514,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
514
// we don't do the bailout and we have to reuse existing props instead.
515
if (nextCoroutine === null) {
516
nextCoroutine = current && current.memoizedProps;
514
- if (!nextCoroutine) {
515
- throw new Error('We should always have pending or current props.');
516
- }
517
+ invariant(
518
+ nextCoroutine != null,
519
+ 'We should always have pending or current props.'
520
+ );
521
}
522
} else if (nextCoroutine === null || workInProgress.memoizedProps === nextCoroutine) {
523
nextCoroutine = workInProgress.memoizedProps;
@@ -575,9 +579,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
579
// we don't do the bailout and we have to reuse existing props instead.
580
if (nextChildren === null) {
581
nextChildren = current && current.memoizedProps;
578
- if (!nextChildren) {
579
- throw new Error('We should always have pending or current props.');
580
- }
582
+ invariant(
583
+ nextChildren != null,
584
+ 'We should always have pending or current props.'
585
+ );
586
}
587
} else if (nextChildren === null || workInProgress.memoizedProps === nextChildren) {
588
return bailoutOnAlreadyFinishedWork(current, workInProgress);
@@ -727,15 +732,16 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
732
case Fragment:
733
return updateFragment(current, workInProgress);
734
default:
730
- throw new Error('Unknown unit of work tag');
735
+ invariant(false, 'Unknown unit of work tag');
736
}
737
}
738
739
function beginFailedWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) {
735
- if (workInProgress.tag !== ClassComponent &&
736
- workInProgress.tag !== HostRoot) {
737
- throw new Error('Invalid type of work');
738
- }
740
+ invariant(
741
+ workInProgress.tag === ClassComponent ||
742
+ workInProgress.tag === HostRoot,
743
+ 'Invalid type of work'
744
+ );
745
746
// Add an error effect so we can handle the error during the commit phase
747
workInProgress.effectTag |= Err;
src/renderers/shared/fiber/ReactFiberClassComponent.js
+12
-9
@@ -257,9 +257,10 @@ module.exports = function(
257
const state = instance.state || null;
258
259
let props = workInProgress.pendingProps;
260
- if (!props) {
261
- throw new Error('There must be pending props for an initial mount.');
262
- }
260
+ invariant(
261
+ props,
262
+ 'There must be pending props for an initial mount.'
263
+ );
264
265
const unmaskedContext = getUnmaskedContext(workInProgress);
266
@@ -298,9 +299,10 @@ module.exports = function(
299
// If there isn't any new props, then we'll reuse the memoized props.
300
// This could be from already completed work.
301
newProps = workInProgress.memoizedProps;
301
- if (!newProps) {
302
- throw new Error('There should always be pending or memoized props.');
303
- }
302
+ invariant(
303
+ newProps != null,
304
+ 'There should always be pending or memoized props.'
305
+ );
306
}
307
const newUnmaskedContext = getUnmaskedContext(workInProgress);
308
const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
@@ -363,9 +365,10 @@ module.exports = function(
365
// If there aren't any new props, then we'll reuse the memoized props.
366
// This could be from already completed work.
367
newProps = oldProps;
366
- if (!newProps) {
367
- throw new Error('There should always be pending or memoized props.');
368
- }
368
+ invariant(
369
+ newProps != null,
370
+ 'There should always be pending or memoized props.'
371
+ );
372
}
373
const oldContext = instance.context;
374
const newUnmaskedContext = getUnmaskedContext(workInProgress);
src/renderers/shared/fiber/ReactFiberCommitWork.js
+30
-10
@@ -34,6 +34,8 @@ var {
34
ContentReset,
35
} = require('ReactTypeOfSideEffect');
36
37
+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
@@ -94,7 +96,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
96
}
97
parent = parent.return;
98
}
97
- throw new Error('Expected to find a host parent.');
99
+ invariant(
100
+ false,
101
+ 'Expected to find a host parent.'
102
+ );
103
}
104
105
function getHostParentFiber(fiber : Fiber) : Fiber {
@@ -105,7 +110,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
110
}
111
parent = parent.return;
112
}
108
- throw new Error('Expected to find a host parent.');
113
+ invariant(
114
+ false,
115
+ 'Expected to find a host parent.'
116
+ );
117
}
118
119
function isHostParent(fiber : Fiber) : boolean {
@@ -173,7 +181,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
181
parent = parentFiber.stateNode.containerInfo;
182
break;
183
default:
176
- throw new Error('Invalid host parent fiber.');
184
+ invariant(
185
+ false,
186
+ 'Invalid host parent fiber.'
187
+ );
188
}
189
if (parentFiber.effectTag & ContentReset) {
190
// Reset the text content of the parent before doing any insertions
@@ -374,9 +385,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
385
return;
386
}
387
case HostText: {
377
- if (finishedWork.stateNode == null || !current) {
378
- throw new Error('This should only be done during updates.');
379
- }
388
+ invariant(
389
+ finishedWork.stateNode !== null && current != null,
390
+ 'This should only be done during updates.'
391
+ );
392
const textInstance : TI = finishedWork.stateNode;
393
const newText : string = finishedWork.memoizedProps;
394
const oldText : string = current.memoizedProps;
@@ -389,8 +401,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
401
case HostPortal: {
402
return;
403
}
392
- default:
393
- throw new Error('This unit of work tag should not have side-effects.');
404
+ default: {
405
+ invariant(
406
+ false,
407
+ 'This unit of work tag should not have side-effects.'
408
+ );
409
+ }
410
}
411
}
412
@@ -450,8 +466,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
466
// We have no life-cycles associated with portals.
467
return;
468
}
453
- default:
454
- throw new Error('This unit of work tag should not have side-effects.');
469
+ default: {
470
+ invariant(
471
+ false,
472
+ 'This unit of work tag should not have side-effects.'
473
+ );
474
+ }
475
}
476
}
477
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+31
-18
@@ -46,6 +46,8 @@ if (__DEV__) {
46
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
47
}
48
49
+var invariant = require('invariant');
50
+
51
module.exports = function<T, P, I, TI, PI, C, CX, PL>(
52
config : HostConfig<T, P, I, TI, PI, C, CX, PL>,
53
hostContext : HostContext<C, CX>,
@@ -91,7 +93,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
93
while (node) {
94
if (node.tag === HostComponent || node.tag === HostText ||
95
node.tag === HostPortal) {
94
- throw new Error('A coroutine cannot have host component children.');
96
+ invariant(
97
+ false,
98
+ 'A coroutine cannot have host component children.'
99
+ );
100
} else if (node.tag === YieldComponent) {
101
yields.push(node.type);
102
} else if (node.child) {
@@ -112,9 +117,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
117
118
function moveCoroutineToHandlerPhase(current : ?Fiber, workInProgress : Fiber) {
119
var coroutine = (workInProgress.memoizedProps : ?ReactCoroutine);
115
- if (!coroutine) {
116
- throw new Error('Should be resolved by now');
117
- }
120
+ invariant(
121
+ coroutine,
122
+ 'Should be resolved by now'
123
+ );
124
125
// First step of the coroutine has completed. Now we need to do the second.
126
// TODO: It would be nice to have a multi stage coroutine represented by a
@@ -229,12 +235,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
235
}
236
} else {
237
if (!newProps) {
232
- if (workInProgress.stateNode === null) {
233
- throw new Error('We must have new props for new mounts.');
234
- } else {
235
- // This can happen when we abort work.
236
- return null;
237
- }
238
+ invariant(
239
+ workInProgress.stateNode !== null,
240
+ 'We must have new props for new mounts'
241
+ );
242
+ // This can happen when we abort work.
243
+ return null;
244
}
245
246
const currentHostContext = getHostContext();
@@ -278,12 +284,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
284
}
285
} else {
286
if (typeof newText !== 'string') {
281
- if (workInProgress.stateNode === null) {
282
- throw new Error('We must have new props for new mounts.');
283
- } else {
284
- // This can happen when we abort work.
285
- return null;
286
- }
287
+ invariant(
288
+ workInProgress.stateNode !== null,
289
+ 'We must have new props for new mounts'
290
+ );
291
+ // This can happen when we abort work.
292
+ return null;
293
}
294
const rootContainerInstance = getRootHostContainer();
295
const currentHostContext = getHostContext();
@@ -311,9 +317,16 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
317
318
// Error cases
319
case IndeterminateComponent:
314
- throw new Error('An indeterminate component should have become determinate before completing.');
320
+ invariant(
321
+ false,
322
+ 'An indeterminate component should have become determinate before completing.'
323
+ );
324
+ // eslint-disable-next-line no-fallthrough
325
default:
316
- throw new Error('Unknown unit of work tag');
326
+ invariant(
327
+ false,
328
+ 'Unknown unit of work tag'
329
+ );
330
}
331
}
332
src/renderers/shared/fiber/ReactFiberHostContext.js
+14
-9
@@ -24,6 +24,8 @@ const {
24
push,
25
} = require('ReactFiberStack');
26
27
+const invariant = require('invariant');
28
+
29
export type HostContext<C, CX> = {
30
getHostContext() : CX,
31
getRootHostContainer() : C,
@@ -48,9 +50,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
50
51
function getRootHostContainer() : C {
52
const rootInstance = rootInstanceStackCursor.current;
51
- if (rootInstance == null) {
52
- throw new Error('Expected root container to exist.');
53
- }
53
+ invariant(
54
+ rootInstance != null,
55
+ 'Expected root container to exist.'
56
+ );
57
return rootInstance;
58
}
59
@@ -75,17 +78,19 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
78
79
function getHostContext() : CX {
80
const context = contextStackCursor.current;
78
- if (context == null) {
79
- throw new Error('Expected host context to exist.');
80
- }
81
+ invariant(
82
+ context != null,
83
+ 'Expected host context to exist.'
84
+ );
85
return context;
86
}
87
88
function pushHostContext(fiber : Fiber) : void {
89
const rootInstance = rootInstanceStackCursor.current;
86
- if (rootInstance == null) {
87
- throw new Error('Expected root host context to exist.');
88
- }
90
+ invariant(
91
+ rootInstance != null,
92
+ 'Expected root host context to exist.'
93
+ );
94
95
const context = contextStackCursor.current || emptyObject;
96
const nextContext = getChildHostContext(context, fiber.type, rootInstance);
src/renderers/shared/fiber/ReactFiberScheduler.js
+31
-24
@@ -83,6 +83,8 @@ var {
83
resetContext,
84
} = require('ReactFiberContext');
85
86
+var invariant = require('invariant');
87
+
88
if (__DEV__) {
89
var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
90
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
@@ -340,12 +342,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
342
343
pendingCommit = null;
344
const root : FiberRoot = (finishedWork.stateNode : any);
343
- if (root.current === finishedWork) {
344
- throw new Error(
345
- 'Cannot commit the same tree as before. This is probably a bug ' +
346
- 'related to the return field.'
347
- );
348
- }
345
+ invariant(
346
+ root.current !== finishedWork,
347
+ 'Cannot commit the same tree as before. This is probably a bug ' +
348
+ 'related to the return field.'
349
+ );
350
351
// Updates that occur during the commit phase should have Task priority
352
const previousPriorityContext = priorityContext;
@@ -378,9 +379,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
379
try {
380
commitAllHostEffects(finishedWork);
381
} catch (error) {
381
- if (!nextEffect) {
382
- throw new Error('Should have nextEffect.');
383
- }
382
+ invariant(
383
+ nextEffect != null,
384
+ 'Should have next effect.'
385
+ );
386
captureError(nextEffect, error);
387
// Clean-up
388
if (nextEffect) {
@@ -406,9 +408,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
408
try {
409
commitAllLifeCycles(finishedWork, nextEffect);
410
} catch (error) {
409
- if (!nextEffect) {
410
- throw new Error('Should have nextEffect.');
411
- }
411
+ invariant(
412
+ nextEffect != null,
413
+ 'Should have next effect.'
414
+ );
415
captureError(nextEffect, error);
416
if (nextEffect) {
417
nextEffect = nextEffect.nextEffect;
@@ -705,9 +708,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
708
}
709
710
function performWork(priorityLevel : PriorityLevel, deadline : Deadline | null) {
708
- if (isPerformingWork) {
709
- throw new Error('performWork was called recursively.');
710
- }
711
+ invariant(
712
+ !isPerformingWork,
713
+ 'performWork was called recursively.'
714
+ );
715
isPerformingWork = true;
716
const isPerformingDeferredWork = Boolean(deadline);
717
let deadlineHasExpired = false;
@@ -716,11 +720,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
720
// catching an error. It also lets us flush Task work at the end of a
721
// deferred batch.
722
while (priorityLevel !== NoWork && !fatalError) {
719
- if (priorityLevel >= HighPriority && !deadline) {
720
- throw new Error(
721
- 'Cannot perform deferred work without a deadline.'
722
- );
723
- }
723
+ invariant(
724
+ deadline || (priorityLevel < HighPriority),
725
+ 'Cannot perform deferred work without a deadline.'
726
+ );
727
728
// Before starting any work, check to see if there are any pending
729
// commits from the previous frame.
@@ -988,9 +991,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
991
}
992
}
993
991
- if (!capturedError) {
992
- throw new Error('No error for given unit of work.');
993
- }
994
+ invariant(
995
+ capturedError != null,
996
+ 'No error for given unit of work.'
997
+ );
998
999
let error;
1000
@@ -1023,7 +1027,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
1027
}
1028
return;
1029
default:
1026
- throw new Error('Invalid type of work.');
1030
+ invariant(
1031
+ false,
1032
+ 'Invalid type of work.'
1033
+ );
1034
}
1035
}
1036