react 0.9.0 → 0.11.0

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 (114) hide show
  1. package/README.md +3 -0
  2. package/dist/JSXTransformer.js +13448 -0
  3. package/dist/react-with-addons.js +20235 -0
  4. package/dist/react-with-addons.min.js +22 -0
  5. package/dist/react.js +18443 -0
  6. package/dist/react.min.js +21 -0
  7. package/lib/AutoFocusMixin.js +3 -1
  8. package/lib/BeforeInputEventPlugin.js +222 -0
  9. package/lib/CSSPropertyOperations.js +3 -3
  10. package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
  11. package/lib/ChangeEventPlugin.js +1 -1
  12. package/lib/CompositionEventPlugin.js +5 -1
  13. package/lib/DOMChildrenOperations.js +33 -20
  14. package/lib/DOMProperty.js +51 -21
  15. package/lib/DOMPropertyOperations.js +28 -16
  16. package/lib/DefaultEventPluginOrder.js +1 -0
  17. package/lib/EventConstants.js +1 -0
  18. package/lib/EventListener.js +5 -2
  19. package/lib/EventPluginHub.js +2 -5
  20. package/lib/EventPluginRegistry.js +6 -4
  21. package/lib/EventPluginUtils.js +11 -1
  22. package/lib/ExecutionEnvironment.js +8 -2
  23. package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +41 -58
  24. package/lib/LinkedValueUtils.js +26 -28
  25. package/lib/LocalEventTrapMixin.js +52 -0
  26. package/lib/React.js +39 -3
  27. package/lib/ReactBrowserComponentMixin.js +46 -0
  28. package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
  29. package/lib/ReactCSSTransitionGroup.js +12 -10
  30. package/lib/ReactCSSTransitionGroupChild.js +2 -5
  31. package/lib/ReactChildren.js +31 -10
  32. package/lib/ReactComponent.js +119 -223
  33. package/lib/ReactComponentBrowserEnvironment.js +3 -36
  34. package/lib/ReactComponentWithPureRenderMixin.js +54 -0
  35. package/lib/ReactCompositeComponent.js +249 -287
  36. package/lib/ReactDOM.js +25 -23
  37. package/lib/ReactDOMButton.js +2 -1
  38. package/lib/ReactDOMComponent.js +42 -23
  39. package/lib/ReactDOMForm.js +7 -12
  40. package/lib/ReactDOMIDOperations.js +2 -31
  41. package/lib/ReactDOMImg.js +7 -13
  42. package/lib/ReactDOMInput.js +2 -1
  43. package/lib/ReactDOMOption.js +11 -7
  44. package/lib/ReactDOMSelect.js +18 -16
  45. package/lib/ReactDOMSelection.js +35 -10
  46. package/lib/ReactDOMTextarea.js +9 -7
  47. package/lib/ReactDefaultBatchingStrategy.js +3 -3
  48. package/lib/ReactDefaultInjection.js +27 -14
  49. package/lib/ReactDefaultPerf.js +28 -11
  50. package/lib/ReactDefaultPerfAnalysis.js +4 -0
  51. package/lib/ReactDescriptor.js +251 -0
  52. package/lib/ReactDescriptorValidator.js +283 -0
  53. package/lib/ReactEmptyComponent.js +78 -0
  54. package/lib/ReactEventEmitterMixin.js +1 -3
  55. package/lib/ReactEventListener.js +189 -0
  56. package/lib/ReactInjection.js +8 -2
  57. package/lib/ReactInputSelection.js +2 -1
  58. package/lib/ReactLink.js +24 -0
  59. package/lib/ReactMount.js +61 -21
  60. package/lib/ReactMultiChild.js +18 -13
  61. package/lib/ReactOwner.js +6 -1
  62. package/lib/ReactPropTransferer.js +44 -29
  63. package/lib/ReactPropTypes.js +226 -242
  64. package/lib/ReactPutListenerQueue.js +2 -2
  65. package/lib/ReactReconcileTransaction.js +21 -20
  66. package/lib/ReactServerRendering.js +41 -11
  67. package/lib/ReactServerRenderingTransaction.js +115 -0
  68. package/lib/ReactTestUtils.js +39 -21
  69. package/lib/ReactTextComponent.js +21 -13
  70. package/lib/ReactTransitionChildMapping.js +2 -2
  71. package/lib/ReactTransitionEvents.js +19 -0
  72. package/lib/ReactTransitionGroup.js +9 -6
  73. package/lib/ReactUpdates.js +139 -22
  74. package/lib/ReactWithAddons.js +8 -3
  75. package/lib/SVGDOMPropertyConfig.js +97 -0
  76. package/lib/SimpleEventPlugin.js +7 -1
  77. package/lib/SyntheticInputEvent.js +52 -0
  78. package/lib/SyntheticKeyboardEvent.js +33 -4
  79. package/lib/SyntheticMouseEvent.js +3 -0
  80. package/lib/SyntheticTouchEvent.js +4 -1
  81. package/lib/SyntheticUIEvent.js +24 -2
  82. package/lib/Transaction.js +0 -32
  83. package/lib/cloneWithProps.js +10 -8
  84. package/lib/createFullPageComponent.js +1 -1
  85. package/lib/dangerousStyleValue.js +11 -5
  86. package/lib/{ReactComponentEnvironment.js → emptyObject.js} +6 -5
  87. package/lib/escapeTextForBrowser.js +2 -3
  88. package/lib/flattenChildren.js +9 -7
  89. package/lib/focusNode.js +33 -0
  90. package/lib/getEventKey.js +35 -5
  91. package/lib/getEventModifierState.js +52 -0
  92. package/lib/getMarkupWrap.js +2 -0
  93. package/lib/getTextContentAccessor.js +1 -1
  94. package/lib/hyphenate.js +3 -0
  95. package/lib/hyphenateStyleName.js +46 -0
  96. package/lib/instantiateReactComponent.js +62 -0
  97. package/lib/invariant.js +17 -19
  98. package/lib/isNode.js +1 -1
  99. package/lib/{objMap.js → mapObject.js} +8 -3
  100. package/lib/mergeHelpers.js +11 -0
  101. package/lib/mergeInto.js +3 -2
  102. package/lib/monitorCodeUse.js +37 -0
  103. package/lib/onlyChild.js +3 -3
  104. package/lib/performance.js +33 -0
  105. package/lib/performanceNow.js +5 -14
  106. package/lib/setInnerHTML.js +77 -0
  107. package/lib/shouldUpdateReactComponent.js +14 -28
  108. package/lib/toArray.js +1 -1
  109. package/lib/traverseAllChildren.js +9 -5
  110. package/lib/update.js +171 -0
  111. package/package.json +4 -3
  112. package/lib/ReactEventTopLevelCallback.js +0 -149
  113. package/lib/createObjectFrom.js +0 -61
  114. package/lib/objMapKeyVal.js +0 -47
