-
Notifications
You must be signed in to change notification settings - Fork 45.7k
/
checkPropTypes.js
108 lines (102 loc) · 3.7 KB
/
checkPropTypes.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
const loggedTypeFailures = {};
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import hasOwnProperty from 'shared/hasOwnProperty';
const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
function setCurrentlyValidatingElement(element) {
if (__DEV__) {
if (element) {
const owner = element._owner;
const stack = describeUnknownElementTypeFrameInDEV(
element.type,
element._source,
owner ? owner.type : null,
);
ReactDebugCurrentFrame.setExtraStackFrame(stack);
} else {
ReactDebugCurrentFrame.setExtraStackFrame(null);
}
}
}
export default function checkPropTypes(
typeSpecs: Object,
values: Object,
location: string,
componentName: ?string,
element?: any,
): void {
if (__DEV__) {
// $FlowFixMe This is okay but Flow doesn't know it.
const has = Function.call.bind(hasOwnProperty);
for (const typeSpecName in typeSpecs) {
if (has(typeSpecs, typeSpecName)) {
let error;
// Prop type validation may throw. In case they do, we don't want to
// fail the render phase where it didn't fail before. So we log it.
// After these have been cleaned up, we'll let them throw.
try {
// This is intentionally an invariant that gets caught. It's the same
// behavior as without this statement except with a better message.
if (typeof typeSpecs[typeSpecName] !== 'function') {
const err = Error(
(componentName || 'React class') +
': ' +
location +
' type `' +
typeSpecName +
'` is invalid; ' +
'it must be a function, usually from the `prop-types` package, but received `' +
typeof typeSpecs[typeSpecName] +
'`.' +
'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.',
);
err.name = 'Invariant Violation';
throw err;
}
error = typeSpecs[typeSpecName](
values,
typeSpecName,
componentName,
location,
null,
'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED',
);
} catch (ex) {
error = ex;
}
if (error && !(error instanceof Error)) {
setCurrentlyValidatingElement(element);
console.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',
location,
typeSpecName,
typeof error,
);
setCurrentlyValidatingElement(null);
}
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;
setCurrentlyValidatingElement(element);
console.error('Failed %s type: %s', location, error.message);
setCurrentlyValidatingElement(null);
}
}
}
}
}