react 0.10.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +3 -0
  2. package/dist/JSXTransformer.js +20344 -0
  3. package/dist/react-with-addons.js +20276 -0
  4. package/dist/react-with-addons.min.js +22 -0
  5. package/dist/react.js +18484 -0
  6. package/dist/react.min.js +21 -0
  7. package/lib/BeforeInputEventPlugin.js +222 -0
  8. package/lib/CSSPropertyOperations.js +3 -3
  9. package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
  10. package/lib/ChangeEventPlugin.js +1 -1
  11. package/lib/CompositionEventPlugin.js +5 -1
  12. package/lib/DOMChildrenOperations.js +21 -14
  13. package/lib/DOMProperty.js +45 -17
  14. package/lib/DOMPropertyOperations.js +22 -10
  15. package/lib/DefaultEventPluginOrder.js +1 -0
  16. package/lib/EventConstants.js +1 -0
  17. package/lib/EventListener.js +5 -2
  18. package/lib/EventPluginHub.js +0 -5
  19. package/lib/EventPluginRegistry.js +6 -4
  20. package/lib/EventPluginUtils.js +11 -1
  21. package/lib/ExecutionEnvironment.js +8 -2
  22. package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +42 -49
  23. package/lib/LinkedValueUtils.js +21 -22
  24. package/lib/LocalEventTrapMixin.js +52 -0
  25. package/lib/React.js +57 -3
  26. package/lib/ReactBrowserComponentMixin.js +4 -0
  27. package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
  28. package/lib/ReactCSSTransitionGroup.js +2 -0
  29. package/lib/ReactCSSTransitionGroupChild.js +2 -5
  30. package/lib/ReactChildren.js +31 -10
  31. package/lib/ReactComponent.js +88 -237
  32. package/lib/ReactComponentBrowserEnvironment.js +3 -2
  33. package/lib/ReactComponentWithPureRenderMixin.js +54 -0
  34. package/lib/ReactCompositeComponent.js +222 -384
  35. package/lib/ReactDOM.js +22 -18
  36. package/lib/ReactDOMComponent.js +26 -24
  37. package/lib/ReactDOMForm.js +5 -13
  38. package/lib/ReactDOMIDOperations.js +2 -31
  39. package/lib/ReactDOMImg.js +5 -14
  40. package/lib/ReactDOMSelect.js +16 -15
  41. package/lib/ReactDOMSelection.js +35 -10
  42. package/lib/ReactDOMTextarea.js +2 -4
  43. package/lib/ReactDefaultBatchingStrategy.js +3 -3
  44. package/lib/ReactDefaultInjection.js +18 -15
  45. package/lib/ReactDefaultPerf.js +28 -11
  46. package/lib/ReactDefaultPerfAnalysis.js +4 -0
  47. package/lib/ReactDescriptor.js +251 -0
  48. package/lib/ReactDescriptorValidator.js +283 -0
  49. package/lib/ReactEmptyComponent.js +78 -0
  50. package/lib/ReactEventEmitterMixin.js +1 -3
  51. package/lib/ReactEventListener.js +189 -0
  52. package/lib/ReactInjection.js +4 -2
  53. package/lib/ReactLink.js +24 -0
  54. package/lib/ReactMount.js +51 -19
  55. package/lib/ReactMultiChild.js +9 -11
  56. package/lib/ReactPropTransferer.js +44 -29
  57. package/lib/ReactPropTypes.js +226 -242
  58. package/lib/ReactPutListenerQueue.js +2 -2
  59. package/lib/ReactReconcileTransaction.js +14 -14
  60. package/lib/ReactServerRendering.js +5 -5
  61. package/lib/ReactServerRenderingTransaction.js +4 -5
  62. package/lib/ReactTestUtils.js +39 -21
  63. package/lib/ReactTextComponent.js +8 -22
  64. package/lib/ReactTransitionChildMapping.js +2 -2
  65. package/lib/ReactTransitionEvents.js +19 -0
  66. package/lib/ReactTransitionGroup.js +9 -6
  67. package/lib/ReactUpdates.js +139 -22
  68. package/lib/ReactWithAddons.js +5 -2
  69. package/lib/SVGDOMPropertyConfig.js +97 -0
  70. package/lib/SimpleEventPlugin.js +7 -1
  71. package/lib/SyntheticInputEvent.js +52 -0
  72. package/lib/SyntheticKeyboardEvent.js +33 -4
  73. package/lib/SyntheticMouseEvent.js +3 -0
  74. package/lib/SyntheticTouchEvent.js +4 -1
  75. package/lib/SyntheticUIEvent.js +24 -2
  76. package/lib/Transaction.js +0 -32
  77. package/lib/cloneWithProps.js +3 -1
  78. package/lib/createFullPageComponent.js +1 -1
  79. package/lib/dangerousStyleValue.js +11 -5
  80. package/lib/escapeTextForBrowser.js +2 -3
  81. package/lib/flattenChildren.js +9 -7
  82. package/lib/getEventKey.js +35 -5
  83. package/lib/getEventModifierState.js +52 -0
  84. package/lib/getMarkupWrap.js +2 -0
  85. package/lib/getTextContentAccessor.js +1 -1
  86. package/lib/hyphenate.js +3 -0
  87. package/lib/hyphenateStyleName.js +46 -0
  88. package/lib/instantiateReactComponent.js +13 -21
  89. package/lib/invariant.js +17 -19
  90. package/lib/{objMap.js → mapObject.js} +8 -3
  91. package/lib/mergeHelpers.js +11 -0
  92. package/lib/mergeInto.js +3 -2
  93. package/lib/onlyChild.js +3 -3
  94. package/lib/performance.js +33 -0
  95. package/lib/performanceNow.js +5 -14
  96. package/lib/setInnerHTML.js +85 -0
  97. package/lib/shouldUpdateReactComponent.js +12 -29
  98. package/lib/toArray.js +1 -1
  99. package/lib/traverseAllChildren.js +7 -4
  100. package/lib/update.js +57 -45
  101. package/package.json +4 -3
  102. package/lib/ReactEventTopLevelCallback.js +0 -149
  103. package/lib/createObjectFrom.js +0 -61
  104. package/lib/objMapKeyVal.js +0 -47
