react 0.10.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +3 -0
  2. package/dist/JSXTransformer.js +20344 -0
  3. package/dist/react-with-addons.js +20276 -0
  4. package/dist/react-with-addons.min.js +22 -0
  5. package/dist/react.js +18484 -0
  6. package/dist/react.min.js +21 -0
  7. package/lib/BeforeInputEventPlugin.js +222 -0
  8. package/lib/CSSPropertyOperations.js +3 -3
  9. package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
  10. package/lib/ChangeEventPlugin.js +1 -1
  11. package/lib/CompositionEventPlugin.js +5 -1
  12. package/lib/DOMChildrenOperations.js +21 -14
  13. package/lib/DOMProperty.js +45 -17
  14. package/lib/DOMPropertyOperations.js +22 -10
  15. package/lib/DefaultEventPluginOrder.js +1 -0
  16. package/lib/EventConstants.js +1 -0
  17. package/lib/EventListener.js +5 -2
  18. package/lib/EventPluginHub.js +0 -5
  19. package/lib/EventPluginRegistry.js +6 -4
  20. package/lib/EventPluginUtils.js +11 -1
  21. package/lib/ExecutionEnvironment.js +8 -2
  22. package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +42 -49
  23. package/lib/LinkedValueUtils.js +21 -22
  24. package/lib/LocalEventTrapMixin.js +52 -0
  25. package/lib/React.js +57 -3
  26. package/lib/ReactBrowserComponentMixin.js +4 -0
  27. package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
  28. package/lib/ReactCSSTransitionGroup.js +2 -0
  29. package/lib/ReactCSSTransitionGroupChild.js +2 -5
  30. package/lib/ReactChildren.js +31 -10
  31. package/lib/ReactComponent.js +88 -237
  32. package/lib/ReactComponentBrowserEnvironment.js +3 -2
  33. package/lib/ReactComponentWithPureRenderMixin.js +54 -0
  34. package/lib/ReactCompositeComponent.js +222 -384
  35. package/lib/ReactDOM.js +22 -18
  36. package/lib/ReactDOMComponent.js +26 -24
  37. package/lib/ReactDOMForm.js +5 -13
  38. package/lib/ReactDOMIDOperations.js +2 -31
  39. package/lib/ReactDOMImg.js +5 -14
  40. package/lib/ReactDOMSelect.js +16 -15
  41. package/lib/ReactDOMSelection.js +35 -10
  42. package/lib/ReactDOMTextarea.js +2 -4
  43. package/lib/ReactDefaultBatchingStrategy.js +3 -3
  44. package/lib/ReactDefaultInjection.js +18 -15
  45. package/lib/ReactDefaultPerf.js +28 -11
  46. package/lib/ReactDefaultPerfAnalysis.js +4 -0
  47. package/lib/ReactDescriptor.js +251 -0
  48. package/lib/ReactDescriptorValidator.js +283 -0
  49. package/lib/ReactEmptyComponent.js +78 -0
  50. package/lib/ReactEventEmitterMixin.js +1 -3
  51. package/lib/ReactEventListener.js +189 -0
  52. package/lib/ReactInjection.js +4 -2
  53. package/lib/ReactLink.js +24 -0
  54. package/lib/ReactMount.js +51 -19
  55. package/lib/ReactMultiChild.js +9 -11
  56. package/lib/ReactPropTransferer.js +44 -29
  57. package/lib/ReactPropTypes.js +226 -242
  58. package/lib/ReactPutListenerQueue.js +2 -2
  59. package/lib/ReactReconcileTransaction.js +14 -14
  60. package/lib/ReactServerRendering.js +5 -5
  61. package/lib/ReactServerRenderingTransaction.js +4 -5
  62. package/lib/ReactTestUtils.js +39 -21
  63. package/lib/ReactTextComponent.js +8 -22
  64. package/lib/ReactTransitionChildMapping.js +2 -2
  65. package/lib/ReactTransitionEvents.js +19 -0
  66. package/lib/ReactTransitionGroup.js +9 -6
  67. package/lib/ReactUpdates.js +139 -22
  68. package/lib/ReactWithAddons.js +5 -2
  69. package/lib/SVGDOMPropertyConfig.js +97 -0
  70. package/lib/SimpleEventPlugin.js +7 -1
  71. package/lib/SyntheticInputEvent.js +52 -0
  72. package/lib/SyntheticKeyboardEvent.js +33 -4
  73. package/lib/SyntheticMouseEvent.js +3 -0
  74. package/lib/SyntheticTouchEvent.js +4 -1
  75. package/lib/SyntheticUIEvent.js +24 -2
  76. package/lib/Transaction.js +0 -32
  77. package/lib/cloneWithProps.js +3 -1
  78. package/lib/createFullPageComponent.js +1 -1
  79. package/lib/dangerousStyleValue.js +11 -5
  80. package/lib/escapeTextForBrowser.js +2 -3
  81. package/lib/flattenChildren.js +9 -7
  82. package/lib/getEventKey.js +35 -5
  83. package/lib/getEventModifierState.js +52 -0
  84. package/lib/getMarkupWrap.js +2 -0
  85. package/lib/getTextContentAccessor.js +1 -1
  86. package/lib/hyphenate.js +3 -0
  87. package/lib/hyphenateStyleName.js +46 -0
  88. package/lib/instantiateReactComponent.js +13 -21
  89. package/lib/invariant.js +17 -19
  90. package/lib/{objMap.js → mapObject.js} +8 -3
  91. package/lib/mergeHelpers.js +11 -0
  92. package/lib/mergeInto.js +3 -2
  93. package/lib/onlyChild.js +3 -3
  94. package/lib/performance.js +33 -0
  95. package/lib/performanceNow.js +5 -14
  96. package/lib/setInnerHTML.js +85 -0
  97. package/lib/shouldUpdateReactComponent.js +12 -29
  98. package/lib/toArray.js +1 -1
  99. package/lib/traverseAllChildren.js +7 -4
  100. package/lib/update.js +57 -45
  101. package/package.json +4 -3
  102. package/lib/ReactEventTopLevelCallback.js +0 -149
  103. package/lib/createObjectFrom.js +0 -61
  104. package/lib/objMapKeyVal.js +0 -47