@@ -28,6 +28,7 @@ var ReactReconcileTransaction = require("./ReactReconcileTransaction");
28
28
 
29
29
  var getReactRootElementInContainer = require("./getReactRootElementInContainer");
30
30
  var invariant = require("./invariant");
31
+ var setInnerHTML = require("./setInnerHTML");
31
32
 
32
33
 
33
34
  var ELEMENT_NODE_TYPE = 1;
@@ -39,26 +40,6 @@ var DOC_NODE_TYPE = 9;
39
40
  * the browser context.
40
41
  */
41
42
  var ReactComponentBrowserEnvironment = {
42
- /**
43
- * Mixed into every component instance.
44
- */
45
- Mixin: {
46
- /**
47
- * Returns the DOM node rendered by this component.
48
- *
49
- * @return {DOMElement} The root node of this component.
50
- * @final
51
- * @protected
52
- */
53
- getDOMNode: function() {
54
- ("production" !== process.env.NODE_ENV ? invariant(
55
- this.isMounted(),
56
- 'getDOMNode(): A component must be mounted to have a DOM node.'
57
- ) : invariant(this.isMounted()));
58
- return ReactMount.getNode(this._rootNodeID);
59
- }
60
- },
61
-
62
43
  ReactReconcileTransaction: ReactReconcileTransaction,
63
44
 
64
45
  BackendIDOperations: ReactDOMIDOperations,
@@ -118,7 +99,7 @@ var ReactComponentBrowserEnvironment = {
118
99
  'React attempted to use reuse markup in a container but the ' +
119
100
  'checksum was invalid. This generally means that you are ' +
120
101
  'using server rendering and the markup generated on the ' +
121
- 'server was not what the client was expecting. React injected' +
102
+ 'server was not what the client was expecting. React injected ' +
122
103
  'new markup to compensate which works but you have lost many ' +
123
104
  'of the benefits of server rendering. Instead, figure out ' +
124
105
  'why the markup being generated is different on the client ' +
@@ -136,21 +117,7 @@ var ReactComponentBrowserEnvironment = {
136
117
  'See renderComponentToString() for server rendering.'
137
118
  ) : invariant(container.nodeType !== DOC_NODE_TYPE));
138
119
 
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
- }
151
- } else {
152
- container.innerHTML = markup;
153
- }
120
+ setInnerHTML(container, markup);
154
121
  }
155
122
  )
156
123
  };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Copyright 2013-2014 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 ReactComponentWithPureRenderMixin
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var shallowEqual = require("./shallowEqual");
22
+
23
+ /**
24
+ * If your React component's render function is "pure", e.g. it will render the
25
+ * same result given the same props and state, provide this Mixin for a
26
+ * considerable performance boost.
27
+ *
28
+ * Most React components have pure render functions.
29
+ *
30
+ * Example:
31
+ *
32
+ * var ReactComponentWithPureRenderMixin =
33
+ * require('ReactComponentWithPureRenderMixin');
34
+ * React.createClass({
35
+ * mixins: [ReactComponentWithPureRenderMixin],
36
+ *
37
+ * render: function() {
38
+ * return <div className={this.props.className}>foo</div>;
39
+ * }
40
+ * });
41
+ *
42
+ * Note: This only checks shallow equality for props and state. If these contain
43
+ * complex data structures this mixin may have false-negatives for deeper
44
+ * differences. Only mixin to components which have simple props and state, or
45
+ * use `forceUpdate()` when you know deep data structures have changed.
46
+ */
47
+ var ReactComponentWithPureRenderMixin = {
48
+ shouldComponentUpdate: function(nextProps, nextState) {
49
+ return !shallowEqual(this.props, nextProps) ||
50
+ !shallowEqual(this.state, nextState);
51
+ }
52
+ };
53
+
54
+ module.exports = ReactComponentWithPureRenderMixin;
@@ -21,6 +21,9 @@
21
21
  var ReactComponent = require("./ReactComponent");
22
22
  var ReactContext = require("./ReactContext");
23
23
  var ReactCurrentOwner = require("./ReactCurrentOwner");
24
+ var ReactDescriptor = require("./ReactDescriptor");
25
+ var ReactDescriptorValidator = require("./ReactDescriptorValidator");
26
+ var ReactEmptyComponent = require("./ReactEmptyComponent");
24
27
  var ReactErrorUtils = require("./ReactErrorUtils");
25
28
  var ReactOwner = require("./ReactOwner");
26
29
  var ReactPerf = require("./ReactPerf");
