react 0.13.3 → 0.14.0-alpha1

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 (193) hide show
  1. package/addons.js +7 -0
  2. package/addons/CSSTransitionGroup.js +1 -0
  3. package/addons/LinkedStateMixin.js +1 -0
  4. package/addons/Perf.js +1 -0
  5. package/addons/PureRenderMixin.js +1 -0
  6. package/addons/TestUtils.js +1 -0
  7. package/addons/TransitionGroup.js +1 -0
  8. package/addons/batchedUpdates.js +1 -0
  9. package/addons/cloneWithProps.js +1 -0
  10. package/addons/createFragment.js +1 -0
  11. package/addons/renderSubtreeIntoContainer.js +1 -0
  12. package/addons/shallowCompare.js +1 -0
  13. package/addons/update.js +1 -0
  14. package/dist/JSXTransformer.js +3355 -1685
  15. package/dist/react-with-addons.js +3092 -5145
  16. package/dist/react-with-addons.min.js +6 -8
  17. package/dist/react.js +2772 -4594
  18. package/dist/react.min.js +5 -6
  19. package/lib/AutoFocusMixin.js +4 -3
  20. package/lib/BeforeInputEventPlugin.js +30 -118
  21. package/lib/CSSCore.js +12 -23
  22. package/lib/CSSProperty.js +4 -3
  23. package/lib/CSSPropertyOperations.js +14 -30
  24. package/lib/CallbackQueue.js +7 -10
  25. package/lib/ChangeEventPlugin.js +24 -88
  26. package/lib/ClientReactRootIndex.js +2 -2
  27. package/lib/DOMChildrenOperations.js +13 -33
  28. package/lib/DOMProperty.js +41 -65
  29. package/lib/DOMPropertyOperations.js +30 -51
  30. package/lib/Danger.js +19 -60
  31. package/lib/DefaultEventPluginOrder.js +2 -12
  32. package/lib/EnterLeaveEventPlugin.js +11 -33
  33. package/lib/EventConstants.js +2 -2
  34. package/lib/EventListener.js +11 -13
  35. package/lib/EventPluginHub.js +44 -47
  36. package/lib/EventPluginRegistry.js +18 -74
  37. package/lib/EventPluginUtils.js +27 -38
  38. package/lib/EventPropagators.js +23 -26
  39. package/lib/ExecutionEnvironment.js +4 -8
  40. package/lib/FallbackCompositionState.js +3 -3
  41. package/lib/HTMLDOMPropertyConfig.js +5 -17
  42. package/lib/LinkedStateMixin.js +3 -6
  43. package/lib/LinkedValueUtils.js +34 -64
  44. package/lib/LocalEventTrapMixin.js +9 -16
  45. package/lib/Object.assign.js +1 -1
  46. package/lib/PooledClass.js +8 -11
  47. package/lib/React.js +20 -38
  48. package/lib/ReactBrowserComponentMixin.js +9 -2
  49. package/lib/ReactBrowserEventEmitter.js +26 -82
  50. package/lib/ReactCSSTransitionGroup.js +13 -24
  51. package/lib/ReactCSSTransitionGroupChild.js +18 -28
  52. package/lib/ReactChildReconciler.js +11 -19
  53. package/lib/ReactChildren.js +7 -16
  54. package/lib/ReactClass.js +78 -231
  55. package/lib/ReactComponent.js +17 -51
  56. package/lib/ReactComponentBrowserEnvironment.js +4 -6
  57. package/lib/ReactComponentEnvironment.js +6 -12
  58. package/lib/ReactComponentWithPureRenderMixin.js +4 -5
  59. package/lib/ReactCompositeComponent.js +83 -318
  60. package/lib/ReactContext.js +2 -44
  61. package/lib/ReactCurrentOwner.js +1 -3
  62. package/lib/ReactDOM.js +3 -2
  63. package/lib/ReactDOMButton.js +3 -4
  64. package/lib/ReactDOMComponent.js +182 -148
  65. package/lib/ReactDOMForm.js +3 -3
  66. package/lib/ReactDOMIDOperations.js +11 -20
  67. package/lib/ReactDOMIframe.js +3 -3
  68. package/lib/ReactDOMImg.js +3 -3
  69. package/lib/ReactDOMInput.js +22 -35
  70. package/lib/ReactDOMOption.js +52 -10
  71. package/lib/ReactDOMSelect.js +50 -28
  72. package/lib/ReactDOMSelection.js +5 -20
  73. package/lib/ReactDOMTextComponent.js +17 -18
  74. package/lib/ReactDOMTextarea.js +15 -27
  75. package/lib/ReactDefaultBatchingStrategy.js +9 -13
  76. package/lib/ReactDefaultInjection.js +21 -40
  77. package/lib/ReactDefaultPerf.js +36 -69
  78. package/lib/ReactDefaultPerfAnalysis.js +8 -14
  79. package/lib/ReactElement.js +35 -72
  80. package/lib/ReactElementValidator.js +51 -110
  81. package/lib/ReactEmptyComponent.js +7 -11
  82. package/lib/ReactErrorUtils.js +2 -2
  83. package/lib/ReactEventEmitterMixin.js +3 -12
  84. package/lib/ReactEventListener.js +16 -38
  85. package/lib/ReactFragment.js +23 -54
  86. package/lib/ReactInjection.js +1 -1
  87. package/lib/ReactInputSelection.js +11 -21
  88. package/lib/ReactInstanceHandles.js +27 -57
  89. package/lib/ReactInstanceMap.js +5 -5
  90. package/lib/ReactLifeCycle.js +1 -1
  91. package/lib/ReactLink.js +2 -4
  92. package/lib/ReactMarkupChecksum.js +5 -10
  93. package/lib/ReactMount.js +136 -260
  94. package/lib/ReactMultiChild.js +19 -45
  95. package/lib/ReactMultiChildUpdateTypes.js +1 -1
  96. package/lib/ReactNativeComponent.js +7 -11
  97. package/lib/ReactOwner.js +7 -24
  98. package/lib/ReactPerf.js +8 -12
  99. package/lib/ReactPropTransferer.js +4 -4
  100. package/lib/ReactPropTypeLocationNames.js +2 -2
  101. package/lib/ReactPropTypeLocations.js +1 -1
  102. package/lib/ReactPropTypes.js +13 -46
  103. package/lib/ReactReconcileTransaction.js +9 -34
  104. package/lib/ReactReconciler.js +9 -19
  105. package/lib/ReactRef.js +5 -8
  106. package/lib/ReactRootIndex.js +2 -2
  107. package/lib/ReactServerRendering.js +7 -15
  108. package/lib/ReactServerRenderingTransaction.js +7 -32
  109. package/lib/ReactStateSetters.js +6 -6
  110. package/lib/ReactTestUtils.js +89 -165
  111. package/lib/ReactTransitionChildMapping.js +5 -7
  112. package/lib/ReactTransitionEvents.js +5 -5
  113. package/lib/ReactTransitionGroup.js +30 -52
  114. package/lib/ReactUpdateQueue.js +27 -90
  115. package/lib/ReactUpdates.js +27 -79
  116. package/lib/ReactWithAddons.js +7 -6
  117. package/lib/SVGDOMPropertyConfig.js +39 -2
  118. package/lib/SelectEventPlugin.js +28 -29
  119. package/lib/ServerReactRootIndex.js +2 -2
  120. package/lib/SimpleEventPlugin.js +136 -128
  121. package/lib/SyntheticClipboardEvent.js +3 -7
  122. package/lib/SyntheticCompositionEvent.js +3 -9
  123. package/lib/SyntheticDragEvent.js +1 -1
  124. package/lib/SyntheticEvent.js +8 -10
  125. package/lib/SyntheticFocusEvent.js +1 -1
  126. package/lib/SyntheticInputEvent.js +3 -9
  127. package/lib/SyntheticKeyboardEvent.js +4 -4
  128. package/lib/SyntheticMouseEvent.js +8 -14
  129. package/lib/SyntheticTouchEvent.js +1 -1
  130. package/lib/SyntheticUIEvent.js +3 -3
  131. package/lib/SyntheticWheelEvent.js +11 -15
  132. package/lib/Transaction.js +12 -24
  133. package/lib/ViewportMetrics.js +2 -2
  134. package/lib/accumulateInto.js +2 -5
  135. package/lib/adler32.js +2 -2
  136. package/lib/camelize.js +4 -2
  137. package/lib/camelizeStyleName.js +2 -2
  138. package/lib/cloneWithProps.js +5 -11
  139. package/lib/containsNode.js +29 -16
  140. package/lib/createArrayFromMixed.js +17 -16
  141. package/lib/createFullPageComponent.js +4 -11
  142. package/lib/createNodesFromMarkup.js +6 -8
  143. package/lib/dangerousStyleValue.js +2 -3
  144. package/lib/emptyFunction.js +10 -4
  145. package/lib/emptyObject.js +1 -1
  146. package/lib/escapeTextContentForBrowser.js +1 -1
  147. package/lib/findDOMNode.js +5 -24
  148. package/lib/flattenChildren.js +4 -10
  149. package/lib/focusNode.js +2 -3
  150. package/lib/forEachAccumulated.js +2 -2
  151. package/lib/getActiveElement.js +4 -2
  152. package/lib/getEventCharCode.js +1 -1
  153. package/lib/getEventKey.js +1 -1
  154. package/lib/getEventModifierState.js +1 -1
  155. package/lib/getEventTarget.js +1 -1
  156. package/lib/getIteratorFn.js +2 -4
  157. package/lib/getMarkupWrap.js +5 -5
  158. package/lib/getNodeForCharacterOffset.js +1 -1
  159. package/lib/getTextContentAccessor.js +2 -4
  160. package/lib/getUnboundedScrollPosition.js +1 -1
  161. package/lib/hyphenate.js +3 -1
  162. package/lib/hyphenateStyleName.js +2 -2
  163. package/lib/instantiateReactComponent.js +14 -38
  164. package/lib/invariant.js +8 -12
  165. package/lib/isEventSupported.js +7 -10
  166. package/lib/isNode.js +4 -6
  167. package/lib/isTextInputElement.js +2 -4
  168. package/lib/isTextNode.js +3 -1
  169. package/lib/joinClasses.js +2 -2
  170. package/lib/keyMirror.js +3 -6
  171. package/lib/keyOf.js +4 -3
  172. package/lib/mapObject.js +1 -1
  173. package/lib/memoizeStringOnly.js +2 -2
  174. package/lib/onlyChild.js +2 -5
  175. package/lib/performance.js +2 -5
  176. package/lib/performanceNow.js +3 -1
  177. package/lib/quoteAttributeValueForBrowser.js +1 -1
  178. package/lib/renderSubtreeIntoContainer.js +16 -0
  179. package/lib/setInnerHTML.js +11 -8
  180. package/lib/setTextContent.js +3 -3
  181. package/lib/shallowCompare.js +24 -0
  182. package/lib/shallowEqual.js +17 -11
  183. package/lib/shouldUpdateReactComponent.js +3 -64
  184. package/lib/toArray.js +8 -19
  185. package/lib/traverseAllChildren.js +19 -82
  186. package/lib/update.js +25 -85
  187. package/lib/validateDOMNesting.js +264 -0
  188. package/lib/warning.js +17 -15
  189. package/package.json +3 -3
  190. package/lib/MobileSafariClickEventPlugin.js +0 -56
  191. package/lib/ReactPutListenerQueue.js +0 -54
  192. package/lib/cx.js +0 -52
  193. package/lib/getReactRootElementInContainer.js +0 -33