@@ -23,7 +23,8 @@ var EventPluginHub = require("./EventPluginHub");
23
23
  var ReactComponent = require("./ReactComponent");
24
24
  var ReactCompositeComponent = require("./ReactCompositeComponent");
25
25
  var ReactDOM = require("./ReactDOM");
26
- var ReactEventEmitter = require("./ReactEventEmitter");
26
+ var ReactEmptyComponent = require("./ReactEmptyComponent");
27
+ var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
27
28
  var ReactPerf = require("./ReactPerf");
28
29
  var ReactRootIndex = require("./ReactRootIndex");
29
30
  var ReactUpdates = require("./ReactUpdates");
@@ -32,9 +33,10 @@ var ReactInjection = {
32
33
  Component: ReactComponent.injection,
33
34
  CompositeComponent: ReactCompositeComponent.injection,
34
35
  DOMProperty: DOMProperty.injection,
36
+ EmptyComponent: ReactEmptyComponent.injection,
35
37
  EventPluginHub: EventPluginHub.injection,
36
38
  DOM: ReactDOM.injection,
37
- EventEmitter: ReactEventEmitter.injection,
39
+ EventEmitter: ReactBrowserEventEmitter.injection,
38
40
  Perf: ReactPerf.injection,
39
41
  RootIndex: ReactRootIndex.injection,
40
42
  Updates: ReactUpdates.injection
package/lib/ReactLink.js CHANGED
@@ -42,6 +42,8 @@
42
42
  * consumption of ReactLink easier; see LinkedValueUtils and LinkedStateMixin.
43
43
  */
44
44
 
45
+ var React = require("./React");
46
+
45
47
  /**
46
48
  * @param {*} value current value of the link
47
49
  * @param {function} requestChange callback to request a change
@@ -51,4 +53,26 @@ function ReactLink(value, requestChange) {
51
53
  this.requestChange = requestChange;
52
54
  }
53
55
 
56
+ /**
57
+ * Creates a PropType that enforces the ReactLink API and optionally checks the
58
+ * type of the value being passed inside the link. Example:
59
+ *
60
+ * MyComponent.propTypes = {
61
+ * tabIndexLink: ReactLink.PropTypes.link(React.PropTypes.number)
62
+ * }
63
+ */
64
+ function createLinkTypeChecker(linkType) {
65
+ var shapes = {
66
+ value: typeof linkType === 'undefined' ?
67
+ React.PropTypes.any.isRequired :
68
+ linkType.isRequired,
69
+ requestChange: React.PropTypes.func.isRequired
70
+ };
71
+ return React.PropTypes.shape(shapes);
72
+ }
73
+
74
+ ReactLink.PropTypes = {
75
+ link: createLinkTypeChecker
76
+ };
77
+
54
78
  module.exports = ReactLink;
package/lib/ReactMount.js CHANGED
@@ -19,7 +19,9 @@
19
19
  "use strict";
20
20
 
21
21
  var DOMProperty = require("./DOMProperty");
22
- var ReactEventEmitter = require("./ReactEventEmitter");
22
+ var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
23
+ var ReactCurrentOwner = require("./ReactCurrentOwner");
24
+ var ReactDescriptor = require("./ReactDescriptor");
23
25
  var ReactInstanceHandles = require("./ReactInstanceHandles");
24
26
  var ReactPerf = require("./ReactPerf");
25
27
 
@@ -28,6 +30,7 @@ var getReactRootElementInContainer = require("./getReactRootElementInContainer")
28
30
  var instantiateReactComponent = require("./instantiateReactComponent");
29
31
  var invariant = require("./invariant");
30
32
  var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
33
+ var warning = require("./warning");
31
34
 
32
35
  var SEPARATOR = ReactInstanceHandles.SEPARATOR;
33
36
 
@@ -210,15 +213,6 @@ function findDeepestCachedAncestor(targetID) {
210
213
  * Inside of `container`, the first element rendered is the "reactRoot".
211
214
  */
212
215
  var ReactMount = {
213
- /** Time spent generating markup. */
214
- totalInstantiationTime: 0,
215
-
216
- /** Time spent inserting markup into the DOM. */
217
- totalInjectionTime: 0,
218
-
219
- /** Whether support for touch events should be initialized. */
220
- useTouchEvents: false,
221
-
222
216
  /** Exposed for debugging purposes **/
223
217
  _instancesByReactRootID: instancesByReactRootID,
224
218
 
@@ -279,7 +273,7 @@ var ReactMount = {
279
273
  container.nodeType === DOC_NODE_TYPE
280
274
  )));
281
275
 
282
- ReactEventEmitter.ensureScrollValueMonitoring();
276
+ ReactBrowserEventEmitter.ensureScrollValueMonitoring();
283
277
 
284
278
  var reactRootID = ReactMount.registerContainer(container);
285
279
  instancesByReactRootID[reactRootID] = nextComponent;
@@ -300,6 +294,16 @@ var ReactMount = {
300
294
  nextComponent,
301
295
  container,
302
296
  shouldReuseMarkup) {
297
+ // Various parts of our code (such as ReactCompositeComponent's
298
+ // _renderValidatedComponent) assume that calls to render aren't nested;
299
+ // verify that that's the case.
300
+ ("production" !== process.env.NODE_ENV ? warning(
301
+ ReactCurrentOwner.current == null,
302
+ '_renderNewRootComponent(): Render methods should be a pure function ' +
303
+ 'of props and state; triggering nested component updates from ' +
304
+ 'render is not allowed. If necessary, trigger nested updates in ' +
305
+ 'componentDidUpdate.'
306
+ ) : null);
303
307
 
304
308
  var componentInstance = instantiateReactComponent(nextComponent);
305
309
  var reactRootID = ReactMount._registerComponent(
@@ -329,19 +333,35 @@ var ReactMount = {
329
333
  * perform an update on it and only mutate the DOM as necessary to reflect the
330
334
  * latest React component.
331
335
  *
332
- * @param {ReactComponent} nextComponent Component instance to render.
336
+ * @param {ReactDescriptor} nextDescriptor Component descriptor to render.
333
337
  * @param {DOMElement} container DOM element to render into.
334
338
  * @param {?function} callback function triggered on completion
335
339
  * @return {ReactComponent} Component instance rendered in `container`.
336
340
  */
337
- renderComponent: function(nextComponent, container, callback) {
341
+ renderComponent: function(nextDescriptor, container, callback) {
342
+ ("production" !== process.env.NODE_ENV ? invariant(
343
+ ReactDescriptor.isValidDescriptor(nextDescriptor),
344
+ 'renderComponent(): Invalid component descriptor.%s',
345
+ (
346
+ ReactDescriptor.isValidFactory(nextDescriptor) ?
347
+ ' Instead of passing a component class, make sure to instantiate ' +
348
+ 'it first by calling it with props.' :
349
+ // Check if it quacks like a descriptor
350
+ typeof nextDescriptor.props !== "undefined" ?
351
+ ' This may be caused by unintentionally loading two independent ' +
352
+ 'copies of React.' :
353
+ ''
354
+ )
355
+ ) : invariant(ReactDescriptor.isValidDescriptor(nextDescriptor)));
356
+
338
357
  var prevComponent = instancesByReactRootID[getReactRootID(container)];
339
358
 
340
359
  if (prevComponent) {
341
- if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
360
+ var prevDescriptor = prevComponent._descriptor;
361
+ if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
342
362
  return ReactMount._updateRootComponent(
343
363
  prevComponent,
344
- nextComponent,
364
+ nextDescriptor,
345
365
  container,
346
366
  callback
347
367
  );
@@ -357,7 +377,7 @@ var ReactMount = {
357
377
  var shouldReuseMarkup = containerHasReactMarkup && !prevComponent;
358
378
 
359
379
  var component = ReactMount._renderNewRootComponent(
360
- nextComponent,
380
+ nextDescriptor,
361
381
  container,
362
382
  shouldReuseMarkup
363
383
  );
@@ -427,6 +447,18 @@ var ReactMount = {
427
447
  * `container`
428
448
  */
429
449
  unmountComponentAtNode: function(container) {
450
+ // Various parts of our code (such as ReactCompositeComponent's
451
+ // _renderValidatedComponent) assume that calls to render aren't nested;
452
+ // verify that that's the case. (Strictly speaking, unmounting won't cause a
453
+ // render but we still don't expect to be in a render call here.)
454
+ ("production" !== process.env.NODE_ENV ? warning(
455
+ ReactCurrentOwner.current == null,
456
+ 'unmountComponentAtNode(): Render methods should be a pure function of ' +
457
+ 'props and state; triggering nested component updates from render is ' +
458
+ 'not allowed. If necessary, trigger nested updates in ' +
459
+ 'componentDidUpdate.'
460
+ ) : null);
461
+
430
462
  var reactRootID = getReactRootID(container);
431
463
  var component = instancesByReactRootID[reactRootID];
432
464
  if (!component) {
@@ -622,9 +654,9 @@ var ReactMount = {
622
654
  false,
623
655
  'findComponentRoot(..., %s): Unable to find element. This probably ' +
624
656
  'means the DOM was unexpectedly mutated (e.g., by the browser), ' +
625
- 'usually due to forgetting a <tbody> when using tables or nesting <p> ' +
626
- 'or <a> tags. Try inspecting the child nodes of the element with React ' +
627
- 'ID `%s`.',
657
+ 'usually due to forgetting a <tbody> when using tables, nesting <p> ' +
658
+ 'or <a> tags, or using non-SVG elements in an <svg> parent. Try ' +
659
+ 'inspecting the child nodes of the element with React ID `%s`.',
628
660
  targetID,
629
661
  ReactMount.getID(ancestorNode)
630
662
  ) : invariant(false));
@@ -286,11 +286,12 @@ var ReactMultiChild = {
286
286
  continue;
287
287
  }
288
288
  var prevChild = prevChildren && prevChildren[name];
289
- var nextChild = nextChildren[name];
290
- if (shouldUpdateReactComponent(prevChild, nextChild)) {
289
+ var prevDescriptor = prevChild && prevChild._descriptor;
290
+ var nextDescriptor = nextChildren[name];
291
+ if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
291
292
  this.moveChild(prevChild, nextIndex, lastIndex);
292
293
  lastIndex = Math.max(prevChild._mountIndex, lastIndex);
293
- prevChild.receiveComponent(nextChild, transaction);
294
+ prevChild.receiveComponent(nextDescriptor, transaction);
294
295
  prevChild._mountIndex = nextIndex;
295
296
  } else {
296
297
  if (prevChild) {
@@ -299,7 +300,7 @@ var ReactMultiChild = {
299
300
  this._unmountChildByName(prevChild, name);
300
301
  }
301
302
  // The child must be instantiated before it's mounted.
302
- var nextChildInstance = instantiateReactComponent(nextChild);
303
+ var nextChildInstance = instantiateReactComponent(nextDescriptor);
303
304
  this._mountChildByNameAtIndex(
304
305
  nextChildInstance, name, nextIndex, transaction
305
306
  );
@@ -416,13 +417,10 @@ var ReactMultiChild = {
416
417
  * @private
417
418
  */
418
419
  _unmountChildByName: function(child, name) {
419
- // TODO: When is this not true?
420
- if (ReactComponent.isValidComponent(child)) {
421
- this.removeChild(child);
422
- child._mountIndex = null;
423
- child.unmountComponent();
424
- delete this._renderedChildren[name];
425
- }
420
+ this.removeChild(child);
421
+ child._mountIndex = null;
422
+ child.unmountComponent();
423
+ delete this._renderedChildren[name];
426
424
  }
427
425
 
428
426
  }
@@ -40,6 +40,13 @@ function createTransferStrategy(mergeStrategy) {
40
40
  };
41
41
  }
42
42
 
43
+ var transferStrategyMerge = createTransferStrategy(function(a, b) {
44
+ // `merge` overrides the first object's (`props[key]` above) keys using the
45
+ // second object's (`value`) keys. An object's style's existing `propA` would
46
+ // get overridden. Flip the order here.
47
+ return merge(b, a);
48
+ });
49
+
43
50
  /**
44
51
  * Transfer strategies dictate how props are transferred by `transferPropsTo`.
45
52
  * NOTE: if you add any more exceptions to this list you should be sure to
@@ -65,9 +72,34 @@ var TransferStrategies = {
65
72
  /**
66
73
  * Transfer the `style` prop (which is an object) by merging them.
67
74
  */
68
- style: createTransferStrategy(merge)
75
+ style: transferStrategyMerge
69
76
  };
70
77
 
78
+ /**
79
+ * Mutates the first argument by transferring the properties from the second
80
+ * argument.
81
+ *
82
+ * @param {object} props
83
+ * @param {object} newProps
84
+ * @return {object}
85
+ */
86
+ function transferInto(props, newProps) {
87
+ for (var thisKey in newProps) {
88
+ if (!newProps.hasOwnProperty(thisKey)) {
89
+ continue;
90
+ }
91
+
92
+ var transferStrategy = TransferStrategies[thisKey];
93
+
94
+ if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) {
95
+ transferStrategy(props, thisKey, newProps[thisKey]);
96
+ } else if (!props.hasOwnProperty(thisKey)) {
97
+ props[thisKey] = newProps[thisKey];
98
+ }
99
+ }
100
+ return props;
101
+ }
102
+
71
103
  /**
72
104
  * ReactPropTransferer are capable of transferring props to another component
73
105
  * using a `transferPropsTo` method.
@@ -86,23 +118,7 @@ var ReactPropTransferer = {
86
118
  * @return {object} a new object containing both sets of props merged.
87
119
  */
88
120
  mergeProps: function(oldProps, newProps) {
89
- var props = merge(oldProps);
90
-
91
- for (var thisKey in newProps) {
92
- if (!newProps.hasOwnProperty(thisKey)) {
93
- continue;
94
- }
95
-
96
- var transferStrategy = TransferStrategies[thisKey];
97
-
98
- if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) {
99
- transferStrategy(props, thisKey, newProps[thisKey]);
100
- } else if (!props.hasOwnProperty(thisKey)) {
101
- props[thisKey] = newProps[thisKey];
102
- }
103
- }
104
-
105
- return props;
121
+ return transferInto(merge(oldProps), newProps);
106
122
  },
107
123
 
108
124
  /**
@@ -118,27 +134,26 @@ var ReactPropTransferer = {
118
134
  *
119
135
  * This is usually used to pass down props to a returned root component.
120
136
  *
121
- * @param {ReactComponent} component Component receiving the properties.
122
- * @return {ReactComponent} The supplied `component`.
137
+ * @param {ReactDescriptor} descriptor Component receiving the properties.
138
+ * @return {ReactDescriptor} The supplied `component`.
123
139
  * @final
124
140
  * @protected
125
141
  */
126
- transferPropsTo: function(component) {
142
+ transferPropsTo: function(descriptor) {
127
143
  ("production" !== process.env.NODE_ENV ? invariant(
128
- component._owner === this,
144
+ descriptor._owner === this,
129
145
  '%s: You can\'t call transferPropsTo() on a component that you ' +
130
146
  'don\'t own, %s. This usually means you are calling ' +
131
147
  'transferPropsTo() on a component passed in as props or children.',
132
148
  this.constructor.displayName,
133
- component.constructor.displayName
134
- ) : invariant(component._owner === this));
149
+ descriptor.type.displayName
150
+ ) : invariant(descriptor._owner === this));
135
151
 
136
- component.props = ReactPropTransferer.mergeProps(
137
- component.props,
138
- this.props
139
- );
152
+ // Because descriptors are immutable we have to merge into the existing
153
+ // props object rather than clone it.
154
+ transferInto(descriptor.props, this.props);
140
155
 
141
- return component;
156
+ return descriptor;
142
157
  }
143
158
 
144
159
  }
@@ -18,11 +18,10 @@
18
18
 
19
19
  "use strict";
20
20
 
21
- var ReactComponent = require("./ReactComponent");
21
+ var ReactDescriptor = require("./ReactDescriptor");
22
22
  var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
23
23
 
24
- var warning = require("./warning");
25
- var createObjectFrom = require("./createObjectFrom");
24
+ var emptyFunction = require("./emptyFunction");
26
25
 
27
26
  /**
28
27
  * Collection of methods that allow declaration and validation of props that are
@@ -51,29 +50,29 @@ var createObjectFrom = require("./createObjectFrom");
51
50
  * Each and every declaration produces a function with the same signature. This
52
51
  * allows the creation of custom validation functions. For example:
53
52
  *
54
- * var Props = require('ReactPropTypes');
55
- * var MyLink = React.createClass({
56
- * propTypes: {
57
- * // An optional string or URI prop named "href".
58
- * href: function(props, propName, componentName) {
59
- * var propValue = props[propName];
60
- * warning(
61
- * propValue == null ||
62
- * typeof propValue === 'string' ||
63
- * propValue instanceof URI,
64
- * 'Invalid `%s` supplied to `%s`, expected string or URI.',
65
- * propName,
66
- * componentName
67
- * );
68
- * }
69
- * },
70
- * render: function() { ... }
71
- * });
53
+ * var MyLink = React.createClass({
54
+ * propTypes: {
55
+ * // An optional string or URI prop named "href".
56
+ * href: function(props, propName, componentName) {
57
+ * var propValue = props[propName];
58
+ * if (propValue != null && typeof propValue !== 'string' &&
59
+ * !(propValue instanceof URI)) {
60
+ * return new Error(
61
+ * 'Expected a string or an URI for ' + propName + ' in ' +
62
+ * componentName
63
+ * );
64
+ * }
65
+ * }
66
+ * },
67
+ * render: function() {...}
68
+ * });
72
69
  *
73
70
  * @internal
74
71
  */
75
- var Props = {
76
72
 
73
+ var ANONYMOUS = '<<anonymous>>';
74
+
75
+ var ReactPropTypes = {
77
76
  array: createPrimitiveTypeChecker('array'),
78
77
  bool: createPrimitiveTypeChecker('boolean'),
79
78
  func: createPrimitiveTypeChecker('function'),
@@ -81,279 +80,264 @@ var Props = {
81
80
  object: createPrimitiveTypeChecker('object'),
82
81
  string: createPrimitiveTypeChecker('string'),
83
82
 
84
- shape: createShapeTypeChecker,
85
- oneOf: createEnumTypeChecker,
86
- oneOfType: createUnionTypeChecker,
83
+ any: createAnyTypeChecker(),
87
84
  arrayOf: createArrayOfTypeChecker,
88
-
85
+ component: createComponentTypeChecker(),
89
86
  instanceOf: createInstanceTypeChecker,
90
-
87
+ objectOf: createObjectOfTypeChecker,
88
+ oneOf: createEnumTypeChecker,
89
+ oneOfType: createUnionTypeChecker,
91
90
  renderable: createRenderableTypeChecker(),
92
-
93
- component: createComponentTypeChecker(),
94
-
95
- any: createAnyTypeChecker()
91
+ shape: createShapeTypeChecker
96
92
  };
97
93
 
98
- var ANONYMOUS = '<<anonymous>>';
99
-
100
- function isRenderable(propValue) {
101
- switch(typeof propValue) {
102
- case 'number':
103
- case 'string':
104
- return true;
105
- case 'object':
106
- if (Array.isArray(propValue)) {
107
- return propValue.every(isRenderable);
108
- }
109
- if (ReactComponent.isValidComponent(propValue)) {
110
- return true;
111
- }
112
- for (var k in propValue) {
113
- if (!isRenderable(propValue[k])) {
114
- return false;
115
- }
94
+ function createChainableTypeChecker(validate) {
95
+ function checkType(isRequired, props, propName, componentName, location) {
96
+ componentName = componentName || ANONYMOUS;
97
+ if (props[propName] == null) {
98
+ var locationName = ReactPropTypeLocationNames[location];
99
+ if (isRequired) {
100
+ return new Error(
101
+ ("Required " + locationName + " `" + propName + "` was not specified in ")+
102
+ ("`" + componentName + "`.")
103
+ );
116
104
  }
117
- return true;
118
- default:
119
- return false;
105
+ } else {
106
+ return validate(props, propName, componentName, location);
107
+ }
120
108
  }
109
+
110
+ var chainedCheckType = checkType.bind(null, false);
111
+ chainedCheckType.isRequired = checkType.bind(null, true);
112
+
113
+ return chainedCheckType;
121
114
  }
122
115
 
123
- // Equivalent of typeof but with special handling for arrays
124
- function getPropType(propValue) {
125
- var propType = typeof propValue;
126
- if (propType === 'object' && Array.isArray(propValue)) {
127
- return 'array';
116
+ function createPrimitiveTypeChecker(expectedType) {
117
+ function validate(props, propName, componentName, location) {
118
+ var propValue = props[propName];
119
+ var propType = getPropType(propValue);
120
+ if (propType !== expectedType) {
121
+ var locationName = ReactPropTypeLocationNames[location];
122
+ // `propValue` being instance of, say, date/regexp, pass the 'object'
123
+ // check, but we can offer a more precise error message here rather than
124
+ // 'of type `object`'.
125
+ var preciseType = getPreciseType(propValue);
126
+
127
+ return new Error(
128
+ ("Invalid " + locationName + " `" + propName + "` of type `" + preciseType + "` ") +
129
+ ("supplied to `" + componentName + "`, expected `" + expectedType + "`.")
130
+ );
131
+ }
128
132
  }
129
- return propType;
133
+ return createChainableTypeChecker(validate);
130
134
  }
131
135
 
132
136
  function createAnyTypeChecker() {
133
- function validateAnyType(
134
- shouldWarn, propValue, propName, componentName, location
135
- ) {
136
- return true; // is always valid
137
- }
138
- return createChainableTypeChecker(validateAnyType);
137
+ return createChainableTypeChecker(emptyFunction.thatReturns());
139
138
  }
140
139
 
141
- function createPrimitiveTypeChecker(expectedType) {
142
- function validatePrimitiveType(
143
- shouldWarn, propValue, propName, componentName, location
144
- ) {
145
- var propType = getPropType(propValue);
146
- var isValid = propType === expectedType;
147
- if (shouldWarn) {
148
- ("production" !== process.env.NODE_ENV ? warning(
149
- isValid,
150
- 'Invalid %s `%s` of type `%s` supplied to `%s`, expected `%s`.',
151
- ReactPropTypeLocationNames[location],
152
- propName,
153
- propType,
154
- componentName,
155
- expectedType
156
- ) : null);
140
+ function createArrayOfTypeChecker(typeChecker) {
141
+ function validate(props, propName, componentName, location) {
142
+ var propValue = props[propName];
143
+ if (!Array.isArray(propValue)) {
144
+ var locationName = ReactPropTypeLocationNames[location];
145
+ var propType = getPropType(propValue);
146
+ return new Error(
147
+ ("Invalid " + locationName + " `" + propName + "` of type ") +
148
+ ("`" + propType + "` supplied to `" + componentName + "`, expected an array.")
149
+ );
150
+ }
151
+ for (var i = 0; i < propValue.length; i++) {
152
+ var error = typeChecker(propValue, i, componentName, location);
153
+ if (error instanceof Error) {
154
+ return error;
155
+ }
157
156
  }
158
- return isValid;
159
157
  }
160
- return createChainableTypeChecker(validatePrimitiveType);
158
+ return createChainableTypeChecker(validate);
161
159
  }
162
160
 
163
- function createEnumTypeChecker(expectedValues) {
164
- var expectedEnum = createObjectFrom(expectedValues);
165
- function validateEnumType(
166
- shouldWarn, propValue, propName, componentName, location
167
- ) {
168
- var isValid = expectedEnum[propValue];
169
- if (shouldWarn) {
170
- ("production" !== process.env.NODE_ENV ? warning(
171
- isValid,
172
- 'Invalid %s `%s` supplied to `%s`, expected one of %s.',
173
- ReactPropTypeLocationNames[location],
174
- propName,
175
- componentName,
176
- JSON.stringify(Object.keys(expectedEnum))
177
- ) : null);
161
+ function createComponentTypeChecker() {
162
+ function validate(props, propName, componentName, location) {
163
+ if (!ReactDescriptor.isValidDescriptor(props[propName])) {
164
+ var locationName = ReactPropTypeLocationNames[location];
165
+ return new Error(
166
+ ("Invalid " + locationName + " `" + propName + "` supplied to ") +
167
+ ("`" + componentName + "`, expected a React component.")
168
+ );
178
169
  }
179
- return isValid;
180
170
  }
181
- return createChainableTypeChecker(validateEnumType);
171
+ return createChainableTypeChecker(validate);
182
172
  }
183
173
 
184
- function createShapeTypeChecker(shapeTypes) {
185
- function validateShapeType(
186
- shouldWarn, propValue, propName, componentName, location
187
- ) {
188
- var propType = getPropType(propValue);
189
- var isValid = propType === 'object';
190
- if (isValid) {
191
- for (var key in shapeTypes) {
192
- var checker = shapeTypes[key];
193
- if (checker && !checker(propValue, key, componentName, location)) {
194
- return false;
195
- }
196
- }
197
- }
198
- if (shouldWarn) {
199
- ("production" !== process.env.NODE_ENV ? warning(
200
- isValid,
201
- 'Invalid %s `%s` of type `%s` supplied to `%s`, expected `object`.',
202
- ReactPropTypeLocationNames[location],
203
- propName,
204
- propType,
205
- componentName
206
- ) : null);
174
+ function createInstanceTypeChecker(expectedClass) {
175
+ function validate(props, propName, componentName, location) {
176
+ if (!(props[propName] instanceof expectedClass)) {
177
+ var locationName = ReactPropTypeLocationNames[location];
178
+ var expectedClassName = expectedClass.name || ANONYMOUS;
179
+ return new Error(
180
+ ("Invalid " + locationName + " `" + propName + "` supplied to ") +
181
+ ("`" + componentName + "`, expected instance of `" + expectedClassName + "`.")
182
+ );
207
183
  }
208
- return isValid;
209
184
  }
210
- return createChainableTypeChecker(validateShapeType);
185
+ return createChainableTypeChecker(validate);
211
186
  }
212
187
 
213
- function createInstanceTypeChecker(expectedClass) {
214
- function validateInstanceType(
215
- shouldWarn, propValue, propName, componentName, location
216
- ) {
217
- var isValid = propValue instanceof expectedClass;
218
- if (shouldWarn) {
219
- ("production" !== process.env.NODE_ENV ? warning(
220
- isValid,
221
- 'Invalid %s `%s` supplied to `%s`, expected instance of `%s`.',
222
- ReactPropTypeLocationNames[location],
223
- propName,
224
- componentName,
225
- expectedClass.name || ANONYMOUS
226
- ) : null);
188
+ function createEnumTypeChecker(expectedValues) {
189
+ function validate(props, propName, componentName, location) {
190
+ var propValue = props[propName];
191
+ for (var i = 0; i < expectedValues.length; i++) {
192
+ if (propValue === expectedValues[i]) {
193
+ return;
194
+ }
227
195
  }
228
- return isValid;
196
+
197
+ var locationName = ReactPropTypeLocationNames[location];
198
+ var valuesString = JSON.stringify(expectedValues);
199
+ return new Error(
200
+ ("Invalid " + locationName + " `" + propName + "` of value `" + propValue + "` ") +
201
+ ("supplied to `" + componentName + "`, expected one of " + valuesString + ".")
202
+ );
229
203
  }
230
- return createChainableTypeChecker(validateInstanceType);
204
+ return createChainableTypeChecker(validate);
231
205
  }
232
206
 
233
- function createArrayOfTypeChecker(propTypeChecker) {
234
- function validateArrayType(
235
- shouldWarn, propValue, propName, componentName, location
236
- ) {
237
- var isValid = Array.isArray(propValue);
238
- if (isValid) {
239
- for (var i = 0; i < propValue.length; i++) {
240
- if (!propTypeChecker(propValue, i, componentName, location)) {
241
- return false;
207
+ function createObjectOfTypeChecker(typeChecker) {
208
+ function validate(props, propName, componentName, location) {
209
+ var propValue = props[propName];
210
+ var propType = getPropType(propValue);
211
+ if (propType !== 'object') {
212
+ var locationName = ReactPropTypeLocationNames[location];
213
+ return new Error(
214
+ ("Invalid " + locationName + " `" + propName + "` of type ") +
215
+ ("`" + propType + "` supplied to `" + componentName + "`, expected an object.")
216
+ );
217
+ }
218
+ for (var key in propValue) {
219
+ if (propValue.hasOwnProperty(key)) {
220
+ var error = typeChecker(propValue, key, componentName, location);
221
+ if (error instanceof Error) {
222
+ return error;
242
223
  }
243
224
  }
244
225
  }
245
- if (shouldWarn) {
246
- ("production" !== process.env.NODE_ENV ? warning(
247
- isValid,
248
- 'Invalid %s `%s` supplied to `%s`, expected an array.',
249
- ReactPropTypeLocationNames[location],
250
- propName,
251
- componentName
252
- ) : null);
253
- }
254
- return isValid;
255
226
  }
256
- return createChainableTypeChecker(validateArrayType);
227
+ return createChainableTypeChecker(validate);
257
228
  }
258
229
 
259
- function createRenderableTypeChecker() {
260
- function validateRenderableType(
261
- shouldWarn, propValue, propName, componentName, location
262
- ) {
263
- var isValid = isRenderable(propValue);
264
- if (shouldWarn) {
265
- ("production" !== process.env.NODE_ENV ? warning(
266
- isValid,
267
- 'Invalid %s `%s` supplied to `%s`, expected a renderable prop.',
268
- ReactPropTypeLocationNames[location],
269
- propName,
270
- componentName
271
- ) : null);
230
+ function createUnionTypeChecker(arrayOfTypeCheckers) {
231
+ function validate(props, propName, componentName, location) {
232
+ for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
233
+ var checker = arrayOfTypeCheckers[i];
234
+ if (checker(props, propName, componentName, location) == null) {
235
+ return;
236
+ }
272
237
  }
273
- return isValid;
238
+
239
+ var locationName = ReactPropTypeLocationNames[location];
240
+ return new Error(
241
+ ("Invalid " + locationName + " `" + propName + "` supplied to ") +
242
+ ("`" + componentName + "`.")
243
+ );
274
244
  }
275
- return createChainableTypeChecker(validateRenderableType);
245
+ return createChainableTypeChecker(validate);
276
246
  }
277
247
 
278
- function createComponentTypeChecker() {
279
- function validateComponentType(
280
- shouldWarn, propValue, propName, componentName, location
281
- ) {
282
- var isValid = ReactComponent.isValidComponent(propValue);
283
- if (shouldWarn) {
284
- ("production" !== process.env.NODE_ENV ? warning(
285
- isValid,
286
- 'Invalid %s `%s` supplied to `%s`, expected a React component.',
287
- ReactPropTypeLocationNames[location],
288
- propName,
289
- componentName
290
- ) : null);
248
+ function createRenderableTypeChecker() {
249
+ function validate(props, propName, componentName, location) {
250
+ if (!isRenderable(props[propName])) {
251
+ var locationName = ReactPropTypeLocationNames[location];
252
+ return new Error(
253
+ ("Invalid " + locationName + " `" + propName + "` supplied to ") +
254
+ ("`" + componentName + "`, expected a renderable prop.")
255
+ );
291
256
  }
292
- return isValid;
293
257
  }
294
- return createChainableTypeChecker(validateComponentType);
258
+ return createChainableTypeChecker(validate);
295
259
  }
296
260
 
297
- function createUnionTypeChecker(arrayOfValidators) {
298
- return function(props, propName, componentName, location) {
299
- var isValid = false;
300
- for (var ii = 0; ii < arrayOfValidators.length; ii++) {
301
- var validate = arrayOfValidators[ii];
302
- if (typeof validate.weak === 'function') {
303
- validate = validate.weak;
261
+ function createShapeTypeChecker(shapeTypes) {
262
+ function validate(props, propName, componentName, location) {
263
+ var propValue = props[propName];
264
+ var propType = getPropType(propValue);
265
+ if (propType !== 'object') {
266
+ var locationName = ReactPropTypeLocationNames[location];
267
+ return new Error(
268
+ ("Invalid " + locationName + " `" + propName + "` of type `" + propType + "` ") +
269
+ ("supplied to `" + componentName + "`, expected `object`.")
270
+ );
271
+ }
272
+ for (var key in shapeTypes) {
273
+ var checker = shapeTypes[key];
274
+ if (!checker) {
275
+ continue;
304
276
  }
305
- if (validate(props, propName, componentName, location)) {
306
- isValid = true;
307
- break;
277
+ var error = checker(propValue, key, componentName, location);
278
+ if (error) {
279
+ return error;
308
280
  }
309
281
  }
310
- ("production" !== process.env.NODE_ENV ? warning(
311
- isValid,
312
- 'Invalid %s `%s` supplied to `%s`.',
313
- ReactPropTypeLocationNames[location],
314
- propName,
315
- componentName || ANONYMOUS
316
- ) : null);
317
- return isValid;
318
- };
282
+ }
283
+ return createChainableTypeChecker(validate, 'expected `object`');
319
284
  }
320
285
 
321
- function createChainableTypeChecker(validate) {
322
- function checkType(
323
- isRequired, shouldWarn, props, propName, componentName, location
324
- ) {
325
- var propValue = props[propName];
326
- if (propValue != null) {
327
- // Only validate if there is a value to check.
328
- return validate(
329
- shouldWarn,
330
- propValue,
331
- propName,
332
- componentName || ANONYMOUS,
333
- location
334
- );
335
- } else {
336
- var isValid = !isRequired;
337
- if (shouldWarn) {
338
- ("production" !== process.env.NODE_ENV ? warning(
339
- isValid,
340
- 'Required %s `%s` was not specified in `%s`.',
341
- ReactPropTypeLocationNames[location],
342
- propName,
343
- componentName || ANONYMOUS
344
- ) : null);
286
+ function isRenderable(propValue) {
287
+ switch(typeof propValue) {
288
+ // TODO: this was probably written with the assumption that we're not
289
+ // returning `this.props.component` directly from `render`. This is
290
+ // currently not supported but we should, to make it consistent.
291
+ case 'number':
292
+ case 'string':
293
+ return true;
294
+ case 'boolean':
295
+ return !propValue;
296
+ case 'object':
297
+ if (Array.isArray(propValue)) {
298
+ return propValue.every(isRenderable);
345
299
  }
346
- return isValid;
347
- }
300
+ if (ReactDescriptor.isValidDescriptor(propValue)) {
301
+ return true;
302
+ }
303
+ for (var k in propValue) {
304
+ if (!isRenderable(propValue[k])) {
305
+ return false;
306
+ }
307
+ }
308
+ return true;
309
+ default:
310
+ return false;
348
311
  }
312
+ }
349
313
 
350
- var checker = checkType.bind(null, false, true);
351
- checker.weak = checkType.bind(null, false, false);
352
- checker.isRequired = checkType.bind(null, true, true);
353
- checker.weak.isRequired = checkType.bind(null, true, false);
354
- checker.isRequired.weak = checker.weak.isRequired;
314
+ // Equivalent of `typeof` but with special handling for array and regexp.
315
+ function getPropType(propValue) {
316
+ var propType = typeof propValue;
317
+ if (Array.isArray(propValue)) {
318
+ return 'array';
319
+ }
320
+ if (propValue instanceof RegExp) {
321
+ // Old webkits (at least until Android 4.0) return 'function' rather than
322
+ // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
323
+ // passes PropTypes.object.
324
+ return 'object';
325
+ }
326
+ return propType;
327
+ }
355
328
 
356
- return checker;
329
+ // This handles more types than `getPropType`. Only used for error messages.
330
+ // See `createPrimitiveTypeChecker`.
331
+ function getPreciseType(propValue) {
332
+ var propType = getPropType(propValue);
333
+ if (propType === 'object') {
334
+ if (propValue instanceof Date) {
335
+ return 'date';
336
+ } else if (propValue instanceof RegExp) {
337
+ return 'regexp';
338
+ }
339
+ }
340
+ return propType;
357
341
  }
358
342
 
359
- module.exports = Props;
343
+ module.exports = ReactPropTypes;