11
12
'use strict';
13
14
-var ReactElement = require('ReactElement');
15
-var ReactPropTypesSecret = require('ReactPropTypesSecret');
14
+var {isValidElement} = require('ReactElement');
15
+var factory = require('prop-types/factory');
16
17
-var emptyFunction = require('fbjs/lib/emptyFunction');
18
-var getIteratorFn = require('getIteratorFn');
19
-var invariant = require('fbjs/lib/invariant');
20
-var warning = require('fbjs/lib/warning');
21
-
22
-/**
23
- * Collection of methods that allow declaration and validation of props that are
24
- * supplied to React components. Example usage:
25
- *
26
- * var Props = require('ReactPropTypes');
27
- * var MyArticle = React.createClass({
28
- * propTypes: {
29
- * // An optional string prop named "description".
30
- * description: Props.string,
31
- *
32
- * // A required enum prop named "category".
33
- * category: Props.oneOf(['News','Photos']).isRequired,
34
- *
35
- * // A prop named "dialog" that requires an instance of Dialog.
36
- * dialog: Props.instanceOf(Dialog).isRequired
37
- * },
38
- * render: function() { ... }
39
- * });
40
- *
41
- * A more formal specification of how these methods are used:
42
- *
43
- * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
44
- * decl := ReactPropTypes.{type}(.isRequired)?
45
- *
46
- * Each and every declaration produces a function with the same signature. This
47
- * allows the creation of custom validation functions. For example:
48
- *
49
- * var MyLink = React.createClass({
50
- * propTypes: {
51
- * // An optional string or URI prop named "href".
52
- * href: function(props, propName, componentName) {
53
- * var propValue = props[propName];
54
- * if (propValue != null && typeof propValue !== 'string' &&
55
- * !(propValue instanceof URI)) {
56
- * return new Error(
57
- * 'Expected a string or an URI for ' + propName + ' in ' +
58
- * componentName
59
- * );
60
- * }
61
- * }
62
- * },
63
- * render: function() {...}
64
- * });
65
- *
66
- * @internal
67
- */
68
-
69
-var ANONYMOUS = '<<anonymous>>';
70
-
71
-var ReactPropTypes;
72
-
73
-if (__DEV__) {
74
- // Keep in sync with production version below
75
- ReactPropTypes = {
76
- array: createPrimitiveTypeChecker('array'),
77
- bool: createPrimitiveTypeChecker('boolean'),
78
- func: createPrimitiveTypeChecker('function'),
79
- number: createPrimitiveTypeChecker('number'),
80
- object: createPrimitiveTypeChecker('object'),
81
- string: createPrimitiveTypeChecker('string'),
82
- symbol: createPrimitiveTypeChecker('symbol'),
83
-
84
- any: createAnyTypeChecker(),
85
- arrayOf: createArrayOfTypeChecker,
86
- element: createElementTypeChecker(),
87
- instanceOf: createInstanceTypeChecker,
88
- node: createNodeChecker(),
89
- objectOf: createObjectOfTypeChecker,
90
- oneOf: createEnumTypeChecker,
91
- oneOfType: createUnionTypeChecker,
92
- shape: createShapeTypeChecker,
93
- };
94
-} else {
95
- var productionTypeChecker = function() {
96
- invariant(
97
- false,
98
- 'React.PropTypes type checking code is stripped in production.',
99
- );
100
- };
101
- productionTypeChecker.isRequired = productionTypeChecker;
102
- var getProductionTypeChecker = () => productionTypeChecker;
103
- // Keep in sync with development version above
104
- ReactPropTypes = {
105
- array: productionTypeChecker,
106
- bool: productionTypeChecker,
107
- func: productionTypeChecker,
108
- number: productionTypeChecker,
109
- object: productionTypeChecker,
110
- string: productionTypeChecker,
111
- symbol: productionTypeChecker,
112
-
113
- any: productionTypeChecker,
114
- arrayOf: getProductionTypeChecker,
115
- element: productionTypeChecker,
116
- instanceOf: getProductionTypeChecker,
117
- node: productionTypeChecker,
118
- objectOf: getProductionTypeChecker,
119
- oneOf: getProductionTypeChecker,
120
- oneOfType: getProductionTypeChecker,
121
- shape: getProductionTypeChecker,
122
- };
123
-}
124
-
125
-/**
126
- * inlined Object.is polyfill to avoid requiring consumers ship their own
127
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
128
- */
129
-/*eslint-disable no-self-compare*/
130
-function is(x, y) {
131
- // SameValue algorithm
132
- if (x === y) {
133
- // Steps 1-5, 7-10
134
- // Steps 6.b-6.e: +0 != -0
135
- return x !== 0 || 1 / x === 1 / y;
136
- } else {
137
- // Step 6.a: NaN == NaN
138
- return x !== x && y !== y;
139
- }
140
-}
141
-/*eslint-enable no-self-compare*/
142
-
143
-/**
144
- * We use an Error-like object for backward compatibility as people may call
145
- * PropTypes directly and inspect their output. However, we don't use real
146
- * Errors anymore. We don't inspect their stack anyway, and creating them
147
- * is prohibitively expensive if they are created too often, such as what
148
- * happens in oneOfType() for any type before the one that matched.
149
- */
150
-function PropTypeError(message) {
151
- this.message = message;
152
- this.stack = '';
153
-}
154
-// Make `instanceof Error` still work for returned errors.
155
-PropTypeError.prototype = Error.prototype;
156
-
157
-function createChainableTypeChecker(validate) {
158
- if (__DEV__) {
159
- var manualPropTypeCallCache = {};
160
- }
161
- function checkType(
162
- isRequired,
163
- props,
164
- propName,
165
- componentName,
166
- location,
167
- propFullName,
168
- secret,
169
- ) {
170
- componentName = componentName || ANONYMOUS;
171
- propFullName = propFullName || propName;
172
- if (__DEV__) {
173
- if (secret !== ReactPropTypesSecret && typeof console !== 'undefined') {
174
- var cacheKey = `${componentName}:${propName}`;
175
- if (!manualPropTypeCallCache[cacheKey]) {
176
- warning(
177
- false,
178
- 'You are manually calling a React.PropTypes validation ' +
179
- 'function for the `%s` prop on `%s`. This is deprecated ' +
180
- 'and will not work in production with the next major version. ' +
181
- 'You may be seeing this warning due to a third-party PropTypes ' +
182
- 'library. See https://fb.me/react-warning-dont-call-proptypes ' +
183
- 'for details.',
184
- propFullName,
185
- componentName,
186
- );
187
- manualPropTypeCallCache[cacheKey] = true;
188
- }
189
- }
190
- }
191
- if (props[propName] == null) {
192
- if (isRequired) {
193
- if (props[propName] === null) {
194
- return new PropTypeError(
195
- `The ${location} \`${propFullName}\` is marked as required ` +
196
- `in \`${componentName}\`, but its value is \`null\`.`,
197
- );
198
- }
199
- return new PropTypeError(
200
- `The ${location} \`${propFullName}\` is marked as required in ` +
201
- `\`${componentName}\`, but its value is \`undefined\`.`,
202
- );
203
- }
204
- return null;
205
- } else {
206
- return validate(props, propName, componentName, location, propFullName);
207
- }
208
- }
209
-
210
- var chainedCheckType = checkType.bind(null, false);
211
- chainedCheckType.isRequired = checkType.bind(null, true);
212
-
213
- return chainedCheckType;
214
-}
215
-
216
-function createPrimitiveTypeChecker(expectedType) {
217
- function validate(
218
- props,
219
- propName,
220
- componentName,
221
- location,
222
- propFullName,
223
- secret,
224
- ) {
225
- var propValue = props[propName];
226
- var propType = getPropType(propValue);
227
- if (propType !== expectedType) {
228
- // `propValue` being instance of, say, date/regexp, pass the 'object'
229
- // check, but we can offer a more precise error message here rather than
230
- // 'of type `object`'.
231
- var preciseType = getPreciseType(propValue);
232
-
233
- return new PropTypeError(
234
- `Invalid ${location} \`${propFullName}\` of type ` +
235
- `\`${preciseType}\` supplied to \`${componentName}\`, expected ` +
236
- `\`${expectedType}\`.`,
237
- );
238
- }
239
- return null;
240
- }
241
- return createChainableTypeChecker(validate);
242
-}
243
-
244
-function createAnyTypeChecker() {
245
- return createChainableTypeChecker(emptyFunction.thatReturnsNull);
246
-}
247
-
248
-function createArrayOfTypeChecker(typeChecker) {
249
- function validate(props, propName, componentName, location, propFullName) {
250
- if (typeof typeChecker !== 'function') {
251
- return new PropTypeError(
252
- `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside arrayOf.`,
253
- );
254
- }
255
- var propValue = props[propName];
256
- if (!Array.isArray(propValue)) {
257
- var propType = getPropType(propValue);
258
- return new PropTypeError(
259
- `Invalid ${location} \`${propFullName}\` of type ` +
260
- `\`${propType}\` supplied to \`${componentName}\`, expected an array.`,
261
- );
262
- }
263
- for (var i = 0; i < propValue.length; i++) {
264
- var error = typeChecker(
265
- propValue,
266
- i,
267
- componentName,
268
- location,
269
- `${propFullName}[${i}]`,
270
- ReactPropTypesSecret,
271
- );
272
- if (error instanceof Error) {
273
- return error;
274
- }
275
- }
276
- return null;
277
- }
278
- return createChainableTypeChecker(validate);
279
-}
280
-
281
-function createElementTypeChecker() {
282
- function validate(props, propName, componentName, location, propFullName) {
283
- var propValue = props[propName];
284
- if (!ReactElement.isValidElement(propValue)) {
285
- var propType = getPropType(propValue);
286
- return new PropTypeError(
287
- `Invalid ${location} \`${propFullName}\` of type ` +
288
- `\`${propType}\` supplied to \`${componentName}\`, expected a single ReactElement.`,
289
- );
290
- }
291
- return null;
292
- }
293
- return createChainableTypeChecker(validate);
294
-}
295
-
296
-function createInstanceTypeChecker(expectedClass) {
297
- function validate(props, propName, componentName, location, propFullName) {
298
- if (!(props[propName] instanceof expectedClass)) {
299
- var expectedClassName = expectedClass.name || ANONYMOUS;
300
- var actualClassName = getClassName(props[propName]);
301
- return new PropTypeError(
302
- `Invalid ${location} \`${propFullName}\` of type ` +
303
- `\`${actualClassName}\` supplied to \`${componentName}\`, expected ` +
304
- `instance of \`${expectedClassName}\`.`,
305
- );
306
- }
307
- return null;
308
- }
309
- return createChainableTypeChecker(validate);
310
-}
311
-
312
-function createEnumTypeChecker(expectedValues) {
313
- if (!Array.isArray(expectedValues)) {
314
- warning(
315
- false,
316
- 'Invalid argument supplied to oneOf, expected an instance of array.',
317
- );
318
- return emptyFunction.thatReturnsNull;
319
- }
320
-
321
- function validate(props, propName, componentName, location, propFullName) {
322
- var propValue = props[propName];
323
- for (var i = 0; i < expectedValues.length; i++) {
324
- if (is(propValue, expectedValues[i])) {
325
- return null;
326
- }
327
- }
328
-
329
- var valuesString = JSON.stringify(expectedValues);
330
- return new PropTypeError(
331
- `Invalid ${location} \`${propFullName}\` of value \`${propValue}\` ` +
332
- `supplied to \`${componentName}\`, expected one of ${valuesString}.`,
333
- );
334
- }
335
- return createChainableTypeChecker(validate);
336
-}
337
-
338
-function createObjectOfTypeChecker(typeChecker) {
339
- function validate(props, propName, componentName, location, propFullName) {
340
- if (typeof typeChecker !== 'function') {
341
- return new PropTypeError(
342
- `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside objectOf.`,
343
- );
344
- }
345
- var propValue = props[propName];
346
- var propType = getPropType(propValue);
347
- if (propType !== 'object') {
348
- return new PropTypeError(
349
- `Invalid ${location} \`${propFullName}\` of type ` +
350
- `\`${propType}\` supplied to \`${componentName}\`, expected an object.`,
351
- );
352
- }
353
- for (var key in propValue) {
354
- if (propValue.hasOwnProperty(key)) {
355
- var error = typeChecker(
356
- propValue,
357
- key,
358
- componentName,
359
- location,
360
- `${propFullName}.${key}`,
361
- ReactPropTypesSecret,
362
- );
363
- if (error instanceof Error) {
364
- return error;
365
- }
366
- }
367
- }
368
- return null;
369
- }
370
- return createChainableTypeChecker(validate);
371
-}
372
-
373
-function createUnionTypeChecker(arrayOfTypeCheckers) {
374
- if (!Array.isArray(arrayOfTypeCheckers)) {
375
- warning(
376
- false,
377
- 'Invalid argument supplied to oneOfType, expected an instance of array.',
378
- );
379
- return emptyFunction.thatReturnsNull;
380
- }
381
-
382
- function validate(props, propName, componentName, location, propFullName) {
383
- for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
384
- var checker = arrayOfTypeCheckers[i];
385
- if (
386
- checker(
387
- props,
388
- propName,
389
- componentName,
390
- location,
391
- propFullName,
392
- ReactPropTypesSecret,
393
- ) == null
394
- ) {
395
- return null;
396
- }
397
- }
398
-
399
- return new PropTypeError(
400
- `Invalid ${location} \`${propFullName}\` supplied to ` +
401
- `\`${componentName}\`.`,
402
- );
403
- }
404
- return createChainableTypeChecker(validate);
405
-}
406
-
407
-function createNodeChecker() {
408
- function validate(props, propName, componentName, location, propFullName) {
409
- if (!isNode(props[propName])) {
410
- return new PropTypeError(
411
- `Invalid ${location} \`${propFullName}\` supplied to ` +
412
- `\`${componentName}\`, expected a ReactNode.`,
413
- );
414
- }
415
- return null;
416
- }
417
- return createChainableTypeChecker(validate);
418
-}
419
-
420
-function createShapeTypeChecker(shapeTypes) {
421
- function validate(props, propName, componentName, location, propFullName) {
422
- var propValue = props[propName];
423
- var propType = getPropType(propValue);
424
- if (propType !== 'object') {
425
- return new PropTypeError(
426
- `Invalid ${location} \`${propFullName}\` of type \`${propType}\` ` +
427
- `supplied to \`${componentName}\`, expected \`object\`.`,
428
- );
429
- }
430
- for (var key in shapeTypes) {
431
- var checker = shapeTypes[key];
432
- if (!checker) {
433
- continue;
434
- }
435
- var error = checker(
436
- propValue,
437
- key,
438
- componentName,
439
- location,
440
- `${propFullName}.${key}`,
441
- ReactPropTypesSecret,
442
- );
443
- if (error) {
444
- return error;
445
- }
446
- }
447
- return null;
448
- }
449
- return createChainableTypeChecker(validate);
450
-}
451
-
452
-function isNode(propValue) {
453
- switch (typeof propValue) {
454
- case 'number':
455
- case 'string':
456
- case 'undefined':
457
- return true;
458
- case 'boolean':
459
- return !propValue;
460
- case 'object':
461
- if (Array.isArray(propValue)) {
462
- return propValue.every(isNode);
463
- }
464
- if (propValue === null || ReactElement.isValidElement(propValue)) {
465
- return true;
466
- }
467
-
468
- var iteratorFn = getIteratorFn(propValue);
469
- if (iteratorFn) {
470
- var iterator = iteratorFn.call(propValue);
471
- var step;
472
- if (iteratorFn !== propValue.entries) {
473
- while (!(step = iterator.next()).done) {
474
- if (!isNode(step.value)) {
475
- return false;
476
- }
477
- }
478
- } else {
479
- // Iterator will provide entry [k,v] tuples rather than values.
480
- while (!(step = iterator.next()).done) {
481
- var entry = step.value;
482
- if (entry) {
483
- if (!isNode(entry[1])) {
484
- return false;
485
- }
486
- }
487
- }
488
- }
489
- } else {
490
- return false;
491
- }
492
-
493
- return true;
494
- default:
495
- return false;
496
- }
497
-}
498
-
499
-function isSymbol(propType, propValue) {
500
- // Native Symbol.
501
- if (propType === 'symbol') {
502
- return true;
503
- }
504
-
505
- // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
506
- if (propValue['@@toStringTag'] === 'Symbol') {
507
- return true;
508
- }
509
-
510
- // Fallback for non-spec compliant Symbols which are polyfilled.
511
- if (typeof Symbol === 'function' && propValue instanceof Symbol) {
512
- return true;
513
- }
514
-
515
- return false;
516
-}
517
-
518
-// Equivalent of `typeof` but with special handling for array and regexp.
519
-function getPropType(propValue) {
520
- var propType = typeof propValue;
521
- if (Array.isArray(propValue)) {
522
- return 'array';
523
- }
524
- if (propValue instanceof RegExp) {
525
- // Old webkits (at least until Android 4.0) return 'function' rather than
526
- // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
527
- // passes PropTypes.object.
528
- return 'object';
529
- }
530
- if (isSymbol(propType, propValue)) {
531
- return 'symbol';
532
- }
533
- return propType;
534
-}
535
-
536
-// This handles more types than `getPropType`. Only used for error messages.
537
-// See `createPrimitiveTypeChecker`.
538
-function getPreciseType(propValue) {
539
- var propType = getPropType(propValue);
540
- if (propType === 'object') {
541
- if (propValue instanceof Date) {
542
- return 'date';
543
- } else if (propValue instanceof RegExp) {
544
- return 'regexp';
545
- }
546
- }
547
- return propType;
548
-}
549
-
550
-// Returns class name of the object, if any.
551
-function getClassName(propValue) {
552
- if (!propValue.constructor || !propValue.constructor.name) {
553
- return ANONYMOUS;
554
- }
555
- return propValue.constructor.name;
556
-}
557
-
558
-module.exports = ReactPropTypes;
17
+module.exports = factory(isValidElement);