react 0.14.0-alpha1 → 0.14.0-beta2

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 (195) hide show
  1. package/README.md +5 -2
  2. package/addons.js +5 -2
  3. package/dist/JSXTransformer.js +634 -274
  4. package/dist/react-with-addons.js +5376 -4800
  5. package/dist/react-with-addons.min.js +6 -6
  6. package/dist/react.js +5175 -4626
  7. package/dist/react.min.js +6 -5
  8. package/lib/{AutoFocusMixin.js → AutoFocusUtils.js} +15 -5
  9. package/lib/BeforeInputEventPlugin.js +13 -13
  10. package/lib/CSSProperty.js +3 -0
  11. package/lib/CSSPropertyOperations.js +13 -13
  12. package/lib/CallbackQueue.js +4 -4
  13. package/lib/ChangeEventPlugin.js +16 -14
  14. package/lib/DOMChildrenOperations.js +10 -6
  15. package/lib/DOMProperty.js +82 -119
  16. package/lib/DOMPropertyOperations.js +78 -33
  17. package/lib/Danger.js +14 -16
  18. package/lib/DefaultEventPluginOrder.js +2 -2
  19. package/lib/EnterLeaveEventPlugin.js +8 -8
  20. package/lib/EventConstants.js +23 -1
  21. package/lib/EventPluginHub.js +13 -13
  22. package/lib/EventPluginRegistry.js +8 -8
  23. package/lib/EventPluginUtils.js +17 -17
  24. package/lib/EventPropagators.js +7 -7
  25. package/lib/FallbackCompositionState.js +3 -3
  26. package/lib/HTMLDOMPropertyConfig.js +14 -5
  27. package/lib/LinkedStateMixin.js +2 -2
  28. package/lib/LinkedValueUtils.js +50 -38
  29. package/lib/MetaMatchers.js +118 -0
  30. package/lib/OrderedMap.js +453 -0
  31. package/lib/PooledClass.js +14 -2
  32. package/lib/React.js +9 -111
  33. package/lib/ReactBrowserComponentMixin.js +4 -4
  34. package/lib/ReactBrowserEventEmitter.js +30 -7
  35. package/lib/ReactCSSTransitionGroup.js +16 -5
  36. package/lib/ReactCSSTransitionGroupChild.js +20 -11
  37. package/lib/ReactChildReconciler.js +25 -18
  38. package/lib/ReactChildren.js +24 -22
  39. package/lib/ReactClass.js +68 -86
  40. package/lib/ReactComponent.js +22 -17
  41. package/lib/ReactComponentBrowserEnvironment.js +2 -4
  42. package/lib/ReactComponentEnvironment.js +2 -2
  43. package/lib/ReactComponentWithPureRenderMixin.js +3 -3
  44. package/lib/ReactCompositeComponent.js +80 -111
  45. package/lib/ReactDOM.js +72 -158
  46. package/lib/ReactDOMButton.js +15 -26
  47. package/lib/ReactDOMComponent.js +384 -62
  48. package/lib/ReactDOMFactories.js +177 -0
  49. package/lib/ReactDOMIDOperations.js +23 -25
  50. package/lib/ReactDOMInput.js +83 -99
  51. package/lib/ReactDOMOption.js +38 -42
  52. package/lib/ReactDOMSelect.js +88 -98
  53. package/lib/ReactDOMSelection.js +3 -3
  54. package/lib/ReactDOMServer.js +24 -0
  55. package/lib/ReactDOMTextComponent.js +13 -13
  56. package/lib/ReactDOMTextarea.js +48 -61
  57. package/lib/ReactDefaultBatchingStrategy.js +4 -4
  58. package/lib/ReactDefaultInjection.js +34 -71
  59. package/lib/ReactDefaultPerf.js +7 -7
  60. package/lib/ReactDefaultPerfAnalysis.js +6 -9
  61. package/lib/ReactElement.js +35 -92
  62. package/lib/ReactElementValidator.js +53 -130
  63. package/lib/ReactEmptyComponent.js +4 -4
  64. package/lib/ReactErrorUtils.js +1 -1
  65. package/lib/ReactEventEmitterMixin.js +3 -4
  66. package/lib/ReactEventListener.js +57 -12
  67. package/lib/ReactFragment.js +22 -17
  68. package/lib/ReactInjection.js +11 -11
  69. package/lib/ReactInputSelection.js +8 -7
  70. package/lib/ReactInstanceHandles.js +12 -12
  71. package/lib/ReactIsomorphic.js +70 -0
  72. package/lib/ReactLink.js +1 -1
  73. package/lib/ReactMarkupChecksum.js +6 -2
  74. package/lib/ReactMount.js +90 -89
  75. package/lib/ReactMultiChild.js +83 -22
  76. package/lib/ReactMultiChildUpdateTypes.js +2 -1
  77. package/lib/ReactNativeComponent.js +3 -8
  78. package/lib/ReactNoopUpdateQueue.js +118 -0
  79. package/lib/ReactOwner.js +3 -3
  80. package/lib/ReactPerf.js +2 -2
  81. package/lib/ReactPropTransferer.js +3 -3
  82. package/lib/ReactPropTypeLocationNames.js +1 -1
  83. package/lib/ReactPropTypeLocations.js +1 -1
  84. package/lib/ReactPropTypes.js +72 -33
  85. package/lib/ReactReconcileTransaction.js +8 -8
  86. package/lib/ReactReconciler.js +18 -20
  87. package/lib/ReactRef.js +1 -1
  88. package/lib/ReactServerBatchingStrategy.js +23 -0
  89. package/lib/ReactServerRendering.js +22 -9
  90. package/lib/ReactServerRenderingTransaction.js +7 -7
  91. package/lib/ReactTestUtils.js +80 -58
  92. package/lib/ReactTransitionChildMapping.js +2 -2
  93. package/lib/ReactTransitionEvents.js +1 -1
  94. package/lib/ReactTransitionGroup.js +5 -6
  95. package/lib/ReactUpdateQueue.js +61 -36
  96. package/lib/ReactUpdates.js +14 -17
  97. package/lib/ReactWithAddons.js +14 -16
  98. package/lib/ResponderEventPlugin.js +514 -0
  99. package/lib/ResponderSyntheticEvent.js +40 -0
  100. package/lib/ResponderTouchHistoryStore.js +180 -0
  101. package/lib/SVGDOMPropertyConfig.js +1 -3
  102. package/lib/SelectEventPlugin.js +14 -15
  103. package/lib/SimpleEventPlugin.js +205 -29
  104. package/lib/SyntheticClipboardEvent.js +3 -3
  105. package/lib/SyntheticCompositionEvent.js +3 -3
  106. package/lib/SyntheticDragEvent.js +3 -3
  107. package/lib/SyntheticEvent.js +9 -8
  108. package/lib/SyntheticFocusEvent.js +3 -3
  109. package/lib/SyntheticInputEvent.js +3 -3
  110. package/lib/SyntheticKeyboardEvent.js +6 -6
  111. package/lib/SyntheticMouseEvent.js +5 -5
  112. package/lib/SyntheticTouchEvent.js +4 -4
  113. package/lib/SyntheticUIEvent.js +4 -4
  114. package/lib/SyntheticWheelEvent.js +3 -3
  115. package/lib/TapEventPlugin.js +119 -0
  116. package/lib/Transaction.js +16 -10
  117. package/lib/accumulate.js +44 -0
  118. package/lib/accumulateInto.js +2 -2
  119. package/lib/adler32.js +19 -9
  120. package/lib/cloneWithProps.js +12 -7
  121. package/lib/createHierarchyRenderer.js +85 -0
  122. package/lib/dangerousStyleValue.js +1 -1
  123. package/lib/deprecated.js +47 -0
  124. package/lib/findDOMNode.js +11 -12
  125. package/lib/flattenChildren.js +4 -4
  126. package/lib/forEachAccumulated.js +1 -1
  127. package/lib/getEventCharCode.js +1 -1
  128. package/lib/getEventKey.js +1 -1
  129. package/lib/getEventModifierState.js +0 -1
  130. package/lib/getTestDocument.js +28 -0
  131. package/lib/getTextContentAccessor.js +1 -1
  132. package/lib/instantiateReactComponent.js +24 -20
  133. package/lib/isEventSupported.js +1 -1
  134. package/lib/isTextInputElement.js +2 -1
  135. package/lib/joinClasses.js +1 -1
  136. package/lib/onlyChild.js +3 -3
  137. package/lib/quoteAttributeValueForBrowser.js +1 -1
  138. package/lib/reactComponentExpect.js +210 -0
  139. package/lib/renderSubtreeIntoContainer.js +1 -1
  140. package/lib/setInnerHTML.js +2 -2
  141. package/lib/setTextContent.js +3 -3
  142. package/lib/shallowCompare.js +1 -1
  143. package/lib/sliceChildren.js +51 -0
  144. package/lib/traverseAllChildren.js +24 -27
  145. package/lib/update.js +13 -13
  146. package/lib/validateDOMNesting.js +199 -100
  147. package/lib/webcomponents.js +6379 -0
  148. package/package.json +4 -6
  149. package/react.js +53 -1
  150. package/addons/CSSTransitionGroup.js +0 -1
  151. package/addons/LinkedStateMixin.js +0 -1
  152. package/addons/Perf.js +0 -1
  153. package/addons/PureRenderMixin.js +0 -1
  154. package/addons/TestUtils.js +0 -1
  155. package/addons/TransitionGroup.js +0 -1
  156. package/addons/batchedUpdates.js +0 -1
  157. package/addons/cloneWithProps.js +0 -1
  158. package/addons/createFragment.js +0 -1
  159. package/addons/renderSubtreeIntoContainer.js +0 -1
  160. package/addons/shallowCompare.js +0 -1
  161. package/addons/update.js +0 -1
  162. package/lib/CSSCore.js +0 -97
  163. package/lib/EventListener.js +0 -84
  164. package/lib/ExecutionEnvironment.js +0 -38
  165. package/lib/LocalEventTrapMixin.js +0 -46
  166. package/lib/ReactContext.js +0 -32
  167. package/lib/ReactDOMForm.js +0 -47
  168. package/lib/ReactDOMIframe.js +0 -43
  169. package/lib/ReactDOMImg.js +0 -44
  170. package/lib/ReactLifeCycle.js +0 -35
  171. package/lib/camelize.js +0 -32
  172. package/lib/camelizeStyleName.js +0 -40
  173. package/lib/containsNode.js +0 -55
  174. package/lib/createArrayFromMixed.js +0 -85
  175. package/lib/createFullPageComponent.js +0 -51
  176. package/lib/createNodesFromMarkup.js +0 -84
  177. package/lib/emptyFunction.js +0 -38
  178. package/lib/emptyObject.js +0 -20
  179. package/lib/focusNode.js +0 -26
  180. package/lib/getActiveElement.js +0 -29
  181. package/lib/getMarkupWrap.js +0 -115
  182. package/lib/getUnboundedScrollPosition.js +0 -38
  183. package/lib/hyphenate.js +0 -33
  184. package/lib/hyphenateStyleName.js +0 -39
  185. package/lib/invariant.js +0 -49
  186. package/lib/isNode.js +0 -23
  187. package/lib/isTextNode.js +0 -25
  188. package/lib/keyMirror.js +0 -48
  189. package/lib/keyOf.js +0 -35
  190. package/lib/mapObject.js +0 -51
  191. package/lib/performance.js +0 -23
  192. package/lib/performanceNow.js +0 -28
  193. package/lib/shallowEqual.js +0 -48
  194. package/lib/toArray.js +0 -57
  195. package/lib/warning.js +0 -61
