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
@@ -341,8 +341,14 @@ var SimpleEventPlugin = {
341
341
  // @see http://www.w3.org/TR/html5/index.html#events-0
342
342
  EventConstructor = SyntheticEvent;
343
343
  break;
344
- case topLevelTypes.topKeyDown:
345
344
  case topLevelTypes.topKeyPress:
345
+ // FireFox creates a keypress event for function keys too. This removes
346
+ // the unwanted keypress events.
347
+ if (nativeEvent.charCode === 0) {
348
+ return null;
349
+ }
350
+ /* falls through */
351
+ case topLevelTypes.topKeyDown:
346
352
  case topLevelTypes.topKeyUp:
347
353
  EventConstructor = SyntheticKeyboardEvent;
348
354
  break;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule SyntheticInputEvent
17
+ * @typechecks static-only
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var SyntheticEvent = require("./SyntheticEvent");
23
+
24
+ /**
25
+ * @interface Event
26
+ * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
27
+ * /#events-inputevents
28
+ */
29
+ var InputEventInterface = {
30
+ data: null
31
+ };
32
+
33
+ /**
34
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
35
+ * @param {string} dispatchMarker Marker identifying the event target.
36
+ * @param {object} nativeEvent Native browser event.
37
+ * @extends {SyntheticUIEvent}
38
+ */
39
+ function SyntheticInputEvent(
40
+ dispatchConfig,
41
+ dispatchMarker,
42
+ nativeEvent) {
43
+ SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent);
44
+ }
45
+
46
+ SyntheticEvent.augmentClass(
47
+ SyntheticInputEvent,
48
+ InputEventInterface
49
+ );
50
+
51
+ module.exports = SyntheticInputEvent;
52
+
@@ -22,6 +22,7 @@
22
22
  var SyntheticUIEvent = require("./SyntheticUIEvent");
23
23
 
24
24
  var getEventKey = require("./getEventKey");
25
+ var getEventModifierState = require("./getEventModifierState");
25
26
 
26
27
  /**
27
28
  * @interface KeyboardEvent
@@ -36,11 +37,39 @@ var KeyboardEventInterface = {
36
37
  metaKey: null,
37
38
  repeat: null,
38
39
  locale: null,
40
+ getModifierState: getEventModifierState,
39
41
  // Legacy Interface
40
- 'char': null,
41
- charCode: null,
42
- keyCode: null,
43
- which: null
42
+ charCode: function(event) {
43
+ // `charCode` is the result of a KeyPress event and represents the value of
44
+ // the actual printable character.
45
+
46
+ // KeyPress is deprecated but its replacement is not yet final and not
47
+ // implemented in any major browser.
48
+ if (event.type === 'keypress') {
49
+ // IE8 does not implement "charCode", but "keyCode" has the correct value.
50
+ return 'charCode' in event ? event.charCode : event.keyCode;
51
+ }
52
+ return 0;
53
+ },
54
+ keyCode: function(event) {
55
+ // `keyCode` is the result of a KeyDown/Up event and represents the value of
56
+ // physical keyboard key.
57
+
58
+ // The actual meaning of the value depends on the users' keyboard layout
59
+ // which cannot be detected. Assuming that it is a US keyboard layout
60
+ // provides a surprisingly accurate mapping for US and European users.
61
+ // Due to this, it is left to the user to implement at this time.
62
+ if (event.type === 'keydown' || event.type === 'keyup') {
63
+ return event.keyCode;
64
+ }
65
+ return 0;
66
+ },
67
+ which: function(event) {
68
+ // `which` is an alias for either `keyCode` or `charCode` depending on the
69
+ // type of the event. There is no need to determine the type of the event
70
+ // as `keyCode` and `charCode` are either aliased or default to zero.
71
+ return event.keyCode || event.charCode;
72
+ }
44
73
  };
45
74
 
46
75
  /**
@@ -22,6 +22,8 @@
22
22
  var SyntheticUIEvent = require("./SyntheticUIEvent");
23
23
  var ViewportMetrics = require("./ViewportMetrics");
24
24
 
25
+ var getEventModifierState = require("./getEventModifierState");
26
+
25
27
  /**
26
28
  * @interface MouseEvent
27
29
  * @see http://www.w3.org/TR/DOM-Level-3-Events/
@@ -35,6 +37,7 @@ var MouseEventInterface = {
35
37
  shiftKey: null,
36
38
  altKey: null,
37
39
  metaKey: null,
40
+ getEventModifierState: getEventModifierState,
38
41
  button: function(event) {
39
42
  // Webkit, Firefox, IE9+
40
43
  // which: 1 2 3
@@ -21,6 +21,8 @@
21
21
 
22
22
  var SyntheticUIEvent = require("./SyntheticUIEvent");
23
23
 
24
+ var getEventModifierState = require("./getEventModifierState");
25
+
24
26
  /**
25
27
  * @interface TouchEvent
26
28
  * @see http://www.w3.org/TR/touch-events/
@@ -32,7 +34,8 @@ var TouchEventInterface = {
32
34
  altKey: null,
33
35
  metaKey: null,
34
36
  ctrlKey: null,
35
- shiftKey: null
37
+ shiftKey: null,
38
+ getModifierState: getEventModifierState
36
39
  };
37
40
 
38
41
  /**
@@ -21,13 +21,35 @@
21
21
 
22
22
  var SyntheticEvent = require("./SyntheticEvent");
23
23
 
24
+ var getEventTarget = require("./getEventTarget");
25
+
24
26
  /**
25
27
  * @interface UIEvent
26
28
  * @see http://www.w3.org/TR/DOM-Level-3-Events/
27
29
  */
