diff --git a/src/renderers/shared/fiber/ReactChildFiber.js b/src/renderers/shared/fiber/ReactChildFiber.js index bc0139c88fc..68d4f7b39cf 100644 --- a/src/renderers/shared/fiber/ReactChildFiber.js +++ b/src/renderers/shared/fiber/ReactChildFiber.js @@ -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; diff --git a/src/renderers/shared/fiber/ReactFiberBeginWork.js b/src/renderers/shared/fiber/ReactFiberBeginWork.js index 8aac659a41e..38eb56ca0b5 100644 --- a/src/renderers/shared/fiber/ReactFiberBeginWork.js +++ b/src/renderers/shared/fiber/ReactFiberBeginWork.js @@ -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( config : HostConfig, hostContext : HostContext, @@ -341,9 +345,11 @@ module.exports = function( // 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( } 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( // 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( // 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( 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; diff --git a/src/renderers/shared/fiber/ReactFiberClassComponent.js b/src/renderers/shared/fiber/ReactFiberClassComponent.js index 609662d471b..d4f7d1f5391 100644 --- a/src/renderers/shared/fiber/ReactFiberClassComponent.js +++ b/src/renderers/shared/fiber/ReactFiberClassComponent.js @@ -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); diff --git a/src/renderers/shared/fiber/ReactFiberCommitWork.js b/src/renderers/shared/fiber/ReactFiberCommitWork.js index 04d24c44f54..dd72e78d241 100644 --- a/src/renderers/shared/fiber/ReactFiberCommitWork.js +++ b/src/renderers/shared/fiber/ReactFiberCommitWork.js @@ -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( config : HostConfig, captureError : (failedFiber : Fiber, error: Error) => ?Fiber @@ -94,7 +99,11 @@ module.exports = function( } 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( } 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( 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( 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( 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( // 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 + ); + } } } diff --git a/src/renderers/shared/fiber/ReactFiberCompleteWork.js b/src/renderers/shared/fiber/ReactFiberCompleteWork.js index 8b4b89af23b..a3e8fa397ba 100644 --- a/src/renderers/shared/fiber/ReactFiberCompleteWork.js +++ b/src/renderers/shared/fiber/ReactFiberCompleteWork.js @@ -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( config : HostConfig, hostContext : HostContext, @@ -91,7 +96,10 @@ module.exports = function( 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( 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( } } 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( } } 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( // 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 + ); } } diff --git a/src/renderers/shared/fiber/ReactFiberHostContext.js b/src/renderers/shared/fiber/ReactFiberHostContext.js index 1d29b709b6f..69c4bb24bde 100644 --- a/src/renderers/shared/fiber/ReactFiberHostContext.js +++ b/src/renderers/shared/fiber/ReactFiberHostContext.js @@ -24,6 +24,8 @@ const { push, } = require('ReactFiberStack'); +const invariant = require('invariant'); + export type HostContext = { getHostContext() : CX, getRootHostContainer() : C, @@ -34,6 +36,9 @@ export type HostContext = { resetHostContainer() : void, }; +const internalErrorMessage = + 'This error is likely caused by a bug in React. Please file an issue.'; + module.exports = function( config : HostConfig ) : HostContext { @@ -48,9 +53,11 @@ module.exports = function( 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( 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); diff --git a/src/renderers/shared/fiber/ReactFiberScheduler.js b/src/renderers/shared/fiber/ReactFiberScheduler.js index cafe85ff7e7..41dd8d6152d 100644 --- a/src/renderers/shared/fiber/ReactFiberScheduler.js +++ b/src/renderers/shared/fiber/ReactFiberScheduler.js @@ -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(config : HostConfig) { const hostContext = ReactFiberHostContext(config); const { popHostContainer, popHostContext, resetHostContainer } = hostContext; @@ -340,12 +345,12 @@ module.exports = function(config : HostConfig(config : HostConfig(config : HostConfig(config : HostConfig(config : HostConfig= 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(config : HostConfig(config : HostConfig