@@ -29,12 +32,15 @@ var ReactPropTypeLocations = require("./ReactPropTypeLocations");
29
32
  var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
30
33
  var ReactUpdates = require("./ReactUpdates");
31
34
 
35
+ var instantiateReactComponent = require("./instantiateReactComponent");
32
36
  var invariant = require("./invariant");
33
37
  var keyMirror = require("./keyMirror");
34
38
  var merge = require("./merge");
35
39
  var mixInto = require("./mixInto");
36
- var objMap = require("./objMap");
40
+ var monitorCodeUse = require("./monitorCodeUse");
41
+ var mapObject = require("./mapObject");
37
42
  var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
43
+ var warning = require("./warning");
38
44
 
39
45
  /**
40
46
  * Policies that describe methods in `ReactCompositeComponentInterface`.
@@ -61,6 +67,9 @@ var SpecPolicy = keyMirror({
61
67
  DEFINE_MANY_MERGED: null
62
68
  });
63
69
 
70
+
71
+ var injectedMixins = [];
72
+
64
73
  /**
65
74
  * Composite components are higher-level components that compose other composite
66
75
  * or native components.
@@ -320,18 +329,17 @@ var ReactCompositeComponentInterface = {
320
329
  * which all other static methods are defined.
321
330
  */
322
331
  var RESERVED_SPEC_KEYS = {
323
- displayName: function(ConvenienceConstructor, displayName) {
324
- ConvenienceConstructor.componentConstructor.displayName = displayName;
332
+ displayName: function(Constructor, displayName) {
333
+ Constructor.displayName = displayName;
325
334
  },
326
- mixins: function(ConvenienceConstructor, mixins) {
335
+ mixins: function(Constructor, mixins) {
327
336
  if (mixins) {
328
337
  for (var i = 0; i < mixins.length; i++) {
329
- mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
338
+ mixSpecIntoComponent(Constructor, mixins[i]);
330
339
  }
331
340
  }
332
341
  },
333
- childContextTypes: function(ConvenienceConstructor, childContextTypes) {
334
- var Constructor = ConvenienceConstructor.componentConstructor;
342
+ childContextTypes: function(Constructor, childContextTypes) {
335
343
  validateTypeDef(
336
344
  Constructor,
337
345
  childContextTypes,
@@ -342,8 +350,7 @@ var RESERVED_SPEC_KEYS = {
342
350
  childContextTypes
343
351
  );
344
352
  },
345
- contextTypes: function(ConvenienceConstructor, contextTypes) {
346
- var Constructor = ConvenienceConstructor.componentConstructor;
353
+ contextTypes: function(Constructor, contextTypes) {
347
354
  validateTypeDef(
348
355
  Constructor,
349
356
  contextTypes,
@@ -351,8 +358,21 @@ var RESERVED_SPEC_KEYS = {
351
358
  );
352
359
  Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
353
360
  },
354
- propTypes: function(ConvenienceConstructor, propTypes) {
355
- var Constructor = ConvenienceConstructor.componentConstructor;
361
+ /**
362
+ * Special case getDefaultProps which should move into statics but requires
363
+ * automatic merging.
364
+ */
365
+ getDefaultProps: function(Constructor, getDefaultProps) {
366
+ if (Constructor.getDefaultProps) {
367
+ Constructor.getDefaultProps = createMergedResultFunction(
368
+ Constructor.getDefaultProps,
369
+ getDefaultProps
370
+ );
371
+ } else {
372
+ Constructor.getDefaultProps = getDefaultProps;
373
+ }
374
+ },
375
+ propTypes: function(Constructor, propTypes) {
356
376
  validateTypeDef(
357
377
  Constructor,
358
378
  propTypes,
@@ -360,11 +380,20 @@ var RESERVED_SPEC_KEYS = {
360
380
  );
361
381
  Constructor.propTypes = merge(Constructor.propTypes, propTypes);
362
382
  },
363
- statics: function(ConvenienceConstructor, statics) {
364
- mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
383
+ statics: function(Constructor, statics) {
384
+ mixStaticSpecIntoComponent(Constructor, statics);
365
385
  }
366
386
  };
367
387
 
388
+ function getDeclarationErrorAddendum(component) {
389
+ var owner = component._owner || null;
390
+ if (owner && owner.constructor && owner.constructor.displayName) {
391
+ return ' Check the render method of `' + owner.constructor.displayName +
392
+ '`.';
393
+ }
394
+ return '';
395
+ }
396
+
368
397
  function validateTypeDef(Constructor, typeDef, location) {
369
398
  for (var propName in typeDef) {
370
399
  if (typeDef.hasOwnProperty(propName)) {
@@ -381,7 +410,9 @@ function validateTypeDef(Constructor, typeDef, location) {
381
410
  }
382
411
 
383
412
  function validateMethodOverride(proto, name) {
384
- var specPolicy = ReactCompositeComponentInterface[name];
413
+ var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
414
+ ReactCompositeComponentInterface[name] :
415
+ null;
385
416
 
386
417
  // Disallow overriding of base class methods unless explicitly allowed.
387
418
  if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
@@ -431,19 +462,18 @@ function validateLifeCycleOnReplaceState(instance) {
431
462
  * Custom version of `mixInto` which handles policy validation and reserved
432
463
  * specification keys when building `ReactCompositeComponent` classses.
433
464
  */
434
- function mixSpecIntoComponent(ConvenienceConstructor, spec) {
465
+ function mixSpecIntoComponent(Constructor, spec) {
435
466
  ("production" !== process.env.NODE_ENV ? invariant(
436
- !isValidClass(spec),
467
+ !ReactDescriptor.isValidFactory(spec),
437
468
  'ReactCompositeComponent: You\'re attempting to ' +
438
469
  'use a component class as a mixin. Instead, just use a regular object.'
439
- ) : invariant(!isValidClass(spec)));
470
+ ) : invariant(!ReactDescriptor.isValidFactory(spec)));
440
471
  ("production" !== process.env.NODE_ENV ? invariant(
441
- !ReactComponent.isValidComponent(spec),
472
+ !ReactDescriptor.isValidDescriptor(spec),
442
473
  'ReactCompositeComponent: You\'re attempting to ' +
443
474
  'use a component as a mixin. Instead, just use a regular object.'
444
- ) : invariant(!ReactComponent.isValidComponent(spec)));
475
+ ) : invariant(!ReactDescriptor.isValidDescriptor(spec)));
445
476
 
446
- var Constructor = ConvenienceConstructor.componentConstructor;
447
477
  var proto = Constructor.prototype;
448
478
  for (var name in spec) {
449
479
  var property = spec[name];
@@ -454,20 +484,21 @@ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
454
484
  validateMethodOverride(proto, name);
455
485
 
456
486
  if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
457
- RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
487
+ RESERVED_SPEC_KEYS[name](Constructor, property);
458
488
  } else {
459
489
  // Setup methods on prototype:
460
490
  // The following member methods should not be automatically bound:
461
491
  // 1. Expected ReactCompositeComponent methods (in the "interface").
462
492
  // 2. Overridden methods (that were mixed in).
463
- var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
464
- var isInherited = name in proto;
493
+ var isCompositeComponentMethod =
494
+ ReactCompositeComponentInterface.hasOwnProperty(name);
495
+ var isAlreadyDefined = proto.hasOwnProperty(name);
465
496
  var markedDontBind = property && property.__reactDontBind;
466
497
  var isFunction = typeof property === 'function';
467
498
  var shouldAutoBind =
468
499
  isFunction &&
469
500
  !isCompositeComponentMethod &&
470
- !isInherited &&
501
+ !isAlreadyDefined &&
471
502
  !markedDontBind;
472
503
 
473
504
  if (shouldAutoBind) {
@@ -477,37 +508,60 @@ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
477
508
  proto.__reactAutoBindMap[name] = property;
478
509
  proto[name] = property;
479
510
  } else {
480
- if (isInherited) {
511
+ if (isAlreadyDefined) {
512
+ var specPolicy = ReactCompositeComponentInterface[name];
513
+
514
+ // These cases should already be caught by validateMethodOverride
515
+ ("production" !== process.env.NODE_ENV ? invariant(
516
+ isCompositeComponentMethod && (
517
+ specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
518
+ specPolicy === SpecPolicy.DEFINE_MANY
519
+ ),
520
+ 'ReactCompositeComponent: Unexpected spec policy %s for key %s ' +
521
+ 'when mixing in component specs.',
522
+ specPolicy,
523
+ name
524
+ ) : invariant(isCompositeComponentMethod && (
525
+ specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
526
+ specPolicy === SpecPolicy.DEFINE_MANY
527
+ )));
528
+
481
529
  // For methods which are defined more than once, call the existing
482
- // methods before calling the new property.
483
- if (ReactCompositeComponentInterface[name] ===
484
- SpecPolicy.DEFINE_MANY_MERGED) {
530
+ // methods before calling the new property, merging if appropriate.
531
+ if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
485
532
  proto[name] = createMergedResultFunction(proto[name], property);
486
- } else {
533
+ } else if (specPolicy === SpecPolicy.DEFINE_MANY) {
487
534
  proto[name] = createChainedFunction(proto[name], property);
488
535
  }
489
536
  } else {
490
537
  proto[name] = property;
538
+ if ("production" !== process.env.NODE_ENV) {
539
+ // Add verbose displayName to the function, which helps when looking
540
+ // at profiling tools.
541
+ if (typeof property === 'function' && spec.displayName) {
542
+ proto[name].displayName = spec.displayName + '_' + name;
543
+ }
544
+ }
491
545
  }
492
546
  }
493
547
  }
494
548
  }
495
549
  }
496
550
 
497
- function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
551
+ function mixStaticSpecIntoComponent(Constructor, statics) {
498
552
  if (!statics) {
499
553
  return;
500
554
  }
501
555
  for (var name in statics) {
502
556
  var property = statics[name];
503
- if (!statics.hasOwnProperty(name) || !property) {
504
- return;
557
+ if (!statics.hasOwnProperty(name)) {
558
+ continue;
505
559
  }
506
560
 
507
- var isInherited = name in ConvenienceConstructor;
561
+ var isInherited = name in Constructor;
508
562
  var result = property;
509
563
  if (isInherited) {
510
- var existingProperty = ConvenienceConstructor[name];
564
+ var existingProperty = Constructor[name];
511
565
  var existingType = typeof existingProperty;
512
566
  var propertyType = typeof property;
513
567
  ("production" !== process.env.NODE_ENV ? invariant(
@@ -520,8 +574,7 @@ function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
520
574
  ) : invariant(existingType === 'function' && propertyType === 'function'));
521
575
  result = createChainedFunction(existingProperty, property);
522
576
  }
523
- ConvenienceConstructor[name] = result;
524
- ConvenienceConstructor.componentConstructor[name] = result;
577
+ Constructor[name] = result;
525
578
  }
526
579
  }
527
580
 
@@ -538,7 +591,7 @@ function mergeObjectsWithNoDuplicateKeys(one, two) {
538
591
  'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
539
592
  ) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
540
593
 
541
- objMap(two, function(value, key) {
594
+ mapObject(two, function(value, key) {
542
595
  ("production" !== process.env.NODE_ENV ? invariant(
543
596
  one[key] === undefined,
544
597
  'mergeObjectsWithNoDuplicateKeys(): ' +
@@ -586,118 +639,6 @@ function createChainedFunction(one, two) {
586
639
  };
587
640
  }
588
641
 
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
-
701
642
  /**
702
643
  * `ReactCompositeComponent` maintains an auxiliary life cycle state in
703
644
  * `this._compositeLifeCycleState` (which can be null).
@@ -755,21 +696,21 @@ var ReactCompositeComponentMixin = {
755
696
  /**
756
697
  * Base constructor for all composite component.
757
698
  *
758
- * @param {?object} initialProps
759
- * @param {*} children
699
+ * @param {ReactDescriptor} descriptor
760
700
  * @final
761
701
  * @internal
762
702
  */
763
- construct: function(initialProps, children) {
703
+ construct: function(descriptor) {
764
704
  // Children can be either an array or more than one argument
765
705
  ReactComponent.Mixin.construct.apply(this, arguments);
706
+ ReactOwner.Mixin.construct.apply(this, arguments);
766
707
 
767
708
  this.state = null;
768
709
  this._pendingState = null;
769
710
 
770
- this.context = this._processContext(ReactContext.current);
771
- this._currentContext = ReactContext.current;
772
- this._pendingContext = null;
711
+ // This is the public post-processed context. The real context and pending
712
+ // context lives on the descriptor.
713
+ this.context = null;
773
714
 
774
715
  this._compositeLifeCycleState = null;
775
716
  },
@@ -789,7 +730,7 @@ var ReactCompositeComponentMixin = {
789
730
  * Initializes the component, renders markup, and registers event listeners.
790
731
  *
791
732
  * @param {string} rootID DOM ID of the root node.
792
- * @param {ReactReconcileTransaction} transaction
733
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
793
734
  * @param {number} mountDepth number of components in the owner hierarchy
794
735
  * @return {?string} Rendered markup to be inserted into the DOM.
795
736
  * @final
@@ -807,13 +748,13 @@ var ReactCompositeComponentMixin = {
807
748
  );
808
749
  this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
809
750
 
810
- this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
811
- this.props = this._processProps(this.props);
812
-
813
751
  if (this.__reactAutoBindMap) {
814
752
  this._bindAutoBindMethods();
815
753
  }
816
754
 
755
+ this.context = this._processContext(this._descriptor._context);
756
+ this.props = this._processProps(this.props);
757
+
817
758
  this.state = this.getInitialState ? this.getInitialState() : null;
818
759
  ("production" !== process.env.NODE_ENV ? invariant(
819
760
  typeof this.state === 'object' && !Array.isArray(this.state),
@@ -834,7 +775,9 @@ var ReactCompositeComponentMixin = {
834
775
  }
835
776
  }
836
777
 
837
- this._renderedComponent = this._renderValidatedComponent();
778
+ this._renderedComponent = instantiateReactComponent(
779
+ this._renderValidatedComponent()
780
+ );
838
781
 
839
782
  // Done with mounting, `setState` will now trigger UI changes.
840
783
  this._compositeLifeCycleState = null;
@@ -844,7 +787,7 @@ var ReactCompositeComponentMixin = {
844
787
  mountDepth + 1
845
788
  );
846
789
  if (this.componentDidMount) {
847
- transaction.getReactMountReady().enqueue(this, this.componentDidMount);
790
+ transaction.getReactMountReady().enqueue(this.componentDidMount, this);
848
791
  }
849
792
  return markup;
850
793
  }
@@ -863,17 +806,11 @@ var ReactCompositeComponentMixin = {
863
806
  }
864
807
  this._compositeLifeCycleState = null;
865
808
 
866
- this._defaultProps = null;
867
-
868
809
  this._renderedComponent.unmountComponent();
869
810
  this._renderedComponent = null;
870
811
 
871
812
  ReactComponent.Mixin.unmountComponent.call(this);
872
813
 
873
- if (this.refs) {
874
- this.refs = null;
875
- }
876
-
877
814
  // Some existing components rely on this.props even after they've been
878
815
  // destroyed (in event handlers).
879
816
  // TODO: this.props = null;
@@ -902,13 +839,12 @@ var ReactCompositeComponentMixin = {
902
839
  typeof partialState === 'object' || partialState == null,
903
840
  'setState(...): takes an object of state variables to update.'
904
841
  ) : 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
- }
842
+ if ("production" !== process.env.NODE_ENV){
843
+ ("production" !== process.env.NODE_ENV ? warning(
844
+ partialState != null,
845
+ 'setState(...): You passed an undefined or null state object; ' +
846
+ 'instead, use forceUpdate().'
847
+ ) : null);
912
848
  }
913
849
  // Merge with `_pendingState` if it exists, otherwise with existing state.
914
850
  this.replaceState(
@@ -1007,12 +943,17 @@ var ReactCompositeComponentMixin = {
1007
943
  * @private
1008
944
  */
1009
945
  _processProps: function(newProps) {
1010
- var props = merge(newProps);
1011
- var defaultProps = this._defaultProps;
1012
- for (var propName in defaultProps) {
1013
- if (typeof props[propName] === 'undefined') {
1014
- props[propName] = defaultProps[propName];
946
+ var defaultProps = this.constructor.defaultProps;
947
+ var props;
948
+ if (defaultProps) {
949
+ props = merge(newProps);
950
+ for (var propName in defaultProps) {
951
+ if (typeof props[propName] === 'undefined') {
952
+ props[propName] = defaultProps[propName];
953
+ }
1015
954
  }
955
+ } else {
956
+ props = newProps;
1016
957
  }
1017
958
  if ("production" !== process.env.NODE_ENV) {
1018
959
  var propTypes = this.constructor.propTypes;
@@ -1032,15 +973,32 @@ var ReactCompositeComponentMixin = {
1032
973
  * @private
1033
974
  */
1034
975
  _checkPropTypes: function(propTypes, props, location) {
976
+ // TODO: Stop validating prop types here and only use the descriptor
977
+ // validation.
1035
978
  var componentName = this.constructor.displayName;
1036
979
  for (var propName in propTypes) {
1037
980
  if (propTypes.hasOwnProperty(propName)) {
1038
- propTypes[propName](props, propName, componentName, location);
981
+ var error =
982
+ propTypes[propName](props, propName, componentName, location);
983
+ if (error instanceof Error) {
984
+ // We may want to extend this logic for similar errors in
985
+ // renderComponent calls, so I'm abstracting it away into
986
+ // a function to minimize refactoring in the future
987
+ var addendum = getDeclarationErrorAddendum(this);
988
+ ("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null);
989
+ }
1039
990
  }
1040
991
  }
1041
992
  },
1042
993
 
1043
- performUpdateIfNecessary: function() {
994
+ /**
995
+ * If any of `_pendingDescriptor`, `_pendingState`, or `_pendingForceUpdate`
996
+ * is set, update the component.
997
+ *
998
+ * @param {ReactReconcileTransaction} transaction
999
+ * @internal
1000
+ */
1001
+ performUpdateIfNecessary: function(transaction) {
1044
1002
  var compositeLifeCycleState = this._compositeLifeCycleState;
1045
1003
  // Do not trigger a state transition if we are in the middle of mounting or
1046
1004
  // receiving props because both of those will already be doing this.
@@ -1048,32 +1006,21 @@ var ReactCompositeComponentMixin = {
1048
1006
  compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
1049
1007
  return;
1050
1008
  }
1051
- ReactComponent.Mixin.performUpdateIfNecessary.call(this);
1052
- },
1053
1009
 
1054
- /**
1055
- * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is
1056
- * set, update the component.
1057
- *
1058
- * @param {ReactReconcileTransaction} transaction
1059
- * @internal
1060
- */
1061
- _performUpdateIfNecessary: function(transaction) {
1062
- if (this._pendingProps == null &&
1010
+ if (this._pendingDescriptor == null &&
1063
1011
  this._pendingState == null &&
1064
- this._pendingContext == null &&
1065
1012
  !this._pendingForceUpdate) {
1066
1013
  return;
1067
1014
  }
1068
1015
 
1069
- var nextFullContext = this._pendingContext || this._currentContext;
1070
- var nextContext = this._processContext(nextFullContext);
1071
- this._pendingContext = null;
1072
-
1016
+ var nextContext = this.context;
1073
1017
  var nextProps = this.props;
1074
- if (this._pendingProps != null) {
1075
- nextProps = this._processProps(this._pendingProps);
1076
- this._pendingProps = null;
1018
+ var nextDescriptor = this._descriptor;
1019
+ if (this._pendingDescriptor != null) {
1020
+ nextDescriptor = this._pendingDescriptor;
1021
+ nextContext = this._processContext(nextDescriptor._context);
1022
+ nextProps = this._processProps(nextDescriptor.props);
1023
+ this._pendingDescriptor = null;
1077
1024
 
1078
1025
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
1079
1026
  if (this.componentWillReceiveProps) {
@@ -1083,37 +1030,46 @@ var ReactCompositeComponentMixin = {
1083
1030
 
1084
1031
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
1085
1032
 
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
-
1092
1033
  var nextState = this._pendingState || this.state;
1093
1034
  this._pendingState = null;
1094
1035
 
1095
1036
  try {
1096
- if (this._pendingForceUpdate ||
1097
- !this.shouldComponentUpdate ||
1098
- this.shouldComponentUpdate(nextProps, nextState, nextContext)) {
1037
+ var shouldUpdate =
1038
+ this._pendingForceUpdate ||
1039
+ !this.shouldComponentUpdate ||
1040
+ this.shouldComponentUpdate(nextProps, nextState, nextContext);
1041
+
1042
+ if ("production" !== process.env.NODE_ENV) {
1043
+ if (typeof shouldUpdate === "undefined") {
1044
+ console.warn(
1045
+ (this.constructor.displayName || 'ReactCompositeComponent') +
1046
+ '.shouldComponentUpdate(): Returned undefined instead of a ' +
1047
+ 'boolean value. Make sure to return true or false.'
1048
+ );
1049
+ }
1050
+ }
1051
+
1052
+ if (shouldUpdate) {
1099
1053
  this._pendingForceUpdate = false;
1100
1054
  // Will set `this.props`, `this.state` and `this.context`.
1101
1055
  this._performComponentUpdate(
1056
+ nextDescriptor,
1102
1057
  nextProps,
1103
- nextOwner,
1104
1058
  nextState,
1105
- nextFullContext,
1106
1059
  nextContext,
1107
1060
  transaction
1108
1061
  );
1109
1062
  } else {
1110
1063
  // If it's determined that a component should not update, we still want
1111
1064
  // to set props and state.
1065
+ this._descriptor = nextDescriptor;
1112
1066
  this.props = nextProps;
1113
- this._owner = nextOwner;
1114
1067
  this.state = nextState;
1115
- this._currentContext = nextFullContext;
1116
1068
  this.context = nextContext;
1069
+
1070
+ // Owner cannot change because shouldUpdateReactComponent doesn't allow
1071
+ // it. TODO: Remove this._owner completely.
1072
+ this._owner = nextDescriptor._owner;
1117
1073
  }
1118
1074
  } finally {
1119
1075
  this._compositeLifeCycleState = null;
@@ -1124,24 +1080,22 @@ var ReactCompositeComponentMixin = {
1124
1080
  * Merges new props and state, notifies delegate methods of update and
1125
1081
  * performs update.
1126
1082
  *
1127
- * @param {object} nextProps Next object to set as properties.
1128
- * @param {?ReactComponent} nextOwner Next component to set as owner
1083
+ * @param {ReactDescriptor} nextDescriptor Next descriptor
1084
+ * @param {object} nextProps Next public object to set as properties.
1129
1085
  * @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.
1086
+ * @param {?object} nextContext Next public object to set as context.
1132
1087
  * @param {ReactReconcileTransaction} transaction
1133
1088
  * @private
1134
1089
  */
1135
1090
  _performComponentUpdate: function(
1091
+ nextDescriptor,
1136
1092
  nextProps,
1137
- nextOwner,
1138
1093
  nextState,
1139
- nextFullContext,
1140
1094
  nextContext,
1141
1095
  transaction
1142
1096
  ) {
1097
+ var prevDescriptor = this._descriptor;
1143
1098
  var prevProps = this.props;
1144
- var prevOwner = this._owner;
1145
1099
  var prevState = this.state;
1146
1100
  var prevContext = this.context;
1147
1101
 
@@ -1149,40 +1103,44 @@ var ReactCompositeComponentMixin = {
1149
1103
  this.componentWillUpdate(nextProps, nextState, nextContext);
1150
1104
  }
1151
1105
 
1106
+ this._descriptor = nextDescriptor;
1152
1107
  this.props = nextProps;
1153
- this._owner = nextOwner;
1154
1108
  this.state = nextState;
1155
- this._currentContext = nextFullContext;
1156
1109
  this.context = nextContext;
1157
1110
 
1111
+ // Owner cannot change because shouldUpdateReactComponent doesn't allow
1112
+ // it. TODO: Remove this._owner completely.
1113
+ this._owner = nextDescriptor._owner;
1114
+
1158
1115
  this.updateComponent(
1159
1116
  transaction,
1160
- prevProps,
1161
- prevOwner,
1162
- prevState,
1163
- prevContext
1117
+ prevDescriptor
1164
1118
  );
1165
1119
 
1166
1120
  if (this.componentDidUpdate) {
1167
1121
  transaction.getReactMountReady().enqueue(
1168
- this,
1169
- this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
1122
+ this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
1123
+ this
1170
1124
  );
1171
1125
  }
1172
1126
  },
1173
1127
 
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.
1128
+ receiveComponent: function(nextDescriptor, transaction) {
1129
+ if (nextDescriptor === this._descriptor &&
1130
+ nextDescriptor._owner != null) {
1131
+ // Since descriptors are immutable after the owner is rendered,
1132
+ // we can do a cheap identity compare here to determine if this is a
1133
+ // superfluous reconcile. It's possible for state to be mutable but such
1134
+ // change should trigger an update of the owner which would recreate
1135
+ // the descriptor. We explicitly check for the existence of an owner since
1136
+ // it's possible for a descriptor created outside a composite to be
1137
+ // deeply mutated and reused.
1179
1138
  return;
1180
1139
  }
1181
1140
 
1182
- this._pendingContext = nextComponent._currentContext;
1183
1141
  ReactComponent.Mixin.receiveComponent.call(
1184
1142
  this,
1185
- nextComponent,
1143
+ nextDescriptor,
1186
1144
  transaction
1187
1145
  );
1188
1146
  },
@@ -1194,34 +1152,32 @@ var ReactCompositeComponentMixin = {
1194
1152
  * Sophisticated clients may wish to override this.
1195
1153
  *
1196
1154
  * @param {ReactReconcileTransaction} transaction
1197
- * @param {object} prevProps
1198
- * @param {?ReactComponent} prevOwner
1199
- * @param {?object} prevState
1200
- * @param {?object} prevContext
1155
+ * @param {ReactDescriptor} prevDescriptor
1201
1156
  * @internal
1202
1157
  * @overridable
1203
1158
  */
1204
1159
  updateComponent: ReactPerf.measure(
1205
1160
  'ReactCompositeComponent',
1206
1161
  'updateComponent',
1207
- function(transaction, prevProps, prevOwner, prevState, prevContext) {
1162
+ function(transaction, prevParentDescriptor) {
1208
1163
  ReactComponent.Mixin.updateComponent.call(
1209
1164
  this,
1210
1165
  transaction,
1211
- prevProps,
1212
- prevOwner
1166
+ prevParentDescriptor
1213
1167
  );
1214
- var prevComponent = this._renderedComponent;
1215
- var nextComponent = this._renderValidatedComponent();
1216
- if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
1217
- prevComponent.receiveComponent(nextComponent, transaction);
1168
+
1169
+ var prevComponentInstance = this._renderedComponent;
1170
+ var prevDescriptor = prevComponentInstance._descriptor;
1171
+ var nextDescriptor = this._renderValidatedComponent();
1172
+ if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
1173
+ prevComponentInstance.receiveComponent(nextDescriptor, transaction);
1218
1174
  } else {
1219
1175
  // These two IDs are actually the same! But nothing should rely on that.
1220
1176
  var thisID = this._rootNodeID;
1221
- var prevComponentID = prevComponent._rootNodeID;
1222
- prevComponent.unmountComponent();
1223
- this._renderedComponent = nextComponent;
1224
- var nextMarkup = nextComponent.mountComponent(
1177
+ var prevComponentID = prevComponentInstance._rootNodeID;
1178
+ prevComponentInstance.unmountComponent();
1179
+ this._renderedComponent = instantiateReactComponent(nextDescriptor);
1180
+ var nextMarkup = this._renderedComponent.mountComponent(
1225
1181
  thisID,
1226
1182
  transaction,
1227
1183
  this._mountDepth + 1
@@ -1277,20 +1233,28 @@ var ReactCompositeComponentMixin = {
1277
1233
  function() {
1278
1234
  var renderedComponent;
1279
1235
  var previousContext = ReactContext.current;
1280
- ReactContext.current = this._processChildContext(this._currentContext);
1236
+ ReactContext.current = this._processChildContext(
1237
+ this._descriptor._context
1238
+ );
1281
1239
  ReactCurrentOwner.current = this;
1282
1240
  try {
1283
1241
  renderedComponent = this.render();
1242
+ if (renderedComponent === null || renderedComponent === false) {
1243
+ renderedComponent = ReactEmptyComponent.getEmptyComponent();
1244
+ ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
1245
+ } else {
1246
+ ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
1247
+ }
1284
1248
  } finally {
1285
1249
  ReactContext.current = previousContext;
1286
1250
  ReactCurrentOwner.current = null;
1287
1251
  }
1288
1252
  ("production" !== process.env.NODE_ENV ? invariant(
1289
- ReactComponent.isValidComponent(renderedComponent),
1253
+ ReactDescriptor.isValidDescriptor(renderedComponent),
1290
1254
  '%s.render(): A valid ReactComponent must be returned. You may have ' +
1291
- 'returned null, undefined, an array, or some other invalid object.',
1255
+ 'returned undefined, an array or some other invalid object.',
1292
1256
  this.constructor.displayName || 'ReactCompositeComponent'
1293
- ) : invariant(ReactComponent.isValidComponent(renderedComponent)));
1257
+ ) : invariant(ReactDescriptor.isValidDescriptor(renderedComponent)));
1294
1258
  return renderedComponent;
1295
1259
  }
1296
1260
  ),
@@ -1333,11 +1297,13 @@ var ReactCompositeComponentMixin = {
1333
1297
  // ignore the value of "this" that the user is trying to use, so
1334
1298
  // let's warn.
1335
1299
  if (newThis !== component && newThis !== null) {
1300
+ monitorCodeUse('react_bind_warning', { component: componentName });
1336
1301
  console.warn(
1337
1302
  'bind(): React component methods may only be bound to the ' +
1338
1303
  'component instance. See ' + componentName
1339
1304
  );
1340
1305
  } else if (!args.length) {
1306
+ monitorCodeUse('react_bind_warning', { component: componentName });
1341
1307
  console.warn(
1342
1308
  'bind(): You are binding a component method to the component. ' +
1343
1309
  'React does this for you automatically in a high-performance ' +
@@ -1362,18 +1328,6 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
1362
1328
  mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
1363
1329
  mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
1364
1330
 
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
- }
1377
1331
  /**
1378
1332
  * Module for creating composite components.
1379
1333
  *
@@ -1396,20 +1350,22 @@ var ReactCompositeComponent = {
1396
1350
  * @public
1397
1351
  */
1398
1352
  createClass: function(spec) {
1399
- var Constructor = function() {};
1353
+ var Constructor = function(props, owner) {
1354
+ this.construct(props, owner);
1355
+ };
1400
1356
  Constructor.prototype = new ReactCompositeComponentBase();
1401
1357
  Constructor.prototype.constructor = Constructor;
1402
1358
 
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;
1359
+ injectedMixins.forEach(
1360
+ mixSpecIntoComponent.bind(null, Constructor)
1361
+ );
1362
+
1363
+ mixSpecIntoComponent(Constructor, spec);
1411
1364
 
1412
- mixSpecIntoComponent(ConvenienceConstructor, spec);
1365
+ // Initialize the defaultProps property after all mixins have been merged
1366
+ if (Constructor.getDefaultProps) {
1367
+ Constructor.defaultProps = Constructor.getDefaultProps();
1368
+ }
1413
1369
 
1414
1370
  ("production" !== process.env.NODE_ENV ? invariant(
1415
1371
  Constructor.prototype.render,
@@ -1418,6 +1374,10 @@ var ReactCompositeComponent = {
1418
1374
 
1419
1375
  if ("production" !== process.env.NODE_ENV) {
1420
1376
  if (Constructor.prototype.componentShouldUpdate) {
1377
+ monitorCodeUse(
1378
+ 'react_component_should_update_warning',
1379
+ { component: spec.displayName }
1380
+ );
1421
1381
  console.warn(
1422
1382
  (spec.displayName || 'A component') + ' has a method called ' +
1423
1383
  'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
@@ -1427,14 +1387,6 @@ var ReactCompositeComponent = {
1427
1387
  }
1428
1388
  }
1429
1389
 
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
-
1438
1390
  // Reduce time spent doing lookups by setting these on the prototype.
1439
1391
  for (var methodName in ReactCompositeComponentInterface) {
1440
1392
  if (!Constructor.prototype[methodName]) {
@@ -1442,14 +1394,24 @@ var ReactCompositeComponent = {
1442
1394
  }
1443
1395
  }
1444
1396
 
1397
+ var descriptorFactory = ReactDescriptor.createFactory(Constructor);
1398
+
1445
1399
  if ("production" !== process.env.NODE_ENV) {
1446
- Constructor.prototype = createMountWarningMembrane(Constructor.prototype);
1400
+ return ReactDescriptorValidator.createFactory(
1401
+ descriptorFactory,
1402
+ Constructor.propTypes,
1403
+ Constructor.contextTypes
1404
+ );
1447
1405
  }
1448
1406
 
1449
- return ConvenienceConstructor;
1407
+ return descriptorFactory;
1450
1408
  },
1451
1409
 
1452
- isValidClass: isValidClass
1410
+ injection: {
1411
+ injectMixin: function(mixin) {
1412
+ injectedMixins.push(mixin);
1413
+ }
1414
+ }
1453
1415
  };
1454
1416
 
1455
1417
  module.exports = ReactCompositeComponent;