28
30
  var UIEventInterface = {
29
- view: null,
30
- detail: null
31
+ view: function(event) {
32
+ if (event.view) {
33
+ return event.view;
34
+ }
35
+
36
+ var target = getEventTarget(event);
37
+ if (target != null && target.window === target) {
38
+ // target is a window object
39
+ return target;
40
+ }
41
+
42
+ var doc = target.ownerDocument;
43
+ // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
44
+ if (doc) {
45
+ return doc.defaultView || doc.parentWindow;
46
+ } else {
47
+ return window;
48
+ }
49
+ },
50
+ detail: function(event) {
51
+ return event.detail || 0;
52
+ }
31
53
  };
32
54
 
33
55
  /**
@@ -57,9 +57,6 @@ var invariant = require("./invariant");
57
57
  * +-----------------------------------------+
58
58
  * </pre>
59
59
  *
60
- * Bonus:
61
- * - Reports timing metrics by method name and wrapper index.
62
- *
63
60
  * Use cases:
64
61
  * - Preserving the input selection ranges before/after reconciliation.
65
62
  * Restoring selection even in the event of an unexpected error.
@@ -99,20 +96,6 @@ var Mixin = {
99
96
  } else {
100
97
  this.wrapperInitData.length = 0;
101
98
  }
102
- if (!this.timingMetrics) {
103
- this.timingMetrics = {};
104
- }
105
- this.timingMetrics.methodInvocationTime = 0;
106
- if (!this.timingMetrics.wrapperInitTimes) {
107
- this.timingMetrics.wrapperInitTimes = [];
108
- } else {
109
- this.timingMetrics.wrapperInitTimes.length = 0;
110
- }
111
- if (!this.timingMetrics.wrapperCloseTimes) {
112
- this.timingMetrics.wrapperCloseTimes = [];
113
- } else {
114
- this.timingMetrics.wrapperCloseTimes.length = 0;
115
- }
116
99
  this._isInTransaction = false;
117
100
  },
118
101
 
@@ -145,7 +128,6 @@ var Mixin = {
145
128
  'Transaction.perform(...): Cannot initialize a transaction when there ' +
146
129
  'is already an outstanding transaction.'
147
130
  ) : invariant(!this.isInTransaction()));
148
- var memberStart = Date.now();
149
131
  var errorThrown;
150
132
  var ret;
151
133
  try {
@@ -159,8 +141,6 @@ var Mixin = {
159
141
  ret = method.call(scope, a, b, c, d, e, f);
160
142
  errorThrown = false;
161
143
  } finally {
162
- var memberEnd = Date.now();
163
- this.methodInvocationTime += (memberEnd - memberStart);
164
144
  try {
165
145
  if (errorThrown) {
166
146
  // If `method` throws, prefer to show that stack trace over any thrown
@@ -183,9 +163,7 @@ var Mixin = {
183
163
 
184
164
  initializeAll: function(startIndex) {
185
165
  var transactionWrappers = this.transactionWrappers;
186
- var wrapperInitTimes = this.timingMetrics.wrapperInitTimes;
187
166
  for (var i = startIndex; i < transactionWrappers.length; i++) {
188
- var initStart = Date.now();
189
167
  var wrapper = transactionWrappers[i];
190
168
  try {
191
169
  // Catching errors makes debugging more difficult, so we start with the
@@ -197,10 +175,6 @@ var Mixin = {
197
175
  wrapper.initialize.call(this) :
198
176
  null;
199
177
  } finally {
200
- var curInitTime = wrapperInitTimes[i];
201
- var initEnd = Date.now();
202
- wrapperInitTimes[i] = (curInitTime || 0) + (initEnd - initStart);
203
-
204
178
  if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {
205
179
  // The initializer for wrapper i threw an error; initialize the
206
180
  // remaining wrappers but silence any exceptions from them to ensure
@@ -226,10 +200,8 @@ var Mixin = {
226
200
  'Transaction.closeAll(): Cannot close transaction when none are open.'
227
201
  ) : invariant(this.isInTransaction()));
228
202
  var transactionWrappers = this.transactionWrappers;
229
- var wrapperCloseTimes = this.timingMetrics.wrapperCloseTimes;
230
203
  for (var i = startIndex; i < transactionWrappers.length; i++) {
231
204
  var wrapper = transactionWrappers[i];
232
- var closeStart = Date.now();
233
205
  var initData = this.wrapperInitData[i];
234
206
  var errorThrown;
235
207
  try {
@@ -243,10 +215,6 @@ var Mixin = {
243
215
  }
244
216
  errorThrown = false;
245
217
  } finally {
246
- var closeEnd = Date.now();
247
- var curCloseTime = wrapperCloseTimes[i];
248
- wrapperCloseTimes[i] = (curCloseTime || 0) + (closeEnd - closeStart);
249
-
250
218
  if (errorThrown) {
251
219
  // The closer for wrapper i threw an error; close the remaining
252
220
  // wrappers but silence any exceptions from them to ensure that the
@@ -22,6 +22,7 @@
22
22
  var ReactPropTransferer = require("./ReactPropTransferer");
23
23
 
24
24
  var keyOf = require("./keyOf");
25
+ var warning = require("./warning");
25
26
 
26
27
  var CHILDREN_PROP = keyOf({children: null});
27
28
 
@@ -36,13 +37,12 @@ var CHILDREN_PROP = keyOf({children: null});
36
37
  */
