react 0.13.2 → 0.14.0-alpha3

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 +3355 -1685
  16. package/dist/react-with-addons.js +3320 -5133
  17. package/dist/react-with-addons.min.js +6 -7
  18. package/dist/react.js +2962 -4548
  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 +4 -3
  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 +7 -19
  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 +87 -311
  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 +182 -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 +67 -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 +41 -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 -38
  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 +25 -85
  191. package/lib/validateDOMNesting.js +363 -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
@@ -11,11 +11,7 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var assign = require("./Object.assign");
15
14
  var emptyObject = require("./emptyObject");
16
- var warning = require("./warning");
17
-
18
- var didWarn = false;
19
15
 
20
16
  /**
21
17
  * Keeps track of the current context.
@@ -29,46 +25,8 @@ var ReactContext = {
29
25
  * @internal
30
26
  * @type {object}
31
27
  */
32
- current: emptyObject,
33
-
34
- /**
35
- * Temporarily extends the current context while executing scopedCallback.
36
- *
37
- * A typical use case might look like
38
- *
39
- * render: function() {
40
- * var children = ReactContext.withContext({foo: 'foo'}, () => (
41
- *
42
- * ));
43
- * return <div>{children}</div>;
44
- * }
45
- *
46
- * @param {object} newContext New context to merge into the existing context
47
- * @param {function} scopedCallback Callback to run with the new context
48
- * @return {ReactComponent|array<ReactComponent>}
49
- */
50
- withContext: function(newContext, scopedCallback) {
51
- if ("production" !== process.env.NODE_ENV) {
52
- ("production" !== process.env.NODE_ENV ? warning(
53
- didWarn,
54
- 'withContext is deprecated and will be removed in a future version. ' +
55
- 'Use a wrapper component with getChildContext instead.'
56
- ) : null);
57
-
58
- didWarn = true;
59
- }
60
-
61
- var result;
62
- var previousContext = ReactContext.current;
63
- ReactContext.current = assign({}, previousContext, newContext);
64
- try {
65
- result = scopedCallback();
66
- } finally {
67
- ReactContext.current = previousContext;
68
- }
69
- return result;
70
- }
28
+ current: emptyObject
71
29
 
72
30
  };
73
31
 
74
- module.exports = ReactContext;
32
+ module.exports = ReactContext;
@@ -16,8 +16,6 @@
16
16
  *
17
17
  * The current owner is the component who should own any components that are
18
18
  * currently being constructed.
19
- *
20
- * The depth indicate how many composite components are above this render level.
21
19
  */