@@ -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;
@@ -98,7 +99,7 @@ var ReactComponentBrowserEnvironment = {
98
99
  'React attempted to use reuse markup in a container but the ' +
99
100
  'checksum was invalid. This generally means that you are ' +
100
101
  'using server rendering and the markup generated on the ' +
101
- 'server was not what the client was expecting. React injected' +
102
+ 'server was not what the client was expecting. React injected ' +
102
103
  'new markup to compensate which works but you have lost many ' +
103
104
  'of the benefits of server rendering. Instead, figure out ' +
104
105
  'why the markup being generated is different on the client ' +
@@ -116,7 +117,7 @@ var ReactComponentBrowserEnvironment = {
116
117
  'See renderComponentToString() for server rendering.'
117
118
  ) : invariant(container.nodeType !== DOC_NODE_TYPE));
118
119
 
119
- container.innerHTML = markup;
120
+ setInnerHTML(container, markup);
120
121
  }
121
122
  )
122
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");
@@ -35,7 +38,7 @@ var keyMirror = require("./keyMirror");
35
38
  var merge = require("./merge");
36
39
  var mixInto = require("./mixInto");
37
40
  var monitorCodeUse = require("./monitorCodeUse");
38
- var objMap = require("./objMap");
41
+ var mapObject = require("./mapObject");
39
42
  var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
40
43
  var warning = require("./warning");
41
44
 