37
38
  function cloneWithProps(child, props) {
38
39
  if ("production" !== process.env.NODE_ENV) {
39
- if (child.props.ref) {
40
- console.warn(
41
- 'You are calling cloneWithProps() on a child with a ref. This is ' +
42
- 'dangerous because you\'re creating a new child which will not be ' +
43
- 'added as a ref to its parent.'
44
- );
45
- }
40
+ ("production" !== process.env.NODE_ENV ? warning(
41
+ !child.props.ref,
42
+ 'You are calling cloneWithProps() on a child with a ref. This is ' +
43
+ 'dangerous because you\'re creating a new child which will not be ' +
44
+ 'added as a ref to its parent.'
45
+ ) : null);
46
46
  }
47
47
 
48
48
  var newProps = ReactPropTransferer.mergeProps(props, child.props);
@@ -53,7 +53,9 @@ function cloneWithProps(child, props) {
53
53
  newProps.children = child.props.children;
54
54
  }
55
55
 
56
- return child.constructor.ConvenienceConstructor(newProps);
56
+ // The current API doesn't retain _owner and _context, which is why this
57
+ // doesn't use ReactDescriptor.cloneAndReplaceProps.
58
+ return child.constructor(newProps);
57
59
  }
58
60
 
59
61
  module.exports = cloneWithProps;
