react 0.13.1 → 0.14.0-alpha2

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 (197) hide show
  1. package/README.md +1 -1
  2. package/addons.js +7 -0
  3. package/addons/CSSTransitionGroup.js +1 -0
  4. package/addons/LinkedStateMixin.js +1 -0
  5. package/addons/Perf.js +1 -0
  6. package/addons/PureRenderMixin.js +1 -0
  7. package/addons/TestUtils.js +1 -0
  8. package/addons/TransitionGroup.js +1 -0
  9. package/addons/batchedUpdates.js +1 -0
  10. package/addons/cloneWithProps.js +1 -0
  11. package/addons/createFragment.js +1 -0
  12. package/addons/renderSubtreeIntoContainer.js +1 -0
  13. package/addons/shallowCompare.js +1 -0
  14. package/addons/update.js +1 -0
  15. package/dist/JSXTransformer.js +3336 -1671
  16. package/dist/react-with-addons.js +3320 -5125
  17. package/dist/react-with-addons.min.js +6 -6
  18. package/dist/react.js +2952 -4533
  19. package/dist/react.min.js +5 -5
  20. package/lib/AutoFocusMixin.js +4 -3
  21. package/lib/BeforeInputEventPlugin.js +30 -118
  22. package/lib/CSSCore.js +12 -23
  23. package/lib/CSSProperty.js +9 -4
  24. package/lib/CSSPropertyOperations.js +14 -30
  25. package/lib/CallbackQueue.js +7 -10
  26. package/lib/ChangeEventPlugin.js +24 -88
  27. package/lib/ClientReactRootIndex.js +2 -2
  28. package/lib/DOMChildrenOperations.js +13 -33
  29. package/lib/DOMProperty.js +41 -67
  30. package/lib/DOMPropertyOperations.js +30 -51
  31. package/lib/Danger.js +19 -62
  32. package/lib/DefaultEventPluginOrder.js +2 -12
  33. package/lib/EnterLeaveEventPlugin.js +11 -33
  34. package/lib/EventConstants.js +2 -2
  35. package/lib/EventListener.js +11 -13
  36. package/lib/EventPluginHub.js +44 -47
  37. package/lib/EventPluginRegistry.js +18 -74
  38. package/lib/EventPluginUtils.js +27 -38
  39. package/lib/EventPropagators.js +23 -26
  40. package/lib/ExecutionEnvironment.js +4 -8
  41. package/lib/FallbackCompositionState.js +3 -3
  42. package/lib/HTMLDOMPropertyConfig.js +13 -20
  43. package/lib/LinkedStateMixin.js +3 -6
  44. package/lib/LinkedValueUtils.js +34 -64
  45. package/lib/LocalEventTrapMixin.js +9 -16
  46. package/lib/Object.assign.js +1 -1
  47. package/lib/PooledClass.js +8 -11
  48. package/lib/React.js +9 -129
  49. package/lib/ReactBrowserComponentMixin.js +9 -2
  50. package/lib/ReactBrowserEventEmitter.js +26 -82
  51. package/lib/ReactCSSTransitionGroup.js +13 -24
  52. package/lib/ReactCSSTransitionGroupChild.js +18 -28
  53. package/lib/ReactChildReconciler.js +11 -19
  54. package/lib/ReactChildren.js +21 -28
  55. package/lib/ReactClass.js +81 -234
  56. package/lib/ReactComponent.js +17 -33
  57. package/lib/ReactComponentBrowserEnvironment.js +4 -8
  58. package/lib/ReactComponentEnvironment.js +6 -12
  59. package/lib/ReactComponentWithPureRenderMixin.js +4 -5
  60. package/lib/ReactCompositeComponent.js +85 -297
  61. package/lib/ReactContext.js +2 -44
  62. package/lib/ReactCurrentOwner.js +1 -3
  63. package/lib/ReactDOM.js +4 -2
  64. package/lib/ReactDOMButton.js +3 -4
  65. package/lib/ReactDOMClient.js +85 -0
  66. package/lib/ReactDOMComponent.js +184 -146
  67. package/lib/ReactDOMForm.js +3 -3
  68. package/lib/ReactDOMIDOperations.js +11 -22
  69. package/lib/ReactDOMIframe.js +3 -3
  70. package/lib/ReactDOMImg.js +3 -3
  71. package/lib/ReactDOMInput.js +22 -35
  72. package/lib/ReactDOMOption.js +68 -10
  73. package/lib/ReactDOMSelect.js +50 -28
  74. package/lib/ReactDOMSelection.js +5 -20
  75. package/lib/ReactDOMServer.js +24 -0
  76. package/lib/ReactDOMTextComponent.js +17 -18
  77. package/lib/ReactDOMTextarea.js +15 -27
  78. package/lib/ReactDefaultBatchingStrategy.js +9 -13
  79. package/lib/ReactDefaultInjection.js +31 -40
  80. package/lib/ReactDefaultPerf.js +36 -69
  81. package/lib/ReactDefaultPerfAnalysis.js +8 -14
  82. package/lib/ReactElement.js +24 -57
  83. package/lib/ReactElementValidator.js +38 -105
  84. package/lib/ReactEmptyComponent.js +7 -11
  85. package/lib/ReactErrorUtils.js +2 -2
  86. package/lib/ReactEventEmitterMixin.js +3 -12
  87. package/lib/ReactEventListener.js +16 -38
  88. package/lib/ReactFragment.js +23 -54
  89. package/lib/ReactInjection.js +1 -1
  90. package/lib/ReactInputSelection.js +11 -21
  91. package/lib/ReactInstanceHandles.js +27 -57
  92. package/lib/ReactInstanceMap.js +5 -5
  93. package/lib/ReactIsomorphic.js +70 -0
  94. package/lib/ReactLifeCycle.js +1 -1
  95. package/lib/ReactLink.js +2 -4
  96. package/lib/ReactMarkupChecksum.js +5 -10
  97. package/lib/ReactMount.js +137 -260
  98. package/lib/ReactMultiChild.js +19 -45
  99. package/lib/ReactMultiChildUpdateTypes.js +1 -1
  100. package/lib/ReactNativeComponent.js +7 -11
  101. package/lib/ReactOwner.js +7 -24
  102. package/lib/ReactPerf.js +8 -12
  103. package/lib/ReactPropTransferer.js +4 -4
  104. package/lib/ReactPropTypeLocationNames.js +2 -2
  105. package/lib/ReactPropTypeLocations.js +1 -1
  106. package/lib/ReactPropTypes.js +29 -61
  107. package/lib/ReactReconcileTransaction.js +9 -34
  108. package/lib/ReactReconciler.js +9 -19
  109. package/lib/ReactRef.js +5 -8
  110. package/lib/ReactRootIndex.js +2 -2
  111. package/lib/ReactServerRendering.js +7 -15
  112. package/lib/ReactServerRenderingTransaction.js +7 -32
  113. package/lib/ReactStateSetters.js +6 -6
  114. package/lib/ReactTestUtils.js +93 -165
  115. package/lib/ReactTransitionChildMapping.js +5 -7
  116. package/lib/ReactTransitionEvents.js +5 -5
  117. package/lib/ReactTransitionGroup.js +30 -52
  118. package/lib/ReactUpdateQueue.js +27 -90
  119. package/lib/ReactUpdates.js +27 -79
  120. package/lib/ReactWithAddons.js +7 -6
  121. package/lib/SVGDOMPropertyConfig.js +41 -4
  122. package/lib/SelectEventPlugin.js +28 -29
  123. package/lib/ServerReactRootIndex.js +2 -2
  124. package/lib/SimpleEventPlugin.js +136 -128
  125. package/lib/SyntheticClipboardEvent.js +3 -7
  126. package/lib/SyntheticCompositionEvent.js +3 -9
  127. package/lib/SyntheticDragEvent.js +1 -1
  128. package/lib/SyntheticEvent.js +8 -10
  129. package/lib/SyntheticFocusEvent.js +1 -1
  130. package/lib/SyntheticInputEvent.js +3 -9
  131. package/lib/SyntheticKeyboardEvent.js +4 -4
  132. package/lib/SyntheticMouseEvent.js +8 -14
  133. package/lib/SyntheticTouchEvent.js +1 -1
  134. package/lib/SyntheticUIEvent.js +3 -3
  135. package/lib/SyntheticWheelEvent.js +11 -15
  136. package/lib/Transaction.js +12 -24
  137. package/lib/ViewportMetrics.js +2 -2
  138. package/lib/accumulateInto.js +2 -5
  139. package/lib/adler32.js +2 -4
  140. package/lib/camelize.js +4 -2
  141. package/lib/camelizeStyleName.js +2 -2
  142. package/lib/cloneWithProps.js +5 -11
  143. package/lib/containsNode.js +29 -16
  144. package/lib/createArrayFromMixed.js +17 -16
  145. package/lib/createFullPageComponent.js +4 -11
  146. package/lib/createNodesFromMarkup.js +6 -8
  147. package/lib/dangerousStyleValue.js +2 -3
  148. package/lib/emptyFunction.js +10 -4
  149. package/lib/emptyObject.js +1 -1
  150. package/lib/escapeTextContentForBrowser.js +1 -1
  151. package/lib/findDOMNode.js +5 -24
  152. package/lib/flattenChildren.js +4 -10
  153. package/lib/focusNode.js +2 -3
  154. package/lib/forEachAccumulated.js +2 -2
  155. package/lib/getActiveElement.js +4 -2
  156. package/lib/getEventCharCode.js +1 -1
  157. package/lib/getEventKey.js +1 -1
  158. package/lib/getEventModifierState.js +1 -1
  159. package/lib/getEventTarget.js +1 -1
  160. package/lib/getIteratorFn.js +2 -4
  161. package/lib/getMarkupWrap.js +7 -5
  162. package/lib/getNodeForCharacterOffset.js +1 -1
  163. package/lib/getTextContentAccessor.js +2 -4
  164. package/lib/getUnboundedScrollPosition.js +1 -1
  165. package/lib/hyphenate.js +3 -1
  166. package/lib/hyphenateStyleName.js +2 -2
  167. package/lib/instantiateReactComponent.js +14 -37
  168. package/lib/invariant.js +8 -12
  169. package/lib/isEventSupported.js +7 -10
  170. package/lib/isNode.js +4 -6
  171. package/lib/isTextInputElement.js +2 -4
  172. package/lib/isTextNode.js +3 -1
  173. package/lib/joinClasses.js +2 -2
  174. package/lib/keyMirror.js +3 -6
  175. package/lib/keyOf.js +4 -3
  176. package/lib/mapObject.js +1 -1
  177. package/lib/memoizeStringOnly.js +2 -2
  178. package/lib/onlyChild.js +2 -5
  179. package/lib/performance.js +2 -5
  180. package/lib/performanceNow.js +3 -1
  181. package/lib/quoteAttributeValueForBrowser.js +1 -1
  182. package/lib/renderSubtreeIntoContainer.js +16 -0
  183. package/lib/setInnerHTML.js +11 -8
  184. package/lib/setTextContent.js +3 -3
  185. package/lib/shallowCompare.js +24 -0
  186. package/lib/shallowEqual.js +17 -11
  187. package/lib/shouldUpdateReactComponent.js +3 -64
  188. package/lib/toArray.js +8 -19
  189. package/lib/traverseAllChildren.js +22 -89
  190. package/lib/update.js +33 -90
  191. package/lib/validateDOMNesting.js +355 -0
  192. package/lib/warning.js +17 -15
  193. package/package.json +3 -3
  194. package/lib/MobileSafariClickEventPlugin.js +0 -56
  195. package/lib/ReactPutListenerQueue.js +0 -54
  196. package/lib/cx.js +0 -52
  197. package/lib/getReactRootElementInContainer.js +0 -33
