react 0.8.0 → 0.9.0-rc1

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 (107) hide show
  1. package/README.md +0 -8
  2. package/addons.js +0 -3
  3. package/lib/AutoFocusMixin.js +30 -0
  4. package/lib/CSSCore.js +22 -21
  5. package/lib/CSSProperty.js +31 -0
  6. package/lib/ChangeEventPlugin.js +26 -4
  7. package/lib/ClientReactRootIndex.js +30 -0
  8. package/lib/CompositionEventPlugin.js +57 -9
  9. package/lib/DOMChildrenOperations.js +32 -2
  10. package/lib/DOMProperty.js +2 -0
  11. package/lib/DOMPropertyOperations.js +14 -1
  12. package/lib/Danger.js +8 -7
  13. package/lib/DefaultDOMPropertyConfig.js +12 -2
  14. package/lib/EnterLeaveEventPlugin.js +37 -4
  15. package/lib/EventConstants.js +3 -0
  16. package/lib/EventListener.js +42 -34
  17. package/lib/EventPluginHub.js +113 -12
  18. package/lib/EventPluginRegistry.js +39 -16
  19. package/lib/EventPluginUtils.js +32 -3
  20. package/lib/EventPropagators.js +6 -42
  21. package/lib/ExecutionEnvironment.js +3 -0
  22. package/lib/LinkedValueUtils.js +161 -0
  23. package/lib/PooledClass.js +6 -0
  24. package/lib/React.js +27 -3
  25. package/lib/ReactCSSTransitionGroup.js +65 -0
  26. package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +21 -35
  27. package/lib/ReactComponent.js +87 -52
  28. package/lib/ReactComponentBrowserEnvironment.js +67 -49
  29. package/lib/ReactComponentEnvironment.js +2 -0
  30. package/lib/ReactCompositeComponent.js +547 -112
  31. package/lib/ReactContext.js +67 -0
  32. package/lib/ReactDOM.js +13 -0
  33. package/lib/ReactDOMButton.js +4 -0
  34. package/lib/ReactDOMComponent.js +46 -21
  35. package/lib/ReactDOMForm.js +9 -2
  36. package/lib/ReactDOMIDOperations.js +105 -60
  37. package/lib/ReactDOMImg.js +58 -0
  38. package/lib/ReactDOMInput.js +26 -14
  39. package/lib/ReactDOMOption.js +1 -0
  40. package/lib/ReactDOMSelect.js +36 -17
  41. package/lib/ReactDOMTextarea.js +12 -8
  42. package/lib/ReactDefaultInjection.js +50 -26
  43. package/lib/ReactDefaultPerf.js +207 -370
  44. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  45. package/lib/ReactErrorUtils.js +5 -14
  46. package/lib/ReactEventEmitter.js +141 -145
  47. package/lib/ReactEventEmitterMixin.js +0 -32
  48. package/lib/ReactEventTopLevelCallback.js +32 -12
  49. package/lib/ReactInjection.js +39 -0
  50. package/lib/ReactInstanceHandles.js +35 -19
  51. package/lib/ReactLink.js +1 -1
  52. package/lib/ReactMount.js +127 -103
  53. package/lib/ReactMountReady.js +1 -1
  54. package/lib/ReactMultiChild.js +30 -46
  55. package/lib/ReactMultiChildUpdateTypes.js +2 -0
  56. package/lib/ReactOwner.js +10 -2
  57. package/lib/ReactPerf.js +5 -8
  58. package/lib/ReactPropTransferer.js +40 -21
  59. package/lib/ReactPropTypeLocationNames.js +31 -0
  60. package/lib/ReactPropTypeLocations.js +29 -0
  61. package/lib/ReactPropTypes.js +248 -47
  62. package/lib/ReactPutListenerQueue.js +61 -0
  63. package/lib/ReactReconcileTransaction.js +20 -0
  64. package/lib/ReactRootIndex.js +36 -0
  65. package/lib/ReactServerRendering.js +8 -11
  66. package/lib/ReactTextComponent.js +8 -3
  67. package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +42 -47
  68. package/lib/ReactTransitionGroup.js +132 -57
  69. package/lib/ReactUpdates.js +14 -11
  70. package/lib/ReactWithAddons.js +7 -2
  71. package/lib/SelectEventPlugin.js +22 -39
  72. package/lib/ServerReactRootIndex.js +36 -0
  73. package/lib/SimpleEventPlugin.js +54 -6
  74. package/lib/SyntheticClipboardEvent.js +7 -1
  75. package/lib/SyntheticDragEvent.js +44 -0
  76. package/lib/SyntheticEvent.js +2 -1
  77. package/lib/SyntheticKeyboardEvent.js +4 -2
  78. package/lib/SyntheticWheelEvent.js +10 -7
  79. package/lib/Transaction.js +61 -36
  80. package/lib/cloneWithProps.js +59 -0
  81. package/lib/createArrayFrom.js +10 -13
  82. package/lib/createFullPageComponent.js +63 -0
  83. package/lib/cx.js +2 -2
  84. package/lib/flattenChildren.js +5 -2
  85. package/lib/getActiveElement.js +4 -3
  86. package/lib/getEventKey.js +85 -0
  87. package/lib/getMarkupWrap.js +10 -0
  88. package/lib/getTextContentAccessor.js +5 -3
  89. package/lib/getUnboundedScrollPosition.js +2 -2
  90. package/lib/invariant.js +12 -4
  91. package/lib/isEventSupported.js +7 -11
  92. package/lib/mergeHelpers.js +5 -6
  93. package/lib/onlyChild.js +43 -0
  94. package/lib/shouldUpdateReactComponent.js +58 -0
  95. package/lib/toArray.js +75 -0
  96. package/lib/traverseAllChildren.js +69 -7
  97. package/lib/warning.js +40 -0
  98. package/package.json +2 -3
  99. package/react.js +0 -3
  100. package/ReactJSErrors.js +0 -40
  101. package/lib/$.js +0 -46
  102. package/lib/CallbackRegistry.js +0 -91
  103. package/lib/LinkedValueMixin.js +0 -68
  104. package/lib/ex.js +0 -49
  105. package/lib/filterAttributes.js +0 -45
  106. package/lib/ge.js +0 -76
  107. package/lib/mutateHTMLNodeWithMarkup.js +0 -100
