1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | 'use strict';
|
12 |
|
13 | var ReactElement = require('./ReactElement');
|
14 | var ReactPropTypeLocationNames = require('./ReactPropTypeLocationNames');
|
15 | var ReactPropTypesSecret = require('./ReactPropTypesSecret');
|
16 |
|
17 | var emptyFunction = require('fbjs/lib/emptyFunction');
|
18 | var getIteratorFn = require('./getIteratorFn');
|
19 | var warning = require('fbjs/lib/warning');
|
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 | var ANONYMOUS = '<<anonymous>>';
|
69 |
|
70 | var ReactPropTypes = {
|
71 | array: createPrimitiveTypeChecker('array'),
|
72 | bool: createPrimitiveTypeChecker('boolean'),
|
73 | func: createPrimitiveTypeChecker('function'),
|
74 | number: createPrimitiveTypeChecker('number'),
|
75 | object: createPrimitiveTypeChecker('object'),
|
76 | string: createPrimitiveTypeChecker('string'),
|
77 | symbol: createPrimitiveTypeChecker('symbol'),
|
78 |
|
79 | any: createAnyTypeChecker(),
|
80 | arrayOf: createArrayOfTypeChecker,
|
81 | element: createElementTypeChecker(),
|
82 | instanceOf: createInstanceTypeChecker,
|
83 | node: createNodeChecker(),
|
84 | objectOf: createObjectOfTypeChecker,
|
85 | oneOf: createEnumTypeChecker,
|
86 | oneOfType: createUnionTypeChecker,
|
87 | shape: createShapeTypeChecker
|
88 | };
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | function is(x, y) {
|
96 |
|
97 | if (x === y) {
|
98 |
|
99 |
|
100 | return x !== 0 || 1 / x === 1 / y;
|
101 | } else {
|
102 |
|
103 | return x !== x && y !== y;
|
104 | }
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | function PropTypeError(message) {
|
116 | this.message = message;
|
117 | this.stack = '';
|
118 | }
|
119 |
|
120 | PropTypeError.prototype = Error.prototype;
|
121 |
|
122 | function createChainableTypeChecker(validate) {
|
123 | if (process.env.NODE_ENV !== 'production') {
|
124 | var manualPropTypeCallCache = {};
|
125 | }
|
126 | function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
|
127 | componentName = componentName || ANONYMOUS;
|
128 | propFullName = propFullName || propName;
|
129 | if (process.env.NODE_ENV !== 'production') {
|
130 | if (secret !== ReactPropTypesSecret && typeof console !== 'undefined') {
|
131 | var cacheKey = componentName + ':' + propName;
|
132 | if (!manualPropTypeCallCache[cacheKey]) {
|
133 | process.env.NODE_ENV !== 'production' ? warning(false, 'You are manually calling a React.PropTypes validation ' + 'function for the `%s` prop on `%s`. This is deprecated ' + 'and will not work in production with the next major version. ' + 'You may be seeing this warning due to a third-party PropTypes ' + 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.', propFullName, componentName) : void 0;
|
134 | manualPropTypeCallCache[cacheKey] = true;
|
135 | }
|
136 | }
|
137 | }
|
138 | if (props[propName] == null) {
|
139 | var locationName = ReactPropTypeLocationNames[location];
|
140 | if (isRequired) {
|
141 | if (props[propName] === null) {
|
142 | return new PropTypeError('The ' + locationName + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
|
143 | }
|
144 | return new PropTypeError('The ' + locationName + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
|
145 | }
|
146 | return null;
|
147 | } else {
|
148 | return validate(props, propName, componentName, location, propFullName);
|
149 | }
|
150 | }
|
151 |
|
152 | var chainedCheckType = checkType.bind(null, false);
|
153 | chainedCheckType.isRequired = checkType.bind(null, true);
|
154 |
|
155 | return chainedCheckType;
|
156 | }
|
157 |
|
158 | function createPrimitiveTypeChecker(expectedType) {
|
159 | function validate(props, propName, componentName, location, propFullName, secret) {
|
160 | var propValue = props[propName];
|
161 | var propType = getPropType(propValue);
|
162 | if (propType !== expectedType) {
|
163 | var locationName = ReactPropTypeLocationNames[location];
|
164 |
|
165 |
|
166 |
|
167 | var preciseType = getPreciseType(propValue);
|
168 |
|
169 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));
|
170 | }
|
171 | return null;
|
172 | }
|
173 | return createChainableTypeChecker(validate);
|
174 | }
|
175 |
|
176 | function createAnyTypeChecker() {
|
177 | return createChainableTypeChecker(emptyFunction.thatReturns(null));
|
178 | }
|
179 |
|
180 | function createArrayOfTypeChecker(typeChecker) {
|
181 | function validate(props, propName, componentName, location, propFullName) {
|
182 | if (typeof typeChecker !== 'function') {
|
183 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
|
184 | }
|
185 | var propValue = props[propName];
|
186 | if (!Array.isArray(propValue)) {
|
187 | var locationName = ReactPropTypeLocationNames[location];
|
188 | var propType = getPropType(propValue);
|
189 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
|
190 | }
|
191 | for (var i = 0; i < propValue.length; i++) {
|
192 | var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
|
193 | if (error instanceof Error) {
|
194 | return error;
|
195 | }
|
196 | }
|
197 | return null;
|
198 | }
|
199 | return createChainableTypeChecker(validate);
|
200 | }
|
201 |
|
202 | function createElementTypeChecker() {
|
203 | function validate(props, propName, componentName, location, propFullName) {
|
204 | var propValue = props[propName];
|
205 | if (!ReactElement.isValidElement(propValue)) {
|
206 | var locationName = ReactPropTypeLocationNames[location];
|
207 | var propType = getPropType(propValue);
|
208 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
|
209 | }
|
210 | return null;
|
211 | }
|
212 | return createChainableTypeChecker(validate);
|
213 | }
|
214 |
|
215 | function createInstanceTypeChecker(expectedClass) {
|
216 | function validate(props, propName, componentName, location, propFullName) {
|
217 | if (!(props[propName] instanceof expectedClass)) {
|
218 | var locationName = ReactPropTypeLocationNames[location];
|
219 | var expectedClassName = expectedClass.name || ANONYMOUS;
|
220 | var actualClassName = getClassName(props[propName]);
|
221 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
|
222 | }
|
223 | return null;
|
224 | }
|
225 | return createChainableTypeChecker(validate);
|
226 | }
|
227 |
|
228 | function createEnumTypeChecker(expectedValues) {
|
229 | if (!Array.isArray(expectedValues)) {
|
230 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.') : void 0;
|
231 | return emptyFunction.thatReturnsNull;
|
232 | }
|
233 |
|
234 | function validate(props, propName, componentName, location, propFullName) {
|
235 | var propValue = props[propName];
|
236 | for (var i = 0; i < expectedValues.length; i++) {
|
237 | if (is(propValue, expectedValues[i])) {
|
238 | return null;
|
239 | }
|
240 | }
|
241 |
|
242 | var locationName = ReactPropTypeLocationNames[location];
|
243 | var valuesString = JSON.stringify(expectedValues);
|
244 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
|
245 | }
|
246 | return createChainableTypeChecker(validate);
|
247 | }
|
248 |
|
249 | function createObjectOfTypeChecker(typeChecker) {
|
250 | function validate(props, propName, componentName, location, propFullName) {
|
251 | if (typeof typeChecker !== 'function') {
|
252 | return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
|
253 | }
|
254 | var propValue = props[propName];
|
255 | var propType = getPropType(propValue);
|
256 | if (propType !== 'object') {
|
257 | var locationName = ReactPropTypeLocationNames[location];
|
258 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
|
259 | }
|
260 | for (var key in propValue) {
|
261 | if (propValue.hasOwnProperty(key)) {
|
262 | var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
|
263 | if (error instanceof Error) {
|
264 | return error;
|
265 | }
|
266 | }
|
267 | }
|
268 | return null;
|
269 | }
|
270 | return createChainableTypeChecker(validate);
|
271 | }
|
272 |
|
273 | function createUnionTypeChecker(arrayOfTypeCheckers) {
|
274 | if (!Array.isArray(arrayOfTypeCheckers)) {
|
275 | process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.') : void 0;
|
276 | return emptyFunction.thatReturnsNull;
|
277 | }
|
278 |
|
279 | function validate(props, propName, componentName, location, propFullName) {
|
280 | for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
|
281 | var checker = arrayOfTypeCheckers[i];
|
282 | if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) {
|
283 | return null;
|
284 | }
|
285 | }
|
286 |
|
287 | var locationName = ReactPropTypeLocationNames[location];
|
288 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));
|
289 | }
|
290 | return createChainableTypeChecker(validate);
|
291 | }
|
292 |
|
293 | function createNodeChecker() {
|
294 | function validate(props, propName, componentName, location, propFullName) {
|
295 | if (!isNode(props[propName])) {
|
296 | var locationName = ReactPropTypeLocationNames[location];
|
297 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
|
298 | }
|
299 | return null;
|
300 | }
|
301 | return createChainableTypeChecker(validate);
|
302 | }
|
303 |
|
304 | function createShapeTypeChecker(shapeTypes) {
|
305 | function validate(props, propName, componentName, location, propFullName) {
|
306 | var propValue = props[propName];
|
307 | var propType = getPropType(propValue);
|
308 | if (propType !== 'object') {
|
309 | var locationName = ReactPropTypeLocationNames[location];
|
310 | return new PropTypeError('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
|
311 | }
|
312 | for (var key in shapeTypes) {
|
313 | var checker = shapeTypes[key];
|
314 | if (!checker) {
|
315 | continue;
|
316 | }
|
317 | var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
|
318 | if (error) {
|
319 | return error;
|
320 | }
|
321 | }
|
322 | return null;
|
323 | }
|
324 | return createChainableTypeChecker(validate);
|
325 | }
|
326 |
|
327 | function isNode(propValue) {
|
328 | switch (typeof propValue) {
|
329 | case 'number':
|
330 | case 'string':
|
331 | case 'undefined':
|
332 | return true;
|
333 | case 'boolean':
|
334 | return !propValue;
|
335 | case 'object':
|
336 | if (Array.isArray(propValue)) {
|
337 | return propValue.every(isNode);
|
338 | }
|
339 | if (propValue === null || ReactElement.isValidElement(propValue)) {
|
340 | return true;
|
341 | }
|
342 |
|
343 | var iteratorFn = getIteratorFn(propValue);
|
344 | if (iteratorFn) {
|
345 | var iterator = iteratorFn.call(propValue);
|
346 | var step;
|
347 | if (iteratorFn !== propValue.entries) {
|
348 | while (!(step = iterator.next()).done) {
|
349 | if (!isNode(step.value)) {
|
350 | return false;
|
351 | }
|
352 | }
|
353 | } else {
|
354 |
|
355 | while (!(step = iterator.next()).done) {
|
356 | var entry = step.value;
|
357 | if (entry) {
|
358 | if (!isNode(entry[1])) {
|
359 | return false;
|
360 | }
|
361 | }
|
362 | }
|
363 | }
|
364 | } else {
|
365 | return false;
|
366 | }
|
367 |
|
368 | return true;
|
369 | default:
|
370 | return false;
|
371 | }
|
372 | }
|
373 |
|
374 | function isSymbol(propType, propValue) {
|
375 |
|
376 | if (propType === 'symbol') {
|
377 | return true;
|
378 | }
|
379 |
|
380 |
|
381 | if (propValue['@@toStringTag'] === 'Symbol') {
|
382 | return true;
|
383 | }
|
384 |
|
385 |
|
386 | if (typeof Symbol === 'function' && propValue instanceof Symbol) {
|
387 | return true;
|
388 | }
|
389 |
|
390 | return false;
|
391 | }
|
392 |
|
393 |
|
394 | function getPropType(propValue) {
|
395 | var propType = typeof propValue;
|
396 | if (Array.isArray(propValue)) {
|
397 | return 'array';
|
398 | }
|
399 | if (propValue instanceof RegExp) {
|
400 |
|
401 |
|
402 |
|
403 | return 'object';
|
404 | }
|
405 | if (isSymbol(propType, propValue)) {
|
406 | return 'symbol';
|
407 | }
|
408 | return propType;
|
409 | }
|
410 |
|
411 |
|
412 |
|
413 | function getPreciseType(propValue) {
|
414 | var propType = getPropType(propValue);
|
415 | if (propType === 'object') {
|
416 | if (propValue instanceof Date) {
|
417 | return 'date';
|
418 | } else if (propValue instanceof RegExp) {
|
419 | return 'regexp';
|
420 | }
|
421 | }
|
422 | return propType;
|
423 | }
|
424 |
|
425 |
|
426 | function getClassName(propValue) {
|
427 | if (!propValue.constructor || !propValue.constructor.name) {
|
428 | return ANONYMOUS;
|
429 | }
|
430 | return propValue.constructor.name;
|
431 | }
|
432 |
|
433 | module.exports = ReactPropTypes; |
\ | No newline at end of file |