package/lib/update.js CHANGED
@@ -9,11 +9,14 @@
9
9
  * @providesModule update
10
10
  */
11
11
 
12
+ /* global hasOwnProperty:true */
13
+
12
14
  'use strict';
13
15
 
14
16
  var assign = require("./Object.assign");
15
17
  var keyOf = require("./keyOf");
16
18
  var invariant = require("./invariant");
19
+ var hasOwnProperty = ({}).hasOwnProperty;
17
20
 
18
21
  function shallowCopy(x) {
19
22
  if (Array.isArray(x)) {
@@ -25,130 +28,70 @@ function shallowCopy(x) {
25
28
  }
26
29
  }
27
30
 
28
- var COMMAND_PUSH = keyOf({$push: null});
29
- var COMMAND_UNSHIFT = keyOf({$unshift: null});
30
- var COMMAND_SPLICE = keyOf({$splice: null});
31
- var COMMAND_SET = keyOf({$set: null});
32
- var COMMAND_MERGE = keyOf({$merge: null});
33
- var COMMAND_APPLY = keyOf({$apply: null});
34
-
35
- var ALL_COMMANDS_LIST = [
36
- COMMAND_PUSH,
37
- COMMAND_UNSHIFT,
38
- COMMAND_SPLICE,
39
- COMMAND_SET,
40
- COMMAND_MERGE,
41
- COMMAND_APPLY
42
- ];
31
+ var COMMAND_PUSH = keyOf({ $push: null });
32
+ var COMMAND_UNSHIFT = keyOf({ $unshift: null });
33
+ var COMMAND_SPLICE = keyOf({ $splice: null });
34
+ var COMMAND_SET = keyOf({ $set: null });
35
+ var COMMAND_MERGE = keyOf({ $merge: null });
36
+ var COMMAND_APPLY = keyOf({ $apply: null });
37
+
38
+ var ALL_COMMANDS_LIST = [COMMAND_PUSH, COMMAND_UNSHIFT, COMMAND_SPLICE, COMMAND_SET, COMMAND_MERGE, COMMAND_APPLY];
43
39
 
44
40
  var ALL_COMMANDS_SET = {};
45
41
 
46
- ALL_COMMANDS_LIST.forEach(function(command) {
42
+ ALL_COMMANDS_LIST.forEach(function (command) {
47
43
  ALL_COMMANDS_SET[command] = true;
48
44
  });
49
45
 
50
46
  function invariantArrayCase(value, spec, command) {
51
- ("production" !== process.env.NODE_ENV ? invariant(
52
- Array.isArray(value),
53
- 'update(): expected target of %s to be an array; got %s.',
54
- command,
55
- value
56
- ) : invariant(Array.isArray(value)));
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));
57
48
  var specValue = spec[command];
58
- ("production" !== process.env.NODE_ENV ? invariant(
59
- Array.isArray(specValue),
60
- 'update(): expected spec of %s to be an array; got %s. ' +
61
- 'Did you forget to wrap your parameter in an array?',
62
- command,
63
- specValue
64
- ) : invariant(Array.isArray(specValue)));
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));
65
50
  }