@@ -66,7 +66,7 @@ mixInto(ReactMountReady, {
66
66
  for (var i = 0, l = queue.length; i < l; i++) {
67
67
  var component = queue[i].component;
68
68
  var callback = queue[i].callback;
69
- callback.call(component, component.getDOMNode());
69
+ callback.call(component);
70
70
  }
71
71
  queue.length = 0;
72
72
  }
@@ -23,19 +23,7 @@ var ReactComponent = require("./ReactComponent");
23
23
  var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes");
24
24
 
25
25
  var flattenChildren = require("./flattenChildren");
26
-
27
- /**
28
- * Given a `curChild` and `newChild`, determines if `curChild` should be
29
- * updated as opposed to being destroyed or replaced.
30
- *
31
- * @param {?ReactComponent} curChild
32
- * @param {?ReactComponent} newChild
33
- * @return {boolean} True if `curChild` should be updated with `newChild`.
34
- * @protected
35
- */
36
- function shouldUpdateChild(curChild, newChild) {
37
- return curChild && newChild && curChild.constructor === newChild.constructor;
38
- }
26
+ var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
39
27
 
40
28
  /**
41
29
  * Updating children of a component may trigger recursive updates. The depth is
@@ -153,7 +141,7 @@ function enqueueTextContent(parentID, textContent) {
153
141
  */
154
142
  function processQueue() {
155
143
  if (updateQueue.length) {
156
- ReactComponent.DOMIDOperations.dangerouslyProcessChildrenUpdates(
144
+ ReactComponent.BackendIDOperations.dangerouslyProcessChildrenUpdates(
157
145
  updateQueue,
158
146
  markupQueue
159
147
  );
@@ -203,15 +191,14 @@ var ReactMultiChild = {
203
191
  this._renderedChildren = children;
204
192
  for (var name in children) {
205
193
  var child = children[name];
206
- if (children.hasOwnProperty(name) && child) {
194
+ if (children.hasOwnProperty(name)) {
207
195
  // Inlined for performance, see `ReactInstanceHandles.createReactID`.
208
- var rootID = this._rootNodeID + '.' + name;
196
+ var rootID = this._rootNodeID + name;
209
197
  var mountImage = child.mountComponent(
210
198
  rootID,
211
199
  transaction,
212
200
  this._mountDepth + 1
213
201
  );
214
- child._mountImage = mountImage;
215
202
  child._mountIndex = index;
216
203
  mountImages.push(mountImage);
217
204
  index++;
@@ -228,24 +215,24 @@ var ReactMultiChild = {
228
215
  */
229
216
  updateTextContent: function(nextContent) {
230
217
  updateDepth++;
218
+ var errorThrown = true;
231
219
  try {
232
220
  var prevChildren = this._renderedChildren;
233
221
  // Remove any rendered children.
234
222
  for (var name in prevChildren) {
235
- if (prevChildren.hasOwnProperty(name) &&
236
- prevChildren[name]) {
223
+ if (prevChildren.hasOwnProperty(name)) {
237
224
  this._unmountChildByName(prevChildren[name], name);
238
225
  }
239
226
  }
240
227
  // Set new text content.
241
228
  this.setTextContent(nextContent);
242
- } catch (error) {
229
+ errorThrown = false;
230
+ } finally {
243
231
  updateDepth--;
244
- updateDepth || clearQueue();
245
- throw error;
232
+ if (!updateDepth) {
233
+ errorThrown ? clearQueue() : processQueue();
234
+ }
246
235
  }
247
- updateDepth--;
248
- updateDepth || processQueue();
249
236
  },
250
237
 
251
238
  /**
@@ -257,15 +244,16 @@ var ReactMultiChild = {
257
244
  */
258
245
  updateChildren: function(nextNestedChildren, transaction) {
259
246
  updateDepth++;
247
+ var errorThrown = true;
260
248
  try {
261
249
  this._updateChildren(nextNestedChildren, transaction);
262
- } catch (error) {
250
+ errorThrown = false;
251
+ } finally {
263
252
  updateDepth--;
264
- updateDepth || clearQueue();
265
- throw error;
253
+ if (!updateDepth) {
254
+ errorThrown ? clearQueue() : processQueue();
255
+ }
266
256
  }
267
- updateDepth--;
268
- updateDepth || processQueue();
269
257
  },
270
258
 
271
259
  /**
@@ -294,7 +282,7 @@ var ReactMultiChild = {
294
282
  }
295
283
  var prevChild = prevChildren && prevChildren[name];
296
284
  var nextChild = nextChildren[name];
297
- if (shouldUpdateChild(prevChild, nextChild)) {
285
+ if (shouldUpdateReactComponent(prevChild, nextChild)) {
298
286
  this.moveChild(prevChild, nextIndex, lastIndex);
299
287
  lastIndex = Math.max(prevChild._mountIndex, lastIndex);
300
288
  prevChild.receiveComponent(nextChild, transaction);
@@ -305,20 +293,15 @@ var ReactMultiChild = {
305
293
  lastIndex = Math.max(prevChild._mountIndex, lastIndex);
306
294
  this._unmountChildByName(prevChild, name);
307
295
  }
308
- if (nextChild) {
309
- this._mountChildByNameAtIndex(
310
- nextChild, name, nextIndex, transaction
311
- );
312
- }
313
- }
314
- if (nextChild) {
315
- nextIndex++;
296
+ this._mountChildByNameAtIndex(
297
+ nextChild, name, nextIndex, transaction
298
+ );
316
299
  }
300
+ nextIndex++;
317
301
  }
318
302
  // Remove children that are no longer present.
319
303
  for (name in prevChildren) {
320
304
  if (prevChildren.hasOwnProperty(name) &&
321
- prevChildren[name] &&
322
305
  !(nextChildren && nextChildren[name])) {
323
306
  this._unmountChildByName(prevChildren[name], name);
324
307
  }
@@ -335,7 +318,8 @@ var ReactMultiChild = {
335
318
  var renderedChildren = this._renderedChildren;
336
319
  for (var name in renderedChildren) {
337
320
  var renderedChild = renderedChildren[name];
338
- if (renderedChild && renderedChild.unmountComponent) {
321
+ // TODO: When is this not true?
322
+ if (renderedChild.unmountComponent) {
339
323
  renderedChild.unmountComponent();
340
324
  }
341
325
  }
@@ -363,10 +347,11 @@ var ReactMultiChild = {
363
347
  * Creates a child component.
364
348
  *
365
349
  * @param {ReactComponent} child Component to create.
350
+ * @param {string} mountImage Markup to insert.
366
351
  * @protected
367
352
  */
368
- createChild: function(child) {
369
- enqueueMarkup(this._rootNodeID, child._mountImage, child._mountIndex);
353
+ createChild: function(child, mountImage) {
354
+ enqueueMarkup(this._rootNodeID, mountImage, child._mountIndex);
370
355
  },
371
356
 
372
357
  /**
@@ -402,15 +387,14 @@ var ReactMultiChild = {
402
387
  */
403
388
  _mountChildByNameAtIndex: function(child, name, index, transaction) {
404
389
  // Inlined for performance, see `ReactInstanceHandles.createReactID`.
405
- var rootID = this._rootNodeID + '.' + name;
390
+ var rootID = this._rootNodeID + name;
406
391
  var mountImage = child.mountComponent(
407
392
  rootID,
408
393
  transaction,
409
394
  this._mountDepth + 1
410
395
  );
411
- child._mountImage = mountImage;
412
396
  child._mountIndex = index;
413
- this.createChild(child);
397
+ this.createChild(child, mountImage);
414
398
  this._renderedChildren = this._renderedChildren || {};
415
399
  this._renderedChildren[name] = child;
416
400
  },
@@ -425,9 +409,9 @@ var ReactMultiChild = {
425
409
  * @private
426
410
  */
427
411
  _unmountChildByName: function(child, name) {
412
+ // TODO: When is this not true?
428
413
  if (ReactComponent.isValidComponent(child)) {
429
414
  this.removeChild(child);
430
- child._mountImage = null;
431
415
  child._mountIndex = null;
432
416
  child.unmountComponent();
433
417
  delete this._renderedChildren[name];
@@ -16,6 +16,8 @@
16
16
  * @providesModule ReactMultiChildUpdateTypes
17
17
  */
18
18
 
19
+ "use strict";
20
+
19
21
  var keyMirror = require("./keyMirror");
20
22
 
21
23
  /**
package/lib/ReactOwner.js CHANGED
@@ -77,7 +77,11 @@ var ReactOwner = {
77
77
  addComponentAsRefTo: function(component, ref, owner) {
78
78
  ("production" !== process.env.NODE_ENV ? invariant(
79
79
  ReactOwner.isValidOwner(owner),
80
- 'addComponentAsRefTo(...): Only a ReactOwner can have refs.'
80
+ 'addComponentAsRefTo(...): Only a ReactOwner can have refs. This ' +
81
+ 'usually means that you\'re trying to add a ref to a component that ' +
82
+ 'doesn\'t have an owner (that is, was not created inside of another ' +
83
+ 'component\'s `render` method). Try rendering this component inside of ' +
84
+ 'a new top-level component which will hold the ref.'
81
85
  ) : invariant(ReactOwner.isValidOwner(owner)));
82
86
  owner.attachRef(ref, component);
83
87
  },
@@ -94,7 +98,11 @@ var ReactOwner = {
94
98
  removeComponentAsRefFrom: function(component, ref, owner) {
95
99
  ("production" !== process.env.NODE_ENV ? invariant(
96
100
  ReactOwner.isValidOwner(owner),
97
- 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs.'
101
+ 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. This ' +
102
+ 'usually means that you\'re trying to remove a ref to a component that ' +
103
+ 'doesn\'t have an owner (that is, was not created inside of another ' +
104
+ 'component\'s `render` method). Try rendering this component inside of ' +
105
+ 'a new top-level component which will hold the ref.'
98
106
  ) : invariant(ReactOwner.isValidOwner(owner)));
99
107
  // Check that `component` is still the current ref because we do not want to
100
108
  // detach the ref if another component stole it.
package/lib/ReactPerf.js CHANGED
@@ -19,6 +19,10 @@
19
19
 
20
20
  "use strict";
21
21
 
22
+ /**
23
+ * ReactPerf is a general AOP system designed to measure performance. This
24
+ * module only has the hooks: see ReactDefaultPerf for the analysis tool.
25
+ */
22
26
  var ReactPerf = {
23
27
  /**
24
28
  * Boolean to enable/disable measurement. Set to false by default to prevent
@@ -33,7 +37,7 @@ var ReactPerf = {
33
37
  storedMeasure: _noMeasure,
34
38
 
35
39
  /**
36
- * Use this to wrap methods you want to measure.
40
+ * Use this to wrap methods you want to measure. Zero overhead in production.
37
41
  *
38
42
  * @param {string} objName
39
43
  * @param {string} fnName
@@ -66,13 +70,6 @@ var ReactPerf = {
66
70
  }
67
71
  };
68
72
 
69
- if ("production" !== process.env.NODE_ENV) {
70
- var ExecutionEnvironment = require("./ExecutionEnvironment");
71
- var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
72
- ReactPerf.enableMeasure = ReactPerf.enableMeasure ||
73
- (/[?&]react_perf\b/).test(url);
74
- }
75
-
76
73
  /**
77
74
  * Simply passes through the measured function, without measuring it.
78
75
  *
@@ -42,6 +42,8 @@ function createTransferStrategy(mergeStrategy) {
42
42
 
43
43
  /**
44
44
  * Transfer strategies dictate how props are transferred by `transferPropsTo`.
45
+ * NOTE: if you add any more exceptions to this list you should be sure to
46
+ * update `cloneWithProps()` accordingly.
45
47
  */
46
48
  var TransferStrategies = {
47
49
  /**
@@ -52,6 +54,10 @@ var TransferStrategies = {
52
54
  * Transfer the `className` prop by merging them.
53
55
  */
54
56
  className: createTransferStrategy(joinClasses),
57
+ /**
58
+ * Never transfer the `key` prop.
59
+ */
60
+ key: emptyFunction,
55
61
  /**
56
62
  * Never transfer the `ref` prop.
57
63
  */
@@ -72,6 +78,33 @@ var ReactPropTransferer = {
72
78
 
73
79
  TransferStrategies: TransferStrategies,
74
80
 
81
+ /**
82
+ * Merge two props objects using TransferStrategies.
83
+ *
84
+ * @param {object} oldProps original props (they take precedence)
85
+ * @param {object} newProps new props to merge in
86
+ * @return {object} a new object containing both sets of props merged.
87
+ */
88
+ 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) {
99
+ transferStrategy(props, thisKey, newProps[thisKey]);
100
+ } else if (!props.hasOwnProperty(thisKey)) {
101
+ props[thisKey] = newProps[thisKey];
102
+ }
103
+ }
104
+
105
+ return props;
106
+ },
107
+
75
108
  /**
76
109
  * @lends {ReactPropTransferer.prototype}
77
110
  */
@@ -92,37 +125,23 @@ var ReactPropTransferer = {
92
125
  */
93
126
  transferPropsTo: function(component) {
94
127
  ("production" !== process.env.NODE_ENV ? invariant(
95
- component.props.__owner__ === this,
128
+ component._owner === this,
96
129
  '%s: You can\'t call transferPropsTo() on a component that you ' +
97
130
  'don\'t own, %s. This usually means you are calling ' +
98
131
  'transferPropsTo() on a component passed in as props or children.',
99
132
  this.constructor.displayName,
100
133
  component.constructor.displayName
101
- ) : invariant(component.props.__owner__ === this));
134
+ ) : invariant(component._owner === this));
135
+
136
+ component.props = ReactPropTransferer.mergeProps(
137
+ component.props,
138
+ this.props
139
+ );
102
140
 
103
- var props = {};
104
- for (var thatKey in component.props) {
105
- if (component.props.hasOwnProperty(thatKey)) {
106
- props[thatKey] = component.props[thatKey];
107
- }
108
- }
109
- for (var thisKey in this.props) {
110
- if (!this.props.hasOwnProperty(thisKey)) {
111
- continue;
112
- }
113
- var transferStrategy = TransferStrategies[thisKey];
114
- if (transferStrategy) {
115
- transferStrategy(props, thisKey, this.props[thisKey]);
116
- } else if (!props.hasOwnProperty(thisKey)) {
117
- props[thisKey] = this.props[thisKey];
118
- }
119
- }
120
- component.props = props;
121
141
  return component;
122
142
  }
123
143
 
124
144
  }
125
-
126
145
  };
127
146
 
128
147
  module.exports = ReactPropTransferer;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactPropTypeLocationNames
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var ReactPropTypeLocationNames = {};
22
+
23
+ if ("production" !== process.env.NODE_ENV) {
24
+ ReactPropTypeLocationNames = {
25
+ prop: 'prop',
26
+ context: 'context',
27
+ childContext: 'child context'
28
+ };
29
+ }
30
+
31
+ module.exports = ReactPropTypeLocationNames;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactPropTypeLocations
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var keyMirror = require("./keyMirror");
22
+
23
+ var ReactPropTypeLocations = keyMirror({
24
+ prop: null,
25
+ context: null,
26
+ childContext: null
27
+ });
28
+
29
+ module.exports = ReactPropTypeLocations;
@@ -18,8 +18,11 @@
18
18
 
19
19
  "use strict";
20
20
 
21
+ var ReactComponent = require("./ReactComponent");
22
+ var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
23
+
24
+ var warning = require("./warning");
21
25
  var createObjectFrom = require("./createObjectFrom");
22
- var invariant = require("./invariant");
23
26
 
24
27
  /**
25
28
  * Collection of methods that allow declaration and validation of props that are
@@ -54,7 +57,7 @@ var invariant = require("./invariant");
54
57
  * // An optional string or URI prop named "href".
55
58
  * href: function(props, propName, componentName) {
56
59
  * var propValue = props[propName];
57
- * invariant(
60
+ * warning(
58
61
  * propValue == null ||
59
62
  * typeof propValue === 'string' ||
60
63
  * propValue instanceof URI,
@@ -78,81 +81,279 @@ var Props = {
78
81
  object: createPrimitiveTypeChecker('object'),
79
82
  string: createPrimitiveTypeChecker('string'),
80
83
 
84
+ shape: createShapeTypeChecker,
81
85
  oneOf: createEnumTypeChecker,
86
+ oneOfType: createUnionTypeChecker,
87
+ arrayOf: createArrayOfTypeChecker,
88
+
89
+ instanceOf: createInstanceTypeChecker,
82
90
 
83
- instanceOf: createInstanceTypeChecker
91
+ renderable: createRenderableTypeChecker(),
84
92
 
93
+ component: createComponentTypeChecker(),
94
+
95
+ any: createAnyTypeChecker()
85
96
  };
86
97
 
87
98
  var ANONYMOUS = '<<anonymous>>';
88
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
+ }
116
+ }
117
+ return true;
118
+ default:
119
+ return false;
120
+ }
121
+ }
122
+
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';
128
+ }
129
+ return propType;
130
+ }
131
+
132
+ function createAnyTypeChecker() {
133
+ function validateAnyType(
134
+ shouldWarn, propValue, propName, componentName, location
135
+ ) {
136
+ return true; // is always valid
137
+ }
138
+ return createChainableTypeChecker(validateAnyType);
139
+ }
140
+
89
141
  function createPrimitiveTypeChecker(expectedType) {
90
- function validatePrimitiveType(propValue, propName, componentName) {
91
- var propType = typeof propValue;
92
- if (propType === 'object' && Array.isArray(propValue)) {
93
- propType = 'array';
142
+ function validatePrimitiveType(
143
+ shouldWarn, propValue, propName, componentName, location
144
+ ) {
145
+ var propType = getPropType(propValue);
146
+ var isValid = propType === expectedType;
147
+ if (shouldWarn) {
148
+ 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
+ );
94
157
  }
95
- ("production" !== process.env.NODE_ENV ? invariant(
96
- propType === expectedType,
97
- 'Invalid prop `%s` of type `%s` supplied to `%s`, expected `%s`.',
98
- propName,
99
- propType,
100
- componentName,
101
- expectedType
102
- ) : invariant(propType === expectedType));
158
+ return isValid;
103
159
  }
104
160
  return createChainableTypeChecker(validatePrimitiveType);
105
161
  }
106
162
 
107
163
  function createEnumTypeChecker(expectedValues) {
108
164
  var expectedEnum = createObjectFrom(expectedValues);
109
- function validateEnumType(propValue, propName, componentName) {
110
- ("production" !== process.env.NODE_ENV ? invariant(
111
- expectedEnum[propValue],
112
- 'Invalid prop `%s` supplied to `%s`, expected one of %s.',
113
- propName,
114
- componentName,
115
- JSON.stringify(Object.keys(expectedEnum))
116
- ) : invariant(expectedEnum[propValue]));
165
+ function validateEnumType(
166
+ shouldWarn, propValue, propName, componentName, location
167
+ ) {
168
+ var isValid = expectedEnum[propValue];
169
+ if (shouldWarn) {
170
+ 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
+ );
178
+ }
179
+ return isValid;
117
180
  }
118
181
  return createChainableTypeChecker(validateEnumType);
119
182
  }
120
183
 
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
+ 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
+ );
207
+ }
208
+ return isValid;
209
+ }
210
+ return createChainableTypeChecker(validateShapeType);
211
+ }
212
+
121
213
  function createInstanceTypeChecker(expectedClass) {
122
- function validateInstanceType(propValue, propName, componentName) {
123
- ("production" !== process.env.NODE_ENV ? invariant(
124
- propValue instanceof expectedClass,
125
- 'Invalid prop `%s` supplied to `%s`, expected instance of `%s`.',
126
- propName,
127
- componentName,
128
- expectedClass.name || ANONYMOUS
129
- ) : invariant(propValue instanceof expectedClass));
214
+ function validateInstanceType(
215
+ shouldWarn, propValue, propName, componentName, location
216
+ ) {
217
+ var isValid = propValue instanceof expectedClass;
218
+ if (shouldWarn) {
219
+ 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
+ );
227
+ }
228
+ return isValid;
130
229
  }
131
230
  return createChainableTypeChecker(validateInstanceType);
132
231
  }
133
232
 
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;
242
+ }
243
+ }
244
+ }
245
+ if (shouldWarn) {
246
+ warning(
247
+ isValid,
248
+ 'Invalid %s `%s` supplied to `%s`, expected an array.',
249
+ ReactPropTypeLocationNames[location],
250
+ propName,
251
+ componentName
252
+ );
253
+ }
254
+ return isValid;
255
+ }
256
+ return createChainableTypeChecker(validateArrayType);
257
+ }
258
+
259
+ function createRenderableTypeChecker() {
260
+ function validateRenderableType(
261
+ shouldWarn, propValue, propName, componentName, location
262
+ ) {
263
+ var isValid = isRenderable(propValue);
264
+ if (shouldWarn) {
265
+ warning(
266
+ isValid,
267
+ 'Invalid %s `%s` supplied to `%s`, expected a renderable prop.',
268
+ ReactPropTypeLocationNames[location],
269
+ propName,
270
+ componentName
271
+ );
272
+ }
273
+ return isValid;
274
+ }
275
+ return createChainableTypeChecker(validateRenderableType);
276
+ }
277
+
278
+ function createComponentTypeChecker() {
279
+ function validateComponentType(
280
+ shouldWarn, propValue, propName, componentName, location
281
+ ) {
282
+ var isValid = ReactComponent.isValidComponent(propValue);
283
+ if (shouldWarn) {
284
+ warning(
285
+ isValid,
286
+ 'Invalid %s `%s` supplied to `%s`, expected a React component.',
287
+ ReactPropTypeLocationNames[location],
288
+ propName,
289
+ componentName
290
+ );
291
+ }
292
+ return isValid;
293
+ }
294
+ return createChainableTypeChecker(validateComponentType);
295
+ }
296
+
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;
304
+ }
305
+ if (validate(props, propName, componentName, location)) {
306
+ isValid = true;
307
+ break;
308
+ }
309
+ }
310
+ warning(
311
+ isValid,
312
+ 'Invalid %s `%s` supplied to `%s`.',
313
+ ReactPropTypeLocationNames[location],
314
+ propName,
315
+ componentName || ANONYMOUS
316
+ );
317
+ return isValid;
318
+ };
319
+ }
320
+
134
321
  function createChainableTypeChecker(validate) {
135
- function createTypeChecker(isRequired) {
136
- function checkType(props, propName, componentName) {
137
- var propValue = props[propName];
138
- if (propValue != null) {
139
- // Only validate if there is a value to check.
140
- validate(propValue, propName, componentName || ANONYMOUS);
141
- } else {
142
- ("production" !== process.env.NODE_ENV ? invariant(
143
- !isRequired,
144
- 'Required prop `%s` was not specified in `%s`.',
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
+ warning(
339
+ isValid,
340
+ 'Required %s `%s` was not specified in `%s`.',
341
+ ReactPropTypeLocationNames[location],
145
342
  propName,
146
343
  componentName || ANONYMOUS
147
- ) : invariant(!isRequired));
344
+ );
148
345
  }
346
+ return isValid;
149
347
  }
150
- if (!isRequired) {
151
- checkType.isRequired = createTypeChecker(true);
152
- }
153
- return checkType;
154
348
  }
155
- return createTypeChecker(false);
349
+
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;
355
+
356
+ return checker;
156
357
  }
157
358
 
158
359
  module.exports = Props;