@@ -31,17 +31,17 @@ var ReactDOMForm = ReactClass.createClass({
31
31
 
32
32
  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
33
33
 
34
- render: function() {
34
+ render: function () {
35
35
  // TODO: Instead of using `ReactDOM` directly, we should use JSX. However,
36
36
  // `jshint` fails to parse JSX so in order for linting to work in the open
37
37
  // source repo, we need to just use `ReactDOM.form`.
38
38
  return form(this.props);
39
39
  },
40
40
 
41
- componentDidMount: function() {
41
+ componentDidMount: function () {
42
42
  this.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset');
43
43
  this.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit');
44
44
  }
45
45
  });
46
46
 
47
- module.exports = ReactDOMForm;
47
+ module.exports = ReactDOMForm;
@@ -30,8 +30,7 @@ var setInnerHTML = require("./setInnerHTML");
30
30
  * @private
31
31
  */
32
32
  var INVALID_PROPERTY_ERRORS = {
33
- dangerouslySetInnerHTML:
34
- '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
33
+ dangerouslySetInnerHTML: '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
35
34
  style: '`style` must be set using `updateStylesByID()`.'
36
35
  };
37
36
 
@@ -50,13 +49,9 @@ var ReactDOMIDOperations = {
50
49
  * @param {*} value New value of the property.
51
50
  * @internal
52
51
  */
53
- updatePropertyByID: function(id, name, value) {
52
+ updatePropertyByID: function (id, name, value) {
54
53
  var node = ReactMount.getNode(id);
55
- ("production" !== process.env.NODE_ENV ? invariant(
56
- !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
57
- 'updatePropertyByID(...): %s',
58
- INVALID_PROPERTY_ERRORS[name]
59
- ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
54
+ 'production' !== process.env.NODE_ENV ? invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name));
60
55
 
61
56
  // If we're updating to null or undefined, we should remove the property
62
57
  // from the DOM node instead of inadvertantly setting to a string. This
@@ -76,13 +71,9 @@ var ReactDOMIDOperations = {
76
71
  * @param {string} name A property name to remove, see `DOMProperty`.
77
72
  * @internal
78
73
  */
79
- deletePropertyByID: function(id, name, value) {
74
+ deletePropertyByID: function (id, name, value) {
80
75
  var node = ReactMount.getNode(id);
81
- ("production" !== process.env.NODE_ENV ? invariant(
82
- !INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
83
- 'updatePropertyByID(...): %s',
84
- INVALID_PROPERTY_ERRORS[name]
85
- ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
76
+ 'production' !== process.env.NODE_ENV ? invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name));
86
77
  DOMPropertyOperations.deleteValueForProperty(node, name, value);
87
78
  },
88
79
 
@@ -94,7 +85,7 @@ var ReactDOMIDOperations = {
94
85
  * @param {object} styles Mapping from styles to values.
95
86
  * @internal
96
87
  */
97
- updateStylesByID: function(id, styles) {
88
+ updateStylesByID: function (id, styles) {
98
89
  var node = ReactMount.getNode(id);
99
90
  CSSPropertyOperations.setValueForStyles(node, styles);
100
91
  },
@@ -106,7 +97,7 @@ var ReactDOMIDOperations = {
106
97
  * @param {string} html An HTML string.
107
98
  * @internal
108
99
  */
109
- updateInnerHTMLByID: function(id, html) {
100
+ updateInnerHTMLByID: function (id, html) {
110
101
  var node = ReactMount.getNode(id);
111
102
  setInnerHTML(node, html);
112
103
  },
@@ -118,7 +109,7 @@ var ReactDOMIDOperations = {
118
109
  * @param {string} content Text content.
119
110
  * @internal
120
111
  */
121
- updateTextContentByID: function(id, content) {
112
+ updateTextContentByID: function (id, content) {
122
113
  var node = ReactMount.getNode(id);
123
114
  DOMChildrenOperations.updateTextContent(node, content);
124
115
  },
@@ -131,7 +122,7 @@ var ReactDOMIDOperations = {
131
122
  * @internal
132
123
  * @see {Danger.dangerouslyReplaceNodeWithMarkup}
133
124
  */
134
- dangerouslyReplaceNodeWithMarkupByID: function(id, markup) {
125
+ dangerouslyReplaceNodeWithMarkupByID: function (id, markup) {
135
126
  var node = ReactMount.getNode(id);
136
127
  DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup);
137
128
  },
@@ -143,7 +134,7 @@ var ReactDOMIDOperations = {
143
134
  * @param {array<string>} markup List of markup strings.
144
135
  * @internal
145
136
  */
146
- dangerouslyProcessChildrenUpdates: function(updates, markup) {
137
+ dangerouslyProcessChildrenUpdates: function (updates, markup) {
147
138
  for (var i = 0; i < updates.length; i++) {
148
139
  updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
149
140
  }
@@ -161,4 +152,4 @@ ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
161
152
  dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
162
153
  });
163
154
 
164
- module.exports = ReactDOMIDOperations;
155
+ module.exports = ReactDOMIDOperations;
@@ -31,13 +31,13 @@ var ReactDOMIframe = ReactClass.createClass({
31
31
 
32
32
  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
33
33
 
34
- render: function() {
34
+ render: function () {
35
35
  return iframe(this.props);
36
36
  },
37
37
 
38
- componentDidMount: function() {
38
+ componentDidMount: function () {
39
39
  this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
40
40
  }
41
41
  });
42
42
 
43
- module.exports = ReactDOMIframe;
43
+ module.exports = ReactDOMIframe;
@@ -31,14 +31,14 @@ var ReactDOMImg = ReactClass.createClass({
31
31
 
32
32
  mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
33
33
 
34
- render: function() {
34
+ render: function () {
35
35
  return img(this.props);
36
36
  },
37
37
 
38
- componentDidMount: function() {
38
+ componentDidMount: function () {
39
39
  this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
40
40
  this.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error');
41
41
  }
42
42
  });
43
43
 
44
- module.exports = ReactDOMImg;
44
+ module.exports = ReactDOMImg;
@@ -21,6 +21,7 @@ var ReactMount = require("./ReactMount");
21
21
  var ReactUpdates = require("./ReactUpdates");
22
22
 
23
23
  var assign = require("./Object.assign");
24
+ var findDOMNode = require("./findDOMNode");
24
25
  var invariant = require("./invariant");
25
26
 
26
27
  var input = ReactElement.createFactory('input');
@@ -56,7 +57,7 @@ var ReactDOMInput = ReactClass.createClass({
56
57
 
57
58
  mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
58
59
 
59
- getInitialState: function() {
60
+ getInitialState: function () {
60
61
  var defaultValue = this.props.defaultValue;
61
62
  return {
62
63
  initialChecked: this.props.defaultChecked || false,
@@ -64,17 +65,17 @@ var ReactDOMInput = ReactClass.createClass({
64
65
  };
65
66
  },
66
67
 
67
- render: function() {
68
+ render: function () {
68
69
  // Clone `this.props` so we don't mutate the input.
69
70
  var props = assign({}, this.props);
70
71
 
71
72
  props.defaultChecked = null;
72
73
  props.defaultValue = null;
73
74
 
74
- var value = LinkedValueUtils.getValue(this);
75
+ var value = LinkedValueUtils.getValue(this.props);
75
76
  props.value = value != null ? value : this.state.initialValue;
76
77
 
77
- var checked = LinkedValueUtils.getChecked(this);
78
+ var checked = LinkedValueUtils.getChecked(this.props);
78
79
  props.checked = checked != null ? checked : this.state.initialChecked;
79
80
 
80
81
  props.onChange = this._handleChange;
@@ -82,28 +83,24 @@ var ReactDOMInput = ReactClass.createClass({
82
83
  return input(props, this.props.children);
83
84
  },
84
85
 
85
- componentDidMount: function() {
86
- var id = ReactMount.getID(this.getDOMNode());
86
+ componentDidMount: function () {
87
+ var id = ReactMount.getID(findDOMNode(this));
87
88
  instancesByReactID[id] = this;
88
89
  },
89
90
 
90
- componentWillUnmount: function() {
91
- var rootNode = this.getDOMNode();
91
+ componentWillUnmount: function () {
92
+ var rootNode = findDOMNode(this);
92
93
  var id = ReactMount.getID(rootNode);
93
94
  delete instancesByReactID[id];
94
95
  },
95
96
 
96
- componentDidUpdate: function(prevProps, prevState, prevContext) {
97
- var rootNode = this.getDOMNode();
97
+ componentDidUpdate: function (prevProps, prevState, prevContext) {
98
+ var rootNode = findDOMNode(this);
98
99
  if (this.props.checked != null) {
99
- DOMPropertyOperations.setValueForProperty(
100
- rootNode,
101
- 'checked',
102
- this.props.checked || false
103
- );
100
+ DOMPropertyOperations.setValueForProperty(rootNode, 'checked', this.props.checked || false);
104
101
  }
105
102
 
106
- var value = LinkedValueUtils.getValue(this);
103
+ var value = LinkedValueUtils.getValue(this.props);
107
104
  if (value != null) {
108
105
  // Cast `value` to a string to ensure the value is set correctly. While
109
106
  // browsers typically do this as necessary, jsdom doesn't.
@@ -111,9 +108,9 @@ var ReactDOMInput = ReactClass.createClass({
111
108
  }
112
109
  },
113
110
 
114
- _handleChange: function(event) {
111
+ _handleChange: function (event) {
115
112
  var returnValue;
116
- var onChange = LinkedValueUtils.getOnChange(this);
113
+ var onChange = LinkedValueUtils.getOnChange(this.props);
117
114
  if (onChange) {
118
115
  returnValue = onChange.call(this, event);
119
116
  }
@@ -124,7 +121,7 @@ var ReactDOMInput = ReactClass.createClass({
124
121
 
125
122
  var name = this.props.name;
126
123
  if (this.props.type === 'radio' && name != null) {
127
- var rootNode = this.getDOMNode();
124
+ var rootNode = findDOMNode(this);
128
125
  var queryRoot = rootNode;
129
126
 
130
127
  while (queryRoot.parentNode) {
@@ -137,27 +134,17 @@ var ReactDOMInput = ReactClass.createClass({
137
134
  // and won't include inputs that use the HTML5 `form=` attribute. Since
138
135
  // the input might not even be in a form, let's just use the global
139
136
  // `querySelectorAll` to ensure we don't miss anything.
140
- var group = queryRoot.querySelectorAll(
141
- 'input[name=' + JSON.stringify('' + name) + '][type="radio"]');
137
+ var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
142
138
 
143
- for (var i = 0, groupLen = group.length; i < groupLen; i++) {
139
+ for (var i = 0; i < group.length; i++) {
144
140
  var otherNode = group[i];
145
- if (otherNode === rootNode ||
146
- otherNode.form !== rootNode.form) {
141
+ if (otherNode === rootNode || otherNode.form !== rootNode.form) {
147
142
  continue;
148
143
  }
149
144
  var otherID = ReactMount.getID(otherNode);
150
- ("production" !== process.env.NODE_ENV ? invariant(
151
- otherID,
152
- 'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
153
- 'same `name` is not supported.'
154
- ) : invariant(otherID));
145
+ 'production' !== process.env.NODE_ENV ? invariant(otherID, 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.') : invariant(otherID);
155
146
  var otherInstance = instancesByReactID[otherID];
156
- ("production" !== process.env.NODE_ENV ? invariant(
157
- otherInstance,
158
- 'ReactDOMInput: Unknown radio button ID %s.',
159
- otherID
160
- ) : invariant(otherInstance));
147
+ 'production' !== process.env.NODE_ENV ? invariant(otherInstance, 'ReactDOMInput: Unknown radio button ID %s.', otherID) : invariant(otherInstance);
161
148
  // If this is a controlled radio button group, forcing the input that
162
149
  // was previously checked to update will cause it to be come re-checked
163
150
  // as appropriate.
@@ -170,4 +157,4 @@ var ReactDOMInput = ReactClass.createClass({
170
157
 
171
158
  });
172
159
 
173
- module.exports = ReactDOMInput;
160
+ module.exports = ReactDOMInput;
@@ -13,12 +13,18 @@
13
13
 
14
14
  var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
15
15
  var ReactClass = require("./ReactClass");
16
+ var ReactDOMSelect = require("./ReactDOMSelect");
16
17
  var ReactElement = require("./ReactElement");
18
+ var ReactInstanceMap = require("./ReactInstanceMap");
19
+ var ReactPropTypes = require("./ReactPropTypes");
17
20
 
21
+ var assign = require("./Object.assign");
18
22
  var warning = require("./warning");
19
23
 
20
24
  var option = ReactElement.createFactory('option');
21
25
 
26
+ var valueContextKey = ReactDOMSelect.valueContextKey;
27
+
22
28
  /**
23
29
  * Implements an <option> native component that warns when `selected` is set.
24
30
  */
@@ -28,21 +34,57 @@ var ReactDOMOption = ReactClass.createClass({
28
34
 
29
35
  mixins: [ReactBrowserComponentMixin],
30
36
 
31
- componentWillMount: function() {
37
+ getInitialState: function () {
38
+ return { selected: null };
39
+ },
40
+
41
+ contextTypes: (function () {
42
+ var obj = {};
43
+ obj[valueContextKey] = ReactPropTypes.any;
44
+ return obj;
45
+ })(),
46
+
47
+ componentWillMount: function () {
32
48
  // TODO (yungsters): Remove support for `selected` in <option>.
33
- if ("production" !== process.env.NODE_ENV) {
34
- ("production" !== process.env.NODE_ENV ? warning(
35
- this.props.selected == null,
36
- 'Use the `defaultValue` or `value` props on <select> instead of ' +
37
- 'setting `selected` on <option>.'
38
- ) : null);
49
+ if ('production' !== process.env.NODE_ENV) {
50
+ 'production' !== process.env.NODE_ENV ? warning(this.props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : null;
51
+ }
52
+
53
+ // Look up whether this option is 'selected' via parent-based context
54
+ var context = ReactInstanceMap.get(this)._context;
55
+ var selectValue = context[valueContextKey];
56
+
57
+ // If context key is null (e.g., no specified value or after initial mount)
58
+ // or missing (e.g., for <datalist>) skip props
59
+ if (selectValue != null) {
60
+ var selected = false;
61
+ if (Array.isArray(selectValue)) {
62
+ // multiple
63
+ for (var i = 0; i < selectValue.length; i++) {
64
+ if ('' + selectValue[i] === '' + this.props.value) {
65
+ selected = true;
66
+ break;
67
+ }
68
+ }
69
+ } else {
70
+ selected = '' + selectValue === '' + this.props.value;
71
+ }
72
+ this.setState({ selected: selected });
39
73
  }
40
74
  },
41
75
 
42
- render: function() {
43
- return option(this.props, this.props.children);
76
+ render: function () {
77
+ var props = this.props;
78
+
79
+ // Read state only from initial mount because <select> updates value
80
+ // manually; we need the initial state only for server rendering
81
+ if (this.state.selected != null) {
82
+ props = assign({}, props, { selected: this.state.selected });
83
+ }
84
+
85
+ return option(props, this.props.children);
44
86
  }
45
87
 
46
88
  });
47
89
 
48
- module.exports = ReactDOMOption;
90
+ module.exports = ReactDOMOption;
@@ -17,16 +17,20 @@ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
17
17
  var ReactClass = require("./ReactClass");
18
18
  var ReactElement = require("./ReactElement");
19
19
  var ReactUpdates = require("./ReactUpdates");
20
+ var ReactPropTypes = require("./ReactPropTypes");
20
21
 
21
22
  var assign = require("./Object.assign");
23
+ var findDOMNode = require("./findDOMNode");
22
24
 
23
25
  var select = ReactElement.createFactory('select');
24
26
 
27
+ var valueContextKey = '__ReactDOMSelect_value$' + Math.random().toString(36).slice(2);
28
+
25
29
  function updateOptionsIfPendingUpdateAndMounted() {
26
30
  /*jshint validthis:true */
27
31
  if (this._pendingUpdate) {
28
32
  this._pendingUpdate = false;
29
- var value = LinkedValueUtils.getValue(this);
33
+ var value = LinkedValueUtils.getValue(this.props);
30
34
  if (value != null && this.isMounted()) {
31
35
  updateOptions(this, value);
32
36
  }
@@ -43,17 +47,11 @@ function selectValueType(props, propName, componentName) {
43
47
  }
44
48
  if (props.multiple) {
45
49
  if (!Array.isArray(props[propName])) {
46
- return new Error(
47
- ("The `" + propName + "` prop supplied to <select> must be an array if ") +
48
- ("`multiple` is true.")
49
- );
50
+ return new Error('The `' + propName + '` prop supplied to <select> must be an array if ' + '`multiple` is true.');
50
51
  }
51
52
  } else {
52
53
  if (Array.isArray(props[propName])) {
53
- return new Error(
54
- ("The `" + propName + "` prop supplied to <select> must be a scalar ") +
55
- ("value if `multiple` is false.")
56
- );
54
+ return new Error('The `' + propName + '` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.');
57
55
  }
58
56
  }
59
57
  }
@@ -64,15 +62,15 @@ function selectValueType(props, propName, componentName) {
64
62
  * @private
65
63
  */
66
64
  function updateOptions(component, propValue) {
67
- var selectedValue, i, l;
68
- var options = component.getDOMNode().options;
65
+ var selectedValue, i;
66
+ var options = findDOMNode(component).options;
69
67
 
70
68
  if (component.props.multiple) {
71
69
  selectedValue = {};
72
- for (i = 0, l = propValue.length; i < l; i++) {
70
+ for (i = 0; i < propValue.length; i++) {
73
71
  selectedValue['' + propValue[i]] = true;
74
72
  }
75
- for (i = 0, l = options.length; i < l; i++) {
73
+ for (i = 0; i < options.length; i++) {
76
74
  var selected = selectedValue.hasOwnProperty(options[i].value);
77
75
  if (options[i].selected !== selected) {
78
76
  options[i].selected = selected;
@@ -82,7 +80,7 @@ function updateOptions(component, propValue) {
82
80
  // Do not set `select.value` as exact behavior isn't consistent across all
83
81
  // browsers for all cases.
84
82
  selectedValue = '' + propValue;
85
- for (i = 0, l = options.length; i < l; i++) {
83
+ for (i = 0; i < options.length; i++) {
86
84
  if (options[i].value === selectedValue) {
87
85
  options[i].selected = true;
88
86
  return;
@@ -115,12 +113,39 @@ var ReactDOMSelect = ReactClass.createClass({
115
113
 
116
114
  mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
117
115
 
116
+ statics: {
117
+ valueContextKey: valueContextKey
118
+ },
119
+
118
120
  propTypes: {
119
121
  defaultValue: selectValueType,
120
122
  value: selectValueType
121
123
  },
122
124
 
123
- render: function() {
125
+ getInitialState: function () {
126
+ // Pass down initial value so initial generated markup has correct
127
+ // `selected` attributes
128
+ var value = LinkedValueUtils.getValue(this.props);
129
+ if (value != null) {
130
+ return { initialValue: value };
131
+ } else {
132
+ return { initialValue: this.props.defaultValue };
133
+ }
134
+ },
135
+
136
+ childContextTypes: (function () {
137
+ var obj = {};
138
+ obj[valueContextKey] = ReactPropTypes.any;
139
+ return obj;
140
+ })(),
141
+
142
+ getChildContext: function () {
143
+ var obj = {};
144
+ obj[valueContextKey] = this.state.initialValue;
145
+ return obj;
146
+ },
147
+
148
+ render: function () {
124
149
  // Clone `this.props` so we don't mutate the input.
125
150
  var props = assign({}, this.props);
126
151
 
@@ -130,21 +155,18 @@ var ReactDOMSelect = ReactClass.createClass({
130
155
  return select(props, this.props.children);
131
156
  },
132
157
 
133
- componentWillMount: function() {
158
+ componentWillMount: function () {
134
159
  this._pendingUpdate = false;
135
160
  },
136
161
 
137
- componentDidMount: function() {
138
- var value = LinkedValueUtils.getValue(this);
139
- if (value != null) {
140
- updateOptions(this, value);
141
- } else if (this.props.defaultValue != null) {
142
- updateOptions(this, this.props.defaultValue);
143
- }
162
+ componentWillReceiveProps: function (nextProps) {
163
+ // After the initial mount, we control selected-ness manually so don't pass
164
+ // the context value down
165
+ this.setState({ initialValue: null });
144
166
  },
145
167
 
146
- componentDidUpdate: function(prevProps) {
147
- var value = LinkedValueUtils.getValue(this);
168
+ componentDidUpdate: function (prevProps) {
169
+ var value = LinkedValueUtils.getValue(this.props);
148
170
  if (value != null) {
149
171
  this._pendingUpdate = false;
150
172
  updateOptions(this, value);
@@ -159,9 +181,9 @@ var ReactDOMSelect = ReactClass.createClass({
159
181
  }
160
182
  },
161
183
 
162
- _handleChange: function(event) {
184
+ _handleChange: function (event) {
163
185
  var returnValue;
164
- var onChange = LinkedValueUtils.getOnChange(this);
186
+ var onChange = LinkedValueUtils.getOnChange(this.props);
165
187
  if (onChange) {
166
188
  returnValue = onChange.call(this, event);
167
189
  }
@@ -173,4 +195,4 @@ var ReactDOMSelect = ReactClass.createClass({
173
195
 
174
196
  });
175
197
 
176
- module.exports = ReactDOMSelect;
198
+ module.exports = ReactDOMSelect;