66
51
 
67
52
  function update(value, spec) {
68
- ("production" !== process.env.NODE_ENV ? invariant(
69
- typeof spec === 'object',
70
- 'update(): You provided a key path to update() that did not contain one ' +
71
- 'of %s. Did you forget to include {%s: ...}?',
72
- ALL_COMMANDS_LIST.join(', '),
73
- COMMAND_SET
74
- ) : invariant(typeof spec === 'object'));
75
-
76
- if (spec.hasOwnProperty(COMMAND_SET)) {
77
- ("production" !== process.env.NODE_ENV ? invariant(
78
- Object.keys(spec).length === 1,
79
- 'Cannot have more than one key in an object with %s',
80
- COMMAND_SET
81
- ) : invariant(Object.keys(spec).length === 1));
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');
54
+
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);
82
57
 
83
58
  return spec[COMMAND_SET];
84
59
  }
85
60
 
86
61
  var nextValue = shallowCopy(value);
87
62
 
88
- if (spec.hasOwnProperty(COMMAND_MERGE)) {
63
+ if (hasOwnProperty.call(spec, COMMAND_MERGE)) {
89
64
  var mergeObj = spec[COMMAND_MERGE];
90
- ("production" !== process.env.NODE_ENV ? invariant(
91
- mergeObj && typeof mergeObj === 'object',
92
- 'update(): %s expects a spec of type \'object\'; got %s',
93
- COMMAND_MERGE,
94
- mergeObj
95
- ) : invariant(mergeObj && typeof mergeObj === 'object'));
96
- ("production" !== process.env.NODE_ENV ? invariant(
97
- nextValue && typeof nextValue === 'object',
98
- 'update(): %s expects a target of type \'object\'; got %s',
99
- COMMAND_MERGE,
100
- nextValue
101
- ) : invariant(nextValue && typeof nextValue === 'object'));
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');
102
67
  assign(nextValue, spec[COMMAND_MERGE]);
103
68
  }
104
69
 
105
- if (spec.hasOwnProperty(COMMAND_PUSH)) {
70
+ if (hasOwnProperty.call(spec, COMMAND_PUSH)) {
106
71
  invariantArrayCase(value, spec, COMMAND_PUSH);
107
- spec[COMMAND_PUSH].forEach(function(item) {
72
+ spec[COMMAND_PUSH].forEach(function (item) {
108
73
  nextValue.push(item);
109
74
  });
110
75
  }
111
76
 
112
- if (spec.hasOwnProperty(COMMAND_UNSHIFT)) {
77
+ if (hasOwnProperty.call(spec, COMMAND_UNSHIFT)) {
113
78
  invariantArrayCase(value, spec, COMMAND_UNSHIFT);
114
- spec[COMMAND_UNSHIFT].forEach(function(item) {
79
+ spec[COMMAND_UNSHIFT].forEach(function (item) {
115
80
  nextValue.unshift(item);
116
81
  });
117
82
  }
118
83
 
119
- if (spec.hasOwnProperty(COMMAND_SPLICE)) {
120
- ("production" !== process.env.NODE_ENV ? invariant(
121
- Array.isArray(value),
122
- 'Expected %s target to be an array; got %s',
123
- COMMAND_SPLICE,
124
- value
125
- ) : invariant(Array.isArray(value)));
126
- ("production" !== process.env.NODE_ENV ? invariant(
127
- Array.isArray(spec[COMMAND_SPLICE]),
128
- 'update(): expected spec of %s to be an array of arrays; got %s. ' +
129
- 'Did you forget to wrap your parameters in an array?',
130
- COMMAND_SPLICE,
131
- spec[COMMAND_SPLICE]
132
- ) : invariant(Array.isArray(spec[COMMAND_SPLICE])));
133
- spec[COMMAND_SPLICE].forEach(function(args) {
134
- ("production" !== process.env.NODE_ENV ? invariant(
135
- Array.isArray(args),
136
- 'update(): expected spec of %s to be an array of arrays; got %s. ' +
137
- 'Did you forget to wrap your parameters in an array?',
138
- COMMAND_SPLICE,
139
- spec[COMMAND_SPLICE]
140
- ) : invariant(Array.isArray(args)));
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]));
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));
141
89
  nextValue.splice.apply(nextValue, args);
142
90
  });
143
91
  }
144
92
 
145
- if (spec.hasOwnProperty(COMMAND_APPLY)) {
146
- ("production" !== process.env.NODE_ENV ? invariant(
147
- typeof spec[COMMAND_APPLY] === 'function',
148
- 'update(): expected spec of %s to be a function; got %s.',
149
- COMMAND_APPLY,
150
- spec[COMMAND_APPLY]
151
- ) : invariant(typeof spec[COMMAND_APPLY] === 'function'));
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');
152
95
  nextValue = spec[COMMAND_APPLY](nextValue);
153
96
  }
154
97
 
@@ -161,4 +104,4 @@ function update(value, spec) {
161
104
  return nextValue;
162
105
  }
163
106
 
164
- module.exports = update;
107
+ module.exports = update;
@@ -0,0 +1,355 @@
1
+ /**
2
+ * Copyright 2015, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule validateDOMNesting
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ var assign = require("./Object.assign");
15
+ var emptyFunction = require("./emptyFunction");
16
+ var warning = require("./warning");
17
+
18
+ var validateDOMNesting = emptyFunction;
19
+
20
+ if ('production' !== process.env.NODE_ENV) {
21
+ // This validation code was written based on the HTML5 parsing spec:
22
+ // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
23
+ //
24
+ // Note: this does not catch all invalid nesting, nor does it try to (as it's
25
+ // not clear what practical benefit doing so provides); instead, we warn only
26
+ // for cases where the parser will give a parse tree differing from what React
27
+ // intended. For example, <b><div></div></b> is invalid but we don't warn
28
+ // because it still parses correctly; we do warn for other cases like nested
29
+ // <p> tags where the beginning of the second element implicitly closes the
30
+ // first, causing a confusing mess.
31
+
32
+ // https://html.spec.whatwg.org/multipage/syntax.html#special
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'];
34
+
35
+ // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
36
+ var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
37
+
38
+ // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
39
+ // TODO: Distinguish by namespace here -- for <title>, including it here
40
+ // errs on the side of fewer warnings
41
+ 'foreignObject', 'desc', 'title'];
42
+
43
+ // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
44
+ var buttonScopeTags = inScopeTags.concat(['button']);
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
60
+ };
61
+
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;
73
+ }
74
+
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
+ };
108
+
109
+ /**
110
+ * Returns whether
111
+ */
112
+ var isTagValidWithParent = function (tag, parentTag) {
113
+ // First, let's check if we're in an unusual parsing mode...
114
+ switch (parentTag) {
115
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
116
+ case 'select':
117
+ return tag === 'option' || tag === 'optgroup' || tag === '#text';
118
+ case 'optgroup':
119
+ return tag === 'option' || tag === '#text';
120
+ // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
121
+ // but
122
+ case 'option':
123
+ return tag === '#text';
124
+
125
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
126
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
127
+ // No special behavior since these rules fall back to "in body" mode for
128
+ // all except special table nodes which cause bad parsing behavior anyway.
129
+
130
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
131
+ case 'tr':
132
+ return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
133
+
134
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
135
+ case 'tbody':
136
+ case 'thead':
137
+ case 'tfoot':
138
+ return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
139
+
140
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
141
+ case 'colgroup':
142
+ return tag === 'col' || tag === 'template';
143
+
144
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
145
+ case 'table':
146
+ return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
147
+
148
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
149
+ case 'head':
150
+ return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
151
+
152
+ // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
153
+ case 'html':
154
+ return tag === 'head' || tag === 'body';
155
+ }
156
+
157
+ // Probably in the "in body" parsing mode, so we outlaw only tag combos
158
+ // where the parsing rules cause implicit opens or closes to be added.
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) {
198
+ switch (tag) {
199
+ case 'address':
200
+ case 'article':
201
+ case 'aside':
202
+ case 'blockquote':
203
+ case 'center':
204
+ case 'details':
205
+ case 'dialog':
206
+ case 'dir':
207
+ case 'div':
208
+ case 'dl':
209
+ case 'fieldset':
210
+ case 'figcaption':
211
+ case 'figure':
212
+ case 'footer':
213
+ case 'header':
214
+ case 'hgroup':
215
+ case 'main':
216
+ case 'menu':
217
+ case 'nav':
218
+ case 'ol':
219
+ case 'p':
220
+ case 'section':
221
+ case 'summary':
222
+ case 'ul':
223
+
224
+ case 'pre':
225
+ case 'listing':
226
+
227
+ case 'table':
228
+
229
+ case 'hr':
230
+
231
+ case 'xmp':
232
+
233
+ case 'h1':
234
+ case 'h2':
235
+ case 'h3':
236
+ case 'h4':
237
+ case 'h5':
238
+ case 'h6':
239
+ return ancestorInfo.pTagInButtonScope;
240
+
241
+ case 'form':
242
+ return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
243
+
244
+ case 'li':
245
+ return ancestorInfo.listItemTagAutoclosing;
246
+
247
+ case 'dd':
248
+ case 'dt':
249
+ return ancestorInfo.dlItemTagAutoclosing;
250
+
251
+ case 'button':
252
+ return ancestorInfo.buttonTagInScope;
253
+
254
+ case 'a':
255
+ // Spec says something about storing a list of markers, but it sounds
256
+ // equivalent to this check.
257
+ return ancestorInfo.aTagInScope;
258
+
259
+ case 'nobr':
260
+ return ancestorInfo.nobrTagInScope;
261
+ }
262
+
263
+ return null;
264
+ };
265
+
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 [];
273
+ }
274
+
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;
283
+ };
284
+
285
+ validateDOMNesting = function (childTag, childInstance, ancestorInfo) {
286
+ ancestorInfo = ancestorInfo || emptyAncestorInfo;
287
+ var parentInfo = ancestorInfo.parentTag;
288
+ var parentTag = parentInfo && parentInfo.tag;
289
+
290
+ var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
291
+ var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
292
+ var problematic = invalidParent || invalidAncestor;
293
+
294
+ if (problematic) {
295
+ var ancestorTag = problematic.tag;
296
+ var ancestorInstance = problematic.instance;
297
+
298
+ var childOwner = childInstance && childInstance._currentElement._owner;
299
+ var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;
300
+
301
+ var childOwners = findOwnerStack(childOwner);
302
+ var ancestorOwners = findOwnerStack(ancestorOwner);
303
+
304
+ var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
305
+ var i;
306
+
307
+ var deepestCommon = -1;
308
+ for (i = 0; i < minStackLen; i++) {
309
+ if (childOwners[i] === ancestorOwners[i]) {
310
+ deepestCommon = i;
311
+ } else {
312
+ break;
313
+ }
314
+ }
315
+
316
+ var UNKNOWN = '(unknown)';
317
+ var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
318
+ return inst.getName() || UNKNOWN;
319
+ });
320
+ var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
321
+ return inst.getName() || UNKNOWN;
322
+ });
323
+ var ownerInfo = [].concat(
324
+ // If the parent and child instances have a common owner ancestor, start
325
+ // with that -- otherwise we just start with the parent's owners.
326
+ deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
327
+ // If we're warning about an invalid (non-parent) ancestry, add '...'
328
+ invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');
329
+
330
+ if (invalidParent) {
331
+ var info = '';
332
+ if (ancestorTag === 'table' && childTag === 'tr') {
333
+ info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
334
+ }
335
+ 'production' !== process.env.NODE_ENV ? warning(false, 'validateDOMNesting(...): <%s> cannot appear as a child of <%s>. ' + 'See %s.%s', childTag, ancestorTag, ownerInfo, info) : null;
336
+ } else {
337
+ 'production' !== process.env.NODE_ENV ? warning(false, 'validateDOMNesting(...): <%s> cannot appear as a descendant of ' + '<%s>. See %s.', childTag, ancestorTag, ownerInfo) : null;
338
+ }
339
+ }
340
+ };
341
+
342
+ validateDOMNesting.ancestorInfoContextKey = '__validateDOMNesting_ancestorInfo$' + Math.random().toString(36).slice(2);
343
+
344
+ validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;
345
+
346
+ // For testing
347
+ validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
348
+ ancestorInfo = ancestorInfo || emptyAncestorInfo;
349
+ var parentInfo = ancestorInfo.parentTag;
350
+ var parentTag = parentInfo && parentInfo.tag;
351
+ return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
352
+ };
353
+ }
354
+
355
+ module.exports = validateDOMNesting;