@@ -11,13 +11,13 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var ReactElement = require("./ReactElement");
15
- var ReactFragment = require("./ReactFragment");
16
- var ReactInstanceHandles = require("./ReactInstanceHandles");
14
+ var ReactElement = require('./ReactElement');
15
+ var ReactFragment = require('./ReactFragment');
16
+ var ReactInstanceHandles = require('./ReactInstanceHandles');
17
17
 
18
- var getIteratorFn = require("./getIteratorFn");
19
- var invariant = require("./invariant");
20
- var warning = require("./warning");
18
+ var getIteratorFn = require('./getIteratorFn');
19
+ var invariant = require('fbjs/lib/invariant');
20
+ var warning = require('fbjs/lib/warning');
21
21
 
22
22
  var SEPARATOR = ReactInstanceHandles.SEPARATOR;
23
23
  var SUBSEPARATOR = ':';
@@ -60,7 +60,7 @@ function getComponentKey(component, index) {
60
60
  /**
61
61
  * Escape a component key so that it is safe to use in a reactid.
62
62
  *
63
- * @param {*} key Component key to be escaped.
63
+ * @param {*} text Component key to be escaped.
64
64
  * @return {string} An escaped string.
65
65
  */
66
66
  function escapeUserProvidedKey(text) {
@@ -81,13 +81,12 @@ function wrapUserProvidedKey(key) {
81
81
  /**
82
82
  * @param {?*} children Children tree container.
83
83
  * @param {!string} nameSoFar Name of the key path so far.
84
- * @param {!number} indexSoFar Number of children encountered until this point.
85
84
  * @param {!function} callback Callback to invoke with each child found.
86
85
  * @param {?*} traverseContext Used to pass information throughout the traversal
87
86
  * process.
88
87
  * @return {!number} The number of children in this subtree.
89
88
  */
90
- function traverseAllChildrenImpl(children, nameSoFar, indexSoFar, callback, traverseContext) {
89
+ function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
91
90
  var type = typeof children;
92
91
 
93
92
  if (type === 'undefined' || type === 'boolean') {
@@ -99,19 +98,20 @@ function traverseAllChildrenImpl(children, nameSoFar, indexSoFar, callback, trav
99
98
  callback(traverseContext, children,
100
99
  // If it's the only child, treat the name as if it was wrapped in an array
101
100
  // so that it's consistent if the number of children grows.
102
- nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar, indexSoFar);
101
+ nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
103
102
  return 1;
104
103
  }
105
104
 
106
- var child, nextName, nextIndex;
105
+ var child;
106
+ var nextName;
107
107
  var subtreeCount = 0; // Count of children found in the current subtree.
108
+ var nextNamePrefix = nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR;
108
109
 
109
110
  if (Array.isArray(children)) {
110
111
  for (var i = 0; i < children.length; i++) {
111
112
  child = children[i];
112
- nextName = (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + getComponentKey(child, i);
113
- nextIndex = indexSoFar + subtreeCount;
114
- subtreeCount += traverseAllChildrenImpl(child, nextName, nextIndex, callback, traverseContext);
113
+ nextName = nextNamePrefix + getComponentKey(child, i);
114
+ subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
115
115
  }
116
116
  } else {
117
117
  var iteratorFn = getIteratorFn(children);
@@ -122,13 +122,12 @@ function traverseAllChildrenImpl(children, nameSoFar, indexSoFar, callback, trav
122
122
  var ii = 0;
123
123
  while (!(step = iterator.next()).done) {
124
124
  child = step.value;
125
- nextName = (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + getComponentKey(child, ii++);
126
- nextIndex = indexSoFar + subtreeCount;
127
- subtreeCount += traverseAllChildrenImpl(child, nextName, nextIndex, callback, traverseContext);
125
+ nextName = nextNamePrefix + getComponentKey(child, ii++);
126
+ subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
128
127
  }
129
128
  } else {
130
- if ('production' !== process.env.NODE_ENV) {
131
- 'production' !== process.env.NODE_ENV ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : null;
129
+ if (process.env.NODE_ENV !== 'production') {
130
+ process.env.NODE_ENV !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : undefined;
132
131
  didWarnAboutMaps = true;
133
132
  }
134
133
  // Iterator will provide entry [k,v] tuples rather than values.
@@ -136,21 +135,19 @@ function traverseAllChildrenImpl(children, nameSoFar, indexSoFar, callback, trav
136
135
  var entry = step.value;
137
136
  if (entry) {
138
137
  child = entry[1];
139
- nextName = (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + wrapUserProvidedKey(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);
140
- nextIndex = indexSoFar + subtreeCount;
141
- subtreeCount += traverseAllChildrenImpl(child, nextName, nextIndex, callback, traverseContext);
138
+ nextName = nextNamePrefix + wrapUserProvidedKey(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);
139
+ subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
142
140
  }
143
141
  }
144
142
  }
145
143
  } else if (type === 'object') {
146
- 'production' !== process.env.NODE_ENV ? invariant(children.nodeType !== 1, 'traverseAllChildren(...): Encountered an invalid child; DOM ' + 'elements are not valid children of React components.') : invariant(children.nodeType !== 1);
144
+ !(children.nodeType !== 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'traverseAllChildren(...): Encountered an invalid child; DOM ' + 'elements are not valid children of React components.') : invariant(false) : undefined;
147
145
  var fragment = ReactFragment.extract(children);
148
146
  for (var key in fragment) {
149
147
  if (fragment.hasOwnProperty(key)) {
150
148
  child = fragment[key];
151
- nextName = (nameSoFar !== '' ? nameSoFar + SUBSEPARATOR : SEPARATOR) + wrapUserProvidedKey(key) + SUBSEPARATOR + getComponentKey(child, 0);
152
- nextIndex = indexSoFar + subtreeCount;
153
- subtreeCount += traverseAllChildrenImpl(child, nextName, nextIndex, callback, traverseContext);
149
+ nextName = nextNamePrefix + wrapUserProvidedKey(key) + SUBSEPARATOR + getComponentKey(child, 0);
150
+ subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
154
151
  }
155
152
  }
156
153
  }
@@ -180,7 +177,7 @@ function traverseAllChildren(children, callback, traverseContext) {
180
177
  return 0;
181
178
  }
182
179
 
183
- return traverseAllChildrenImpl(children, '', 0, callback, traverseContext);
180
+ return traverseAllChildrenImpl(children, '', callback, traverseContext);
184
181
  }
185
182
 
186
183
  module.exports = traverseAllChildren;
package/lib/update.js CHANGED
@@ -13,9 +13,9 @@
13
13
 
14
14
  'use strict';
15
15
 
16
- var assign = require("./Object.assign");
17
- var keyOf = require("./keyOf");
18
- var invariant = require("./invariant");
16
+ var assign = require('./Object.assign');
17
+ var keyOf = require('fbjs/lib/keyOf');
18
+ var invariant = require('fbjs/lib/invariant');
19
19
  var hasOwnProperty = ({}).hasOwnProperty;
20
20
 
21
21
  function shallowCopy(x) {
@@ -44,16 +44,16 @@ ALL_COMMANDS_LIST.forEach(function (command) {
44
44
  });
45
45
 
46
46
  function invariantArrayCase(value, spec, command) {
47
- 'production' !== process.env.NODE_ENV ? invariant(Array.isArray(value), 'update(): expected target of %s to be an array; got %s.', command, value) : invariant(Array.isArray(value));
47
+ !Array.isArray(value) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): expected target of %s to be an array; got %s.', command, value) : invariant(false) : undefined;
48
48
  var specValue = spec[command];
49
- 'production' !== process.env.NODE_ENV ? invariant(Array.isArray(specValue), 'update(): expected spec of %s to be an array; got %s. ' + 'Did you forget to wrap your parameter in an array?', command, specValue) : invariant(Array.isArray(specValue));
49
+ !Array.isArray(specValue) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): expected spec of %s to be an array; got %s. ' + 'Did you forget to wrap your parameter in an array?', command, specValue) : invariant(false) : undefined;
50
50
  }
51
51
 
52
52
  function update(value, spec) {
53
- 'production' !== process.env.NODE_ENV ? invariant(typeof spec === 'object', 'update(): You provided a key path to update() that did not contain one ' + 'of %s. Did you forget to include {%s: ...}?', ALL_COMMANDS_LIST.join(', '), COMMAND_SET) : invariant(typeof spec === 'object');
53
+ !(typeof spec === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): You provided a key path to update() that did not contain one ' + 'of %s. Did you forget to include {%s: ...}?', ALL_COMMANDS_LIST.join(', '), COMMAND_SET) : invariant(false) : undefined;
54
54
 
55
55
  if (hasOwnProperty.call(spec, COMMAND_SET)) {
56
- 'production' !== process.env.NODE_ENV ? invariant(Object.keys(spec).length === 1, 'Cannot have more than one key in an object with %s', COMMAND_SET) : invariant(Object.keys(spec).length === 1);
56
+ !(Object.keys(spec).length === 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot have more than one key in an object with %s', COMMAND_SET) : invariant(false) : undefined;
57
57
 
58
58
  return spec[COMMAND_SET];
59
59
  }
@@ -62,8 +62,8 @@ function update(value, spec) {
62
62
 
63
63
  if (hasOwnProperty.call(spec, COMMAND_MERGE)) {
64
64
  var mergeObj = spec[COMMAND_MERGE];
65
- 'production' !== process.env.NODE_ENV ? invariant(mergeObj && typeof mergeObj === 'object', 'update(): %s expects a spec of type \'object\'; got %s', COMMAND_MERGE, mergeObj) : invariant(mergeObj && typeof mergeObj === 'object');
66
- 'production' !== process.env.NODE_ENV ? invariant(nextValue && typeof nextValue === 'object', 'update(): %s expects a target of type \'object\'; got %s', COMMAND_MERGE, nextValue) : invariant(nextValue && typeof nextValue === 'object');
65
+ !(mergeObj && typeof mergeObj === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): %s expects a spec of type \'object\'; got %s', COMMAND_MERGE, mergeObj) : invariant(false) : undefined;
66
+ !(nextValue && typeof nextValue === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): %s expects a target of type \'object\'; got %s', COMMAND_MERGE, nextValue) : invariant(false) : undefined;
67
67
  assign(nextValue, spec[COMMAND_MERGE]);
68
68
  }
69
69
 
@@ -82,16 +82,16 @@ function update(value, spec) {
82
82
  }
83
83
 
84
84
  if (hasOwnProperty.call(spec, COMMAND_SPLICE)) {
85
- 'production' !== process.env.NODE_ENV ? invariant(Array.isArray(value), 'Expected %s target to be an array; got %s', COMMAND_SPLICE, value) : invariant(Array.isArray(value));
86
- 'production' !== process.env.NODE_ENV ? invariant(Array.isArray(spec[COMMAND_SPLICE]), 'update(): expected spec of %s to be an array of arrays; got %s. ' + 'Did you forget to wrap your parameters in an array?', COMMAND_SPLICE, spec[COMMAND_SPLICE]) : invariant(Array.isArray(spec[COMMAND_SPLICE]));
85
+ !Array.isArray(value) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected %s target to be an array; got %s', COMMAND_SPLICE, value) : invariant(false) : undefined;
86
+ !Array.isArray(spec[COMMAND_SPLICE]) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): expected spec of %s to be an array of arrays; got %s. ' + 'Did you forget to wrap your parameters in an array?', COMMAND_SPLICE, spec[COMMAND_SPLICE]) : invariant(false) : undefined;
87
87
  spec[COMMAND_SPLICE].forEach(function (args) {
88
- 'production' !== process.env.NODE_ENV ? invariant(Array.isArray(args), 'update(): expected spec of %s to be an array of arrays; got %s. ' + 'Did you forget to wrap your parameters in an array?', COMMAND_SPLICE, spec[COMMAND_SPLICE]) : invariant(Array.isArray(args));
88
+ !Array.isArray(args) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): expected spec of %s to be an array of arrays; got %s. ' + 'Did you forget to wrap your parameters in an array?', COMMAND_SPLICE, spec[COMMAND_SPLICE]) : invariant(false) : undefined;
89
89
  nextValue.splice.apply(nextValue, args);
90
90
  });
91
91
  }
92
92
 
93
93
  if (hasOwnProperty.call(spec, COMMAND_APPLY)) {
94
- 'production' !== process.env.NODE_ENV ? invariant(typeof spec[COMMAND_APPLY] === 'function', 'update(): expected spec of %s to be a function; got %s.', COMMAND_APPLY, spec[COMMAND_APPLY]) : invariant(typeof spec[COMMAND_APPLY] === 'function');
94
+ !(typeof spec[COMMAND_APPLY] === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'update(): expected spec of %s to be a function; got %s.', COMMAND_APPLY, spec[COMMAND_APPLY]) : invariant(false) : undefined;
95
95
  nextValue = spec[COMMAND_APPLY](nextValue);
96
96
  }
97
97
 
@@ -11,12 +11,13 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var emptyFunction = require("./emptyFunction");
15
- var warning = require("./warning");
14
+ var assign = require('./Object.assign');
15
+ var emptyFunction = require('fbjs/lib/emptyFunction');
16
+ var warning = require('fbjs/lib/warning');
16
17
 
17
18
  var validateDOMNesting = emptyFunction;
18
19
 
19
- if ('production' !== process.env.NODE_ENV) {
20
+ if (process.env.NODE_ENV !== 'production') {
20
21
  // This validation code was written based on the HTML5 parsing spec:
21
22
  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
22
23
  //
@@ -31,81 +32,86 @@ if ('production' !== process.env.NODE_ENV) {
31
32
  // https://html.spec.whatwg.org/multipage/syntax.html#special
32
33
  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];
33
34
 
34
- /**
35
- * Return whether `stack` contains `tag` and the last occurrence of `tag` is
36
- * deeper than any element in the `scope` array.
37
- *
38
- * https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-the-specific-scope
39
- *
40
- * Examples:
41
- * stackHasTagInSpecificScope(['p', 'quote'], 'p', ['button']) is true
42
- * stackHasTagInSpecificScope(['p', 'button'], 'p', ['button']) is false
43
- *
44
- * @param {Array<string>} stack
45
- * @param {string} tag
46
- * @param {Array<string>} scope
47
- */
48
- var stackHasTagInSpecificScope = function (stack, tag, scope) {
49
- for (var i = stack.length - 1; i >= 0; i--) {
50
- if (stack[i] === tag) {
51
- return true;
52
- }
53
- if (scope.indexOf(stack[i]) !== -1) {
54
- return false;
55
- }
56
- }
57
- return false;
58
- };
59
-
60
35
  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
61
36
  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
62
37
 
63
38
  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
64
- // TODO: Distinguish by namespace here
39
+ // TODO: Distinguish by namespace here -- for <title>, including it here
40
+ // errs on the side of fewer warnings
65
41
  'foreignObject', 'desc', 'title'];
66
- var stackHasTagInScope = function (stack, tag) {
67
- return stackHasTagInSpecificScope(stack, tag, inScopeTags);
68
- };
69
42
 
70
43
  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
71
44
  var buttonScopeTags = inScopeTags.concat(['button']);
72
- var stackHasTagInButtonScope = function (stack, tag) {
73
- return stackHasTagInSpecificScope(stack, tag, buttonScopeTags);
45
+
46
+ // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
47
+ var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
48
+
49
+ var emptyAncestorInfo = {
50
+ parentTag: null,
51
+
52
+ formTag: null,
53
+ aTagInScope: null,
54
+ buttonTagInScope: null,
55
+ nobrTagInScope: null,
56
+ pTagInButtonScope: null,
57
+
58
+ listItemTagAutoclosing: null,
59
+ dlItemTagAutoclosing: null
74
60
  };
75
61
 
76
- // See rules for 'li', 'dd', 'dt' start tags in
77
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
78
- var listItemTagAllowed = function (tags, stack) {
79
- // tags is ['li'] or ['dd, 'dt']
80
- for (var i = stack.length - 1; i >= 0; i--) {
81
- if (tags.indexOf(stack[i]) !== -1) {
82
- return false;
83
- } else if (specialTags.indexOf(stack[i]) !== -1 && stack[i] !== 'address' && stack[i] !== 'div' && stack[i] !== 'p') {
84
- return true;
85
- }
62
+ var updatedAncestorInfo = function (oldInfo, tag, instance) {
63
+ var ancestorInfo = assign({}, oldInfo || emptyAncestorInfo);
64
+ var info = { tag: tag, instance: instance };
65
+
66
+ if (inScopeTags.indexOf(tag) !== -1) {
67
+ ancestorInfo.aTagInScope = null;
68
+ ancestorInfo.buttonTagInScope = null;
69
+ ancestorInfo.nobrTagInScope = null;
70
+ }
71
+ if (buttonScopeTags.indexOf(tag) !== -1) {
72
+ ancestorInfo.pTagInButtonScope = null;
86
73
  }
87
- return true;
88
- };
89
74
 
90
- // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
91
- var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
75
+ // See rules for 'li', 'dd', 'dt' start tags in
76
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
77
+ if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
78
+ ancestorInfo.listItemTagAutoclosing = null;
79
+ ancestorInfo.dlItemTagAutoclosing = null;
80
+ }
81
+
82
+ ancestorInfo.parentTag = info;
83
+
84
+ if (tag === 'form') {
85
+ ancestorInfo.formTag = info;
86
+ }
87
+ if (tag === 'a') {
88
+ ancestorInfo.aTagInScope = info;
89
+ }
90
+ if (tag === 'button') {
91
+ ancestorInfo.buttonTagInScope = info;
92
+ }
93
+ if (tag === 'nobr') {
94
+ ancestorInfo.nobrTagInScope = info;
95
+ }
96
+ if (tag === 'p') {
97
+ ancestorInfo.pTagInButtonScope = info;
98
+ }
99
+ if (tag === 'li') {
100
+ ancestorInfo.listItemTagAutoclosing = info;
101
+ }
102
+ if (tag === 'dd' || tag === 'dt') {
103
+ ancestorInfo.dlItemTagAutoclosing = info;
104
+ }
105
+
106
+ return ancestorInfo;
107
+ };
92
108
 
93
109
  /**
94
- * Returns whether we allow putting `tag` in the document if the current stack
95
- * of open tags is `openTagStack`.
96
- *
97
- * Examples:
98
- * isTagValidInContext('tr', [..., 'table', 'tbody']) is true
99
- * isTagValidInContext('tr', [..., 'table']) is false
100
- *
101
- * @param {string} tag Lowercase HTML tag name or node name like '#text'
102
- * @param {Array<string>} openTagStack
110
+ * Returns whether
103
111
  */
104
- var isTagValidInContext = function (tag, openTagStack) {
105
- var currentTag = openTagStack[openTagStack.length - 1];
106
-
112
+ var isTagValidWithParent = function (tag, parentTag) {
107
113
  // First, let's check if we're in an unusual parsing mode...
108
- switch (currentTag) {
114
+ switch (parentTag) {
109
115
  // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
110
116
  case 'select':
111
117
  return tag === 'option' || tag === 'optgroup' || tag === '#text';
@@ -151,6 +157,44 @@ if ('production' !== process.env.NODE_ENV) {
151
157
  // Probably in the "in body" parsing mode, so we outlaw only tag combos
152
158
  // where the parsing rules cause implicit opens or closes to be added.
153
159
  // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
160
+ switch (tag) {
161
+ case 'h1':
162
+ case 'h2':
163
+ case 'h3':
164
+ case 'h4':
165
+ case 'h5':
166
+ case 'h6':
167
+ return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
168
+
169
+ case 'rp':
170
+ case 'rt':
171
+ return impliedEndTags.indexOf(parentTag) === -1;
172
+
173
+ case 'caption':
174
+ case 'col':
175
+ case 'colgroup':
176
+ case 'frame':
177
+ case 'head':
178
+ case 'tbody':
179
+ case 'td':
180
+ case 'tfoot':
181
+ case 'th':
182
+ case 'thead':
183
+ case 'tr':
184
+ // These tags are only valid with a few parents that have special child
185
+ // parsing rules -- if we're down here, then none of those matched and
186
+ // so we allow it only if we don't know what the parent is, as all other
187
+ // cases are invalid.
188
+ return parentTag == null;
189
+ }
190
+
191
+ return true;
192
+ };
193
+
194
+ /**
195
+ * Returns whether
196
+ */
197
+ var findInvalidAncestorForTag = function (tag, ancestorInfo) {
154
198
  switch (tag) {
155
199
  case 'address':
156
200
  case 'article':
@@ -185,7 +229,6 @@ if ('production' !== process.env.NODE_ENV) {
185
229
  case 'hr':
186
230
 
187
231
  case 'xmp':
188
- return !stackHasTagInButtonScope(openTagStack, 'p');
189
232
 
190
233
  case 'h1':
191
234
  case 'h2':
@@ -193,72 +236,128 @@ if ('production' !== process.env.NODE_ENV) {
193
236
  case 'h4':
194
237
  case 'h5':
195
238
  case 'h6':
196
- return !stackHasTagInButtonScope(openTagStack, 'p') && currentTag !== 'h1' && currentTag !== 'h2' && currentTag !== 'h3' && currentTag !== 'h4' && currentTag !== 'h5' && currentTag !== 'h6';
239
+ return ancestorInfo.pTagInButtonScope;
197
240
 
198
241
  case 'form':
199
- return openTagStack.indexOf('form') === -1 && !stackHasTagInButtonScope(openTagStack, 'p');
242
+ return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
200
243
 
201
244
  case 'li':
202
- return listItemTagAllowed(['li'], openTagStack);
245
+ return ancestorInfo.listItemTagAutoclosing;
203
246
 
204
247
  case 'dd':
205
248
  case 'dt':
206
- return listItemTagAllowed(['dd', 'dt'], openTagStack);
249
+ return ancestorInfo.dlItemTagAutoclosing;
207
250
 
208
251
  case 'button':
209
- return !stackHasTagInScope(openTagStack, 'button');
252
+ return ancestorInfo.buttonTagInScope;
210
253
 
211
254
  case 'a':
212
255
  // Spec says something about storing a list of markers, but it sounds
213
256
  // equivalent to this check.
214
- return !stackHasTagInScope(openTagStack, 'a');
257
+ return ancestorInfo.aTagInScope;
215
258
 
216
259
  case 'nobr':
217
- return !stackHasTagInScope(openTagStack, 'nobr');
260
+ return ancestorInfo.nobrTagInScope;
261
+ }
218
262
 
219
- case 'rp':
220
- case 'rt':
221
- return impliedEndTags.indexOf(currentTag) === -1;
263
+ return null;
264
+ };
222
265
 
223
- case 'caption':
224
- case 'col':
225
- case 'colgroup':
226
- case 'frame':
227
- case 'head':
228
- case 'tbody':
229
- case 'td':
230
- case 'tfoot':
231
- case 'th':
232
- case 'thead':
233
- case 'tr':
234
- return currentTag === undefined;
266
+ /**
267
+ * Given a ReactCompositeComponent instance, return a list of its recursive
268
+ * owners, starting at the root and ending with the instance itself.
269
+ */
270
+ var findOwnerStack = function (instance) {
271
+ if (!instance) {
272
+ return [];
235
273
  }
236
274
 
237
- return true;
275
+ var stack = [];
276
+ /*eslint-disable space-after-keywords */
277
+ do {
278
+ /*eslint-enable space-after-keywords */
279
+ stack.push(instance);
280
+ } while (instance = instance._currentElement._owner);
281
+ stack.reverse();
282
+ return stack;
238
283
  };
239
284
 
240
- validateDOMNesting = function (parentStack, childTag, element) {
241
- if (!isTagValidInContext(childTag, parentStack)) {
242
- var info = '';
243
- var parentTag = parentStack[parentStack.length - 1];
244
- if (parentTag === 'table' && childTag === 'tr') {
245
- info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
246
- }
247
- if (element && element._owner) {
248
- var name = element._owner.getName();
249
- if (name) {
250
- info += ' Check the render method of `' + name + '`.';
285
+ var didWarn = {};
286
+
287
+ validateDOMNesting = function (childTag, childInstance, ancestorInfo) {
288
+ ancestorInfo = ancestorInfo || emptyAncestorInfo;
289
+ var parentInfo = ancestorInfo.parentTag;
290
+ var parentTag = parentInfo && parentInfo.tag;
291
+
292
+ var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
293
+ var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
294
+ var problematic = invalidParent || invalidAncestor;
295
+
296
+ if (problematic) {
297
+ var ancestorTag = problematic.tag;
298
+ var ancestorInstance = problematic.instance;
299
+
300
+ var childOwner = childInstance && childInstance._currentElement._owner;
301
+ var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;
302
+
303
+ var childOwners = findOwnerStack(childOwner);
304
+ var ancestorOwners = findOwnerStack(ancestorOwner);
305
+
306
+ var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
307
+ var i;
308
+
309
+ var deepestCommon = -1;
310
+ for (i = 0; i < minStackLen; i++) {
311
+ if (childOwners[i] === ancestorOwners[i]) {
312
+ deepestCommon = i;
313
+ } else {
314
+ break;
251
315
  }
252
316
  }
253
317
 
254
- 'production' !== process.env.NODE_ENV ? warning(false, 'validateDOMNesting(...): <%s> cannot appear as a child of <%s> ' + 'in this context (%s).%s', childTag, parentTag, parentStack.join(' > '), info) : null;
318
+ var UNKNOWN = '(unknown)';
319
+ var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
320
+ return inst.getName() || UNKNOWN;
321
+ });
322
+ var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
323
+ return inst.getName() || UNKNOWN;
324
+ });
325
+ var ownerInfo = [].concat(
326
+ // If the parent and child instances have a common owner ancestor, start
327
+ // with that -- otherwise we just start with the parent's owners.
328
+ deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
329
+ // If we're warning about an invalid (non-parent) ancestry, add '...'
330
+ invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');
331
+
332
+ var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;
333
+ if (didWarn[warnKey]) {
334
+ return;
335
+ }
336
+ didWarn[warnKey] = true;
337
+
338
+ if (invalidParent) {
339
+ var info = '';
340
+ if (ancestorTag === 'table' && childTag === 'tr') {
341
+ info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
342
+ }
343
+ process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): <%s> cannot appear as a child of <%s>. ' + 'See %s.%s', childTag, ancestorTag, ownerInfo, info) : undefined;
344
+ } else {
345
+ process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): <%s> cannot appear as a descendant of ' + '<%s>. See %s.', childTag, ancestorTag, ownerInfo) : undefined;
346
+ }
255
347
  }
256
348
  };
257
349
 
258
- validateDOMNesting.tagStackContextKey = '__validateDOMNesting_tagStack$' + Math.random().toString(36).slice(2);
350
+ validateDOMNesting.ancestorInfoContextKey = '__validateDOMNesting_ancestorInfo$' + Math.random().toString(36).slice(2);
351
+
352
+ validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;
259
353
 
260
354
  // For testing
261
- validateDOMNesting.isTagValidInContext = isTagValidInContext;
355
+ validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
356
+ ancestorInfo = ancestorInfo || emptyAncestorInfo;
357
+ var parentInfo = ancestorInfo.parentTag;
358
+ var parentTag = parentInfo && parentInfo.tag;
359
+ return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
360
+ };
262
361
  }
263
362
 
264
363
  module.exports = validateDOMNesting;