mirror of
https://github.com/status-im/react-native.git
synced 2025-01-28 02:04:55 +00:00
Sync React Native with React 16.0.0-alpha.3 (take 2)
Reviewed By: spicyj Differential Revision: D4623242 fbshipit-source-id: 7ddb057cb47e005dda73070f45d108af40d93c8f
This commit is contained in:
parent
6439f65fcb
commit
41f1bcc5ac
@ -77,11 +77,11 @@ class Animated {
|
|||||||
throw new Error('This node cannot be made a "native" animated node');
|
throw new Error('This node cannot be made a "native" animated node');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__getNativeTag(): number {
|
__getNativeTag(): ?number {
|
||||||
NativeAnimatedHelper.assertNativeAnimatedModule();
|
NativeAnimatedHelper.assertNativeAnimatedModule();
|
||||||
invariant(this.__isNative, 'Attempt to get native tag from node not marked as "native"');
|
invariant(this.__isNative, 'Attempt to get native tag from node not marked as "native"');
|
||||||
if (this.__nativeTag == null) {
|
if (this.__nativeTag == null) {
|
||||||
var nativeTag: number = NativeAnimatedHelper.generateNewNodeTag();
|
var nativeTag: ?number = NativeAnimatedHelper.generateNewNodeTag();
|
||||||
NativeAnimatedAPI.createAnimatedNode(nativeTag, this.__getNativeConfig());
|
NativeAnimatedAPI.createAnimatedNode(nativeTag, this.__getNativeConfig());
|
||||||
this.__nativeTag = nativeTag;
|
this.__nativeTag = nativeTag;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ type EndResult = {finished: boolean};
|
|||||||
type EndCallback = (result: EndResult) => void;
|
type EndCallback = (result: EndResult) => void;
|
||||||
type EventMapping = {
|
type EventMapping = {
|
||||||
nativeEventPath: Array<string>,
|
nativeEventPath: Array<string>,
|
||||||
animatedValueTag: number,
|
animatedValueTag: ?number,
|
||||||
};
|
};
|
||||||
|
|
||||||
let nativeEventEmitter;
|
let nativeEventEmitter;
|
||||||
@ -33,67 +33,67 @@ let nativeEventEmitter;
|
|||||||
* the native module methods
|
* the native module methods
|
||||||
*/
|
*/
|
||||||
const API = {
|
const API = {
|
||||||
createAnimatedNode: function(tag: number, config: Object): void {
|
createAnimatedNode: function(tag: ?number, config: Object): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.createAnimatedNode(tag, config);
|
NativeAnimatedModule.createAnimatedNode(tag, config);
|
||||||
},
|
},
|
||||||
startListeningToAnimatedNodeValue: function(tag: number) {
|
startListeningToAnimatedNodeValue: function(tag: ?number) {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.startListeningToAnimatedNodeValue(tag);
|
NativeAnimatedModule.startListeningToAnimatedNodeValue(tag);
|
||||||
},
|
},
|
||||||
stopListeningToAnimatedNodeValue: function(tag: number) {
|
stopListeningToAnimatedNodeValue: function(tag: ?number) {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag);
|
NativeAnimatedModule.stopListeningToAnimatedNodeValue(tag);
|
||||||
},
|
},
|
||||||
connectAnimatedNodes: function(parentTag: number, childTag: number): void {
|
connectAnimatedNodes: function(parentTag: ?number, childTag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag);
|
NativeAnimatedModule.connectAnimatedNodes(parentTag, childTag);
|
||||||
},
|
},
|
||||||
disconnectAnimatedNodes: function(parentTag: number, childTag: number): void {
|
disconnectAnimatedNodes: function(parentTag: ?number, childTag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag);
|
NativeAnimatedModule.disconnectAnimatedNodes(parentTag, childTag);
|
||||||
},
|
},
|
||||||
startAnimatingNode: function(animationId: number, nodeTag: number, config: Object, endCallback: EndCallback): void {
|
startAnimatingNode: function(animationId: ?number, nodeTag: ?number, config: Object, endCallback: EndCallback): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.startAnimatingNode(animationId, nodeTag, config, endCallback);
|
NativeAnimatedModule.startAnimatingNode(animationId, nodeTag, config, endCallback);
|
||||||
},
|
},
|
||||||
stopAnimation: function(animationId: number) {
|
stopAnimation: function(animationId: ?number) {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.stopAnimation(animationId);
|
NativeAnimatedModule.stopAnimation(animationId);
|
||||||
},
|
},
|
||||||
setAnimatedNodeValue: function(nodeTag: number, value: number): void {
|
setAnimatedNodeValue: function(nodeTag: ?number, value: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value);
|
NativeAnimatedModule.setAnimatedNodeValue(nodeTag, value);
|
||||||
},
|
},
|
||||||
setAnimatedNodeOffset: function(nodeTag: number, offset: number): void {
|
setAnimatedNodeOffset: function(nodeTag: ?number, offset: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset);
|
NativeAnimatedModule.setAnimatedNodeOffset(nodeTag, offset);
|
||||||
},
|
},
|
||||||
flattenAnimatedNodeOffset: function(nodeTag: number): void {
|
flattenAnimatedNodeOffset: function(nodeTag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag);
|
NativeAnimatedModule.flattenAnimatedNodeOffset(nodeTag);
|
||||||
},
|
},
|
||||||
extractAnimatedNodeOffset: function(nodeTag: number): void {
|
extractAnimatedNodeOffset: function(nodeTag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag);
|
NativeAnimatedModule.extractAnimatedNodeOffset(nodeTag);
|
||||||
},
|
},
|
||||||
connectAnimatedNodeToView: function(nodeTag: number, viewTag: number): void {
|
connectAnimatedNodeToView: function(nodeTag: ?number, viewTag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag);
|
NativeAnimatedModule.connectAnimatedNodeToView(nodeTag, viewTag);
|
||||||
},
|
},
|
||||||
disconnectAnimatedNodeFromView: function(nodeTag: number, viewTag: number): void {
|
disconnectAnimatedNodeFromView: function(nodeTag: ?number, viewTag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag);
|
NativeAnimatedModule.disconnectAnimatedNodeFromView(nodeTag, viewTag);
|
||||||
},
|
},
|
||||||
dropAnimatedNode: function(tag: number): void {
|
dropAnimatedNode: function(tag: ?number): void {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.dropAnimatedNode(tag);
|
NativeAnimatedModule.dropAnimatedNode(tag);
|
||||||
},
|
},
|
||||||
addAnimatedEventToView: function(viewTag: number, eventName: string, eventMapping: EventMapping) {
|
addAnimatedEventToView: function(viewTag: ?number, eventName: string, eventMapping: EventMapping) {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.addAnimatedEventToView(viewTag, eventName, eventMapping);
|
NativeAnimatedModule.addAnimatedEventToView(viewTag, eventName, eventMapping);
|
||||||
},
|
},
|
||||||
removeAnimatedEventFromView(viewTag: number, eventName: string) {
|
removeAnimatedEventFromView(viewTag: ?number, eventName: string) {
|
||||||
assertNativeAnimatedModule();
|
assertNativeAnimatedModule();
|
||||||
NativeAnimatedModule.removeAnimatedEventFromView(viewTag, eventName);
|
NativeAnimatedModule.removeAnimatedEventFromView(viewTag, eventName);
|
||||||
}
|
}
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = '16.0.0-alpha.2';
|
module.exports = '16.0.0-alpha.3';
|
||||||
|
@ -53,6 +53,7 @@ function uncacheNode(inst) {
|
|||||||
|
|
||||||
function uncacheFiberNode(tag) {
|
function uncacheFiberNode(tag) {
|
||||||
delete instanceCache[tag];
|
delete instanceCache[tag];
|
||||||
|
delete instanceProps[tag];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInstanceFromTag(tag) {
|
function getInstanceFromTag(tag) {
|
||||||
@ -61,7 +62,9 @@ function getInstanceFromTag(tag) {
|
|||||||
|
|
||||||
function getTagFromInstance(inst) {
|
function getTagFromInstance(inst) {
|
||||||
// TODO (bvaughn) Clean up once Stack is deprecated
|
// TODO (bvaughn) Clean up once Stack is deprecated
|
||||||
var tag = inst._rootNodeID || inst.stateNode._nativeTag;
|
var tag = typeof inst.tag !== 'number'
|
||||||
|
? inst._rootNodeID
|
||||||
|
: inst.stateNode._nativeTag;
|
||||||
invariant(tag, 'All native instances should have a tag.');
|
invariant(tag, 'All native instances should have a tag.');
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
@ -96,11 +96,7 @@ const NativeRenderer = ReactFiberReconciler({
|
|||||||
},
|
},
|
||||||
|
|
||||||
appendInitialChild(parentInstance : Instance, child : Instance | TextInstance) : void {
|
appendInitialChild(parentInstance : Instance, child : Instance | TextInstance) : void {
|
||||||
if (typeof child === 'number') {
|
parentInstance._children.push(child);
|
||||||
parentInstance._children.push(child);
|
|
||||||
} else {
|
|
||||||
parentInstance._children.push(child);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
commitTextUpdate(
|
commitTextUpdate(
|
||||||
|
@ -16,10 +16,10 @@ var ReactNativeGlobalResponderHandler = {
|
|||||||
onChange: function(from, to, blockNativeResponder) {
|
onChange: function(from, to, blockNativeResponder) {
|
||||||
if (to !== null) {
|
if (to !== null) {
|
||||||
// TODO (bvaughn) Clean up once Stack is deprecated
|
// TODO (bvaughn) Clean up once Stack is deprecated
|
||||||
UIManager.setJSResponder(
|
var tag = typeof to.tag !== 'number'
|
||||||
to._rootNodeID || to.stateNode._nativeTag,
|
? to._rootNodeID
|
||||||
blockNativeResponder
|
: to.stateNode._nativeTag;
|
||||||
);
|
UIManager.setJSResponder(tag, blockNativeResponder);
|
||||||
} else {
|
} else {
|
||||||
UIManager.clearJSResponder();
|
UIManager.clearJSResponder();
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ var RCTEventEmitter;
|
|||||||
var React;
|
var React;
|
||||||
var ReactErrorUtils;
|
var ReactErrorUtils;
|
||||||
var ReactNative;
|
var ReactNative;
|
||||||
|
var ResponderEventPlugin;
|
||||||
var UIManager;
|
var UIManager;
|
||||||
var createReactNativeComponentClass;
|
var createReactNativeComponentClass;
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ beforeEach(() => {
|
|||||||
React = require('React');
|
React = require('React');
|
||||||
ReactErrorUtils = require('ReactErrorUtils');
|
ReactErrorUtils = require('ReactErrorUtils');
|
||||||
ReactNative = require('ReactNative');
|
ReactNative = require('ReactNative');
|
||||||
|
ResponderEventPlugin = require('ResponderEventPlugin');
|
||||||
UIManager = require('UIManager');
|
UIManager = require('UIManager');
|
||||||
createReactNativeComponentClass = require('createReactNativeComponentClass');
|
createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||||
|
|
||||||
@ -91,3 +93,97 @@ it('handles events', () => {
|
|||||||
'outer touchend',
|
'outer touchend',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles when a responder is unmounted while a touch sequence is in progress', () => {
|
||||||
|
var EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
|
||||||
|
var View = createReactNativeComponentClass({
|
||||||
|
validAttributes: { id: true },
|
||||||
|
uiViewClassName: 'View',
|
||||||
|
});
|
||||||
|
|
||||||
|
function getViewById(id) {
|
||||||
|
return UIManager.createView.mock.calls.find(
|
||||||
|
args => args[3] && args[3].id === id
|
||||||
|
)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getResponderId() {
|
||||||
|
const responder = ResponderEventPlugin._getResponder();
|
||||||
|
if (responder === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const props = typeof responder.tag === 'number'
|
||||||
|
? responder.memoizedProps
|
||||||
|
: responder._currentElement.props;
|
||||||
|
return props ? props.id : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var log = [];
|
||||||
|
ReactNative.render(
|
||||||
|
<View id="parent">
|
||||||
|
<View key={1}>
|
||||||
|
<View
|
||||||
|
id="one"
|
||||||
|
onResponderEnd={() => log.push('one responder end')}
|
||||||
|
onResponderStart={() => log.push('one responder start')}
|
||||||
|
onStartShouldSetResponder={() => true}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View key={2}>
|
||||||
|
<View
|
||||||
|
id="two"
|
||||||
|
onResponderEnd={() => log.push('two responder end')}
|
||||||
|
onResponderStart={() => log.push('two responder start')}
|
||||||
|
onStartShouldSetResponder={() => true}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
EventEmitter.receiveTouches(
|
||||||
|
'topTouchStart',
|
||||||
|
[{target: getViewById('one'), identifier: 17}],
|
||||||
|
[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getResponderId()).toBe('one');
|
||||||
|
expect(log).toEqual(['one responder start']);
|
||||||
|
log.splice(0);
|
||||||
|
|
||||||
|
ReactNative.render(
|
||||||
|
<View id="parent">
|
||||||
|
<View key={2}>
|
||||||
|
<View
|
||||||
|
id="two"
|
||||||
|
onResponderEnd={() => log.push('two responder end')}
|
||||||
|
onResponderStart={() => log.push('two responder start')}
|
||||||
|
onStartShouldSetResponder={() => true}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO Verify the onResponderEnd listener has been called (before the unmount)
|
||||||
|
// expect(log).toEqual(['one responder end']);
|
||||||
|
// log.splice(0);
|
||||||
|
|
||||||
|
EventEmitter.receiveTouches(
|
||||||
|
'topTouchEnd',
|
||||||
|
[{target: getViewById('two'), identifier: 17}],
|
||||||
|
[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getResponderId()).toBeNull();
|
||||||
|
expect(log).toEqual([]);
|
||||||
|
|
||||||
|
EventEmitter.receiveTouches(
|
||||||
|
'topTouchStart',
|
||||||
|
[{target: getViewById('two'), identifier: 17}],
|
||||||
|
[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getResponderId()).toBe('two');
|
||||||
|
expect(log).toEqual(['two responder start']);
|
||||||
|
});
|
||||||
|
@ -27,13 +27,13 @@ type ReactNativeBaseComponentViewConfig = {
|
|||||||
* @param {string} config iOS View configuration.
|
* @param {string} config iOS View configuration.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const createReactNativeFiberComponentClass = function(
|
const createReactNativeFiberComponentClass = function(
|
||||||
viewConfig: ReactNativeBaseComponentViewConfig
|
viewConfig: ReactNativeBaseComponentViewConfig
|
||||||
): ReactClass<any> {
|
): ReactClass<any> {
|
||||||
// TODO(sema): This actually returns a string. Need to fix this before
|
// TODO(sema): This actually returns a string. Need to fix this before
|
||||||
// we deploy Fiber.
|
// we deploy Fiber.
|
||||||
return (ReactNativeViewConfigRegistry.register(viewConfig) : any);
|
return (ReactNativeViewConfigRegistry.register(viewConfig) : any);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} config iOS View configuration.
|
* @param {string} config iOS View configuration.
|
||||||
@ -59,6 +59,6 @@ const createReactNativeComponentClass = function(
|
|||||||
return ((Constructor: any): ReactClass<any>);
|
return ((Constructor: any): ReactClass<any>);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = (ReactNativeFeatureFlags.useFiber
|
module.exports = ReactNativeFeatureFlags.useFiber
|
||||||
? createReactNativeFiberComponentClass
|
? createReactNativeFiberComponentClass
|
||||||
: createReactNativeComponentClass);
|
: createReactNativeComponentClass;
|
||||||
|
@ -53,8 +53,7 @@ import type { ReactInstance } from 'ReactInstanceType';
|
|||||||
let injectedFindNode;
|
let injectedFindNode;
|
||||||
let injectedFindRootNodeID;
|
let injectedFindRootNodeID;
|
||||||
|
|
||||||
// TODO(sema): Type this more specifically.
|
function findNodeHandle(componentOrHandle: any): ?number {
|
||||||
function findNodeHandle(componentOrHandle: any): any {
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// TODO: fix this unsafe cast to work with Fiber.
|
// TODO: fix this unsafe cast to work with Fiber.
|
||||||
var owner = ((ReactCurrentOwner.current: any): ReactInstance | null);
|
var owner = ((ReactCurrentOwner.current: any): ReactInstance | null);
|
||||||
|
@ -223,8 +223,12 @@ var createFiber = function(tag : TypeOfWork, key : null | string) : Fiber {
|
|||||||
fiber._debugID = debugCounter++;
|
fiber._debugID = debugCounter++;
|
||||||
fiber._debugSource = null;
|
fiber._debugSource = null;
|
||||||
fiber._debugOwner = null;
|
fiber._debugOwner = null;
|
||||||
|
if (typeof Object.preventExtensions === 'function') {
|
||||||
|
Object.preventExtensions(fiber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return fiber;
|
return fiber;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ var invariant = require('fbjs/lib/invariant');
|
|||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
|
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
|
||||||
var warning = require('fbjs/lib/warning');
|
var warning = require('fbjs/lib/warning');
|
||||||
|
|
||||||
var warnedAboutStatelessRefs = {};
|
var warnedAboutStatelessRefs = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,6 +478,15 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
|
|||||||
// Proceed under the assumption that this is a functional component
|
// Proceed under the assumption that this is a functional component
|
||||||
workInProgress.tag = FunctionalComponent;
|
workInProgress.tag = FunctionalComponent;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
const Component = workInProgress.type;
|
||||||
|
|
||||||
|
if (Component) {
|
||||||
|
warning(
|
||||||
|
!Component.childContextTypes,
|
||||||
|
'%s(...): childContextTypes cannot be defined on a functional component.',
|
||||||
|
Component.displayName || Component.name || 'Component'
|
||||||
|
);
|
||||||
|
}
|
||||||
if (workInProgress.ref !== null) {
|
if (workInProgress.ref !== null) {
|
||||||
let info = '';
|
let info = '';
|
||||||
const ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
|
const ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
|
||||||
|
@ -291,6 +291,7 @@ module.exports = function(
|
|||||||
|
|
||||||
instance.props = props;
|
instance.props = props;
|
||||||
instance.state = state;
|
instance.state = state;
|
||||||
|
instance.refs = emptyObject;
|
||||||
instance.context = getMaskedContext(workInProgress, unmaskedContext);
|
instance.context = getMaskedContext(workInProgress, unmaskedContext);
|
||||||
|
|
||||||
if (typeof instance.componentWillMount === 'function') {
|
if (typeof instance.componentWillMount === 'function') {
|
||||||
@ -408,6 +409,19 @@ module.exports = function(
|
|||||||
if (oldProps !== newProps || oldContext !== newContext) {
|
if (oldProps !== newProps || oldContext !== newContext) {
|
||||||
if (typeof instance.componentWillReceiveProps === 'function') {
|
if (typeof instance.componentWillReceiveProps === 'function') {
|
||||||
instance.componentWillReceiveProps(newProps, newContext);
|
instance.componentWillReceiveProps(newProps, newContext);
|
||||||
|
|
||||||
|
if (instance.state !== workInProgress.memoizedState) {
|
||||||
|
if (__DEV__) {
|
||||||
|
warning(
|
||||||
|
false,
|
||||||
|
'%s.componentWillReceiveProps(): Assigning directly to ' +
|
||||||
|
'this.state is deprecated (except inside a component\'s ' +
|
||||||
|
'constructor). Use setState instead.',
|
||||||
|
getComponentName(workInProgress)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
updater.enqueueReplaceState(instance, instance.state, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ const {
|
|||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
var checkReactTypeSpec = require('checkReactTypeSpec');
|
var checkReactTypeSpec = require('checkReactTypeSpec');
|
||||||
|
var ReactDebugCurrentFrame = require('react/lib/ReactDebugCurrentFrame');
|
||||||
var warnedAboutMissingGetChildContext = {};
|
var warnedAboutMissingGetChildContext = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +92,9 @@ exports.getMaskedContext = function(workInProgress : Fiber, unmaskedContext : Ob
|
|||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
const name = getComponentName(workInProgress);
|
const name = getComponentName(workInProgress);
|
||||||
checkReactTypeSpec(contextTypes, context, 'context', name, null, workInProgress);
|
ReactDebugCurrentFrame.current = workInProgress;
|
||||||
|
checkReactTypeSpec(contextTypes, context, 'context', name);
|
||||||
|
ReactDebugCurrentFrame.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache unmasked context so we can avoid recreating masked context unless necessary.
|
// Cache unmasked context so we can avoid recreating masked context unless necessary.
|
||||||
@ -182,7 +185,9 @@ function processChildContext(fiber : Fiber, parentContext : Object, isReconcilin
|
|||||||
// assume anything about the given fiber. We won't pass it down if we aren't sure.
|
// assume anything about the given fiber. We won't pass it down if we aren't sure.
|
||||||
// TODO: remove this hack when we delete unstable_renderSubtree in Fiber.
|
// TODO: remove this hack when we delete unstable_renderSubtree in Fiber.
|
||||||
const workInProgress = isReconciling ? fiber : null;
|
const workInProgress = isReconciling ? fiber : null;
|
||||||
checkReactTypeSpec(childContextTypes, childContext, 'childContext', name, null, workInProgress);
|
ReactDebugCurrentFrame.current = workInProgress;
|
||||||
|
checkReactTypeSpec(childContextTypes, childContext, 'child context', name);
|
||||||
|
ReactDebugCurrentFrame.current = null;
|
||||||
}
|
}
|
||||||
return {...parentContext, ...childContext};
|
return {...parentContext, ...childContext};
|
||||||
}
|
}
|
||||||
|
@ -12,15 +12,13 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var warning = require('fbjs/lib/warning');
|
||||||
|
|
||||||
import type { Fiber } from 'ReactFiber';
|
import type { Fiber } from 'ReactFiber';
|
||||||
import type { FiberRoot } from 'ReactFiberRoot';
|
import type { FiberRoot } from 'ReactFiberRoot';
|
||||||
|
|
||||||
declare var __REACT_DEVTOOLS_GLOBAL_HOOK__ : Object | void;
|
declare var __REACT_DEVTOOLS_GLOBAL_HOOK__ : Object | void;
|
||||||
|
|
||||||
if (__DEV__) {
|
|
||||||
var warning = require('fbjs/lib/warning');
|
|
||||||
}
|
|
||||||
|
|
||||||
let rendererID = null;
|
let rendererID = null;
|
||||||
let injectInternals = null;
|
let injectInternals = null;
|
||||||
let onCommitRoot = null;
|
let onCommitRoot = null;
|
||||||
|
@ -21,6 +21,7 @@ export type CapturedError = {
|
|||||||
componentName : ?string,
|
componentName : ?string,
|
||||||
componentStack : string,
|
componentStack : string,
|
||||||
error : Error,
|
error : Error,
|
||||||
|
errorBoundary : ?Object,
|
||||||
errorBoundaryFound : boolean,
|
errorBoundaryFound : boolean,
|
||||||
errorBoundaryName : string | null,
|
errorBoundaryName : string | null,
|
||||||
willRetry : boolean,
|
willRetry : boolean,
|
||||||
@ -86,8 +87,21 @@ var {
|
|||||||
var invariant = require('fbjs/lib/invariant');
|
var invariant = require('fbjs/lib/invariant');
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
var warning = require('fbjs/lib/warning');
|
||||||
var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
|
var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
|
||||||
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
|
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
|
||||||
|
|
||||||
|
var warnAboutUpdateOnUnmounted = function(instance : ReactClass<any>) {
|
||||||
|
const ctor = instance.constructor;
|
||||||
|
warning(
|
||||||
|
false,
|
||||||
|
'Can only update a mounted or mounting component. This usually means ' +
|
||||||
|
'you called setState, replaceState, or forceUpdate on an unmounted ' +
|
||||||
|
'component. This is a no-op.\n\nPlease check the code for the ' +
|
||||||
|
'%s component.',
|
||||||
|
ctor && (ctor.displayName || ctor.name) || 'ReactClass'
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeHeuristicForUnitOfWork = 1;
|
var timeHeuristicForUnitOfWork = 1;
|
||||||
@ -349,6 +363,9 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
|
|||||||
'in React. Please file an issue.'
|
'in React. Please file an issue.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Reset this to null before calling lifecycles
|
||||||
|
ReactCurrentOwner.current = null;
|
||||||
|
|
||||||
// Updates that occur during the commit phase should have Task priority
|
// Updates that occur during the commit phase should have Task priority
|
||||||
const previousPriorityContext = priorityContext;
|
const previousPriorityContext = priorityContext;
|
||||||
priorityContext = TaskPriority;
|
priorityContext = TaskPriority;
|
||||||
@ -941,6 +958,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
|
|||||||
componentName,
|
componentName,
|
||||||
componentStack,
|
componentStack,
|
||||||
error,
|
error,
|
||||||
|
errorBoundary: errorBoundaryFound ? boundary.stateNode : null,
|
||||||
errorBoundaryFound,
|
errorBoundaryFound,
|
||||||
errorBoundaryName,
|
errorBoundaryName,
|
||||||
willRetry,
|
willRetry,
|
||||||
@ -1129,7 +1147,11 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: Warn about setting state on an unmounted component.
|
if (__DEV__) {
|
||||||
|
if (fiber.tag === ClassComponent) {
|
||||||
|
warnAboutUpdateOnUnmounted(fiber.stateNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,19 @@
|
|||||||
import type { Fiber } from 'ReactFiber';
|
import type { Fiber } from 'ReactFiber';
|
||||||
|
|
||||||
var ReactInstanceMap = require('ReactInstanceMap');
|
var ReactInstanceMap = require('ReactInstanceMap');
|
||||||
|
var ReactCurrentOwner = require('react/lib/ReactCurrentOwner');
|
||||||
|
|
||||||
var invariant = require('fbjs/lib/invariant');
|
var invariant = require('fbjs/lib/invariant');
|
||||||
|
|
||||||
|
if (__DEV__) {
|
||||||
|
var warning = require('fbjs/lib/warning');
|
||||||
|
}
|
||||||
|
|
||||||
var {
|
var {
|
||||||
HostRoot,
|
HostRoot,
|
||||||
HostComponent,
|
HostComponent,
|
||||||
HostText,
|
HostText,
|
||||||
|
ClassComponent,
|
||||||
} = require('ReactTypeOfWork');
|
} = require('ReactTypeOfWork');
|
||||||
|
|
||||||
var {
|
var {
|
||||||
@ -66,6 +72,24 @@ exports.isFiberMounted = function(fiber : Fiber) : boolean {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.isMounted = function(component : ReactComponent<any, any, any>) : boolean {
|
exports.isMounted = function(component : ReactComponent<any, any, any>) : boolean {
|
||||||
|
if (__DEV__) {
|
||||||
|
const owner = (ReactCurrentOwner.current : any);
|
||||||
|
if (owner !== null && owner.tag === ClassComponent) {
|
||||||
|
const ownerFiber : Fiber = owner;
|
||||||
|
const instance = ownerFiber.stateNode;
|
||||||
|
warning(
|
||||||
|
instance._warnedAboutRefsInRender,
|
||||||
|
'%s is accessing isMounted inside its render() function. ' +
|
||||||
|
'render() should be a pure function of props and state. It should ' +
|
||||||
|
'never access something that requires stale data from the previous ' +
|
||||||
|
'render, such as refs. Move this logic to componentDidMount and ' +
|
||||||
|
'componentDidUpdate instead.',
|
||||||
|
getComponentName(ownerFiber)
|
||||||
|
);
|
||||||
|
instance._warnedAboutRefsInRender = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var fiber : ?Fiber = ReactInstanceMap.get(component);
|
var fiber : ?Fiber = ReactInstanceMap.get(component);
|
||||||
if (!fiber) {
|
if (!fiber) {
|
||||||
return false;
|
return false;
|
||||||
@ -243,7 +267,7 @@ exports.findCurrentHostFiber = function(parent : Fiber) : Fiber | null {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getComponentName = function(fiber: Fiber): string {
|
function getComponentName(fiber: Fiber): string {
|
||||||
const type = fiber.type;
|
const type = fiber.type;
|
||||||
const instance = fiber.stateNode;
|
const instance = fiber.stateNode;
|
||||||
const constructor = instance && instance.constructor;
|
const constructor = instance && instance.constructor;
|
||||||
@ -252,4 +276,5 @@ exports.getComponentName = function(fiber: Fiber): string {
|
|||||||
type.name || (constructor && constructor.name) ||
|
type.name || (constructor && constructor.name) ||
|
||||||
'A Component'
|
'A Component'
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
exports.getComponentName = getComponentName;
|
||||||
|
@ -24,6 +24,7 @@ var ReactReconciler = require('ReactReconciler');
|
|||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
var checkReactTypeSpec = require('checkReactTypeSpec');
|
var checkReactTypeSpec = require('checkReactTypeSpec');
|
||||||
|
var ReactDebugCurrentFrame = require('react/lib/ReactDebugCurrentFrame');
|
||||||
var warningAboutMissingGetChildContext = {};
|
var warningAboutMissingGetChildContext = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,8 +34,6 @@ var shallowEqual = require('fbjs/lib/shallowEqual');
|
|||||||
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
|
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
|
||||||
var warning = require('fbjs/lib/warning');
|
var warning = require('fbjs/lib/warning');
|
||||||
|
|
||||||
import type { ReactPropTypeLocations } from 'ReactPropTypeLocations';
|
|
||||||
|
|
||||||
function StatelessComponent(Component) {
|
function StatelessComponent(Component) {
|
||||||
}
|
}
|
||||||
StatelessComponent.prototype.render = function() {
|
StatelessComponent.prototype.render = function() {
|
||||||
@ -687,7 +686,7 @@ var ReactCompositeComponent = {
|
|||||||
this._checkContextTypes(
|
this._checkContextTypes(
|
||||||
Component.childContextTypes,
|
Component.childContextTypes,
|
||||||
childContext,
|
childContext,
|
||||||
'childContext'
|
'child context'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (var name in childContext) {
|
for (var name in childContext) {
|
||||||
@ -730,17 +729,17 @@ var ReactCompositeComponent = {
|
|||||||
_checkContextTypes: function(
|
_checkContextTypes: function(
|
||||||
typeSpecs,
|
typeSpecs,
|
||||||
values,
|
values,
|
||||||
location: ReactPropTypeLocations,
|
location: string,
|
||||||
) {
|
) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
ReactDebugCurrentFrame.current = this._debugID;
|
||||||
checkReactTypeSpec(
|
checkReactTypeSpec(
|
||||||
typeSpecs,
|
typeSpecs,
|
||||||
values,
|
values,
|
||||||
location,
|
location,
|
||||||
this.getName(),
|
this.getName()
|
||||||
null,
|
|
||||||
this._debugID
|
|
||||||
);
|
);
|
||||||
|
ReactDebugCurrentFrame.current = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -850,6 +849,7 @@ var ReactCompositeComponent = {
|
|||||||
// _pendingStateQueue which will ensure that any state updates gets
|
// _pendingStateQueue which will ensure that any state updates gets
|
||||||
// immediately reconciled instead of waiting for the next batch.
|
// immediately reconciled instead of waiting for the next batch.
|
||||||
if (willReceive && inst.componentWillReceiveProps) {
|
if (willReceive && inst.componentWillReceiveProps) {
|
||||||
|
const beforeState = inst.state;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
measureLifeCyclePerf(
|
measureLifeCyclePerf(
|
||||||
() => inst.componentWillReceiveProps(nextProps, nextContext),
|
() => inst.componentWillReceiveProps(nextProps, nextContext),
|
||||||
@ -859,6 +859,20 @@ var ReactCompositeComponent = {
|
|||||||
} else {
|
} else {
|
||||||
inst.componentWillReceiveProps(nextProps, nextContext);
|
inst.componentWillReceiveProps(nextProps, nextContext);
|
||||||
}
|
}
|
||||||
|
const afterState = inst.state;
|
||||||
|
if (beforeState !== afterState) {
|
||||||
|
inst.state = beforeState;
|
||||||
|
inst.updater.enqueueReplaceState(inst, afterState);
|
||||||
|
if (__DEV__) {
|
||||||
|
warning(
|
||||||
|
false,
|
||||||
|
'%s.componentWillReceiveProps(): Assigning directly to ' +
|
||||||
|
'this.state is deprecated (except inside a component\'s ' +
|
||||||
|
'constructor). Use setState instead.',
|
||||||
|
this.getName() || 'ReactCompositeComponent'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If updating happens to enqueue any new updates, we shouldn't execute new
|
// If updating happens to enqueue any new updates, we shouldn't execute new
|
||||||
|
@ -38,16 +38,12 @@ function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
|
|||||||
if (!internalInstance) {
|
if (!internalInstance) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
var ctor = publicInstance.constructor;
|
var ctor = publicInstance.constructor;
|
||||||
// Only warn when we have a callerName. Otherwise we should be silent.
|
|
||||||
// We're probably calling from enqueueCallback. We don't want to warn
|
|
||||||
// there because we already warned for the corresponding lifecycle method.
|
|
||||||
warning(
|
warning(
|
||||||
!callerName,
|
false,
|
||||||
'%s(...): Can only update a mounted or mounting component. ' +
|
'Can only update a mounted or mounting component. This usually means ' +
|
||||||
'This usually means you called %s() on an unmounted component. ' +
|
'you called setState, replaceState, or forceUpdate on an unmounted ' +
|
||||||
'This is a no-op.\n\nPlease check the code for the %s component.',
|
'component. This is a no-op.\n\nPlease check the code for the ' +
|
||||||
callerName,
|
'%s component.',
|
||||||
callerName,
|
|
||||||
ctor && (ctor.displayName || ctor.name) || 'ReactClass'
|
ctor && (ctor.displayName || ctor.name) || 'ReactClass'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -57,12 +53,10 @@ function getInternalInstanceReadyForUpdate(publicInstance, callerName) {
|
|||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
warning(
|
warning(
|
||||||
ReactCurrentOwner.current == null,
|
ReactCurrentOwner.current == null,
|
||||||
'%s(...): Cannot update during an existing state transition (such as ' +
|
'Cannot update during an existing state transition (such as within ' +
|
||||||
'within `render` or another component\'s constructor). Render methods ' +
|
'`render` or another component\'s constructor). Render methods should ' +
|
||||||
'should be a pure function of props and state; constructor ' +
|
'be a pure function of props and state; constructor side-effects are ' +
|
||||||
'side-effects are an anti-pattern, but can be moved to ' +
|
'an anti-pattern, but can be moved to `componentWillMount`.',
|
||||||
'`componentWillMount`.',
|
|
||||||
callerName
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,10 +128,7 @@ var ReactUpdateQueue = {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
enqueueForceUpdate: function(publicInstance, callback, callerName) {
|
enqueueForceUpdate: function(publicInstance, callback, callerName) {
|
||||||
var internalInstance = getInternalInstanceReadyForUpdate(
|
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
|
||||||
publicInstance,
|
|
||||||
'forceUpdate'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!internalInstance) {
|
if (!internalInstance) {
|
||||||
return;
|
return;
|
||||||
@ -174,10 +165,7 @@ var ReactUpdateQueue = {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
enqueueReplaceState: function(publicInstance, completeState, callback, callerName) {
|
enqueueReplaceState: function(publicInstance, completeState, callback, callerName) {
|
||||||
var internalInstance = getInternalInstanceReadyForUpdate(
|
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
|
||||||
publicInstance,
|
|
||||||
'replaceState'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!internalInstance) {
|
if (!internalInstance) {
|
||||||
return;
|
return;
|
||||||
@ -223,10 +211,7 @@ var ReactUpdateQueue = {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var internalInstance = getInternalInstanceReadyForUpdate(
|
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
|
||||||
publicInstance,
|
|
||||||
'setState'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!internalInstance) {
|
if (!internalInstance) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-present, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
* @providesModule ReactPropTypeLocationNames
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import type { ReactPropTypeLocations } from 'ReactPropTypeLocations';
|
|
||||||
|
|
||||||
type NamesType = {[key: ReactPropTypeLocations]: string};
|
|
||||||
|
|
||||||
var ReactPropTypeLocationNames: NamesType = {};
|
|
||||||
|
|
||||||
if (__DEV__) {
|
|
||||||
ReactPropTypeLocationNames = {
|
|
||||||
prop: 'prop',
|
|
||||||
context: 'context',
|
|
||||||
childContext: 'child context',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ReactPropTypeLocationNames;
|
|
@ -1,18 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-present, Facebook, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the BSD-style license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
* @providesModule ReactPropTypeLocations
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
export type ReactPropTypeLocations =
|
|
||||||
'prop' |
|
|
||||||
'context' |
|
|
||||||
'childContext';
|
|
@ -11,124 +11,22 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
|
var checkPropTypes = require('react/lib/checkPropTypes');
|
||||||
var ReactPropTypesSecret = require('ReactPropTypesSecret');
|
var { getStackAddendum } = require('react/lib/ReactDebugCurrentFrame');
|
||||||
|
|
||||||
var invariant = require('fbjs/lib/invariant');
|
|
||||||
var warning = require('fbjs/lib/warning');
|
|
||||||
|
|
||||||
import type { ReactPropTypeLocations } from 'ReactPropTypeLocations';
|
|
||||||
|
|
||||||
var ReactComponentTreeHook;
|
|
||||||
|
|
||||||
if (
|
|
||||||
typeof process !== 'undefined' &&
|
|
||||||
process.env &&
|
|
||||||
process.env.NODE_ENV === 'test'
|
|
||||||
) {
|
|
||||||
// Temporary hack.
|
|
||||||
// Inline requires don't work well with Jest:
|
|
||||||
// https://github.com/facebook/react/issues/7240
|
|
||||||
// Remove the inline requires when we don't need them anymore:
|
|
||||||
// https://github.com/facebook/react/pull/7178
|
|
||||||
ReactComponentTreeHook = require('react/lib/ReactComponentTreeHook');
|
|
||||||
}
|
|
||||||
|
|
||||||
var loggedTypeFailures = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assert that the values match with the type specs.
|
|
||||||
* Error messages are memorized and will only be shown once.
|
|
||||||
*
|
|
||||||
* @param {object} typeSpecs Map of name to a ReactPropType
|
|
||||||
* @param {object} values Runtime values that need to be type-checked
|
|
||||||
* @param {string} location e.g. "prop", "context", "child context"
|
|
||||||
* @param {string} componentName Name of the component for error messages.
|
|
||||||
* @param {?object} element The React element that is being type-checked
|
|
||||||
* @param {?number} workInProgressOrDebugID The React component instance that is being type-checked
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function checkReactTypeSpec(
|
function checkReactTypeSpec(
|
||||||
typeSpecs,
|
typeSpecs,
|
||||||
values,
|
values,
|
||||||
location: ReactPropTypeLocations,
|
location: string,
|
||||||
componentName,
|
componentName
|
||||||
element,
|
|
||||||
// It is only safe to pass fiber if it is the work-in-progress version, and
|
|
||||||
// only during reconciliation (begin and complete phase).
|
|
||||||
workInProgressOrDebugID,
|
|
||||||
) {
|
) {
|
||||||
for (var typeSpecName in typeSpecs) {
|
checkPropTypes(
|
||||||
if (typeSpecs.hasOwnProperty(typeSpecName)) {
|
typeSpecs,
|
||||||
var error;
|
values,
|
||||||
// Prop type validation may throw. In case they do, we don't want to
|
location,
|
||||||
// fail the render phase where it didn't fail before. So we log it.
|
componentName,
|
||||||
// After these have been cleaned up, we'll let them throw.
|
getStackAddendum
|
||||||
try {
|
);
|
||||||
// This is intentionally an invariant that gets caught. It's the same
|
|
||||||
// behavior as without this statement except with a better message.
|
|
||||||
invariant(
|
|
||||||
typeof typeSpecs[typeSpecName] === 'function',
|
|
||||||
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
|
|
||||||
'React.PropTypes.',
|
|
||||||
componentName || 'React class',
|
|
||||||
ReactPropTypeLocationNames[location],
|
|
||||||
typeSpecName
|
|
||||||
);
|
|
||||||
error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
|
|
||||||
} catch (ex) {
|
|
||||||
error = ex;
|
|
||||||
}
|
|
||||||
warning(
|
|
||||||
!error || error instanceof Error,
|
|
||||||
'%s: type specification of %s `%s` is invalid; the type checker ' +
|
|
||||||
'function must return `null` or an `Error` but returned a %s. ' +
|
|
||||||
'You may have forgotten to pass an argument to the type checker ' +
|
|
||||||
'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
|
|
||||||
'shape all require an argument).',
|
|
||||||
componentName || 'React class',
|
|
||||||
ReactPropTypeLocationNames[location],
|
|
||||||
typeSpecName,
|
|
||||||
typeof error
|
|
||||||
);
|
|
||||||
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
|
|
||||||
// Only monitor this failure once because there tends to be a lot of the
|
|
||||||
// same error.
|
|
||||||
loggedTypeFailures[error.message] = true;
|
|
||||||
|
|
||||||
var componentStackInfo = '';
|
|
||||||
|
|
||||||
if (__DEV__) {
|
|
||||||
if (!ReactComponentTreeHook) {
|
|
||||||
ReactComponentTreeHook = require('react/lib/ReactComponentTreeHook');
|
|
||||||
}
|
|
||||||
if (workInProgressOrDebugID != null) {
|
|
||||||
if (typeof workInProgressOrDebugID === 'number') {
|
|
||||||
// DebugID from Stack.
|
|
||||||
const debugID = workInProgressOrDebugID;
|
|
||||||
componentStackInfo = ReactComponentTreeHook.getStackAddendumByID(debugID);
|
|
||||||
} else if (typeof workInProgressOrDebugID.tag === 'number') {
|
|
||||||
// This is a Fiber.
|
|
||||||
// The stack will only be correct if this is a work in progress
|
|
||||||
// version and we're calling it during reconciliation.
|
|
||||||
const workInProgress = workInProgressOrDebugID;
|
|
||||||
componentStackInfo = ReactComponentTreeHook.getStackAddendumByWorkInProgressFiber(workInProgress);
|
|
||||||
}
|
|
||||||
} else if (element !== null) {
|
|
||||||
componentStackInfo = ReactComponentTreeHook.getCurrentStackAddendum(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
warning(
|
|
||||||
false,
|
|
||||||
'Failed %s type: %s%s',
|
|
||||||
location,
|
|
||||||
error.message,
|
|
||||||
componentStackInfo
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = checkReactTypeSpec;
|
module.exports = checkReactTypeSpec;
|
||||||
|
@ -10,17 +10,14 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ReactPropTypeLocationNames = require('react/lib/ReactPropTypeLocationNames');
|
|
||||||
|
|
||||||
var normalizeColor = require('normalizeColor');
|
var normalizeColor = require('normalizeColor');
|
||||||
|
|
||||||
var colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
|
var colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
|
||||||
var color = props[propName];
|
var color = props[propName];
|
||||||
if (color === undefined || color === null) {
|
if (color === undefined || color === null) {
|
||||||
if (isRequired) {
|
if (isRequired) {
|
||||||
var locationName = ReactPropTypeLocationNames[location];
|
|
||||||
return new Error(
|
return new Error(
|
||||||
'Required ' + locationName + ' `' + (propFullName || propName) +
|
'Required ' + location + ' `' + (propFullName || propName) +
|
||||||
'` was not specified in `' + componentName + '`.'
|
'` was not specified in `' + componentName + '`.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -35,9 +32,8 @@ var colorPropType = function(isRequired, props, propName, componentName, locatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (normalizeColor(color) === null) {
|
if (normalizeColor(color) === null) {
|
||||||
var locationName = ReactPropTypeLocationNames[location];
|
|
||||||
return new Error(
|
return new Error(
|
||||||
'Invalid ' + locationName + ' `' + (propFullName || propName) +
|
'Invalid ' + location + ' `' + (propFullName || propName) +
|
||||||
'` supplied to `' + componentName + '`: ' + color + '\n' +
|
'` supplied to `' + componentName + '`: ' + color + '\n' +
|
||||||
`Valid color formats are
|
`Valid color formats are
|
||||||
- '#f0f' (#rgb)
|
- '#f0f' (#rgb)
|
||||||
|
10
package.json
10
package.json
@ -127,7 +127,7 @@
|
|||||||
"react-native": "local-cli/wrong-react-native.js"
|
"react-native": "local-cli/wrong-react-native.js"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "16.0.0-alpha.2"
|
"react": "~16.0.0-alpha.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"absolute-path": "^0.0.0",
|
"absolute-path": "^0.0.0",
|
||||||
@ -159,7 +159,7 @@
|
|||||||
"debug": "^2.2.0",
|
"debug": "^2.2.0",
|
||||||
"denodeify": "^1.2.1",
|
"denodeify": "^1.2.1",
|
||||||
"event-target-shim": "^1.0.5",
|
"event-target-shim": "^1.0.5",
|
||||||
"fbjs": "^0.8.9",
|
"fbjs": "~0.8.9",
|
||||||
"fbjs-scripts": "^0.7.0",
|
"fbjs-scripts": "^0.7.0",
|
||||||
"form-data": "^2.1.1",
|
"form-data": "^2.1.1",
|
||||||
"fs-extra": "^0.26.2",
|
"fs-extra": "^0.26.2",
|
||||||
@ -222,9 +222,9 @@
|
|||||||
"jest-repl": "19.0.2",
|
"jest-repl": "19.0.2",
|
||||||
"jest-runtime": "19.0.2",
|
"jest-runtime": "19.0.2",
|
||||||
"mock-fs": "^3.11.0",
|
"mock-fs": "^3.11.0",
|
||||||
"react": "16.0.0-alpha.2",
|
"react": "~16.0.0-alpha.3",
|
||||||
"react-dom": "16.0.0-alpha.2",
|
"react-dom": "~16.0.0-alpha.3",
|
||||||
"react-test-renderer": "16.0.0-alpha.2",
|
"react-test-renderer": "~16.0.0-alpha.3",
|
||||||
"shelljs": "0.6.0",
|
"shelljs": "0.6.0",
|
||||||
"sinon": "^2.0.0-pre.2"
|
"sinon": "^2.0.0-pre.2"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user