Merge pull request #8926 from acdlite/fiberuseinvariant

[Fiber] Replace `throw new Error` with invariant module
This commit is contained in:
Andrew Clark authored and GitHub committed 2017-02-06 14:49:14 -08:00
commit a2c49f48bf
7 files changed
+217 -103

No files matched your search

+24 -15
View File
@@ -72,6 +72,9 @@ const {
Deletion,
} = ReactTypeOfSideEffect;
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
function coerceRef(current: ?Fiber, element: ReactElement) {
let mixedRef = element.ref;
if (mixedRef != null && typeof mixedRef !== 'function') {
@@ -88,7 +91,11 @@ function coerceRef(current: ?Fiber, element: ReactElement) {
inst = (owner : any).getPublicInstance();
}
}
invariant(inst, 'Missing owner for string ref %s', mixedRef);
invariant(
inst, 'Missing owner for string ref %s. (%s)',
mixedRef,
internalErrorMessage
);
const stringRef = String(mixedRef);
// Check if previous string ref matches new string ref
if (current && current.ref && current.ref._stringRef === stringRef) {
@@ -797,29 +804,31 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// but using the iterator instead.
const iteratorFn = getIteratorFn(newChildrenIterable);
if (typeof iteratorFn !== 'function') {
throw new Error('An object is not an iterable.');
}
invariant(
typeof iteratorFn === 'function',
'An object is not an iterable. (%s)',
internalErrorMessage
);
if (__DEV__) {
// First, validate keys.
// We'll get a different iterator later for the main pass.
const newChildren = iteratorFn.call(newChildrenIterable);
if (newChildren == null) {
throw new Error('An iterable object provided no iterator.');
}
let knownKeys = null;
let step = newChildren.next();
for (; !step.done; step = newChildren.next()) {
const child = step.value;
knownKeys = warnOnDuplicateKey(child, knownKeys);
if (newChildren) {
let knownKeys = null;
let step = newChildren.next();
for (; !step.done; step = newChildren.next()) {
const child = step.value;
knownKeys = warnOnDuplicateKey(child, knownKeys);
}
}
}
const newChildren = iteratorFn.call(newChildrenIterable);
if (newChildren == null) {
throw new Error('An iterable object provided no iterator.');
}
invariant(
newChildren != null,
'An iterable object provided no iterator.',
);
let resultingFirstChild : ?Fiber = null;
let previousNewFiber : ?Fiber = null;
@@ -62,14 +62,18 @@ var {
} = require('ReactTypeOfSideEffect');
var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactFiberClassComponent = require('ReactFiberClassComponent');
var warning = require('warning');
var invariant = require('invariant');
if (__DEV__) {
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
var warning = require('warning');
var warnedAboutStatelessRefs = {};
}
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
module.exports = function<T, P, I, TI, PI, C, CX, PL>(
config : HostConfig<T, P, I, TI, PI, C, CX, PL>,
hostContext : HostContext<C, CX>,
@@ -341,9 +345,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
// we don't do the bailout and we have to reuse existing props instead.
if (nextProps === null) {
nextProps = memoizedProps;
if (!nextProps) {
throw new Error('We should always have pending or current props.');
}
invariant(
nextProps !== null,
'We should always have pending or current props. (%s)',
internalErrorMessage
);
}
} else if (nextProps === null || memoizedProps === nextProps) {
if (memoizedProps.hidden &&
@@ -442,9 +448,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
}
function mountIndeterminateComponent(current, workInProgress, priorityLevel) {
if (current) {
throw new Error('An indeterminate component should never have mounted.');
}
invariant(
current === null,
'An indeterminate component should never have mounted. (%s)',
internalErrorMessage
);
var fn = workInProgress.type;
var props = workInProgress.pendingProps;
var unmaskedContext = getUnmaskedContext(workInProgress);
@@ -511,9 +519,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
// we don't do the bailout and we have to reuse existing props instead.
if (nextCoroutine === null) {
nextCoroutine = current && current.memoizedProps;
if (!nextCoroutine) {
throw new Error('We should always have pending or current props.');
}
invariant(
nextCoroutine != null,
'We should always have pending or current props. (%s)',
internalErrorMessage
);
}
} else if (nextCoroutine === null || workInProgress.memoizedProps === nextCoroutine) {
nextCoroutine = workInProgress.memoizedProps;
@@ -575,9 +585,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
// we don't do the bailout and we have to reuse existing props instead.
if (nextChildren === null) {
nextChildren = current && current.memoizedProps;
if (!nextChildren) {
throw new Error('We should always have pending or current props.');
}
invariant(
nextChildren != null,
'We should always have pending or current props. (%s)',
internalErrorMessage
);
}
} else if (nextChildren === null || workInProgress.memoizedProps === nextChildren) {
return bailoutOnAlreadyFinishedWork(current, workInProgress);
@@ -727,15 +739,21 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
case Fragment:
return updateFragment(current, workInProgress);
default:
throw new Error('Unknown unit of work tag');
invariant(
false,
'Unknown unit of work tag. (%s)',
internalErrorMessage
);
}
}
function beginFailedWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) {
if (workInProgress.tag !== ClassComponent &&
workInProgress.tag !== HostRoot) {
throw new Error('Invalid type of work');
}
invariant(
workInProgress.tag === ClassComponent ||
workInProgress.tag === HostRoot,
'Invalid type of work. (%s)',
internalErrorMessage
);
// Add an error effect so we can handle the error during the commit phase
workInProgress.effectTag |= Err;
@@ -40,6 +40,9 @@ var invariant = require('invariant');
const isArray = Array.isArray;
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
module.exports = function(
scheduleUpdate : (fiber : Fiber, priorityLevel : PriorityLevel) => void,
getPriorityContext : () => PriorityLevel,
@@ -257,9 +260,11 @@ module.exports = function(
const state = instance.state || null;
let props = workInProgress.pendingProps;
if (!props) {
throw new Error('There must be pending props for an initial mount.');
}
invariant(
props,
'There must be pending props for an initial mount. (%s)',
internalErrorMessage
);
const unmaskedContext = getUnmaskedContext(workInProgress);
@@ -298,9 +303,11 @@ module.exports = function(
// If there isn't any new props, then we'll reuse the memoized props.
// This could be from already completed work.
newProps = workInProgress.memoizedProps;
if (!newProps) {
throw new Error('There should always be pending or memoized props.');
}
invariant(
newProps != null,
'There should always be pending or memoized props. (%s)',
internalErrorMessage
);
}
const newUnmaskedContext = getUnmaskedContext(workInProgress);
const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
@@ -363,9 +370,11 @@ module.exports = function(
// If there aren't any new props, then we'll reuse the memoized props.
// This could be from already completed work.
newProps = oldProps;
if (!newProps) {
throw new Error('There should always be pending or memoized props.');
}
invariant(
newProps != null,
'There should always be pending or memoized props. (%s)',
internalErrorMessage
);
}
const oldContext = instance.context;
const newUnmaskedContext = getUnmaskedContext(workInProgress);
@@ -34,6 +34,11 @@ var {
ContentReset,
} = require('ReactTypeOfSideEffect');
var invariant = require('invariant');
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
module.exports = function<T, P, I, TI, PI, C, CX, PL>(
config : HostConfig<T, P, I, TI, PI, C, CX, PL>,
captureError : (failedFiber : Fiber, error: Error) => ?Fiber
@@ -94,7 +99,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
}
parent = parent.return;
}
throw new Error('Expected to find a host parent.');
invariant(
false,
'Expected to find a host parent. (%s)',
internalErrorMessage
);
}
function getHostParentFiber(fiber : Fiber) : Fiber {
@@ -105,7 +114,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
}
parent = parent.return;
}
throw new Error('Expected to find a host parent.');
invariant(
false,
'Expected to find a host parent. (%s)',
internalErrorMessage
);
}
function isHostParent(fiber : Fiber) : boolean {
@@ -173,7 +186,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
parent = parentFiber.stateNode.containerInfo;
break;
default:
throw new Error('Invalid host parent fiber.');
invariant(
false,
'Invalid host parent fiber. (%s)',
internalErrorMessage
);
}
if (parentFiber.effectTag & ContentReset) {
// Reset the text content of the parent before doing any insertions
@@ -374,9 +391,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
return;
}
case HostText: {
if (finishedWork.stateNode == null || !current) {
throw new Error('This should only be done during updates.');
}
invariant(
finishedWork.stateNode !== null && current != null,
'This should only be done during updates. (%s)',
internalErrorMessage
);
const textInstance : TI = finishedWork.stateNode;
const newText : string = finishedWork.memoizedProps;
const oldText : string = current.memoizedProps;
@@ -389,8 +408,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
case HostPortal: {
return;
}
default:
throw new Error('This unit of work tag should not have side-effects.');
default: {
invariant(
false,
'This unit of work tag should not have side-effects. (%s)',
internalErrorMessage
);
}
}
}
@@ -450,8 +474,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
// We have no life-cycles associated with portals.
return;
}
default:
throw new Error('This unit of work tag should not have side-effects.');
default: {
invariant(
false,
'This unit of work tag should not have side-effects. (%s)',
internalErrorMessage
);
}
}
}
@@ -46,6 +46,11 @@ if (__DEV__) {
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
}
var invariant = require('invariant');
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
module.exports = function<T, P, I, TI, PI, C, CX, PL>(
config : HostConfig<T, P, I, TI, PI, C, CX, PL>,
hostContext : HostContext<C, CX>,
@@ -91,7 +96,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
while (node) {
if (node.tag === HostComponent || node.tag === HostText ||
node.tag === HostPortal) {
throw new Error('A coroutine cannot have host component children.');
invariant(
false,
'A coroutine cannot have host component children.'
);
} else if (node.tag === YieldComponent) {
yields.push(node.type);
} else if (node.child) {
@@ -112,9 +120,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
function moveCoroutineToHandlerPhase(current : ?Fiber, workInProgress : Fiber) {
var coroutine = (workInProgress.memoizedProps : ?ReactCoroutine);
if (!coroutine) {
throw new Error('Should be resolved by now');
}
invariant(
coroutine,
'Should be resolved by now. (%s)',
internalErrorMessage
);
// First step of the coroutine has completed. Now we need to do the second.
// TODO: It would be nice to have a multi stage coroutine represented by a
@@ -229,12 +239,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
}
} else {
if (!newProps) {
if (workInProgress.stateNode === null) {
throw new Error('We must have new props for new mounts.');
} else {
// This can happen when we abort work.
return null;
}
invariant(
workInProgress.stateNode !== null,
'We must have new props for new mounts. (%s)',
internalErrorMessage
);
// This can happen when we abort work.
return null;
}
const currentHostContext = getHostContext();
@@ -278,12 +289,13 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
}
} else {
if (typeof newText !== 'string') {
if (workInProgress.stateNode === null) {
throw new Error('We must have new props for new mounts.');
} else {
// This can happen when we abort work.
return null;
}
invariant(
workInProgress.stateNode !== null,
'We must have new props for new mounts. (%s)',
internalErrorMessage
);
// This can happen when we abort work.
return null;
}
const rootContainerInstance = getRootHostContainer();
const currentHostContext = getHostContext();
@@ -311,9 +323,18 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
// Error cases
case IndeterminateComponent:
throw new Error('An indeterminate component should have become determinate before completing.');
invariant(
false,
'An indeterminate component should have become determinate before completing. (%s)',
internalErrorMessage
);
// eslint-disable-next-line no-fallthrough
default:
throw new Error('Unknown unit of work tag');
invariant(
false,
'Unknown unit of work tag. (%s)',
internalErrorMessage
);
}
}
@@ -24,6 +24,8 @@ const {
push,
} = require('ReactFiberStack');
const invariant = require('invariant');
export type HostContext<C, CX> = {
getHostContext() : CX,
getRootHostContainer() : C,
@@ -34,6 +36,9 @@ export type HostContext<C, CX> = {
resetHostContainer() : void,
};
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
module.exports = function<T, P, I, TI, PI, C, CX, PL>(
config : HostConfig<T, P, I, TI, PI, C, CX, PL>
) : HostContext<C, CX> {
@@ -48,9 +53,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
function getRootHostContainer() : C {
const rootInstance = rootInstanceStackCursor.current;
if (rootInstance == null) {
throw new Error('Expected root container to exist.');
}
invariant(
rootInstance != null,
'Expected root container to exist. (%s)',
internalErrorMessage
);
return rootInstance;
}
@@ -75,17 +82,21 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
function getHostContext() : CX {
const context = contextStackCursor.current;
if (context == null) {
throw new Error('Expected host context to exist.');
}
invariant(
context != null,
'Expected host context to exist. (%s)',
internalErrorMessage
);
return context;
}
function pushHostContext(fiber : Fiber) : void {
const rootInstance = rootInstanceStackCursor.current;
if (rootInstance == null) {
throw new Error('Expected root host context to exist.');
}
invariant(
rootInstance != null,
'Expected root host context to exist. (%s)',
internalErrorMessage
);
const context = contextStackCursor.current || emptyObject;
const nextContext = getChildHostContext(context, fiber.type, rootInstance);
@@ -83,6 +83,8 @@ var {
resetContext,
} = require('ReactFiberContext');
var invariant = require('invariant');
if (__DEV__) {
var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
@@ -90,6 +92,9 @@ if (__DEV__) {
var timeHeuristicForUnitOfWork = 1;
const internalErrorMessage =
'This error is likely caused by a bug in React. Please file an issue.';
module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P, I, TI, PI, C, CX, PL>) {
const hostContext = ReactFiberHostContext(config);
const { popHostContainer, popHostContext, resetHostContainer } = hostContext;
@@ -340,12 +345,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
pendingCommit = null;
const root : FiberRoot = (finishedWork.stateNode : any);
if (root.current === finishedWork) {
throw new Error(
'Cannot commit the same tree as before. This is probably a bug ' +
'related to the return field.'
);
}
invariant(
root.current !== finishedWork,
'Cannot commit the same tree as before. This is probably a bug ' +
'related to the return field. (%s)',
internalErrorMessage
);
// Updates that occur during the commit phase should have Task priority
const previousPriorityContext = priorityContext;
@@ -378,9 +383,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
try {
commitAllHostEffects(finishedWork);
} catch (error) {
if (!nextEffect) {
throw new Error('Should have nextEffect.');
}
invariant(
nextEffect != null,
'Should have next effect. (%s)',
internalErrorMessage
);
captureError(nextEffect, error);
// Clean-up
if (nextEffect) {
@@ -406,9 +413,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
try {
commitAllLifeCycles(finishedWork, nextEffect);
} catch (error) {
if (!nextEffect) {
throw new Error('Should have nextEffect.');
}
invariant(
nextEffect != null,
'Should have next effect. (%s)',
internalErrorMessage
);
captureError(nextEffect, error);
if (nextEffect) {
nextEffect = nextEffect.nextEffect;
@@ -705,9 +714,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
}
function performWork(priorityLevel : PriorityLevel, deadline : Deadline | null) {
if (isPerformingWork) {
throw new Error('performWork was called recursively.');
}
invariant(
!isPerformingWork,
'performWork was called recursively. (%s)',
internalErrorMessage
);
isPerformingWork = true;
const isPerformingDeferredWork = Boolean(deadline);
let deadlineHasExpired = false;
@@ -716,11 +727,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
// catching an error. It also lets us flush Task work at the end of a
// deferred batch.
while (priorityLevel !== NoWork && !fatalError) {
if (priorityLevel >= HighPriority && !deadline) {
throw new Error(
'Cannot perform deferred work without a deadline.'
);
}
invariant(
deadline || (priorityLevel < HighPriority),
'Cannot perform deferred work without a deadline. (%s)',
internalErrorMessage
);
// Before starting any work, check to see if there are any pending
// commits from the previous frame.
@@ -988,9 +999,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
}
}
if (!capturedError) {
throw new Error('No error for given unit of work.');
}
invariant(
capturedError != null,
'No error for given unit of work. (%s)',
internalErrorMessage
);
let error;
@@ -1023,7 +1036,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
}
return;
default:
throw new Error('Invalid type of work.');
invariant(
false,
'Invalid type of work. (%s)',
internalErrorMessage
);
}
}