22
20
  var ReactCurrentOwner = {
23
21
 
@@ -29,4 +27,4 @@ var ReactCurrentOwner = {
29
27
 
30
28
  };
31
29
 
32
- module.exports = ReactCurrentOwner;
30
+ module.exports = ReactCurrentOwner;
package/lib/ReactDOM.js CHANGED
@@ -24,7 +24,7 @@ var mapObject = require("./mapObject");
24
24
  * @private
25
25
  */
26
26
  function createDOMFactory(tag) {
27
- if ("production" !== process.env.NODE_ENV) {
27
+ if ('production' !== process.env.NODE_ENV) {
28
28
  return ReactElementValidator.createFactory(tag);
29
29
  }
30
30
  return ReactElement.createFactory(tag);
@@ -84,6 +84,7 @@ var ReactDOM = mapObject({
84
84
  h6: 'h6',
85
85
  head: 'head',
86
86
  header: 'header',
87
+ hgroup: 'hgroup',
87
88
  hr: 'hr',
88
89
  html: 'html',
89
90
  i: 'i',
@@ -152,6 +153,7 @@ var ReactDOM = mapObject({
152
153
 
153
154
  // SVG
154
155
  circle: 'circle',
156
+ clipPath: 'clipPath',
155
157
  defs: 'defs',
156
158
  ellipse: 'ellipse',
157
159
  g: 'g',
@@ -171,4 +173,4 @@ var ReactDOM = mapObject({
171
173
 
172
174
  }, createDOMFactory);
173
175
 
174
- module.exports = ReactDOM;
176
+ module.exports = ReactDOM;
@@ -43,13 +43,12 @@ var ReactDOMButton = ReactClass.createClass({
43
43
 
44
44
  mixins: [AutoFocusMixin, ReactBrowserComponentMixin],
45
45
 
46
- render: function() {
46
+ render: function () {
47
47
  var props = {};
48
48
 
49
49
  // Copy the props; except the mouse listeners if we're disabled
50
50
  for (var key in this.props) {
51
- if (this.props.hasOwnProperty(key) &&
52
- (!this.props.disabled || !mouseListenerNames[key])) {
51
+ if (this.props.hasOwnProperty(key) && (!this.props.disabled || !mouseListenerNames[key])) {
53
52
  props[key] = this.props[key];
54
53
  }
55
54
  }
@@ -59,4 +58,4 @@ var ReactDOMButton = ReactClass.createClass({
59
58
 
60
59
  });
61
60
 
62
- module.exports = ReactDOMButton;
61
+ module.exports = ReactDOMButton;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Copyright 2013-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 ReactDOMClient
10
+ */
11
+
12
+ /* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
13
+
14
+ 'use strict';
15
+
16
+ var ReactCurrentOwner = require("./ReactCurrentOwner");
17
+ var ReactDOMTextComponent = require("./ReactDOMTextComponent");
18
+ var ReactDefaultInjection = require("./ReactDefaultInjection");
19
+ var ReactInstanceHandles = require("./ReactInstanceHandles");
20
+ var ReactMount = require("./ReactMount");
21
+ var ReactPerf = require("./ReactPerf");
22
+ var ReactReconciler = require("./ReactReconciler");
23
+
24
+ var findDOMNode = require("./findDOMNode");
25
+ var warning = require("./warning");
26
+
27
+ ReactDefaultInjection.inject();
28
+
29
+ var render = ReactPerf.measure('React', 'render', ReactMount.render);
30
+
31
+ var React = {
32
+ constructAndRenderComponent: ReactMount.constructAndRenderComponent,
33
+ constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID,
34
+ findDOMNode: findDOMNode,
35
+ render: render,
36
+ unmountComponentAtNode: ReactMount.unmountComponentAtNode
37
+ };
38
+
39
+ // Inject the runtime into a devtools global hook regardless of browser.
40
+ // Allows for debugging when the hook is injected on the page.
41
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
42
+ __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
43
+ CurrentOwner: ReactCurrentOwner,
44
+ InstanceHandles: ReactInstanceHandles,
45
+ Mount: ReactMount,
46
+ Reconciler: ReactReconciler,
47
+ TextComponent: ReactDOMTextComponent
48
+ });
49
+ }
50
+
51
+ if ('production' !== process.env.NODE_ENV) {
52
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
53
+ if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
54
+
55
+ // If we're in Chrome, look for the devtools marker and provide a download
56
+ // link if not installed.
57
+ if (navigator.userAgent.indexOf('Chrome') > -1) {
58
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
59
+ console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
60
+ }
61
+ }
62
+
63
+ // If we're in IE8, check to see if we are in combatibility mode and provide
64
+ // information on preventing compatibility mode
65
+ var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
66
+
67
+ 'production' !== process.env.NODE_ENV ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : undefined;
68
+
69
+ var expectedFeatures = [
70
+ // shims
71
+ Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim,
72
+
73
+ // shams
74
+ Object.create, Object.freeze];
75
+
76
+ for (var i = 0; i < expectedFeatures.length; i++) {
77
+ if (!expectedFeatures[i]) {
78
+ console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ module.exports = React;
@@ -18,8 +18,7 @@ var CSSPropertyOperations = require("./CSSPropertyOperations");
18
18
  var DOMProperty = require("./DOMProperty");
19
19
  var DOMPropertyOperations = require("./DOMPropertyOperations");
20
20
  var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
21
- var ReactComponentBrowserEnvironment =
22
- require("./ReactComponentBrowserEnvironment");
21
+ var ReactComponentBrowserEnvironment = require("./ReactComponentBrowserEnvironment");
23
22
  var ReactMount = require("./ReactMount");
24
23
  var ReactMultiChild = require("./ReactMultiChild");
25
24
  var ReactPerf = require("./ReactPerf");
@@ -29,6 +28,8 @@ var escapeTextContentForBrowser = require("./escapeTextContentForBrowser");
29
28
  var invariant = require("./invariant");
30
29
  var isEventSupported = require("./isEventSupported");
31
30
  var keyOf = require("./keyOf");
31
+ var shallowEqual = require("./shallowEqual");
32
+ var validateDOMNesting = require("./validateDOMNesting");
32
33
  var warning = require("./warning");
33
34
 
34
35
  var deleteListener = ReactBrowserEventEmitter.deleteListener;
@@ -36,12 +37,40 @@ var listenTo = ReactBrowserEventEmitter.listenTo;
36
37
  var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
37
38
 
38
39
  // For quickly matching children type, to test if can be treated as content.
39
- var CONTENT_TYPES = {'string': true, 'number': true};
40
+ var CONTENT_TYPES = { 'string': true, 'number': true };
40
41
 
41
- var STYLE = keyOf({style: null});
42
+ var STYLE = keyOf({ style: null });
42
43
 
43
44
  var ELEMENT_NODE_TYPE = 1;
44
45
 
46
+ var styleMutationWarning = {};
47
+
48
+ function checkAndWarnForMutatedStyle(style1, style2, component) {
49
+ if (style1 == null || style2 == null) {
50
+ return;
51
+ }
52
+ if (shallowEqual(style1, style2)) {
53
+ return;
54
+ }
55
+
56
+ var componentName = component._tag;
57
+ var owner = component._currentElement._owner;
58
+ var ownerName;
59
+ if (owner) {
60
+ ownerName = owner.getName();
61
+ }
62
+
63
+ var hash = ownerName + '|' + componentName;
64
+
65
+ if (styleMutationWarning.hasOwnProperty(hash)) {
66
+ return;
67
+ }
68
+
69
+ styleMutationWarning[hash] = true;
70
+
71
+ 'production' !== process.env.NODE_ENV ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', JSON.stringify(style1), JSON.stringify(style2)) : undefined;
72
+ }
73
+
45
74
  /**
46
75
  * Optionally injectable operations for mutating the DOM
47
76
  */
@@ -50,66 +79,48 @@ var BackendIDOperations = null;
50
79
  /**
51
80
  * @param {?object} props
52
81
  */
53
- function assertValidProps(props) {
82
+ function assertValidProps(component, props) {
54
83
  if (!props) {
55
84
  return;
56
85
  }
57
86
  // Note the use of `==` which checks for null or undefined.
87
+ if ('production' !== process.env.NODE_ENV) {
88
+ if (voidElementTags[component._tag]) {
89
+ 'production' !== process.env.NODE_ENV ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.', component._tag) : undefined;
90
+ }
91
+ }
58
92
  if (props.dangerouslySetInnerHTML != null) {
59
- ("production" !== process.env.NODE_ENV ? invariant(
60
- props.children == null,
61
- 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.'
62
- ) : invariant(props.children == null));
63
- ("production" !== process.env.NODE_ENV ? invariant(
64
- props.dangerouslySetInnerHTML.__html != null,
65
- '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
66
- 'Please visit http://fb.me/react-invariant-dangerously-set-inner-html ' +
67
- 'for more information.'
68
- ) : invariant(props.dangerouslySetInnerHTML.__html != null));
93
+ !(props.children == null) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : undefined;
94
+ !(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML) ? 'production' !== process.env.NODE_ENV ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(false) : undefined;
69
95
  }
70
- if ("production" !== process.env.NODE_ENV) {
71
- ("production" !== process.env.NODE_ENV ? warning(
72
- props.innerHTML == null,
73
- 'Directly setting property `innerHTML` is not permitted. ' +
74
- 'For more information, lookup documentation on `dangerouslySetInnerHTML`.'
75
- ) : null);
76
- ("production" !== process.env.NODE_ENV ? warning(
77
- !props.contentEditable || props.children == null,
78
- 'A component is `contentEditable` and contains `children` managed by ' +
79
- 'React. It is now your responsibility to guarantee that none of ' +
80
- 'those nodes are unexpectedly modified or duplicated. This is ' +
81
- 'probably not intentional.'
82
- ) : null);
96
+ if ('production' !== process.env.NODE_ENV) {
97
+ 'production' !== process.env.NODE_ENV ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : undefined;
98
+ 'production' !== process.env.NODE_ENV ? warning(!props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : undefined;
83
99
  }
84
- ("production" !== process.env.NODE_ENV ? invariant(
85
- props.style == null || typeof props.style === 'object',
86
- 'The `style` prop expects a mapping from style properties to values, ' +
87
- 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' +
88
- 'using JSX.'
89
- ) : invariant(props.style == null || typeof props.style === 'object'));
100
+ !(props.style == null || typeof props.style === 'object') ? 'production' !== process.env.NODE_ENV ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.') : invariant(false) : undefined;
90
101
  }
91
102
 
92
- function putListener(id, registrationName, listener, transaction) {
93
- if ("production" !== process.env.NODE_ENV) {
103
+ function enqueuePutListener(id, registrationName, listener, transaction) {
104
+ if ('production' !== process.env.NODE_ENV) {
94
105
  // IE8 has no API for event capturing and the `onScroll` event doesn't
95
106
  // bubble.
96
- ("production" !== process.env.NODE_ENV ? warning(
97
- registrationName !== 'onScroll' || isEventSupported('scroll', true),
98
- 'This browser doesn\'t support the `onScroll` event'
99
- ) : null);
107
+ 'production' !== process.env.NODE_ENV ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : undefined;
100
108
  }
101
109
  var container = ReactMount.findReactContainerForID(id);
102
110
  if (container) {
103
- var doc = container.nodeType === ELEMENT_NODE_TYPE ?
104
- container.ownerDocument :
105
- container;
111
+ var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
106
112
  listenTo(registrationName, doc);
107
113
  }
108
- transaction.getPutListenerQueue().enqueuePutListener(
109
- id,
110
- registrationName,
111
- listener
112
- );
114
+ transaction.getReactMountReady().enqueue(putListener, {
115
+ id: id,
116
+ registrationName: registrationName,
117
+ listener: listener
118
+ });
119
+ }
120
+
121
+ function putListener() {
122
+ var listenerToPut = this;
123
+ ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
113
124
  }
114
125
 
115
126
  // For HTML, certain tags should omit their close tag. We keep a whitelist for
@@ -134,21 +145,44 @@ var omittedCloseTags = {
134
145
  // NOTE: menuitem's close tag should be omitted, but that causes problems.
135
146
  };
136
147
 
137
- // We accept any tag to be rendered but since this gets injected into abitrary
148
+ var newlineEatingTags = {
149
+ 'listing': true,
150
+ 'pre': true,
151
+ 'textarea': true
152
+ };
153
+
154
+ // For HTML, certain tags cannot have children. This has the same purpose as
155
+ // `omittedCloseTags` except that `menuitem` should still have its closing tag.
156
+
157
+ var voidElementTags = assign({
158
+ 'menuitem': true
159
+ }, omittedCloseTags);
160
+
161
+ // We accept any tag to be rendered but since this gets injected into arbitrary
138
162
  // HTML, we want to make sure that it's a safe tag.
139
163
  // http://www.w3.org/TR/REC-xml/#NT-Name
140
164
 
141
165
  var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
142
166
  var validatedTagCache = {};
143
- var hasOwnProperty = {}.hasOwnProperty;
167
+ var hasOwnProperty = ({}).hasOwnProperty;
144
168
 
145
169
  function validateDangerousTag(tag) {
146
170
  if (!hasOwnProperty.call(validatedTagCache, tag)) {
147
- ("production" !== process.env.NODE_ENV ? invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag) : invariant(VALID_TAG_REGEX.test(tag)));
171
+ !VALID_TAG_REGEX.test(tag) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : undefined;
148
172
  validatedTagCache[tag] = true;
149
173
  }
150
174
  }
151
175
 
176
+ function processChildContext(context, inst) {
177
+ if ('production' !== process.env.NODE_ENV) {
178
+ // Pass down our tag name to child components for validation purposes
179
+ context = assign({}, context);
180
+ var info = context[validateDOMNesting.ancestorInfoContextKey];
181
+ context[validateDOMNesting.ancestorInfoContextKey] = validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
182
+ }
183
+ return context;
184
+ }
185
+
152
186
  /**
153
187
  * Creates a new React class that is idempotent and capable of containing other
154
188
  * React components. It accepts event listeners and DOM properties that are
@@ -167,6 +201,7 @@ function ReactDOMComponent(tag) {
167
201
  validateDangerousTag(tag);
168
202
  this._tag = tag;
169
203
  this._renderedChildren = null;
204
+ this._previousStyle = null;
170
205
  this._previousStyleCopy = null;
171
206
  this._rootNodeID = null;
172
207
  }
@@ -175,7 +210,7 @@ ReactDOMComponent.displayName = 'ReactDOMComponent';
175
210
 
176
211
  ReactDOMComponent.Mixin = {
177
212
 
178
- construct: function(element) {
213
+ construct: function (element) {
179
214
  this._currentElement = element;
180
215
  },
181
216
 
@@ -186,17 +221,25 @@ ReactDOMComponent.Mixin = {
186
221
  * @internal
187
222
  * @param {string} rootID The root DOM ID for this node.
188
223
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
224
+ * @param {object} context
189
225
  * @return {string} The computed markup.
190
226
  */
191
- mountComponent: function(rootID, transaction, context) {
227
+ mountComponent: function (rootID, transaction, context) {
192
228
  this._rootNodeID = rootID;
193
- assertValidProps(this._currentElement.props);
194
- var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>';
195
- return (
196
- this._createOpenTagMarkupAndPutListeners(transaction) +
197
- this._createContentMarkup(transaction, context) +
198
- closeTag
199
- );
229
+
230
+ assertValidProps(this, this._currentElement.props);
231
+ if ('production' !== process.env.NODE_ENV) {
232
+ if (context[validateDOMNesting.ancestorInfoContextKey]) {
233
+ validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
234
+ }
235
+ }
236
+
237
+ var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction);
238
+ var tagContent = this._createContentMarkup(transaction, context);
239
+ if (!tagContent && omittedCloseTags[this._tag]) {
240
+ return tagOpen + '/>';
241
+ }
242
+ return tagOpen + '>' + tagContent + '</' + this._tag + '>';
200
243
  },
201
244
 
202
245
  /**
@@ -211,7 +254,7 @@ ReactDOMComponent.Mixin = {
211
254
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
212
255
  * @return {string} Markup of opening tag.
213
256
  */
214
- _createOpenTagMarkupAndPutListeners: function(transaction) {
257
+ _createOpenTagMarkupAndPutListeners: function (transaction) {
215
258
  var props = this._currentElement.props;
216
259
  var ret = '<' + this._tag;
217
260
 
@@ -224,16 +267,19 @@ ReactDOMComponent.Mixin = {
224
267
  continue;
225
268
  }
226
269
  if (registrationNameModules.hasOwnProperty(propKey)) {
227
- putListener(this._rootNodeID, propKey, propValue, transaction);
270
+ enqueuePutListener(this._rootNodeID, propKey, propValue, transaction);
228
271
  } else {
229
272
  if (propKey === STYLE) {
230
273
  if (propValue) {
274
+ if ('production' !== process.env.NODE_ENV) {
275
+ // See `_updateDOMProperties`. style block
276
+ this._previousStyle = propValue;
277
+ }
231
278
  propValue = this._previousStyleCopy = assign({}, props.style);
232
279
  }
233
280
  propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
234
281
  }
235
- var markup =
236
- DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
282
+ var markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
237
283
  if (markup) {
238
284
  ret += ' ' + markup;
239
285
  }
@@ -243,11 +289,11 @@ ReactDOMComponent.Mixin = {
243
289
  // For static pages, no need to put React ID and checksum. Saves lots of
244
290
  // bytes.
245
291
  if (transaction.renderToStaticMarkup) {
246
- return ret + '>';
292
+ return ret;
247
293
  }
248
294
 
249
295
  var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID);
250
- return ret + ' ' + markupForID + '>';
296
+ return ret + ' ' + markupForID;
251
297
  },
252
298
 
253
299
  /**
@@ -258,44 +304,53 @@ ReactDOMComponent.Mixin = {
258
304
  * @param {object} context
259
305
  * @return {string} Content markup.
260
306
  */
261
- _createContentMarkup: function(transaction, context) {
262
- var prefix = '';
263
- if (this._tag === 'listing' ||
264
- this._tag === 'pre' ||
265
- this._tag === 'textarea') {
266
- // Add an initial newline because browsers ignore the first newline in
267
- // a <listing>, <pre>, or <textarea> as an "authoring convenience" -- see
268
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody.
269
- prefix = '\n';
270
- }
271
-
307
+ _createContentMarkup: function (transaction, context) {
308
+ var ret = '';
272
309
  var props = this._currentElement.props;
273
310
 
274
311
  // Intentional use of != to avoid catching zero/false.
275
312
  var innerHTML = props.dangerouslySetInnerHTML;
276
313
  if (innerHTML != null) {
277
314
  if (innerHTML.__html != null) {
278
- return prefix + innerHTML.__html;
315
+ ret = innerHTML.__html;
279
316
  }
280
317
  } else {
281
- var contentToUse =
282
- CONTENT_TYPES[typeof props.children] ? props.children : null;
318
+ var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
283
319
  var childrenToUse = contentToUse != null ? null : props.children;
284
320
  if (contentToUse != null) {
285
- return prefix + escapeTextContentForBrowser(contentToUse);
321
+ // TODO: Validate that text is allowed as a child of this node
322
+ ret = escapeTextContentForBrowser(contentToUse);
286
323
  } else if (childrenToUse != null) {
287
- var mountImages = this.mountChildren(
288
- childrenToUse,
289
- transaction,
290
- context
291
- );
292
- return prefix + mountImages.join('');
324
+ var mountImages = this.mountChildren(childrenToUse, transaction, processChildContext(context, this));
325
+ ret = mountImages.join('');
293
326
  }
294
327
  }
295
- return prefix;
328
+ if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
329
+ // text/html ignores the first character in these tags if it's a newline
330
+ // Prefer to break application/xml over text/html (for now) by adding
331
+ // a newline specifically to get eaten by the parser. (Alternately for
332
+ // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
333
+ // \r is normalized out by HTMLTextAreaElement#value.)
334
+ // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
335
+ // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
336
+ // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
337
+ // See: Parsing of "textarea" "listing" and "pre" elements
338
+ // from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
339
+ return '\n' + ret;
340
+ } else {
341
+ return ret;
342
+ }
296
343
  },
297
344
 
298
- receiveComponent: function(nextElement, transaction, context) {
345
+ /**
346
+ * Receives a next element and updates the component.
347
+ *
348
+ * @internal
349
+ * @param {ReactElement} nextElement
350
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
351
+ * @param {object} context
352
+ */
353
+ receiveComponent: function (nextElement, transaction, context) {
299
354
  var prevElement = this._currentElement;
300
355
  this._currentElement = nextElement;
301
356
  this.updateComponent(transaction, prevElement, nextElement, context);
@@ -311,10 +366,10 @@ ReactDOMComponent.Mixin = {
311
366
  * @internal
312
367
  * @overridable
313
368
  */
314
- updateComponent: function(transaction, prevElement, nextElement, context) {
315
- assertValidProps(this._currentElement.props);
369
+ updateComponent: function (transaction, prevElement, nextElement, context) {
370
+ assertValidProps(this, this._currentElement.props);
316
371
  this._updateDOMProperties(prevElement.props, transaction);
317
- this._updateDOMChildren(prevElement.props, transaction, context);
372
+ this._updateDOMChildren(prevElement.props, transaction, processChildContext(context, this));
318
373
  },
319
374
 
320
375
  /**
@@ -332,14 +387,13 @@ ReactDOMComponent.Mixin = {
332
387
  * @param {object} lastProps
333
388
  * @param {ReactReconcileTransaction} transaction
334
389
  */
335
- _updateDOMProperties: function(lastProps, transaction) {
390
+ _updateDOMProperties: function (lastProps, transaction) {
336
391
  var nextProps = this._currentElement.props;
337
392
  var propKey;
338
393
  var styleName;
339
394
  var styleUpdates;
340
395
  for (propKey in lastProps) {
341
- if (nextProps.hasOwnProperty(propKey) ||
342
- !lastProps.hasOwnProperty(propKey)) {
396
+ if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey)) {
343
397
  continue;
344
398
  }
345
399
  if (propKey === STYLE) {
@@ -352,26 +406,28 @@ ReactDOMComponent.Mixin = {
352
406
  }
353
407
  this._previousStyleCopy = null;
354
408
  } else if (registrationNameModules.hasOwnProperty(propKey)) {
355
- deleteListener(this._rootNodeID, propKey);
356
- } else if (
357
- DOMProperty.isStandardName[propKey] ||
358
- DOMProperty.isCustomAttribute(propKey)) {
359
- BackendIDOperations.deletePropertyByID(
360
- this._rootNodeID,
361
- propKey
362
- );
409
+ if (lastProps[propKey]) {
410
+ // Only call deleteListener if there was a listener previously or
411
+ // else willDeleteListener gets called when there wasn't actually a
412
+ // listener (e.g., onClick={null})
413
+ deleteListener(this._rootNodeID, propKey);
414
+ }
415
+ } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
416
+ BackendIDOperations.deletePropertyByID(this._rootNodeID, propKey);
363
417
  }
364
418
  }
365
419
  for (propKey in nextProps) {
366
420
  var nextProp = nextProps[propKey];
367
- var lastProp = propKey === STYLE ?
368
- this._previousStyleCopy :
369
- lastProps[propKey];
421
+ var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps[propKey];
370
422
  if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) {
371
423
  continue;
372
424
  }
373
425
  if (propKey === STYLE) {
374
426
  if (nextProp) {
427
+ if ('production' !== process.env.NODE_ENV) {
428
+ checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
429
+ this._previousStyle = nextProp;
430
+ }
375
431
  nextProp = this._previousStyleCopy = assign({}, nextProp);
376
432
  } else {
377
433
  this._previousStyleCopy = null;
@@ -379,16 +435,14 @@ ReactDOMComponent.Mixin = {
379
435
  if (lastProp) {
380
436
  // Unset styles on `lastProp` but not on `nextProp`.
381
437
  for (styleName in lastProp) {
382
- if (lastProp.hasOwnProperty(styleName) &&
383
- (!nextProp || !nextProp.hasOwnProperty(styleName))) {
438
+ if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
384
439
  styleUpdates = styleUpdates || {};
385
440
  styleUpdates[styleName] = '';
386
441
  }
387
442
  }
388
443
  // Update styles that changed since `lastProp`.
389
444
  for (styleName in nextProp) {
390
- if (nextProp.hasOwnProperty(styleName) &&
391
- lastProp[styleName] !== nextProp[styleName]) {
445
+ if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
392
446
  styleUpdates = styleUpdates || {};
393
447
  styleUpdates[styleName] = nextProp[styleName];
394
448
  }
@@ -398,22 +452,17 @@ ReactDOMComponent.Mixin = {
398
452
  styleUpdates = nextProp;
399
453
  }
400
454
  } else if (registrationNameModules.hasOwnProperty(propKey)) {
401
- putListener(this._rootNodeID, propKey, nextProp, transaction);
402
- } else if (
403
- DOMProperty.isStandardName[propKey] ||
404
- DOMProperty.isCustomAttribute(propKey)) {
405
- BackendIDOperations.updatePropertyByID(
406
- this._rootNodeID,
407
- propKey,
408
- nextProp
409
- );
455
+ if (nextProp) {
456
+ enqueuePutListener(this._rootNodeID, propKey, nextProp, transaction);
457
+ } else if (lastProp) {
458
+ deleteListener(this._rootNodeID, propKey);
459
+ }
460
+ } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
461
+ BackendIDOperations.updatePropertyByID(this._rootNodeID, propKey, nextProp);
410
462
  }
411
463
  }
412
464
  if (styleUpdates) {
413
- BackendIDOperations.updateStylesByID(
414
- this._rootNodeID,
415
- styleUpdates
416
- );
465
+ BackendIDOperations.updateStylesByID(this._rootNodeID, styleUpdates);
417
466
  }
418
467
  },
419
468
 
@@ -424,20 +473,14 @@ ReactDOMComponent.Mixin = {
424
473
  * @param {object} lastProps
425
474
  * @param {ReactReconcileTransaction} transaction
426
475
  */
427
- _updateDOMChildren: function(lastProps, transaction, context) {
476
+ _updateDOMChildren: function (lastProps, transaction, context) {
428
477
  var nextProps = this._currentElement.props;
429
478
 
430
- var lastContent =
431
- CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
432
- var nextContent =
433
- CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
479
+ var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
480
+ var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
434
481
 
435
- var lastHtml =
436
- lastProps.dangerouslySetInnerHTML &&
437
- lastProps.dangerouslySetInnerHTML.__html;
438
- var nextHtml =
439
- nextProps.dangerouslySetInnerHTML &&
440
- nextProps.dangerouslySetInnerHTML.__html;
482
+ var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
483
+ var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;
441
484
 
442
485
  // Note the use of `!=` which checks for null or undefined.
443
486
  var lastChildren = lastContent != null ? null : lastProps.children;
@@ -459,10 +502,7 @@ ReactDOMComponent.Mixin = {
459
502
  }
460
503
  } else if (nextHtml != null) {
461
504
  if (lastHtml !== nextHtml) {
462
- BackendIDOperations.updateInnerHTMLByID(
463
- this._rootNodeID,
464
- nextHtml
465
- );
505
+ BackendIDOperations.updateInnerHTMLByID(this._rootNodeID, nextHtml);
466
506
  }
467
507
  } else if (nextChildren != null) {
468
508
  this.updateChildren(nextChildren, transaction, context);
@@ -475,7 +515,7 @@ ReactDOMComponent.Mixin = {
475
515
  *
476
516
  * @internal
477
517
  */
478
- unmountComponent: function() {
518
+ unmountComponent: function () {
479
519
  this.unmountChildren();
480
520
  ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
481
521
  ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
@@ -489,16 +529,12 @@ ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
489
529
  updateComponent: 'updateComponent'
490
530
  });
491
531
 
492
- assign(
493
- ReactDOMComponent.prototype,
494
- ReactDOMComponent.Mixin,
495
- ReactMultiChild.Mixin
496
- );
532
+ assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
497
533
 
498
534
  ReactDOMComponent.injection = {
499
- injectIDOperations: function(IDOperations) {
535
+ injectIDOperations: function (IDOperations) {
500
536
  ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
501
537
  }
502
538
  };
503
539
 
504
- module.exports = ReactDOMComponent;
540
+ module.exports = ReactDOMComponent;