@@ -326,18 +329,17 @@ var ReactCompositeComponentInterface = {
326
329
  * which all other static methods are defined.
327
330
  */
328
331
  var RESERVED_SPEC_KEYS = {
329
- displayName: function(ConvenienceConstructor, displayName) {
330
- ConvenienceConstructor.componentConstructor.displayName = displayName;
332
+ displayName: function(Constructor, displayName) {
333
+ Constructor.displayName = displayName;
331
334
  },
332
- mixins: function(ConvenienceConstructor, mixins) {
335
+ mixins: function(Constructor, mixins) {
333
336
  if (mixins) {
334
337
  for (var i = 0; i < mixins.length; i++) {
335
- mixSpecIntoComponent(ConvenienceConstructor, mixins[i]);
338
+ mixSpecIntoComponent(Constructor, mixins[i]);
336
339
  }
337
340
  }
338
341
  },
339
- childContextTypes: function(ConvenienceConstructor, childContextTypes) {
340
- var Constructor = ConvenienceConstructor.componentConstructor;
342
+ childContextTypes: function(Constructor, childContextTypes) {
341
343
  validateTypeDef(
342
344
  Constructor,
343
345
  childContextTypes,
@@ -348,8 +350,7 @@ var RESERVED_SPEC_KEYS = {
348
350
  childContextTypes
349
351
  );
350
352
  },
351
- contextTypes: function(ConvenienceConstructor, contextTypes) {
352
- var Constructor = ConvenienceConstructor.componentConstructor;
353
+ contextTypes: function(Constructor, contextTypes) {
353
354
  validateTypeDef(
354
355
  Constructor,
355
356
  contextTypes,
@@ -357,8 +358,21 @@ var RESERVED_SPEC_KEYS = {
357
358
  );
358
359
  Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes);
359
360
  },
360
- propTypes: function(ConvenienceConstructor, propTypes) {
361
- 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) {
362
376
  validateTypeDef(
363
377
  Constructor,
364
378
  propTypes,
@@ -366,11 +380,20 @@ var RESERVED_SPEC_KEYS = {
366
380
  );
367
381
  Constructor.propTypes = merge(Constructor.propTypes, propTypes);
368
382
  },
369
- statics: function(ConvenienceConstructor, statics) {
370
- mixStaticSpecIntoComponent(ConvenienceConstructor, statics);
383
+ statics: function(Constructor, statics) {
384
+ mixStaticSpecIntoComponent(Constructor, statics);
371
385
  }
372
386
  };
373
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
+
374
397
  function validateTypeDef(Constructor, typeDef, location) {
375
398
  for (var propName in typeDef) {
376
399
  if (typeDef.hasOwnProperty(propName)) {
@@ -387,7 +410,9 @@ function validateTypeDef(Constructor, typeDef, location) {
387
410
  }
388
411
 
389
412
  function validateMethodOverride(proto, name) {
390
- var specPolicy = ReactCompositeComponentInterface[name];
413
+ var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
414
+ ReactCompositeComponentInterface[name] :
415
+ null;
391
416
 
392
417
  // Disallow overriding of base class methods unless explicitly allowed.
393
418
  if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
@@ -437,19 +462,18 @@ function validateLifeCycleOnReplaceState(instance) {
437
462
  * Custom version of `mixInto` which handles policy validation and reserved
438
463
  * specification keys when building `ReactCompositeComponent` classses.
439
464
  */
440
- function mixSpecIntoComponent(ConvenienceConstructor, spec) {
465
+ function mixSpecIntoComponent(Constructor, spec) {
441
466
  ("production" !== process.env.NODE_ENV ? invariant(
442
- !isValidClass(spec),
467
+ !ReactDescriptor.isValidFactory(spec),
443
468
  'ReactCompositeComponent: You\'re attempting to ' +
444
469
  'use a component class as a mixin. Instead, just use a regular object.'
445
- ) : invariant(!isValidClass(spec)));
470
+ ) : invariant(!ReactDescriptor.isValidFactory(spec)));
446
471
  ("production" !== process.env.NODE_ENV ? invariant(
447
- !ReactComponent.isValidComponent(spec),
472
+ !ReactDescriptor.isValidDescriptor(spec),
448
473
  'ReactCompositeComponent: You\'re attempting to ' +
449
474
  'use a component as a mixin. Instead, just use a regular object.'
450
- ) : invariant(!ReactComponent.isValidComponent(spec)));
475
+ ) : invariant(!ReactDescriptor.isValidDescriptor(spec)));
451
476
 
452
- var Constructor = ConvenienceConstructor.componentConstructor;
453
477
  var proto = Constructor.prototype;
454
478
  for (var name in spec) {
455
479
  var property = spec[name];
@@ -460,20 +484,21 @@ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
460
484
  validateMethodOverride(proto, name);
461
485
 
462
486
  if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
463
- RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property);
487
+ RESERVED_SPEC_KEYS[name](Constructor, property);
464
488
  } else {
465
489
  // Setup methods on prototype:
466
490
  // The following member methods should not be automatically bound:
467
491
  // 1. Expected ReactCompositeComponent methods (in the "interface").
468
492
  // 2. Overridden methods (that were mixed in).
469
- var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
470
- var isInherited = name in proto;
493
+ var isCompositeComponentMethod =
494
+ ReactCompositeComponentInterface.hasOwnProperty(name);
495
+ var isAlreadyDefined = proto.hasOwnProperty(name);
471
496
  var markedDontBind = property && property.__reactDontBind;
472
497
  var isFunction = typeof property === 'function';
473
498
  var shouldAutoBind =
474
499
  isFunction &&
475
500
  !isCompositeComponentMethod &&
476
- !isInherited &&
501
+ !isAlreadyDefined &&
477
502
  !markedDontBind;
478
503
 
479
504
  if (shouldAutoBind) {
@@ -483,37 +508,60 @@ function mixSpecIntoComponent(ConvenienceConstructor, spec) {
483
508
  proto.__reactAutoBindMap[name] = property;
484
509
  proto[name] = property;
485
510
  } else {
486
- 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
+
487
529
  // For methods which are defined more than once, call the existing
488
- // methods before calling the new property.
489
- if (ReactCompositeComponentInterface[name] ===
490
- SpecPolicy.DEFINE_MANY_MERGED) {
530
+ // methods before calling the new property, merging if appropriate.
531
+ if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
491
532
  proto[name] = createMergedResultFunction(proto[name], property);
492
- } else {
533
+ } else if (specPolicy === SpecPolicy.DEFINE_MANY) {
493
534
  proto[name] = createChainedFunction(proto[name], property);
494
535
  }
495
536
  } else {
496
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
+ }
497
545
  }
498
546
  }
499
547
  }
500
548
  }
501
549
  }
502
550
 
503
- function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
551
+ function mixStaticSpecIntoComponent(Constructor, statics) {
504
552
  if (!statics) {
505
553
  return;
506
554
  }
507
555
  for (var name in statics) {
508
556
  var property = statics[name];
509
557
  if (!statics.hasOwnProperty(name)) {
510
- return;
558
+ continue;
511
559
  }
512
560
 
513
- var isInherited = name in ConvenienceConstructor;
561
+ var isInherited = name in Constructor;
514
562
  var result = property;
515
563
  if (isInherited) {
516
- var existingProperty = ConvenienceConstructor[name];
564
+ var existingProperty = Constructor[name];
517
565
  var existingType = typeof existingProperty;
518
566
  var propertyType = typeof property;
519
567
  ("production" !== process.env.NODE_ENV ? invariant(
@@ -526,8 +574,7 @@ function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) {
526
574
  ) : invariant(existingType === 'function' && propertyType === 'function'));
527
575
  result = createChainedFunction(existingProperty, property);
528
576
  }
529
- ConvenienceConstructor[name] = result;
530
- ConvenienceConstructor.componentConstructor[name] = result;
577
+ Constructor[name] = result;
531
578
  }
532
579
  }
533
580
 
@@ -544,7 +591,7 @@ function mergeObjectsWithNoDuplicateKeys(one, two) {
544
591
  'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
545
592
  ) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
546
593
 
547
- objMap(two, function(value, key) {
594
+ mapObject(two, function(value, key) {
548
595
  ("production" !== process.env.NODE_ENV ? invariant(
549
596
  one[key] === undefined,
550
597
  'mergeObjectsWithNoDuplicateKeys(): ' +
@@ -592,203 +639,6 @@ function createChainedFunction(one, two) {
592
639
  };
593
640
  }
594
641
 
595
- if ("production" !== process.env.NODE_ENV) {
596
-
597
- var unmountedPropertyWhitelist = {
598
- constructor: true,
599
- construct: true,
600
- isOwnedBy: true, // should be deprecated but can have code mod (internal)
601
- type: true,
602
- props: true,
603
- // currently private but belong on the descriptor and are valid for use
604
- // inside the framework:
605
- __keyValidated__: true,
606
- _owner: true,
607
- _currentContext: true
608
- };
609
-
610
- var componentInstanceProperties = {
611
- __keyValidated__: true,
612
- __keySetters: true,
613
- _compositeLifeCycleState: true,
614
- _currentContext: true,
615
- _defaultProps: true,
616
- _instance: true,
617
- _lifeCycleState: true,
618
- _mountDepth: true,
619
- _owner: true,
620
- _pendingCallbacks: true,
621
- _pendingContext: true,
622
- _pendingForceUpdate: true,
623
- _pendingOwner: true,
624
- _pendingProps: true,
625
- _pendingState: true,
626
- _renderedComponent: true,
627
- _rootNodeID: true,
628
- context: true,
629
- props: true,
630
- refs: true,
631
- state: true,
632
-
633
- // These are known instance properties coming from other sources
634
- _pendingQueries: true,
635
- _queryPropListeners: true,
636
- queryParams: true
637
-
638
- };
639
-
640
- var hasWarnedOnComponentType = {};
641
-
642
- var warningStackCounter = 0;
643
-
644
- var issueMembraneWarning = function(instance, key) {
645
- var isWhitelisted = unmountedPropertyWhitelist.hasOwnProperty(key);
646
- if (warningStackCounter > 0 || isWhitelisted) {
647
- return;
648
- }
649
- var name = instance.constructor.displayName || 'Unknown';
650
- var owner = ReactCurrentOwner.current;
651
- var ownerName = (owner && owner.constructor.displayName) || 'Unknown';
652
- var warningKey = key + '|' + name + '|' + ownerName;
653
- if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) {
654
- // We have already warned for this combination. Skip it this time.
655
- return;
656
- }
657
- hasWarnedOnComponentType[warningKey] = true;
658
-
659
- var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
660
- var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
661
-
662
- monitorCodeUse('react_descriptor_property_access', { component: name });
663
- console.warn(
664
- 'Invalid access to component property "' + key + '" on ' + name +
665
- context + ' See http://fb.me/react-warning-descriptors .' +
666
- ' Use a static method instead: ' + staticMethodExample
667
- );
668
- };
669
-
670
- var wrapInMembraneFunction = function(fn, thisBinding) {
671
- if (fn.__reactMembraneFunction && fn.__reactMembraneSelf === thisBinding) {
672
- return fn.__reactMembraneFunction;
673
- }
674
- return fn.__reactMembraneFunction = function() {
675
- /**
676
- * By getting this function, you've already received a warning. The
677
- * internals of this function will likely cause more warnings. To avoid
678
- * Spamming too much we disable any warning triggered inside of this
679
- * stack.
680
- */
681
- warningStackCounter++;
682
- try {
683
- // If the this binding is unchanged, we defer to the real component.
684
- // This is important to keep some referential integrity in the
685
- // internals. E.g. owner equality check.
686
- var self = this === thisBinding ? this.__realComponentInstance : this;
687
- return fn.apply(self, arguments);
688
- } finally {
689
- warningStackCounter--;
690
- }
691
- };
692
- };
693
-
694
- var defineMembraneProperty = function(membrane, prototype, key) {
695
- Object.defineProperty(membrane, key, {
696
-
697
- configurable: false,
698
- enumerable: true,
699
-
700
- get: function() {
701
- if (this === membrane) {
702
- // We're allowed to access the prototype directly.
703
- return prototype[key];
704
- }
705
- issueMembraneWarning(this, key);
706
-
707
- var realValue = this.__realComponentInstance[key];
708
- // If the real value is a function, we need to provide a wrapper that
709
- // disables nested warnings. The properties type and constructors are
710
- // expected to the be constructors and therefore is often use with an
711
- // equality check and we shouldn't try to rebind those.
712
- if (typeof realValue === 'function' &&
713
- key !== 'type' &&
714
- key !== 'constructor') {
715
- return wrapInMembraneFunction(realValue, this);
716
- }
717
- return realValue;
718
- },
719
-
720
- set: function(value) {
721
- if (this === membrane) {
722
- // We're allowed to set a value on the prototype directly.
723
- prototype[key] = value;
724
- return;
725
- }
726
- issueMembraneWarning(this, key);
727
- this.__realComponentInstance[key] = value;
728
- }
729
-
730
- });
731
- };
732
-
733
- /**
734
- * Creates a membrane prototype which wraps the original prototype. If any
735
- * property is accessed in an unmounted state, a warning is issued.
736
- *
737
- * @param {object} prototype Original prototype.
738
- * @return {object} The membrane prototype.
739
- * @private
740
- */
741
- var createMountWarningMembrane = function(prototype) {
742
- var membrane = {};
743
- var key;
744
- for (key in prototype) {
745
- defineMembraneProperty(membrane, prototype, key);
746
- }
747
- // These are properties that goes into the instance but not the prototype.
748
- // We can create the membrane on the prototype even though this will
749
- // result in a faulty hasOwnProperty check it's better perf.
750
- for (key in componentInstanceProperties) {
751
- if (componentInstanceProperties.hasOwnProperty(key) &&
752
- !(key in prototype)) {
753
- defineMembraneProperty(membrane, prototype, key);
754
- }
755
- }
756
- return membrane;
757
- };
758
-
759
- /**
760
- * Creates a membrane constructor which wraps the component that gets mounted.
761
- *
762
- * @param {function} constructor Original constructor.
763
- * @return {function} The membrane constructor.
764
- * @private
765
- */
766
- var createDescriptorProxy = function(constructor) {
767
- try {
768
- var ProxyConstructor = function() {
769
- this.__realComponentInstance = new constructor();
770
-
771
- // We can only safely pass through known instance variables. Unknown
772
- // expandos are not safe. Use the real mounted instance to avoid this
773
- // problem if it blows something up.
774
- Object.freeze(this);
775
- };
776
-
777
- ProxyConstructor.prototype = createMountWarningMembrane(
778
- constructor.prototype
779
- );
780
-
781
- return ProxyConstructor;
782
- } catch(x) {
783
- // In IE8 define property will fail on non-DOM objects. If anything in
784
- // the membrane creation fails, we'll bail out and just use the plain
785
- // constructor without warnings.
786
- return constructor;
787
- }
788
- };
789
-
790
- }
791
-
792
642
  /**
793
643
  * `ReactCompositeComponent` maintains an auxiliary life cycle state in
794
644
  * `this._compositeLifeCycleState` (which can be null).
@@ -846,12 +696,11 @@ var ReactCompositeComponentMixin = {
846
696
  /**
847
697
  * Base constructor for all composite component.
848
698
  *
849
- * @param {?object} initialProps
850
- * @param {*} children
699
+ * @param {ReactDescriptor} descriptor
851
700
  * @final
852
701
  * @internal
853
702
  */
854
- construct: function(initialProps, children) {
703
+ construct: function(descriptor) {
855
704
  // Children can be either an array or more than one argument
856
705
  ReactComponent.Mixin.construct.apply(this, arguments);
857
706
  ReactOwner.Mixin.construct.apply(this, arguments);
@@ -859,29 +708,13 @@ var ReactCompositeComponentMixin = {
859
708
  this.state = null;
860
709
  this._pendingState = null;
861
710
 
711
+ // This is the public post-processed context. The real context and pending
712
+ // context lives on the descriptor.
862
713
  this.context = null;
863
- this._currentContext = ReactContext.current;
864
- this._pendingContext = null;
865
-
866
- // The descriptor that was used to instantiate this component. Will be
867
- // set by the instantiator instead of the constructor since this
868
- // constructor is currently used by both instances and descriptors.
869
- this._descriptor = null;
870
714
 
871
715
  this._compositeLifeCycleState = null;
872
716
  },
873
717
 
874
- /**
875
- * Components in the intermediate state now has cyclic references. To avoid
876
- * breaking JSON serialization we expose a custom JSON format.
877
- * @return {object} JSON compatible representation.
878
- * @internal
879
- * @final
880
- */
881
- toJSON: function() {
882
- return { type: this.type, props: this.props };
883
- },
884
-
885
718
  /**
886
719
  * Checks whether or not this composite component is mounted.
887
720
  * @return {boolean} True if mounted, false otherwise.
@@ -915,14 +748,13 @@ var ReactCompositeComponentMixin = {
915
748
  );
916
749
  this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
917
750
 
918
- this.context = this._processContext(this._currentContext);
919
- this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
920
- this.props = this._processProps(this.props);
921
-
922
751
  if (this.__reactAutoBindMap) {
923
752
  this._bindAutoBindMethods();
924
753
  }
925
754
 
755
+ this.context = this._processContext(this._descriptor._context);
756
+ this.props = this._processProps(this.props);
757
+
926
758
  this.state = this.getInitialState ? this.getInitialState() : null;
927
759
  ("production" !== process.env.NODE_ENV ? invariant(
928
760
  typeof this.state === 'object' && !Array.isArray(this.state),
@@ -955,7 +787,7 @@ var ReactCompositeComponentMixin = {
955
787
  mountDepth + 1
956
788
  );
957
789
  if (this.componentDidMount) {
958
- transaction.getReactMountReady().enqueue(this, this.componentDidMount);
790
+ transaction.getReactMountReady().enqueue(this.componentDidMount, this);
959
791
  }
960
792
  return markup;
961
793
  }
@@ -974,8 +806,6 @@ var ReactCompositeComponentMixin = {
974
806
  }
975
807
  this._compositeLifeCycleState = null;
976
808
 
977
- this._defaultProps = null;
978
-
979
809
  this._renderedComponent.unmountComponent();
980
810
  this._renderedComponent = null;
981
811
 
@@ -1009,7 +839,7 @@ var ReactCompositeComponentMixin = {
1009
839
  typeof partialState === 'object' || partialState == null,
1010
840
  'setState(...): takes an object of state variables to update.'
1011
841
  ) : invariant(typeof partialState === 'object' || partialState == null));
1012
- if ("production" !== process.env.NODE_ENV) {
842
+ if ("production" !== process.env.NODE_ENV){
1013
843
  ("production" !== process.env.NODE_ENV ? warning(
1014
844
  partialState != null,
1015
845
  'setState(...): You passed an undefined or null state object; ' +
@@ -1038,7 +868,15 @@ var ReactCompositeComponentMixin = {
1038
868
  replaceState: function(completeState, callback) {
1039
869
  validateLifeCycleOnReplaceState(this);
1040
870
  this._pendingState = completeState;
1041
- ReactUpdates.enqueueUpdate(this, callback);
871
+ if (this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING) {
872
+ // If we're in a componentWillMount handler, don't enqueue a rerender
873
+ // because ReactUpdates assumes we're in a browser context (which is wrong
874
+ // for server rendering) and we're about to do a render anyway.
875
+ // TODO: The callback here is ignored when setState is called from
876
+ // componentWillMount. Either fix it or disallow doing so completely in
877
+ // favor of getInitialState.
878
+ ReactUpdates.enqueueUpdate(this, callback);
879
+ }
1042
880
  },
1043
881
 
1044
882
  /**
@@ -1113,12 +951,17 @@ var ReactCompositeComponentMixin = {
1113
951
  * @private
1114
952
  */
1115
953
  _processProps: function(newProps) {
1116
- var props = merge(newProps);
1117
- var defaultProps = this._defaultProps;
1118
- for (var propName in defaultProps) {
1119
- if (typeof props[propName] === 'undefined') {
1120
- props[propName] = defaultProps[propName];
954
+ var defaultProps = this.constructor.defaultProps;
955
+ var props;
956
+ if (defaultProps) {
957
+ props = merge(newProps);
958
+ for (var propName in defaultProps) {
959
+ if (typeof props[propName] === 'undefined') {
960
+ props[propName] = defaultProps[propName];
961
+ }
1121
962
  }
963
+ } else {
964
+ props = newProps;
1122
965
  }
1123
966
  if ("production" !== process.env.NODE_ENV) {
1124
967
  var propTypes = this.constructor.propTypes;
@@ -1138,15 +981,32 @@ var ReactCompositeComponentMixin = {
1138
981
  * @private
1139
982
  */
1140
983
  _checkPropTypes: function(propTypes, props, location) {
984
+ // TODO: Stop validating prop types here and only use the descriptor
985
+ // validation.
1141
986
  var componentName = this.constructor.displayName;
1142
987
  for (var propName in propTypes) {
1143
988
  if (propTypes.hasOwnProperty(propName)) {
1144
- propTypes[propName](props, propName, componentName, location);
989
+ var error =
990
+ propTypes[propName](props, propName, componentName, location);
991
+ if (error instanceof Error) {
992
+ // We may want to extend this logic for similar errors in
993
+ // renderComponent calls, so I'm abstracting it away into
994
+ // a function to minimize refactoring in the future
995
+ var addendum = getDeclarationErrorAddendum(this);
996
+ ("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null);
997
+ }
1145
998
  }
1146
999
  }
1147
1000
  },
1148
1001
 
1149
- performUpdateIfNecessary: function() {
1002
+ /**
1003
+ * If any of `_pendingDescriptor`, `_pendingState`, or `_pendingForceUpdate`
1004
+ * is set, update the component.
1005
+ *
1006
+ * @param {ReactReconcileTransaction} transaction
1007
+ * @internal
1008
+ */
1009
+ performUpdateIfNecessary: function(transaction) {
1150
1010
  var compositeLifeCycleState = this._compositeLifeCycleState;
1151
1011
  // Do not trigger a state transition if we are in the middle of mounting or
1152
1012
  // receiving props because both of those will already be doing this.
@@ -1154,32 +1014,21 @@ var ReactCompositeComponentMixin = {
1154
1014
  compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
1155
1015
  return;
1156
1016
  }
1157
- ReactComponent.Mixin.performUpdateIfNecessary.call(this);
1158
- },
1159
1017
 
1160
- /**
1161
- * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is
1162
- * set, update the component.
1163
- *
1164
- * @param {ReactReconcileTransaction} transaction
1165
- * @internal
1166
- */
1167
- _performUpdateIfNecessary: function(transaction) {
1168
- if (this._pendingProps == null &&
1018
+ if (this._pendingDescriptor == null &&
1169
1019
  this._pendingState == null &&
1170
- this._pendingContext == null &&
1171
1020
  !this._pendingForceUpdate) {
1172
1021
  return;
1173
1022
  }
1174
1023
 
1175
- var nextFullContext = this._pendingContext || this._currentContext;
1176
- var nextContext = this._processContext(nextFullContext);
1177
- this._pendingContext = null;
1178
-
1024
+ var nextContext = this.context;
1179
1025
  var nextProps = this.props;
1180
- if (this._pendingProps != null) {
1181
- nextProps = this._processProps(this._pendingProps);
1182
- this._pendingProps = null;
1026
+ var nextDescriptor = this._descriptor;
1027
+ if (this._pendingDescriptor != null) {
1028
+ nextDescriptor = this._pendingDescriptor;
1029
+ nextContext = this._processContext(nextDescriptor._context);
1030
+ nextProps = this._processProps(nextDescriptor.props);
1031
+ this._pendingDescriptor = null;
1183
1032
 
1184
1033
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
1185
1034
  if (this.componentWillReceiveProps) {
@@ -1189,37 +1038,46 @@ var ReactCompositeComponentMixin = {
1189
1038
 
1190
1039
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
1191
1040
 
1192
- // Unlike props, state, and context, we specifically don't want to set
1193
- // _pendingOwner to null here because it's possible for a component to have
1194
- // a null owner, so we instead make `this._owner === this._pendingOwner`
1195
- // mean that there's no owner change pending.
1196
- var nextOwner = this._pendingOwner;
1197
-
1198
1041
  var nextState = this._pendingState || this.state;
1199
1042
  this._pendingState = null;
1200
1043
 
1201
1044
  try {
1202
- if (this._pendingForceUpdate ||
1203
- !this.shouldComponentUpdate ||
1204
- this.shouldComponentUpdate(nextProps, nextState, nextContext)) {
1045
+ var shouldUpdate =
1046
+ this._pendingForceUpdate ||
1047
+ !this.shouldComponentUpdate ||
1048
+ this.shouldComponentUpdate(nextProps, nextState, nextContext);
1049
+
1050
+ if ("production" !== process.env.NODE_ENV) {
1051
+ if (typeof shouldUpdate === "undefined") {
1052
+ console.warn(
1053
+ (this.constructor.displayName || 'ReactCompositeComponent') +
1054
+ '.shouldComponentUpdate(): Returned undefined instead of a ' +
1055
+ 'boolean value. Make sure to return true or false.'
1056
+ );
1057
+ }
1058
+ }
1059
+
1060
+ if (shouldUpdate) {
1205
1061
  this._pendingForceUpdate = false;
1206
1062
  // Will set `this.props`, `this.state` and `this.context`.
1207
1063
  this._performComponentUpdate(
1064
+ nextDescriptor,
1208
1065
  nextProps,
1209
- nextOwner,
1210
1066
  nextState,
1211
- nextFullContext,
1212
1067
  nextContext,
1213
1068
  transaction
1214
1069
  );
1215
1070
  } else {
1216
1071
  // If it's determined that a component should not update, we still want
1217
1072
  // to set props and state.
1073
+ this._descriptor = nextDescriptor;
1218
1074
  this.props = nextProps;
1219
- this._owner = nextOwner;
1220
1075
  this.state = nextState;
1221
- this._currentContext = nextFullContext;
1222
1076
  this.context = nextContext;
1077
+
1078
+ // Owner cannot change because shouldUpdateReactComponent doesn't allow
1079
+ // it. TODO: Remove this._owner completely.
1080
+ this._owner = nextDescriptor._owner;
1223
1081
  }
1224
1082
  } finally {
1225
1083
  this._compositeLifeCycleState = null;
@@ -1230,24 +1088,22 @@ var ReactCompositeComponentMixin = {
1230
1088
  * Merges new props and state, notifies delegate methods of update and
1231
1089
  * performs update.
1232
1090
  *
1233
- * @param {object} nextProps Next object to set as properties.
1234
- * @param {?ReactComponent} nextOwner Next component to set as owner
1091
+ * @param {ReactDescriptor} nextDescriptor Next descriptor
1092
+ * @param {object} nextProps Next public object to set as properties.
1235
1093
  * @param {?object} nextState Next object to set as state.
1236
- * @param {?object} nextFullContext Next object to set as _currentContext.
1237
- * @param {?object} nextContext Next object to set as context.
1094
+ * @param {?object} nextContext Next public object to set as context.
1238
1095
  * @param {ReactReconcileTransaction} transaction
1239
1096
  * @private
1240
1097
  */
1241
1098
  _performComponentUpdate: function(
1099
+ nextDescriptor,
1242
1100
  nextProps,
1243
- nextOwner,
1244
1101
  nextState,
1245
- nextFullContext,
1246
1102
  nextContext,
1247
1103
  transaction
1248
1104
  ) {
1105
+ var prevDescriptor = this._descriptor;
1249
1106
  var prevProps = this.props;
1250
- var prevOwner = this._owner;
1251
1107
  var prevState = this.state;
1252
1108
  var prevContext = this.context;
1253
1109
 
@@ -1255,43 +1111,44 @@ var ReactCompositeComponentMixin = {
1255
1111
  this.componentWillUpdate(nextProps, nextState, nextContext);
1256
1112
  }
1257
1113
 
1114
+ this._descriptor = nextDescriptor;
1258
1115
  this.props = nextProps;
1259
- this._owner = nextOwner;
1260
1116
  this.state = nextState;
1261
- this._currentContext = nextFullContext;
1262
1117
  this.context = nextContext;
1263
1118
 
1119
+ // Owner cannot change because shouldUpdateReactComponent doesn't allow
1120
+ // it. TODO: Remove this._owner completely.
1121
+ this._owner = nextDescriptor._owner;
1122
+
1264
1123
  this.updateComponent(
1265
1124
  transaction,
1266
- prevProps,
1267
- prevOwner,
1268
- prevState,
1269
- prevContext
1125
+ prevDescriptor
1270
1126
  );
1271
1127
 
1272
1128
  if (this.componentDidUpdate) {
1273
1129
  transaction.getReactMountReady().enqueue(
1274
- this,
1275
- this.componentDidUpdate.bind(this, prevProps, prevState, prevContext)
1130
+ this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
1131
+ this
1276
1132
  );
1277
1133
  }
1278
1134
  },
1279
1135
 
1280
- receiveComponent: function(nextComponent, transaction) {
1281
- if (nextComponent === this._descriptor) {
1282
- // Since props and context are immutable after the component is
1283
- // mounted, we can do a cheap identity compare here to determine
1284
- // if this is a superfluous reconcile.
1136
+ receiveComponent: function(nextDescriptor, transaction) {
1137
+ if (nextDescriptor === this._descriptor &&
1138
+ nextDescriptor._owner != null) {
1139
+ // Since descriptors are immutable after the owner is rendered,
1140
+ // we can do a cheap identity compare here to determine if this is a
1141
+ // superfluous reconcile. It's possible for state to be mutable but such
1142
+ // change should trigger an update of the owner which would recreate
1143
+ // the descriptor. We explicitly check for the existence of an owner since
1144
+ // it's possible for a descriptor created outside a composite to be
1145
+ // deeply mutated and reused.
1285
1146
  return;
1286
1147
  }
1287
1148
 
1288
- // Update the descriptor that was last used by this component instance
1289
- this._descriptor = nextComponent;
1290
-
1291
- this._pendingContext = nextComponent._currentContext;
1292
1149
  ReactComponent.Mixin.receiveComponent.call(
1293
1150
  this,
1294
- nextComponent,
1151
+ nextDescriptor,
1295
1152
  transaction
1296
1153
  );
1297
1154
  },
@@ -1303,35 +1160,31 @@ var ReactCompositeComponentMixin = {
1303
1160
  * Sophisticated clients may wish to override this.
1304
1161
  *
1305
1162
  * @param {ReactReconcileTransaction} transaction
1306
- * @param {object} prevProps
1307
- * @param {?ReactComponent} prevOwner
1308
- * @param {?object} prevState
1309
- * @param {?object} prevContext
1163
+ * @param {ReactDescriptor} prevDescriptor
1310
1164
  * @internal
1311
1165
  * @overridable
1312
1166
  */
1313
1167
  updateComponent: ReactPerf.measure(
1314
1168
  'ReactCompositeComponent',
1315
1169
  'updateComponent',
1316
- function(transaction, prevProps, prevOwner, prevState, prevContext) {
1170
+ function(transaction, prevParentDescriptor) {
1317
1171
  ReactComponent.Mixin.updateComponent.call(
1318
1172
  this,
1319
1173
  transaction,
1320
- prevProps,
1321
- prevOwner
1174
+ prevParentDescriptor
1322
1175
  );
1323
1176
 
1324
-
1325
1177
  var prevComponentInstance = this._renderedComponent;
1326
- var nextComponent = this._renderValidatedComponent();
1327
- if (shouldUpdateReactComponent(prevComponentInstance, nextComponent)) {
1328
- prevComponentInstance.receiveComponent(nextComponent, transaction);
1178
+ var prevDescriptor = prevComponentInstance._descriptor;
1179
+ var nextDescriptor = this._renderValidatedComponent();
1180
+ if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
1181
+ prevComponentInstance.receiveComponent(nextDescriptor, transaction);
1329
1182
  } else {
1330
1183
  // These two IDs are actually the same! But nothing should rely on that.
1331
1184
  var thisID = this._rootNodeID;
1332
1185
  var prevComponentID = prevComponentInstance._rootNodeID;
1333
1186
  prevComponentInstance.unmountComponent();
1334
- this._renderedComponent = instantiateReactComponent(nextComponent);
1187
+ this._renderedComponent = instantiateReactComponent(nextDescriptor);
1335
1188
  var nextMarkup = this._renderedComponent.mountComponent(
1336
1189
  thisID,
1337
1190
  transaction,
@@ -1388,20 +1241,28 @@ var ReactCompositeComponentMixin = {
1388
1241
  function() {
1389
1242
  var renderedComponent;
1390
1243
  var previousContext = ReactContext.current;
1391
- ReactContext.current = this._processChildContext(this._currentContext);
1244
+ ReactContext.current = this._processChildContext(
1245
+ this._descriptor._context
1246
+ );
1392
1247
  ReactCurrentOwner.current = this;
1393
1248
  try {
1394
1249
  renderedComponent = this.render();
1250
+ if (renderedComponent === null || renderedComponent === false) {
1251
+ renderedComponent = ReactEmptyComponent.getEmptyComponent();
1252
+ ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
1253
+ } else {
1254
+ ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
1255
+ }
1395
1256
  } finally {
1396
1257
  ReactContext.current = previousContext;
1397
1258
  ReactCurrentOwner.current = null;
1398
1259
  }
1399
1260
  ("production" !== process.env.NODE_ENV ? invariant(
1400
- ReactComponent.isValidComponent(renderedComponent),
1261
+ ReactDescriptor.isValidDescriptor(renderedComponent),
1401
1262
  '%s.render(): A valid ReactComponent must be returned. You may have ' +
1402
- 'returned null, undefined, an array, or some other invalid object.',
1263
+ 'returned undefined, an array or some other invalid object.',
1403
1264
  this.constructor.displayName || 'ReactCompositeComponent'
1404
- ) : invariant(ReactComponent.isValidComponent(renderedComponent)));
1265
+ ) : invariant(ReactDescriptor.isValidDescriptor(renderedComponent)));
1405
1266
  return renderedComponent;
1406
1267
  }
1407
1268
  ),
@@ -1475,18 +1336,6 @@ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
1475
1336
  mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
1476
1337
  mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
1477
1338
 
1478
- /**
1479
- * Checks if a value is a valid component constructor.
1480
- *
1481
- * @param {*}
1482
- * @return {boolean}
1483
- * @public
1484
- */
1485
- function isValidClass(componentClass) {
1486
- return componentClass instanceof Function &&
1487
- 'componentConstructor' in componentClass &&
1488
- componentClass.componentConstructor instanceof Function;
1489
- }
1490
1339
  /**
1491
1340
  * Module for creating composite components.
1492
1341
  *
@@ -1509,26 +1358,22 @@ var ReactCompositeComponent = {
1509
1358
  * @public
1510
1359
  */
1511
1360
  createClass: function(spec) {
1512
- var Constructor = function() {};
1361
+ var Constructor = function(props, owner) {
1362
+ this.construct(props, owner);
1363
+ };
1513
1364
  Constructor.prototype = new ReactCompositeComponentBase();
1514
1365
  Constructor.prototype.constructor = Constructor;
1515
1366
 
1516
- var DescriptorConstructor = Constructor;
1517
-
1518
- var ConvenienceConstructor = function(props, children) {
1519
- var descriptor = new DescriptorConstructor();
1520
- descriptor.construct.apply(descriptor, arguments);
1521
- return descriptor;
1522
- };
1523
- ConvenienceConstructor.componentConstructor = Constructor;
1524
- Constructor.ConvenienceConstructor = ConvenienceConstructor;
1525
- ConvenienceConstructor.originalSpec = spec;
1526
-
1527
1367
  injectedMixins.forEach(
1528
- mixSpecIntoComponent.bind(null, ConvenienceConstructor)
1368
+ mixSpecIntoComponent.bind(null, Constructor)
1529
1369
  );
1530
1370
 
1531
- mixSpecIntoComponent(ConvenienceConstructor, spec);
1371
+ mixSpecIntoComponent(Constructor, spec);
1372
+
1373
+ // Initialize the defaultProps property after all mixins have been merged
1374
+ if (Constructor.getDefaultProps) {
1375
+ Constructor.defaultProps = Constructor.getDefaultProps();
1376
+ }
1532
1377
 
1533
1378
  ("production" !== process.env.NODE_ENV ? invariant(
1534
1379
  Constructor.prototype.render,
@@ -1550,14 +1395,6 @@ var ReactCompositeComponent = {
1550
1395
  }
1551
1396
  }
1552
1397
 
1553
- // Expose the convience constructor on the prototype so that it can be
1554
- // easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for
1555
- // static methods like <Foo />.type.staticMethod();
1556
- // This should not be named constructor since this may not be the function
1557
- // that created the descriptor, and it may not even be a constructor.
1558
- ConvenienceConstructor.type = Constructor;
1559
- Constructor.prototype.type = Constructor;
1560
-
1561
1398
  // Reduce time spent doing lookups by setting these on the prototype.
1562
1399
  for (var methodName in ReactCompositeComponentInterface) {
1563
1400
  if (!Constructor.prototype[methodName]) {
@@ -1565,18 +1402,19 @@ var ReactCompositeComponent = {
1565
1402
  }
1566
1403
  }
1567
1404
 
1405
+ var descriptorFactory = ReactDescriptor.createFactory(Constructor);
1406
+
1568
1407
  if ("production" !== process.env.NODE_ENV) {
1569
- // In DEV the convenience constructor generates a proxy to another
1570
- // instance around it to warn about access to properties on the
1571
- // descriptor.
1572
- DescriptorConstructor = createDescriptorProxy(Constructor);
1408
+ return ReactDescriptorValidator.createFactory(
1409
+ descriptorFactory,
1410
+ Constructor.propTypes,
1411
+ Constructor.contextTypes
1412
+ );
1573
1413
  }
1574
1414
 
1575
- return ConvenienceConstructor;
1415
+ return descriptorFactory;
1576
1416
  },
1577
1417
 
1578
- isValidClass: isValidClass,
1579
-
1580
1418
  injection: {
1581
1419
  injectMixin: function(mixin) {
1582
1420
  injectedMixins.push(mixin);