@@ -38,7 +38,7 @@ var invariant = require("./invariant");
38
38
  function createFullPageComponent(componentClass) {
39
39
  var FullPageComponent = ReactCompositeComponent.createClass({
40
40
  displayName: 'ReactFullPageComponent' + (
41
- componentClass.componentConstructor.displayName || ''
41
+ componentClass.type.displayName || ''
42
42
  ),
43
43
 
44
44
  componentWillUnmount: function() {
@@ -21,16 +21,18 @@
21
21
 
22
22
  var CSSProperty = require("./CSSProperty");
23
23
 
24
+ var isUnitlessNumber = CSSProperty.isUnitlessNumber;
25
+
24
26
  /**
25
- * Convert a value into the proper css writable value. The `styleName` name
26
- * name should be logical (no hyphens), as specified
27
+ * Convert a value into the proper css writable value. The style name `name`
28
+ * should be logical (no hyphens), as specified
27
29
  * in `CSSProperty.isUnitlessNumber`.
28
30
  *
29
- * @param {string} styleName CSS property name such as `topMargin`.
31
+ * @param {string} name CSS property name such as `topMargin`.
30
32
  * @param {*} value CSS property value such as `10px`.
31
33
  * @return {string} Normalized style value with dimensions applied.
32
34
  */
33
- function dangerousStyleValue(styleName, value) {
35
+ function dangerousStyleValue(name, value) {
34
36
  // Note that we've removed escapeTextForBrowser() calls here since the
35
37
  // whole string will be escaped when the attribute is injected into
36
38
  // the markup. If you provide unsafe user data here they can inject
@@ -47,10 +49,14 @@ function dangerousStyleValue(styleName, value) {
47
49
  }
48
50
 
49
51
  var isNonNumeric = isNaN(value);
50
- if (isNonNumeric || value === 0 || CSSProperty.isUnitlessNumber[styleName]) {
52
+ if (isNonNumeric || value === 0 ||
53
+ isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {
51
54
  return '' + value; // cast to string
52
55
  }
53
56
 
57
+ if (typeof value === 'string') {
58
+ value = value.trim();
59
+ }
54
60
  return value + 'px';
55
61
  }
56
62
 
@@ -13,14 +13,15 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  *
16
- * @providesModule ReactComponentEnvironment
16
+ * @providesModule emptyObject
17
17
  */
18
18
 
19
19
  "use strict";
20
20
 
21
- var ReactComponentBrowserEnvironment =
22
- require("./ReactComponentBrowserEnvironment");
21
+ var emptyObject = {};
23
22
 
24
- var ReactComponentEnvironment = ReactComponentBrowserEnvironment;
23
+ if ("production" !== process.env.NODE_ENV) {
24
+ Object.freeze(emptyObject);
25
+ }
25
26
 
26
- module.exports = ReactComponentEnvironment;
27
+ module.exports = emptyObject;
@@ -24,11 +24,10 @@ var ESCAPE_LOOKUP = {
24
24
  ">": "&gt;",
25
25
  "<": "&lt;",
26
26
  "\"": "&quot;",
27
- "'": "&#x27;",
28
- "/": "&#x2f;"
27
+ "'": "&#x27;"
29
28
  };
30
29
 
31
- var ESCAPE_REGEX = /[&><"'\/]/g;
30
+ var ESCAPE_REGEX = /[&><"']/g;
32
31
 
33
32
  function escaper(match) {
34
33
  return ESCAPE_LOOKUP[match];
@@ -18,8 +18,8 @@
18
18
 
19
19
  "use strict";
20
20
 
21
- var invariant = require("./invariant");
22
21
  var traverseAllChildren = require("./traverseAllChildren");
22
+ var warning = require("./warning");
23
23
 
24
24
  /**
25
25
  * @param {function} traverseContext Context passed through traversal.
@@ -29,13 +29,15 @@ var traverseAllChildren = require("./traverseAllChildren");
29
29
  function flattenSingleChildIntoContext(traverseContext, child, name) {
30
30
  // We found a component instance.
31
31
  var result = traverseContext;
32
- ("production" !== process.env.NODE_ENV ? invariant(
33
- !result.hasOwnProperty(name),
34
- 'flattenChildren(...): Encountered two children with the same key, `%s`. ' +
35
- 'Children keys must be unique.',
32
+ var keyUnique = !result.hasOwnProperty(name);
33
+ ("production" !== process.env.NODE_ENV ? warning(
34
+ keyUnique,
35
+ 'flattenChildren(...): Encountered two children with the same key, ' +
36
+ '`%s`. Child keys must be unique; when two children share a key, only ' +
37
+ 'the first child will be used.',
36
38
  name
37
- ) : invariant(!result.hasOwnProperty(name)));
38
- if (child != null) {
39
+ ) : null);
40
+ if (keyUnique && child != null) {
39
41
  result[name] = child;
40
42
  }
41
43
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright 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 focusNode
17
+ */
18
+
19
+ "use strict";
20
+
21
+ /**
22
+ * IE8 throws if an input/textarea is disabled and we try to focus it.
23
+ * Focus only when necessary.
24
+ *
25
+ * @param {DOMElement} node input/textarea to focus
26
+ */
27
+ function focusNode(node) {
28
+ if (!node.disabled) {
29
+ node.focus();
30
+ }
31
+ }
32
+
33
+ module.exports = focusNode;