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
@@ -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" />') : null;
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)) : null;
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) : null;
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
+ 'production' !== process.env.NODE_ENV ? invariant(props.children == null, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(props.children == null);
94
+ 'production' !== process.env.NODE_ENV ? invariant(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML);
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`.') : null;
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.') : null;
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
+ 'production' !== process.env.NODE_ENV ? invariant(props.style == null || typeof props.style === 'object', 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.') : invariant(props.style == null || typeof props.style === 'object');
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') : null;
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
+ 'production' !== process.env.NODE_ENV ? invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag) : invariant(VALID_TAG_REGEX.test(tag));
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,41 +406,43 @@ 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);
432
+ } else {
433
+ this._previousStyleCopy = null;
376
434
  }
377
435
  if (lastProp) {
378
436
  // Unset styles on `lastProp` but not on `nextProp`.
379
437
  for (styleName in lastProp) {
380
- if (lastProp.hasOwnProperty(styleName) &&
381
- (!nextProp || !nextProp.hasOwnProperty(styleName))) {
438
+ if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
382
439
  styleUpdates = styleUpdates || {};
383
440
  styleUpdates[styleName] = '';
384
441
  }
385
442
  }
386
443
  // Update styles that changed since `lastProp`.
387
444
  for (styleName in nextProp) {
388
- if (nextProp.hasOwnProperty(styleName) &&
389
- lastProp[styleName] !== nextProp[styleName]) {
445
+ if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
390
446
  styleUpdates = styleUpdates || {};
391
447
  styleUpdates[styleName] = nextProp[styleName];
392
448
  }
@@ -396,22 +452,17 @@ ReactDOMComponent.Mixin = {
396
452
  styleUpdates = nextProp;
397
453
  }
398
454
  } else if (registrationNameModules.hasOwnProperty(propKey)) {
399
- putListener(this._rootNodeID, propKey, nextProp, transaction);
400
- } else if (
401
- DOMProperty.isStandardName[propKey] ||
402
- DOMProperty.isCustomAttribute(propKey)) {
403
- BackendIDOperations.updatePropertyByID(
404
- this._rootNodeID,
405
- propKey,
406
- nextProp
407
- );
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);
408
462
  }
409
463
  }
410
464
  if (styleUpdates) {
411
- BackendIDOperations.updateStylesByID(
412
- this._rootNodeID,
413
- styleUpdates
414
- );
465
+ BackendIDOperations.updateStylesByID(this._rootNodeID, styleUpdates);
415
466
  }
416
467
  },
417
468
 
@@ -422,20 +473,14 @@ ReactDOMComponent.Mixin = {
422
473
  * @param {object} lastProps
423
474
  * @param {ReactReconcileTransaction} transaction
424
475
  */
425
- _updateDOMChildren: function(lastProps, transaction, context) {
476
+ _updateDOMChildren: function (lastProps, transaction, context) {
426
477
  var nextProps = this._currentElement.props;
427
478
 
428
- var lastContent =
429
- CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
430
- var nextContent =
431
- 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;
432
481
 
433
- var lastHtml =
434
- lastProps.dangerouslySetInnerHTML &&
435
- lastProps.dangerouslySetInnerHTML.__html;
436
- var nextHtml =
437
- nextProps.dangerouslySetInnerHTML &&
438
- nextProps.dangerouslySetInnerHTML.__html;
482
+ var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
483
+ var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;
439
484
 
440
485
  // Note the use of `!=` which checks for null or undefined.
441
486
  var lastChildren = lastContent != null ? null : lastProps.children;
@@ -457,10 +502,7 @@ ReactDOMComponent.Mixin = {
457
502
  }
458
503
  } else if (nextHtml != null) {
459
504
  if (lastHtml !== nextHtml) {
460
- BackendIDOperations.updateInnerHTMLByID(
461
- this._rootNodeID,
462
- nextHtml
463
- );
505
+ BackendIDOperations.updateInnerHTMLByID(this._rootNodeID, nextHtml);
464
506
  }
465
507
  } else if (nextChildren != null) {
466
508
  this.updateChildren(nextChildren, transaction, context);
@@ -473,7 +515,7 @@ ReactDOMComponent.Mixin = {
473
515
  *
474
516
  * @internal
475
517
  */
476
- unmountComponent: function() {
518
+ unmountComponent: function () {
477
519
  this.unmountChildren();
478
520
  ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
479
521
  ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
@@ -487,16 +529,12 @@ ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
487
529
  updateComponent: 'updateComponent'
488
530
  });
489
531
 
490
- assign(
491
- ReactDOMComponent.prototype,
492
- ReactDOMComponent.Mixin,
493
- ReactMultiChild.Mixin
494
- );
532
+ assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
495
533
 
496
534
  ReactDOMComponent.injection = {
497
- injectIDOperations: function(IDOperations) {
535
+ injectIDOperations: function (IDOperations) {
498
536
  ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
499
537
  }
500
538
  };
501
539
 
502
- module.exports = ReactDOMComponent;
540
+ module.exports = ReactDOMComponent;