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
@@ -23,11 +23,11 @@
23
23
  var ReactDOMIDOperations = require("./ReactDOMIDOperations");
24
24
  var ReactMarkupChecksum = require("./ReactMarkupChecksum");
25
25
  var ReactMount = require("./ReactMount");
26
+ var ReactPerf = require("./ReactPerf");
26
27
  var ReactReconcileTransaction = require("./ReactReconcileTransaction");
27
28
 
28
29
  var getReactRootElementInContainer = require("./getReactRootElementInContainer");
29
30
  var invariant = require("./invariant");
30
- var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup");
31
31
 
32
32
 
33
33
  var ELEMENT_NODE_TYPE = 1;
@@ -61,7 +61,7 @@ var ReactComponentBrowserEnvironment = {
61
61
 
62
62
  ReactReconcileTransaction: ReactReconcileTransaction,
63
63
 
64
- DOMIDOperations: ReactDOMIDOperations,
64
+ BackendIDOperations: ReactDOMIDOperations,
65
65
 
66
66
  /**
67
67
  * If a particular environment requires that some resources be cleaned up,
@@ -80,61 +80,79 @@ var ReactComponentBrowserEnvironment = {
80
80
  * @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
81
81
  * container if possible.
82
82
  */
83
- mountImageIntoNode: function(markup, container, shouldReuseMarkup) {
84
- ("production" !== process.env.NODE_ENV ? invariant(
85
- container && (
83
+ mountImageIntoNode: ReactPerf.measure(
84
+ 'ReactComponentBrowserEnvironment',
85
+ 'mountImageIntoNode',
86
+ function(markup, container, shouldReuseMarkup) {
87
+ ("production" !== process.env.NODE_ENV ? invariant(
88
+ container && (
89
+ container.nodeType === ELEMENT_NODE_TYPE ||
90
+ container.nodeType === DOC_NODE_TYPE
91
+ ),
92
+ 'mountComponentIntoNode(...): Target container is not valid.'
93
+ ) : invariant(container && (
86
94
  container.nodeType === ELEMENT_NODE_TYPE ||
87
- container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender
88
- ),
89
- 'mountComponentIntoNode(...): Target container is not valid.'
90
- ) : invariant(container && (
91
- container.nodeType === ELEMENT_NODE_TYPE ||
92
- container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender
93
- )));
94
- if (shouldReuseMarkup) {
95
- if (ReactMarkupChecksum.canReuseMarkup(
96
- markup,
97
- getReactRootElementInContainer(container))) {
98
- return;
99
- } else {
100
- if ("production" !== process.env.NODE_ENV) {
101
- console.warn(
102
- 'React attempted to use reuse markup in a container but the ' +
103
- 'checksum was invalid. This generally means that you are using ' +
104
- 'server rendering and the markup generated on the server was ' +
105
- 'not what the client was expecting. React injected new markup ' +
106
- 'to compensate which works but you have lost many of the ' +
107
- 'benefits of server rendering. Instead, figure out why the ' +
108
- 'markup being generated is different on the client or server.'
109
- );
95
+ container.nodeType === DOC_NODE_TYPE
96
+ )));
97
+
98
+ if (shouldReuseMarkup) {
99
+ if (ReactMarkupChecksum.canReuseMarkup(
100
+ markup,
101
+ getReactRootElementInContainer(container))) {
102
+ return;
103
+ } else {
104
+ ("production" !== process.env.NODE_ENV ? invariant(
105
+ container.nodeType !== DOC_NODE_TYPE,
106
+ 'You\'re trying to render a component to the document using ' +
107
+ 'server rendering but the checksum was invalid. This usually ' +
108
+ 'means you rendered a different component type or props on ' +
109
+ 'the client from the one on the server, or your render() ' +
110
+ 'methods are impure. React cannot handle this case due to ' +
111
+ 'cross-browser quirks by rendering at the document root. You ' +
112
+ 'should look for environment dependent code in your components ' +
113
+ 'and ensure the props are the same client and server side.'
114
+ ) : invariant(container.nodeType !== DOC_NODE_TYPE));
115
+
116
+ if ("production" !== process.env.NODE_ENV) {
117
+ console.warn(
118
+ 'React attempted to use reuse markup in a container but the ' +
119
+ 'checksum was invalid. This generally means that you are ' +
120
+ 'using server rendering and the markup generated on the ' +
121
+ 'server was not what the client was expecting. React injected' +
122
+ 'new markup to compensate which works but you have lost many ' +
123
+ 'of the benefits of server rendering. Instead, figure out ' +
124
+ 'why the markup being generated is different on the client ' +
125
+ 'or server.'
126
+ );
127
+ }
110
128
  }
111
129
  }
112
- }
113
130
 
114
- // You can't naively set the innerHTML of the entire document. You need
115
- // to mutate documentElement which requires doing some crazy tricks. See
116
- // mutateHTMLNodeWithMarkup()
117
- if (container.nodeType === DOC_NODE_TYPE) {
118
- mutateHTMLNodeWithMarkup(container.documentElement, markup);
119
- return;
120
- }
131
+ ("production" !== process.env.NODE_ENV ? invariant(
132
+ container.nodeType !== DOC_NODE_TYPE,
133
+ 'You\'re trying to render a component to the document but ' +
134
+ 'you didn\'t use server rendering. We can\'t do this ' +
135
+ 'without using server rendering due to cross-browser quirks. ' +
136
+ 'See renderComponentToString() for server rendering.'
137
+ ) : invariant(container.nodeType !== DOC_NODE_TYPE));
121
138
 
122
- // Asynchronously inject markup by ensuring that the container is not in
123
- // the document when settings its `innerHTML`.
124
- var parent = container.parentNode;
125
- if (parent) {
126
- var next = container.nextSibling;
127
- parent.removeChild(container);
128
- container.innerHTML = markup;
129
- if (next) {
130
- parent.insertBefore(container, next);
139
+ // Asynchronously inject markup by ensuring that the container is not in
140
+ // the document when settings its `innerHTML`.
141
+ var parent = container.parentNode;
142
+ if (parent) {
143
+ var next = container.nextSibling;
144
+ parent.removeChild(container);
145
+ container.innerHTML = markup;
146
+ if (next) {
147
+ parent.insertBefore(container, next);
148
+ } else {
149
+ parent.appendChild(container);
150
+ }
131
151
  } else {
132
- parent.appendChild(container);
152
+ container.innerHTML = markup;
133
153
  }
134
- } else {
135
- container.innerHTML = markup;
136
154
  }
137
- }
155
+ )
138
156
  };
139
157
 
140
158
  module.exports = ReactComponentBrowserEnvironment;
@@ -16,6 +16,8 @@
16
16
  * @providesModule ReactComponentEnvironment
17
17
  */
18
18
 
19
+ "use strict";
20
+
19
21
  var ReactComponentBrowserEnvironment =
20
22
  require("./ReactComponentBrowserEnvironment");
21
23
 
@@ -19,11 +19,14 @@
19
19
  "use strict";
20
20
 
21
21
  var ReactComponent = require("./ReactComponent");
22
+ var ReactContext = require("./ReactContext");
22
23
  var ReactCurrentOwner = require("./ReactCurrentOwner");
23
24
  var ReactErrorUtils = require("./ReactErrorUtils");
24
25
  var ReactOwner = require("./ReactOwner");
25
26
  var ReactPerf = require("./ReactPerf");
26
27
  var ReactPropTransferer = require("./ReactPropTransferer");
28
+ var ReactPropTypeLocations = require("./ReactPropTypeLocations");
29
+ var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
27
30
  var ReactUpdates = require("./ReactUpdates");
28
31
 
29
32
  var invariant = require("./invariant");
@@ -31,6 +34,7 @@ var keyMirror = require("./keyMirror");
31
34
  var merge = require("./merge");
32
35
  var mixInto = require("./mixInto");
33
36
  var objMap = require("./objMap");
37
+ var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
34
38
 
35
39
  /**
36
40
  * Policies that describe methods in `ReactCompositeComponentInterface`.
@@ -89,15 +93,38 @@ var ReactCompositeComponentInterface = {
89
93
  */
90
94
  mixins: SpecPolicy.DEFINE_MANY,
91
95
 
96
+ /**
97
+ * An object containing properties and methods that should be defined on
98
+ * the component's constructor instead of its prototype (static methods).
99
+ *
100
+ * @type {object}
101
+ * @optional
102
+ */
103
+ statics: SpecPolicy.DEFINE_MANY,
104
+
92
105
  /**
93
106
  * Definition of prop types for this component.
94
107
  *
95
108
  * @type {object}
96
109
  * @optional
97
110
  */
98
- propTypes: SpecPolicy.DEFINE_ONCE,
111
+ propTypes: SpecPolicy.DEFINE_MANY,
99
112
 
113
+ /**
114
+ * Definition of context types for this component.
115
+ *
116
+ * @type {object}
117
+ * @optional
118
+ */
119
+ contextTypes: SpecPolicy.DEFINE_MANY,
100
120
 
121
+ /**
122
+ * Definition of context types this component sets for its children.
123
+ *
124
+ * @type {object}
125
+ * @optional
126
+ */
127
+ childContextTypes: SpecPolicy.DEFINE_MANY,
101
128
 
102
129
  // ==== Definition methods ====
103
130
 
@@ -129,6 +156,12 @@ var ReactCompositeComponentInterface = {
129
156
  */
130
157
  getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
131
158
 
159
+ /**
160
+ * @return {object}
161
+ * @optional
162
+ */
163
+ getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
164
+
132
165
  /**
133
166
  * Uses props from `this.props` and state from `this.state` to render the
134
167
  * structure of the component.
@@ -178,7 +211,7 @@ var ReactCompositeComponentInterface = {
178
211
  * Use this as an opportunity to react to a prop transition by updating the
179
212
  * state using `this.setState`. Current props are accessed via `this.props`.
180
213
  *
181
- * componentWillReceiveProps: function(nextProps) {
214
+ * componentWillReceiveProps: function(nextProps, nextContext) {
182
215
  * this.setState({
183
216
  * likesIncreasing: nextProps.likeCount > this.props.likeCount
184
217
  * });
@@ -195,17 +228,21 @@ var ReactCompositeComponentInterface = {
195
228
 
196
229
  /**
197
230
  * Invoked while deciding if the component should be updated as a result of
198
- * receiving new props and state.
231
+ * receiving new props, state and/or context.
199
232
  *
200
233
  * Use this as an opportunity to `return false` when you're certain that the
201
- * transition to the new props and state will not require a component update.
234
+ * transition to the new props/state/context will not require a component
235
+ * update.
202
236
  *
203
- * shouldComponentUpdate: function(nextProps, nextState) {
204
- * return !equal(nextProps, this.props) || !equal(nextState, this.state);
237
+ * shouldComponentUpdate: function(nextProps, nextState, nextContext) {
238
+ * return !equal(nextProps, this.props) ||
239
+ * !equal(nextState, this.state) ||
240
+ * !equal(nextContext, this.context);
205
241
  * }
206
242
  *
207
243
  * @param {object} nextProps
208
244
  * @param {?object} nextState
245
+ * @param {?object} nextContext
209
246
  * @return {boolean} True if the component should update.
210
247
  * @optional
211
248
  */
@@ -213,7 +250,8 @@ var ReactCompositeComponentInterface = {
213
250
 
214
251
  /**
215
252
  * Invoked when the component is about to update due to a transition from
216
- * `this.props` and `this.state` to `nextProps` and `nextState`.
253
+ * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
254
+ * and `nextContext`.
217
255
  *
218
256
  * Use this as an opportunity to perform preparation before an update occurs.
219
257
  *
@@ -221,6 +259,7 @@ var ReactCompositeComponentInterface = {
221
259
  *
222
260
  * @param {object} nextProps
223
261
  * @param {?object} nextState
262
+ * @param {?object} nextContext
224
263
  * @param {ReactReconcileTransaction} transaction
225
264
  * @optional
226
265
  */
@@ -234,6 +273,7 @@ var ReactCompositeComponentInterface = {
234
273
  *
235
274
  * @param {object} prevProps
236
275
  * @param {?object} prevState
276
+ * @param {?object} prevContext
237
277
  * @param {DOMElement} rootNode DOM element representing the component.
238
278
  * @optional
239
279
  */
@@ -273,25 +313,73 @@ var ReactCompositeComponentInterface = {
273
313
  /**
274
314
  * Mapping from class specification keys to special processing functions.
275
315
  *
276
- * Although these are declared in the specification when defining classes
277
- * using `React.createClass`, they will not be on the component's prototype.
316
+ * Although these are declared like instance properties in the specification
317
+ * when defining classes using `React.createClass`, they are actually static
318
+ * and are accessible on the constructor instead of the prototype. Despite
319
+ * being static, they must be defined outside of the "statics" key under
320
+ * which all other static methods are defined.
278
321
  */
279
322
  var RESERVED_SPEC_KEYS = {
280
- displayName: function(Constructor, displayName) {
281
- Constructor.displayName = displayName;
323
+ displayName: function(ConvenienceConstructor, displayName) {
324
+ ConvenienceConstructor.componentConstructor.displayName = displayName;
282
325
  },
283
- mixins: function(Constructor, mixins) {
326
+ mixins: function(ConvenienceConstructor, mixins) {
284
327
  if (mixins) {
285
328
  for (var i = 0; i < mixins.length; i++) {
286
- mixSpecIntoComponent(Constructor, mixins[i]);
329
+ mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
287
330
  }
288
331
  }
289
332
  },
290
- propTypes: function(Constructor, propTypes) {
291
- Constructor.propTypes = propTypes;
333
+ childContextTypes: function(ConvenienceConstructor, childContextTypes) {
334
+ var Constructor = ConvenienceConstructor.componentConstructor;
335
+ validateTypeDef(
336
+ Constructor,
337
+ childContextTypes,
338
+ ReactPropTypeLocations.childContext
339
+ );
340
+ Constructor.childContextTypes = merge(
341
+ Constructor.childContextTypes,
342
+ childContextTypes
343
+ );
344
+ },
345
+ contextTypes: function(ConvenienceConstructor, contextTypes) {
346
+ var Constructor = ConvenienceConstructor.componentConstructor;
347
+ validateTypeDef(
348
+ Constructor,
349
+ contextTypes,
350
+ ReactPropTypeLocations.context
351
+ );
352
+ Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
353
+ },
354
+ propTypes: function(ConvenienceConstructor, propTypes) {
355
+ var Constructor = ConvenienceConstructor.componentConstructor;
356
+ validateTypeDef(
357
+ Constructor,
358
+ propTypes,
359
+ ReactPropTypeLocations.prop
360
+ );
361
+ Constructor.propTypes = merge(Constructor.propTypes, propTypes);
362
+ },
363
+ statics: function(ConvenienceConstructor, statics) {
364
+ mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
292
365
  }
293
366
  };
294
367
 
368
+ function validateTypeDef(Constructor, typeDef, location) {
369
+ for (var propName in typeDef) {
370
+ if (typeDef.hasOwnProperty(propName)) {
371
+ ("production" !== process.env.NODE_ENV ? invariant(
372
+ typeof typeDef[propName] == 'function',
373
+ '%s: %s type `%s` is invalid; it must be a function, usually from ' +
374
+ 'React.PropTypes.',
375
+ Constructor.displayName || 'ReactCompositeComponent',
376
+ ReactPropTypeLocationNames[location],
377
+ propName
378
+ ) : invariant(typeof typeDef[propName] == 'function'));
379
+ }
380
+ }
381
+ }
382
+
295
383
  function validateMethodOverride(proto, name) {
296
384
  var specPolicy = ReactCompositeComponentInterface[name];
297
385
 
@@ -320,7 +408,6 @@ function validateMethodOverride(proto, name) {
320
408
  }
321
409
  }
322
410
 
323
-
324
411
  function validateLifeCycleOnReplaceState(instance) {
325
412
  var compositeLifeCycleState = instance._compositeLifeCycleState;
326
413
  ("production" !== process.env.NODE_ENV ? invariant(
@@ -344,17 +431,30 @@ function validateLifeCycleOnReplaceState(instance) {
344
431
  * Custom version of `mixInto` which handles policy validation and reserved
345
432
  * specification keys when building `ReactCompositeComponent` classses.
346
433
  */
347
- function mixSpecIntoComponent(Constructor, spec) {
434
+ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
435
+ ("production" !== process.env.NODE_ENV ? invariant(
436
+ !isValidClass(spec),
437
+ 'ReactCompositeComponent: You\'re attempting to ' +
438
+ 'use a component class as a mixin. Instead, just use a regular object.'
439
+ ) : invariant(!isValidClass(spec)));
440
+ ("production" !== process.env.NODE_ENV ? invariant(
441
+ !ReactComponent.isValidComponent(spec),
442
+ 'ReactCompositeComponent: You\'re attempting to ' +
443
+ 'use a component as a mixin. Instead, just use a regular object.'
444
+ ) : invariant(!ReactComponent.isValidComponent(spec)));
445
+
446
+ var Constructor = ConvenienceConstructor.componentConstructor;
348
447
  var proto = Constructor.prototype;
349
448
  for (var name in spec) {
350
449
  var property = spec[name];
351
- if (!spec.hasOwnProperty(name) || !property) {
450
+ if (!spec.hasOwnProperty(name)) {
352
451
  continue;
353
452
  }
453
+
354
454
  validateMethodOverride(proto, name);
355
455
 
356
456
  if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
357
- RESERVED_SPEC_KEYS[name](Constructor, property);
457
+ RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
358
458
  } else {
359
459
  // Setup methods on prototype:
360
460
  // The following member methods should not be automatically bound:
@@ -362,7 +462,7 @@ function mixSpecIntoComponent(Constructor, spec) {
362
462
  // 2. Overridden methods (that were mixed in).
363
463
  var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
364
464
  var isInherited = name in proto;
365
- var markedDontBind = property.__reactDontBind;
465
+ var markedDontBind = property && property.__reactDontBind;
366
466
  var isFunction = typeof property === 'function';
367
467
  var shouldAutoBind =
368
468
  isFunction &&
@@ -394,6 +494,37 @@ function mixSpecIntoComponent(Constructor, spec) {
394
494
  }
395
495
  }
396
496
 
497
+ function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
498
+ if (!statics) {
499
+ return;
500
+ }
501
+ for (var name in statics) {
502
+ var property = statics[name];
503
+ if (!statics.hasOwnProperty(name) || !property) {
504
+ return;
505
+ }
506
+
507
+ var isInherited = name in ConvenienceConstructor;
508
+ var result = property;
509
+ if (isInherited) {
510
+ var existingProperty = ConvenienceConstructor[name];
511
+ var existingType = typeof existingProperty;
512
+ var propertyType = typeof property;
513
+ ("production" !== process.env.NODE_ENV ? invariant(
514
+ existingType === 'function' && propertyType === 'function',
515
+ 'ReactCompositeComponent: You are attempting to define ' +
516
+ '`%s` on your component more than once, but that is only supported ' +
517
+ 'for functions, which are chained together. This conflict may be ' +
518
+ 'due to a mixin.',
519
+ name
520
+ ) : invariant(existingType === 'function' && propertyType === 'function'));
521
+ result = createChainedFunction(existingProperty, property);
522
+ }
523
+ ConvenienceConstructor[name] = result;
524
+ ConvenienceConstructor.componentConstructor[name] = result;
525
+ }
526
+ }
527
+
397
528
  /**
398
529
  * Merge two objects, but throw if both contain the same key.
399
530
  *
@@ -429,10 +560,14 @@ function mergeObjectsWithNoDuplicateKeys(one, two) {
429
560
  */
430
561
  function createMergedResultFunction(one, two) {
431
562
  return function mergedResult() {
432
- return mergeObjectsWithNoDuplicateKeys(
433
- one.apply(this, arguments),
434
- two.apply(this, arguments)
435
- );
563
+ var a = one.apply(this, arguments);
564
+ var b = two.apply(this, arguments);
565
+ if (a == null) {
566
+ return b;
567
+ } else if (b == null) {
568
+ return a;
569
+ }
570
+ return mergeObjectsWithNoDuplicateKeys(a, b);
436
571
  };
437
572
  }
438
573
 
@@ -451,6 +586,118 @@ function createChainedFunction(one, two) {
451
586
  };
452
587
  }
453
588
 
589
+ if ("production" !== process.env.NODE_ENV) {
590
+
591
+ var unmountedPropertyWhitelist = {
592
+ constructor: true,
593
+ construct: true,
594
+ isOwnedBy: true, // should be deprecated but can have code mod (internal)
595
+ mountComponent: true,
596
+ mountComponentIntoNode: true,
597
+ props: true,
598
+ type: true,
599
+ _checkPropTypes: true,
600
+ _mountComponentIntoNode: true,
601
+ _processContext: true
602
+ };
603
+
604
+ var hasWarnedOnComponentType = {};
605
+
606
+ var warnIfUnmounted = function(instance, key) {
607
+ if (instance.__hasBeenMounted) {
608
+ return;
609
+ }
610
+ var name = instance.constructor.displayName || 'Unknown';
611
+ var owner = ReactCurrentOwner.current;
612
+ var ownerName = (owner && owner.constructor.displayName) || 'Unknown';
613
+ var warningKey = key + '|' + name + '|' + ownerName;
614
+ if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) {
615
+ // We have already warned for this combination. Skip it this time.
616
+ return;
617
+ }
618
+ hasWarnedOnComponentType[warningKey] = true;
619
+
620
+ var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
621
+ var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
622
+
623
+ console.warn(
624
+ 'Invalid access to component property "' + key + '" on ' + name +
625
+ context + ' See http://fb.me/react-warning-descriptors .' +
626
+ ' Use a static method instead: ' + staticMethodExample
627
+ );
628
+ };
629
+
630
+ var defineMembraneProperty = function(membrane, prototype, key) {
631
+ Object.defineProperty(membrane, key, {
632
+
633
+ configurable: false,
634
+ enumerable: true,
635
+
636
+ get: function() {
637
+ if (this !== membrane) {
638
+ // When this is accessed through a prototype chain we need to check if
639
+ // this component was mounted.
640
+ warnIfUnmounted(this, key);
641
+ }
642
+ return prototype[key];
643
+ },
644
+
645
+ set: function(value) {
646
+ if (this !== membrane) {
647
+ // When this is accessed through a prototype chain, we first check if
648
+ // this component was mounted. Then we define a value on "this"
649
+ // instance, effectively disabling the membrane on that prototype
650
+ // chain.
651
+ warnIfUnmounted(this, key);
652
+ Object.defineProperty(this, key, {
653
+ enumerable: true,
654
+ configurable: true,
655
+ writable: true,
656
+ value: value
657
+ });
658
+ } else {
659
+ // Otherwise, this should modify the prototype
660
+ prototype[key] = value;
661
+ }
662
+ }
663
+
664
+ });
665
+ };
666
+
667
+ /**
668
+ * Creates a membrane prototype which wraps the original prototype. If any
669
+ * property is accessed in an unmounted state, a warning is issued.
670
+ *
671
+ * @param {object} prototype Original prototype.
672
+ * @return {object} The membrane prototype.
673
+ * @private
674
+ */
675
+ var createMountWarningMembrane = function(prototype) {
676
+ try {
677
+ var membrane = Object.create(prototype);
678
+ for (var key in prototype) {
679
+ if (unmountedPropertyWhitelist.hasOwnProperty(key)) {
680
+ continue;
681
+ }
682
+ defineMembraneProperty(membrane, prototype, key);
683
+ }
684
+
685
+ membrane.mountComponent = function() {
686
+ this.__hasBeenMounted = true;
687
+ return prototype.mountComponent.apply(this, arguments);
688
+ };
689
+
690
+ return membrane;
691
+ } catch(x) {
692
+ // In IE8 define property will fail on non-DOM objects. If anything in
693
+ // the membrane creation fails, we'll bail out and just use the prototype
694
+ // without warnings.
695
+ return prototype;
696
+ }
697
+ };
698
+
699
+ }
700
+
454
701
  /**
455
702
  * `ReactCompositeComponent` maintains an auxiliary life cycle state in
456
703
  * `this._compositeLifeCycleState` (which can be null).
@@ -516,8 +763,14 @@ var ReactCompositeComponentMixin = {
516
763
  construct: function(initialProps, children) {
517
764
  // Children can be either an array or more than one argument
518
765
  ReactComponent.Mixin.construct.apply(this, arguments);
766
+
519
767
  this.state = null;
520
768
  this._pendingState = null;
769
+
770
+ this.context = this._processContext(ReactContext.current);
771
+ this._currentContext = ReactContext.current;
772
+ this._pendingContext = null;
773
+
521
774
  this._compositeLifeCycleState = null;
522
775
  },
523
776
 
@@ -555,13 +808,19 @@ var ReactCompositeComponentMixin = {
555
808
  this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
556
809
 
557
810
  this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
558
- this._processProps(this.props);
811
+ this.props = this._processProps(this.props);
559
812
 
560
813
  if (this.__reactAutoBindMap) {
561
814
  this._bindAutoBindMethods();
562
815
  }
563
816
 
564
817
  this.state = this.getInitialState ? this.getInitialState() : null;
818
+ ("production" !== process.env.NODE_ENV ? invariant(
819
+ typeof this.state === 'object' && !Array.isArray(this.state),
820
+ '%s.getInitialState(): must return an object or null',
821
+ this.constructor.displayName || 'ReactCompositeComponent'
822
+ ) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
823
+
565
824
  this._pendingState = null;
566
825
  this._pendingForceUpdate = false;
567
826
 
@@ -606,10 +865,11 @@ var ReactCompositeComponentMixin = {
606
865
 
607
866
  this._defaultProps = null;
608
867
 
609
- ReactComponent.Mixin.unmountComponent.call(this);
610
868
  this._renderedComponent.unmountComponent();
611
869
  this._renderedComponent = null;
612
870
 
871
+ ReactComponent.Mixin.unmountComponent.call(this);
872
+
613
873
  if (this.refs) {
614
874
  this.refs = null;
615
875
  }
@@ -638,6 +898,18 @@ var ReactCompositeComponentMixin = {
638
898
  * @protected
639
899
  */
640
900
  setState: function(partialState, callback) {
901
+ ("production" !== process.env.NODE_ENV ? invariant(
902
+ typeof partialState === 'object' || partialState == null,
903
+ 'setState(...): takes an object of state variables to update.'
904
+ ) : invariant(typeof partialState === 'object' || partialState == null));
905
+ if ("production" !== process.env.NODE_ENV) {
906
+ if (partialState == null) {
907
+ console.warn(
908
+ 'setState(...): You passed an undefined or null state object; ' +
909
+ 'instead, use forceUpdate().'
910
+ );
911
+ }
912
+ }
641
913
  // Merge with `_pendingState` if it exists, otherwise with existing state.
642
914
  this.replaceState(
643
915
  merge(this._pendingState || this.state, partialState),
@@ -663,29 +935,107 @@ var ReactCompositeComponentMixin = {
663
935
  ReactUpdates.enqueueUpdate(this, callback);
664
936
  },
665
937
 
938
+ /**
939
+ * Filters the context object to only contain keys specified in
940
+ * `contextTypes`, and asserts that they are valid.
941
+ *
942
+ * @param {object} context
943
+ * @return {?object}
944
+ * @private
945
+ */
946
+ _processContext: function(context) {
947
+ var maskedContext = null;
948
+ var contextTypes = this.constructor.contextTypes;
949
+ if (contextTypes) {
950
+ maskedContext = {};
951
+ for (var contextName in contextTypes) {
952
+ maskedContext[contextName] = context[contextName];
953
+ }
954
+ if ("production" !== process.env.NODE_ENV) {
955
+ this._checkPropTypes(
956
+ contextTypes,
957
+ maskedContext,
958
+ ReactPropTypeLocations.context
959
+ );
960
+ }
961
+ }
962
+ return maskedContext;
963
+ },
964
+
965
+ /**
966
+ * @param {object} currentContext
967
+ * @return {object}
968
+ * @private
969
+ */
970
+ _processChildContext: function(currentContext) {
971
+ var childContext = this.getChildContext && this.getChildContext();
972
+ var displayName = this.constructor.displayName || 'ReactCompositeComponent';
973
+ if (childContext) {
974
+ ("production" !== process.env.NODE_ENV ? invariant(
975
+ typeof this.constructor.childContextTypes === 'object',
976
+ '%s.getChildContext(): childContextTypes must be defined in order to ' +
977
+ 'use getChildContext().',
978
+ displayName
979
+ ) : invariant(typeof this.constructor.childContextTypes === 'object'));
980
+ if ("production" !== process.env.NODE_ENV) {
981
+ this._checkPropTypes(
982
+ this.constructor.childContextTypes,
983
+ childContext,
984
+ ReactPropTypeLocations.childContext
985
+ );
986
+ }
987
+ for (var name in childContext) {
988
+ ("production" !== process.env.NODE_ENV ? invariant(
989
+ name in this.constructor.childContextTypes,
990
+ '%s.getChildContext(): key "%s" is not defined in childContextTypes.',
991
+ displayName,
992
+ name
993
+ ) : invariant(name in this.constructor.childContextTypes));
994
+ }
995
+ return merge(currentContext, childContext);
996
+ }
997
+ return currentContext;
998
+ },
999
+
666
1000
  /**
667
1001
  * Processes props by setting default values for unspecified props and
668
- * asserting that the props are valid.
1002
+ * asserting that the props are valid. Does not mutate its argument; returns
1003
+ * a new props object with defaults merged in.
669
1004
  *
670
- * @param {object} props
1005
+ * @param {object} newProps
1006
+ * @return {object}
671
1007
  * @private
672
1008
  */
673
- _processProps: function(props) {
674
- var propName;
1009
+ _processProps: function(newProps) {
1010
+ var props = merge(newProps);
675
1011
  var defaultProps = this._defaultProps;
676
- for (propName in defaultProps) {
677
- if (!(propName in props)) {
1012
+ for (var propName in defaultProps) {
1013
+ if (typeof props[propName] === 'undefined') {
678
1014
  props[propName] = defaultProps[propName];
679
1015
  }
680
1016
  }
681
- var propTypes = this.constructor.propTypes;
682
- if (propTypes) {
683
- var componentName = this.constructor.displayName;
684
- for (propName in propTypes) {
685
- var checkProp = propTypes[propName];
686
- if (checkProp) {
687
- checkProp(props, propName, componentName);
688
- }
1017
+ if ("production" !== process.env.NODE_ENV) {
1018
+ var propTypes = this.constructor.propTypes;
1019
+ if (propTypes) {
1020
+ this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
1021
+ }
1022
+ }
1023
+ return props;
1024
+ },
1025
+
1026
+ /**
1027
+ * Assert that the props are valid
1028
+ *
1029
+ * @param {object} propTypes Map of prop name to a ReactPropType
1030
+ * @param {object} props
1031
+ * @param {string} location e.g. "prop", "context", "child context"
1032
+ * @private
1033
+ */
1034
+ _checkPropTypes: function(propTypes, props, location) {
1035
+ var componentName = this.constructor.displayName;
1036
+ for (var propName in propTypes) {
1037
+ if (propTypes.hasOwnProperty(propName)) {
1038
+ propTypes[propName](props, propName, componentName, location);
689
1039
  }
690
1040
  }
691
1041
  },
@@ -711,41 +1061,63 @@ var ReactCompositeComponentMixin = {
711
1061
  _performUpdateIfNecessary: function(transaction) {
712
1062
  if (this._pendingProps == null &&
713
1063
  this._pendingState == null &&
1064
+ this._pendingContext == null &&
714
1065
  !this._pendingForceUpdate) {
715
1066
  return;
716
1067
  }
717
1068
 
1069
+ var nextFullContext = this._pendingContext || this._currentContext;
1070
+ var nextContext = this._processContext(nextFullContext);
1071
+ this._pendingContext = null;
1072
+
718
1073
  var nextProps = this.props;
719
1074
  if (this._pendingProps != null) {
720
- nextProps = this._pendingProps;
721
- this._processProps(nextProps);
1075
+ nextProps = this._processProps(this._pendingProps);
722
1076
  this._pendingProps = null;
723
1077
 
724
1078
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
725
1079
  if (this.componentWillReceiveProps) {
726
- this.componentWillReceiveProps(nextProps, transaction);
1080
+ this.componentWillReceiveProps(nextProps, nextContext);
727
1081
  }
728
1082
  }
729
1083
 
730
1084
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
731
1085
 
1086
+ // Unlike props, state, and context, we specifically don't want to set
1087
+ // _pendingOwner to null here because it's possible for a component to have
1088
+ // a null owner, so we instead make `this._owner === this._pendingOwner`
1089
+ // mean that there's no owner change pending.
1090
+ var nextOwner = this._pendingOwner;
1091
+
732
1092
  var nextState = this._pendingState || this.state;
733
1093
  this._pendingState = null;
734
1094
 
735
- if (this._pendingForceUpdate ||
736
- !this.shouldComponentUpdate ||
737
- this.shouldComponentUpdate(nextProps, nextState)) {
738
- this._pendingForceUpdate = false;
739
- // Will set `this.props` and `this.state`.
740
- this._performComponentUpdate(nextProps, nextState, transaction);
741
- } else {
742
- // If it's determined that a component should not update, we still want
743
- // to set props and state.
744
- this.props = nextProps;
745
- this.state = nextState;
1095
+ try {
1096
+ if (this._pendingForceUpdate ||
1097
+ !this.shouldComponentUpdate ||
1098
+ this.shouldComponentUpdate(nextProps, nextState, nextContext)) {
1099
+ this._pendingForceUpdate = false;
1100
+ // Will set `this.props`, `this.state` and `this.context`.
1101
+ this._performComponentUpdate(
1102
+ nextProps,
1103
+ nextOwner,
1104
+ nextState,
1105
+ nextFullContext,
1106
+ nextContext,
1107
+ transaction
1108
+ );
1109
+ } else {
1110
+ // If it's determined that a component should not update, we still want
1111
+ // to set props and state.
1112
+ this.props = nextProps;
1113
+ this._owner = nextOwner;
1114
+ this.state = nextState;
1115
+ this._currentContext = nextFullContext;
1116
+ this.context = nextContext;
1117
+ }
1118
+ } finally {
1119
+ this._compositeLifeCycleState = null;
746
1120
  }
747
-
748
- this._compositeLifeCycleState = null;
749
1121
  },
750
1122
 
751
1123
  /**
@@ -753,31 +1125,68 @@ var ReactCompositeComponentMixin = {
753
1125
  * performs update.
754
1126
  *
755
1127
  * @param {object} nextProps Next object to set as properties.
1128
+ * @param {?ReactComponent} nextOwner Next component to set as owner
756
1129
  * @param {?object} nextState Next object to set as state.
1130
+ * @param {?object} nextFullContext Next object to set as _currentContext.
1131
+ * @param {?object} nextContext Next object to set as context.
757
1132
  * @param {ReactReconcileTransaction} transaction
758
1133
  * @private
759
1134
  */
760
- _performComponentUpdate: function(nextProps, nextState, transaction) {
1135
+ _performComponentUpdate: function(
1136
+ nextProps,
1137
+ nextOwner,
1138
+ nextState,
1139
+ nextFullContext,
1140
+ nextContext,
1141
+ transaction
1142
+ ) {
761
1143
  var prevProps = this.props;
1144
+ var prevOwner = this._owner;
762
1145
  var prevState = this.state;
1146
+ var prevContext = this.context;
763
1147
 
764
1148
  if (this.componentWillUpdate) {
765
- this.componentWillUpdate(nextProps, nextState, transaction);
1149
+ this.componentWillUpdate(nextProps, nextState, nextContext);
766
1150
  }
767
1151
 
768
1152
  this.props = nextProps;
1153
+ this._owner = nextOwner;
769
1154
  this.state = nextState;
770
-
771
- this.updateComponent(transaction, prevProps, prevState);
1155
+ this._currentContext = nextFullContext;
1156
+ this.context = nextContext;
1157
+
1158
+ this.updateComponent(
1159
+ transaction,
1160
+ prevProps,
1161
+ prevOwner,
1162
+ prevState,
1163
+ prevContext
1164
+ );
772
1165
 
773
1166
  if (this.componentDidUpdate) {
774
1167
  transaction.getReactMountReady().enqueue(
775
1168
  this,
776
- this.componentDidUpdate.bind(this, prevProps, prevState)
1169
+ this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
777
1170
  );
778
1171
  }
779
1172
  },
780
1173
 
1174
+ receiveComponent: function(nextComponent, transaction) {
1175
+ if (nextComponent === this) {
1176
+ // Since props and context are immutable after the component is
1177
+ // mounted, we can do a cheap identity compare here to determine
1178
+ // if this is a superfluous reconcile.
1179
+ return;
1180
+ }
1181
+
1182
+ this._pendingContext = nextComponent._currentContext;
1183
+ ReactComponent.Mixin.receiveComponent.call(
1184
+ this,
1185
+ nextComponent,
1186
+ transaction
1187
+ );
1188
+ },
1189
+
781
1190
  /**
782
1191
  * Updates the component's currently mounted DOM representation.
783
1192
  *
@@ -786,32 +1195,39 @@ var ReactCompositeComponentMixin = {
786
1195
  *
787
1196
  * @param {ReactReconcileTransaction} transaction
788
1197
  * @param {object} prevProps
1198
+ * @param {?ReactComponent} prevOwner
789
1199
  * @param {?object} prevState
1200
+ * @param {?object} prevContext
790
1201
  * @internal
791
1202
  * @overridable
792
1203
  */
793
1204
  updateComponent: ReactPerf.measure(
794
1205
  'ReactCompositeComponent',
795
1206
  'updateComponent',
796
- function(transaction, prevProps, prevState) {
797
- ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps);
798
- var currentComponent = this._renderedComponent;
1207
+ function(transaction, prevProps, prevOwner, prevState, prevContext) {
1208
+ ReactComponent.Mixin.updateComponent.call(
1209
+ this,
1210
+ transaction,
1211
+ prevProps,
1212
+ prevOwner
1213
+ );
1214
+ var prevComponent = this._renderedComponent;
799
1215
  var nextComponent = this._renderValidatedComponent();
800
- if (currentComponent.constructor === nextComponent.constructor) {
801
- currentComponent.receiveComponent(nextComponent, transaction);
1216
+ if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
1217
+ prevComponent.receiveComponent(nextComponent, transaction);
802
1218
  } else {
803
1219
  // These two IDs are actually the same! But nothing should rely on that.
804
1220
  var thisID = this._rootNodeID;
805
- var currentComponentID = currentComponent._rootNodeID;
806
- currentComponent.unmountComponent();
1221
+ var prevComponentID = prevComponent._rootNodeID;
1222
+ prevComponent.unmountComponent();
807
1223
  this._renderedComponent = nextComponent;
808
1224
  var nextMarkup = nextComponent.mountComponent(
809
1225
  thisID,
810
1226
  transaction,
811
1227
  this._mountDepth + 1
812
1228
  );
813
- ReactComponent.DOMIDOperations.dangerouslyReplaceNodeWithMarkupByID(
814
- currentComponentID,
1229
+ ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
1230
+ prevComponentID,
815
1231
  nextMarkup
816
1232
  );
817
1233
  }
@@ -855,25 +1271,29 @@ var ReactCompositeComponentMixin = {
855
1271
  /**
856
1272
  * @private
857
1273
  */
858
- _renderValidatedComponent: function() {
859
- var renderedComponent;
860
- ReactCurrentOwner.current = this;
861
- try {
862
- renderedComponent = this.render();
863
- } catch (error) {
864
- // IE8 requires `catch` in order to use `finally`.
865
- throw error;
866
- } finally {
867
- ReactCurrentOwner.current = null;
1274
+ _renderValidatedComponent: ReactPerf.measure(
1275
+ 'ReactCompositeComponent',
1276
+ '_renderValidatedComponent',
1277
+ function() {
1278
+ var renderedComponent;
1279
+ var previousContext = ReactContext.current;
1280
+ ReactContext.current = this._processChildContext(this._currentContext);
1281
+ ReactCurrentOwner.current = this;
1282
+ try {
1283
+ renderedComponent = this.render();
1284
+ } finally {
1285
+ ReactContext.current = previousContext;
1286
+ ReactCurrentOwner.current = null;
1287
+ }
1288
+ ("production" !== process.env.NODE_ENV ? invariant(
1289
+ ReactComponent.isValidComponent(renderedComponent),
1290
+ '%s.render(): A valid ReactComponent must be returned. You may have ' +
1291
+ 'returned null, undefined, an array, or some other invalid object.',
1292
+ this.constructor.displayName || 'ReactCompositeComponent'
1293
+ ) : invariant(ReactComponent.isValidComponent(renderedComponent)));
1294
+ return renderedComponent;
868
1295
  }
869
- ("production" !== process.env.NODE_ENV ? invariant(
870
- ReactComponent.isValidComponent(renderedComponent),
871
- '%s.render(): A valid ReactComponent must be returned. You may have ' +
872
- 'returned null, undefined, an array, or some other invalid object.',
873
- this.constructor.displayName || 'ReactCompositeComponent'
874
- ) : invariant(ReactComponent.isValidComponent(renderedComponent)));
875
- return renderedComponent;
876
- },
1296
+ ),
877
1297
 
878
1298
  /**
879
1299
  * @private
@@ -908,7 +1328,7 @@ var ReactCompositeComponentMixin = {
908
1328
  boundMethod.__reactBoundArguments = null;
909
1329
  var componentName = component.constructor.displayName;
910
1330
  var _bind = boundMethod.bind;
911
- boundMethod.bind = function(newThis) {
1331
+ boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1);
912
1332
  // User is trying to bind() an autobound method; we effectively will
913
1333
  // ignore the value of "this" that the user is trying to use, so
914
1334
  // let's warn.
@@ -917,7 +1337,7 @@ var ReactCompositeComponentMixin = {
917
1337
  'bind(): React component methods may only be bound to the ' +
918
1338
  'component instance. See ' + componentName
919
1339
  );
920
- } else if (arguments.length === 1) {
1340
+ } else if (!args.length) {
921
1341
  console.warn(
922
1342
  'bind(): You are binding a component method to the component. ' +
923
1343
  'React does this for you automatically in a high-performance ' +
@@ -928,8 +1348,7 @@ var ReactCompositeComponentMixin = {
928
1348
  var reboundMethod = _bind.apply(boundMethod, arguments);
929
1349
  reboundMethod.__reactBoundContext = component;
930
1350
  reboundMethod.__reactBoundMethod = method;
931
- reboundMethod.__reactBoundArguments =
932
- Array.prototype.slice.call(arguments, 1);
1351
+ reboundMethod.__reactBoundArguments = args;
933
1352
  return reboundMethod;
934
1353
  };
935
1354
  }
@@ -943,6 +1362,18 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
943
1362
  mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
944
1363
  mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
945
1364
 
1365
+ /**
1366
+ * Checks if a value is a valid component constructor.
1367
+ *
1368
+ * @param {*}
1369
+ * @return {boolean}
1370
+ * @public
1371
+ */
1372
+ function isValidClass(componentClass) {
1373
+ return componentClass instanceof Function &&
1374
+ 'componentConstructor' in componentClass &&
1375
+ componentClass.componentConstructor instanceof Function;
1376
+ }
946
1377
  /**
947
1378
  * Module for creating composite components.
948
1379
  *
@@ -968,7 +1399,17 @@ var ReactCompositeComponent = {
968
1399
  var Constructor = function() {};
969
1400
  Constructor.prototype = new ReactCompositeComponentBase();
970
1401
  Constructor.prototype.constructor = Constructor;
971
- mixSpecIntoComponent(Constructor, spec);
1402
+
1403
+ var ConvenienceConstructor = function(props, children) {
1404
+ var instance = new Constructor();
1405
+ instance.construct.apply(instance, arguments);
1406
+ return instance;
1407
+ };
1408
+ ConvenienceConstructor.componentConstructor = Constructor;
1409
+ Constructor.ConvenienceConstructor = ConvenienceConstructor;
1410
+ ConvenienceConstructor.originalSpec = spec;
1411
+
1412
+ mixSpecIntoComponent(ConvenienceConstructor, spec);
972
1413
 
973
1414
  ("production" !== process.env.NODE_ENV ? invariant(
974
1415
  Constructor.prototype.render,
@@ -986,6 +1427,14 @@ var ReactCompositeComponent = {
986
1427
  }
987
1428
  }
988
1429
 
1430
+ // Expose the convience constructor on the prototype so that it can be
1431
+ // easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
1432
+ // static methods like <Foo />.type.staticMethod();
1433
+ // This should not be named constructor since this may not be the function
1434
+ // that created the descriptor, and it may not even be a constructor.
1435
+ ConvenienceConstructor.type = Constructor;
1436
+ Constructor.prototype.type = Constructor;
1437
+
989
1438
  // Reduce time spent doing lookups by setting these on the prototype.
990
1439
  for (var methodName in ReactCompositeComponentInterface) {
991
1440
  if (!Constructor.prototype[methodName]) {
@@ -993,28 +1442,14 @@ var ReactCompositeComponent = {
993
1442
  }
994
1443
  }
995
1444
 
996
- var ConvenienceConstructor = function(props, children) {
997
- var instance = new Constructor();
998
- instance.construct.apply(instance, arguments);
999
- return instance;
1000
- };
1001
- ConvenienceConstructor.componentConstructor = Constructor;
1002
- ConvenienceConstructor.originalSpec = spec;
1445
+ if ("production" !== process.env.NODE_ENV) {
1446
+ Constructor.prototype = createMountWarningMembrane(Constructor.prototype);
1447
+ }
1448
+
1003
1449
  return ConvenienceConstructor;
1004
1450
  },
1005
1451
 
1006
- /**
1007
- * Checks if a value is a valid component constructor.
1008
- *
1009
- * @param {*}
1010
- * @return {boolean}
1011
- * @public
1012
- */
1013
- isValidClass: function(componentClass) {
1014
- return componentClass instanceof Function &&
1015
- 'componentConstructor' in componentClass &&
1016
- componentClass.componentConstructor instanceof Function;
1017
- }
1452
+ isValidClass: isValidClass
1018
1453
  };
1019
1454
 
1020
1455
  module.exports = ReactCompositeComponent;