function findHostInstanceWithWarning( component: Object, methodName: string, ): PublicInstance | null { if (__DEV__) { const fiber = getInstance(component); if (fiber === undefined) { if (typeof component.render === 'function') { invariant(false, 'Unable to find node on an unmounted component.'); } else { invariant( false, 'Argument appears to not be a ReactComponent. Keys: %s', Object.keys(component), ); } } const hostFiber = findCurrentHostFiber(fiber); if (hostFiber === null) { return null; } if (hostFiber.mode & StrictMode) { const componentName = getComponentName(fiber.type) || 'Component'; if (!didWarnAboutFindNodeInStrictMode[componentName]) { didWarnAboutFindNodeInStrictMode[componentName] = true; if (fiber.mode & StrictMode) { warningWithoutStack( false, '%s is deprecated in StrictMode. ' + '%s was passed an instance of %s which is inside StrictMode. ' + 'Instead, add a ref directly to the element you want to reference.' + '\n%s' + '\n\nLearn more about using refs safely here:' + '\nhttps://fb.me/react-strict-mode-find-node', methodName, methodName, componentName, getStackByFiberInDevAndProd(hostFiber), ); } else { warningWithoutStack( false, '%s is deprecated in StrictMode. ' + '%s was passed an instance of %s which renders StrictMode children. ' + 'Instead, add a ref directly to the element you want to reference.' + '\n%s' + '\n\nLearn more about using refs safely here:' + '\nhttps://fb.me/react-strict-mode-find-node', methodName, methodName, componentName, getStackByFiberInDevAndProd(hostFiber), ); } } } return hostFiber.stateNode; } return findHostInstance(component); }
function assertValidProps(tag: string, props: ?Object) { if (!props) { return; } // Note the use of `==` which checks for null or undefined. if (voidElementTags[tag]) { invariant( (props.children == null || (enableEventAPI && props.children.type && props.children.type.$$typeof === REACT_EVENT_TARGET_TYPE)) && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must neither have `children` nor ' + 'use `dangerouslySetInnerHTML`.%s', tag, __DEV__ ? ReactDebugCurrentFrame.getStackAddendum() : '', ); } if (props.dangerouslySetInnerHTML != null) { invariant( props.children == null, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.', ); invariant( typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.', ); } if (__DEV__) { warning( props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.', ); } invariant( props.style == null || typeof props.style === 'object', 'The `style` prop expects a mapping from style properties to values, ' + "not a string. For example, style={{marginRight: spacing + 'em'}} when " + 'using JSX.%s', __DEV__ ? ReactDebugCurrentFrame.getStackAddendum() : '', ); }
return function(domNode, eventData) { invariant( !React.isValidElement(domNode), 'TestUtils.Simulate expected a DOM node as the first argument but received ' + 'a React element. Pass the DOM node you wish to simulate the event on instead. ' + 'Note that TestUtils.Simulate will not work if you are using shallow rendering.', ); invariant( !ReactTestUtils.isCompositeComponent(domNode), 'TestUtils.Simulate expected a DOM node as the first argument but received ' + 'a component instance. Pass the DOM node you wish to simulate the event on instead.', ); const dispatchConfig = EventPluginRegistry.eventNameDispatchConfigs[eventType]; const fakeNativeEvent = new Event(); fakeNativeEvent.target = domNode; fakeNativeEvent.type = eventType.toLowerCase(); // We don't use SyntheticEvent.getPooled in order to not have to worry about // properly destroying any properties assigned from `eventData` upon release const targetInst = ReactDOMComponentTree.getInstanceFromNode(domNode); const event = new SyntheticEvent( dispatchConfig, targetInst, fakeNativeEvent, domNode, ); // Since we aren't using pooling, always persist the event. This will make // sure it's marked and won't warn when setting additional properties. event.persist(); Object.assign(event, eventData); if (dispatchConfig.phasedRegistrationNames) { EventPropagators.accumulateTwoPhaseDispatches(event); } else { EventPropagators.accumulateDirectDispatches(event); } ReactDOM.unstable_batchedUpdates(function() { // Normally extractEvent enqueues a state restore, but we'll just always // do that since we we're by-passing it here. ReactControlledComponent.enqueueStateRestore(domNode); EventPluginHub.runEventsInBatch(event, true); }); ReactControlledComponent.restoreStateIfNeeded(); };
manageChildren: jest.fn(function manageChildren( parentTag, moveFromIndices = [], moveToIndices = [], addChildReactTags = [], addAtIndices = [], removeAtIndices = [], ) { autoCreateRoot(parentTag); // This logic ported from iOS (RCTUIManager.m) invariant( moveFromIndices.length === moveToIndices.length, 'Mismatched move indices %s and %s', moveFromIndices, moveToIndices, ); invariant( addChildReactTags.length === addAtIndices.length, 'Mismatched add indices %s and %s', addChildReactTags, addAtIndices, ); const parentInfo = views.get(parentTag); const permanentlyRemovedChildren = removeAtIndices.map( index => parentInfo.children[index], ); const temporarilyRemovedChildren = moveFromIndices.map( index => parentInfo.children[index], ); permanentlyRemovedChildren.forEach(tag => removeChild(parentTag, tag)); temporarilyRemovedChildren.forEach(tag => removeChild(parentTag, tag)); permanentlyRemovedChildren.forEach(tag => { views.delete(tag); }); // List of [index, tag] const indicesToInsert = []; temporarilyRemovedChildren.forEach((tag, i) => { indicesToInsert.push([moveToIndices[i], temporarilyRemovedChildren[i]]); }); addChildReactTags.forEach((tag, i) => { indicesToInsert.push([addAtIndices[i], addChildReactTags[i]]); }); indicesToInsert.sort((a, b) => a[0] - b[0]); // eslint-disable-next-line no-for-of-loops/no-for-of-loops for (const [i, tag] of indicesToInsert) { insertSubviewAtIndex(parentTag, tag, i); } }),
function resolveCurrentlyRenderingFiber(): Fiber { invariant( currentlyRenderingFiber !== null, 'Hooks can only be called inside the body of a function component.', ); return currentlyRenderingFiber; }
export function getListener(inst: Fiber, registrationName: string) { let listener; // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not // live here; needs to be moved to a better place soon const stateNode = inst.stateNode; if (!stateNode) { // Work in progress (ex: onload events in incremental mode). return null; } const props = getFiberCurrentPropsFromNode(stateNode); if (!props) { // Work in progress. return null; } listener = props[registrationName]; if (shouldPreventMouseEvent(registrationName, inst.type, props)) { return null; } invariant( !listener || typeof listener === 'function', 'Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener, ); return listener; }
/** * Returns the first child in a collection of children and verifies that there is only one child in the collection. * 返回集合中第一个子元素,并验证集合中只有一个子元素。 * * See https://reactjs.org/docs/react-api.html#reactchildrenonly * * The current implementation of this function assumes that a single child gets passed without a wrapper, but the purpose of this helper function is to abstract away the particular structure of children. * 该函数的当前实现假定单个子进程没有包装器传递,但是这个helper函数的目的是抽象出特定的子结构。 * * @param {?object} children Child collection structure. * @return {ReactElement} The first and only `ReactElement` contained in the structure. */ function onlyChild(children) { invariant( isValidElement(children), 'React.Children.only expected to receive a single React element child.', ); return children; }
warnForMissingKey = (child: mixed) => { if (child === null || typeof child !== 'object') { return; } if (!child._store || child._store.validated || child.key != null) { return; } invariant( typeof child._store === 'object', 'React Component in warnForMissingKey should have a _store. ' + 'This error is likely caused by a bug in React. Please file an issue.', ); child._store.validated = true; const currentComponentErrorInfo = 'Each child in an array or iterator should have a unique ' + '"key" prop. See https://fb.me/react-warning-keys for ' + 'more information.' + getCurrentFiberStackInDev(); if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { return; } ownerHasKeyUseWarning[currentComponentErrorInfo] = true; warning( false, 'Each child in an array or iterator should have a unique ' + '"key" prop. See https://fb.me/react-warning-keys for ' + 'more information.', ); };
_validateCurrentlyRenderingComponent() { invariant( this._currentlyRenderingComponent !== null, 'Hooks can only be called inside the body of a function component. ' + '(https://fb.me/react-invalid-hook-call)', ); }
/** * Accumulates items that must not be null or undefined. * * This is used to conserve memory by avoiding array allocations. * * @return {*|array<*>} An accumulation of items. */ function accumulate<T>( current: ?(T | Array<T>), next: T | Array<T>, ): T | Array<T> { invariant( next != null, 'accumulate(...): Accumulated items must not be null or undefined.', ); if (current == null) { return next; } // Both are not empty. Warning: Never call x.concat(y) when you are not // certain that x is an Array (x could be a string with concat method). if (Array.isArray(current)) { return current.concat(next); } if (Array.isArray(next)) { return [current].concat(next); } return [current, next]; }
extractEvents: function( topLevelType: TopLevelType, targetInst: null | Object, nativeEvent: AnyNativeEvent, nativeEventTarget: Object, ): ?Object { if (targetInst == null) { // Probably a node belonging to another renderer's tree. return null; } const bubbleDispatchConfig = customBubblingEventTypes[topLevelType]; const directDispatchConfig = customDirectEventTypes[topLevelType]; invariant( bubbleDispatchConfig || directDispatchConfig, 'Unsupported top level event type "%s" dispatched', topLevelType, ); const event = SyntheticEvent.getPooled( bubbleDispatchConfig || directDispatchConfig, targetInst, nativeEvent, nativeEventTarget, ); if (bubbleDispatchConfig) { accumulateTwoPhaseDispatches(event); } else if (directDispatchConfig) { accumulateDirectDispatches(event); } else { return null; } return event; },
export function cloneChildFibers( current: Fiber | null, workInProgress: Fiber, ): void { invariant( current === null || workInProgress.child === current.child, 'Resuming work not yet implemented.', ); if (workInProgress.child === null) { return; } let currentChild = workInProgress.child; let newChild = createWorkInProgress( currentChild, currentChild.pendingProps, currentChild.expirationTime, ); workInProgress.child = newChild; newChild.return = workInProgress; while (currentChild.sibling !== null) { currentChild = currentChild.sibling; newChild = newChild.sibling = createWorkInProgress( currentChild, currentChild.pendingProps, currentChild.expirationTime, ); newChild.return = workInProgress; } newChild.sibling = null; }
function validateClassInstance(inst, methodName) { if (!inst) { // This is probably too relaxed but it's existing behavior. return; } if (ReactInstanceMap.get(inst)) { // This is a public instance indeed. return; } let received; const stringified = '' + inst; if (Array.isArray(inst)) { received = 'an array'; } else if (inst && inst.nodeType === 1 && inst.tagName) { received = 'a DOM node'; } else if (stringified === '[object Object]') { received = 'object with keys {' + Object.keys(inst).join(', ') + '}'; } else { received = stringified; } invariant( false, '%s(...): the first argument must be a React class instance. ' + 'Instead received: %s.', methodName, received, ); }
function validateResponderContext(): void { invariant( currentEventQueue && currentInstance, 'An event responder context was used outside of an event cycle. ' + 'Use context.setTimeout() to use asynchronous responder context outside of event cycle .', ); }
function commitContainer(finishedWork: Fiber) { if (!supportsPersistence) { return; } switch (finishedWork.tag) { case ClassComponent: case HostComponent: case HostText: case EventTarget: case EventComponent: { return; } case HostRoot: case HostPortal: { const portalOrRoot: { containerInfo: Container, pendingChildren: ChildSet, } = finishedWork.stateNode; const {containerInfo, pendingChildren} = portalOrRoot; replaceContainerChildren(containerInfo, pendingChildren); return; } default: { invariant( false, 'This unit of work tag should not have side-effects. This error is ' + 'likely caused by a bug in React. Please file an issue.', ); } } }
export function insertInContainerBefore(parentInstance, child, beforeChild) { invariant( child !== beforeChild, 'ReactART: Can not insert node before itself', ); child.injectBefore(beforeChild); }
export function createInstance(type, props, internalInstanceHandle) { let instance; switch (type) { case TYPES.CLIPPING_RECTANGLE: instance = Mode.ClippingRectangle(); instance._applyProps = applyClippingRectangleProps; break; case TYPES.GROUP: instance = Mode.Group(); instance._applyProps = applyGroupProps; break; case TYPES.SHAPE: instance = Mode.Shape(); instance._applyProps = applyShapeProps; break; case TYPES.TEXT: instance = Mode.Text( props.children, props.font, props.alignment, props.path, ); instance._applyProps = applyTextProps; break; } invariant(instance, 'ReactART does not support the type "%s"', type); instance._applyProps(instance, props); return instance; }
export function createTextInstance( text: string, rootContainerInstance: Container, hostContext: HostContext, internalInstanceHandle: Object, ): TextInstance { invariant( hostContext.isInAParentText, 'Text strings must be rendered within a <Text> component.', ); const tag = nextReactTag; nextReactTag += 2; const node = createNode( tag, // reactTag 'RCTRawText', // viewName rootContainerInstance, // rootTag {text: text}, // props internalInstanceHandle, // instance handle ); return { node: node, }; }
function getTagFromInstance(inst) { let tag = inst.stateNode._nativeTag; if (tag === undefined) { tag = inst.stateNode.canonical._nativeTag; } invariant(tag, 'All native instances should have a tag.'); return tag; }
function shim(...args: any) { invariant( false, 'The current renderer does not support hydration. ' + 'This error is likely caused by a bug in React. ' + 'Please file an issue.', ); }
function assertYieldsWereCleared(root) { const actualYields = root.unstable_clearYields(); invariant( actualYields.length === 0, 'Log of yielded values is not empty. ' + 'Call expect(ReactTestRenderer).unstable_toHaveYielded(...) first.', ); }
function removeChild(parent, child) { const parentInfo = views.get(parent); const childInfo = views.get(child); const index = parentInfo.children.indexOf(child); invariant(index >= 0, 'Missing view %s during removal', child); parentInfo.children.splice(index, 1); childInfo.parent = null; }
function requiredContext<Value>(c: Value | NoContextT): Value { invariant( c !== NO_CONTEXT, 'Expected host context to exist. This error is likely caused by a bug ' + 'in React. Please file an issue.', ); return (c: any); }
function resolveDispatcher() { const dispatcher = ReactCurrentDispatcher.current; invariant( dispatcher !== null, 'Hooks can only be called inside the body of a function component. ' + '(https://fb.me/react-invalid-hook-call)', ); return dispatcher; }
constructor(fiber: Fiber) { invariant( validWrapperTypes.has(fiber.tag), 'Unexpected object passed to ReactTestInstance constructor (tag: %s). ' + 'This is probably a bug in React.', fiber.tag, ); this._fiber = fiber; }
function insertSubviewAtIndex(parent, child, index) { const parentInfo = views.get(parent); const childInfo = views.get(child); invariant( childInfo.parent === null, 'Inserting view %s %s which already has parent', child, JSON.stringify(childInfo.props), ); invariant( 0 <= index && index <= parentInfo.children.length, 'Invalid index %s for children %s', index, parentInfo.children, ); parentInfo.children.splice(index, 0, child); childInfo.parent = parent; }
function callCallback(callback, context) { invariant( typeof callback === 'function', 'Invalid argument passed as callback. Expected a function. Instead ' + 'received: %s', callback, ); callback.call(context); }
export function appendInitialChild(parentInstance, child) { if (typeof child === 'string') { // Noop for string children of Text (eg <Text>{'foo'}{'bar'}</Text>) invariant(false, 'Text children should already be flattened.'); return; } child.inject(parentInstance); }
Component.prototype.setState = function(partialState, callback) { invariant( typeof partialState === 'object' || typeof partialState === 'function' || partialState == null, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.', ); this.updater.enqueueSetState(this, partialState, callback, 'setState'); };
function createHook(): Hook { if (numberOfReRenders > 0) { invariant(false, 'Rendered more hooks than during the previous render'); } return { memoizedState: null, queue: null, next: null, }; }