react 0.14.0-alpha3 → 0.14.0-rc1

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 (200) hide show
  1. package/README.md +5 -2
  2. package/addons.js +8 -3
  3. package/dist/react-dom.js +42 -0
  4. package/dist/react-dom.min.js +12 -0
  5. package/dist/react-with-addons.js +6076 -5337
  6. package/dist/react-with-addons.min.js +6 -6
  7. package/dist/react.js +5445 -4839
  8. package/dist/react.min.js +6 -5
  9. package/lib/{AutoFocusMixin.js → AutoFocusUtils.js} +15 -5
  10. package/lib/BeforeInputEventPlugin.js +13 -13
  11. package/lib/CSSProperty.js +18 -3
  12. package/lib/CSSPropertyOperations.js +22 -14
  13. package/lib/CallbackQueue.js +4 -4
  14. package/lib/ChangeEventPlugin.js +18 -15
  15. package/lib/DOMChildrenOperations.js +17 -7
  16. package/lib/DOMProperty.js +82 -117
  17. package/lib/DOMPropertyOperations.js +84 -33
  18. package/lib/Danger.js +21 -16
  19. package/lib/DefaultEventPluginOrder.js +2 -2
  20. package/lib/EnterLeaveEventPlugin.js +21 -13
  21. package/lib/EventConstants.js +23 -1
  22. package/lib/EventPluginHub.js +17 -20
  23. package/lib/EventPluginRegistry.js +8 -8
  24. package/lib/EventPluginUtils.js +33 -42
  25. package/lib/EventPropagators.js +8 -8
  26. package/lib/FallbackCompositionState.js +9 -3
  27. package/lib/HTMLDOMPropertyConfig.js +19 -3
  28. package/lib/LinkedStateMixin.js +2 -2
  29. package/lib/LinkedValueUtils.js +50 -38
  30. package/lib/MetaMatchers.js +118 -0
  31. package/lib/OrderedMap.js +453 -0
  32. package/lib/PooledClass.js +15 -5
  33. package/lib/React.js +18 -7
  34. package/lib/ReactBrowserComponentMixin.js +4 -4
  35. package/lib/ReactBrowserEventEmitter.js +30 -7
  36. package/lib/ReactCSSTransitionGroup.js +35 -9
  37. package/lib/ReactCSSTransitionGroupChild.js +56 -30
  38. package/lib/ReactChildReconciler.js +24 -19
  39. package/lib/ReactChildren.js +75 -35
  40. package/lib/ReactClass.js +70 -87
  41. package/lib/ReactComponent.js +27 -20
  42. package/lib/ReactComponentBrowserEnvironment.js +2 -2
  43. package/lib/ReactComponentEnvironment.js +2 -2
  44. package/lib/ReactComponentWithPureRenderMixin.js +3 -3
  45. package/lib/ReactCompositeComponent.js +117 -106
  46. package/lib/ReactDOM.js +74 -158
  47. package/lib/ReactDOMButton.js +15 -26
  48. package/lib/ReactDOMComponent.js +441 -72
  49. package/lib/ReactDOMFactories.js +177 -0
  50. package/lib/{emptyObject.js → ReactDOMFeatureFlags.js} +6 -8
  51. package/lib/ReactDOMIDOperations.js +8 -66
  52. package/lib/ReactDOMInput.js +87 -99
  53. package/lib/ReactDOMOption.js +25 -44
  54. package/lib/ReactDOMSelect.js +88 -98
  55. package/lib/ReactDOMSelection.js +3 -3
  56. package/lib/ReactDOMServer.js +5 -3
  57. package/lib/ReactDOMTextComponent.js +33 -20
  58. package/lib/ReactDOMTextarea.js +48 -61
  59. package/lib/ReactDefaultBatchingStrategy.js +4 -4
  60. package/lib/ReactDefaultInjection.js +23 -72
  61. package/lib/ReactDefaultPerf.js +7 -7
  62. package/lib/ReactDefaultPerfAnalysis.js +6 -11
  63. package/lib/ReactElement.js +92 -107
  64. package/lib/ReactElementValidator.js +53 -173
  65. package/lib/ReactEmptyComponent.js +26 -62
  66. package/lib/ReactEmptyComponentRegistry.js +48 -0
  67. package/lib/ReactErrorUtils.js +45 -9
  68. package/lib/ReactEventEmitterMixin.js +3 -4
  69. package/lib/ReactEventListener.js +64 -12
  70. package/lib/ReactFragment.js +29 -115
  71. package/lib/ReactInjection.js +10 -12
  72. package/lib/ReactInputSelection.js +8 -7
  73. package/lib/ReactInstanceHandles.js +12 -12
  74. package/lib/ReactIsomorphic.js +15 -11
  75. package/lib/ReactLink.js +1 -1
  76. package/lib/ReactMarkupChecksum.js +6 -2
  77. package/lib/ReactMount.js +196 -122
  78. package/lib/ReactMultiChild.js +119 -25
  79. package/lib/ReactMultiChildUpdateTypes.js +2 -1
  80. package/lib/ReactNativeComponent.js +3 -8
  81. package/lib/ReactNoopUpdateQueue.js +118 -0
  82. package/lib/ReactOwner.js +3 -3
  83. package/lib/ReactPerf.js +2 -2
  84. package/lib/ReactPropTransferer.js +3 -3
  85. package/lib/ReactPropTypeLocationNames.js +1 -1
  86. package/lib/ReactPropTypeLocations.js +1 -1
  87. package/lib/ReactPropTypes.js +41 -12
  88. package/lib/ReactReconcileTransaction.js +12 -10
  89. package/lib/ReactReconciler.js +8 -11
  90. package/lib/ReactRef.js +15 -2
  91. package/lib/ReactServerBatchingStrategy.js +23 -0
  92. package/lib/ReactServerRendering.js +22 -9
  93. package/lib/ReactServerRenderingTransaction.js +8 -7
  94. package/lib/ReactTestUtils.js +89 -64
  95. package/lib/ReactTransitionChildMapping.js +3 -6
  96. package/lib/ReactTransitionEvents.js +1 -1
  97. package/lib/ReactTransitionGroup.js +5 -6
  98. package/lib/ReactUpdateQueue.js +60 -35
  99. package/lib/ReactUpdates.js +15 -18
  100. package/lib/{isTextNode.js → ReactVersion.js} +2 -13
  101. package/lib/ReactWithAddons.js +24 -17
  102. package/lib/ResponderEventPlugin.js +514 -0
  103. package/lib/ResponderSyntheticEvent.js +40 -0
  104. package/lib/ResponderTouchHistoryStore.js +180 -0
  105. package/lib/SVGDOMPropertyConfig.js +1 -1
  106. package/lib/SelectEventPlugin.js +25 -16
  107. package/lib/SimpleEventPlugin.js +200 -45
  108. package/lib/SyntheticClipboardEvent.js +3 -3
  109. package/lib/SyntheticCompositionEvent.js +3 -3
  110. package/lib/SyntheticDragEvent.js +3 -3
  111. package/lib/SyntheticEvent.js +24 -8
  112. package/lib/SyntheticFocusEvent.js +3 -3
  113. package/lib/SyntheticInputEvent.js +3 -3
  114. package/lib/SyntheticKeyboardEvent.js +6 -6
  115. package/lib/SyntheticMouseEvent.js +5 -5
  116. package/lib/SyntheticTouchEvent.js +4 -4
  117. package/lib/SyntheticUIEvent.js +4 -4
  118. package/lib/SyntheticWheelEvent.js +3 -3
  119. package/lib/TapEventPlugin.js +119 -0
  120. package/lib/Transaction.js +17 -11
  121. package/lib/accumulate.js +44 -0
  122. package/lib/accumulateInto.js +2 -2
  123. package/lib/adler32.js +19 -7
  124. package/lib/cloneWithProps.js +12 -7
  125. package/lib/createHierarchyRenderer.js +85 -0
  126. package/lib/dangerousStyleValue.js +1 -1
  127. package/lib/deprecated.js +48 -0
  128. package/lib/findDOMNode.js +11 -12
  129. package/lib/flattenChildren.js +4 -4
  130. package/lib/forEachAccumulated.js +1 -1
  131. package/lib/getEventCharCode.js +1 -1
  132. package/lib/getEventKey.js +1 -1
  133. package/lib/getEventModifierState.js +0 -1
  134. package/lib/getTestDocument.js +28 -0
  135. package/lib/getTextContentAccessor.js +1 -1
  136. package/lib/instantiateReactComponent.js +27 -25
  137. package/lib/isEventSupported.js +1 -1
  138. package/lib/isTextInputElement.js +2 -1
  139. package/lib/joinClasses.js +1 -1
  140. package/lib/onlyChild.js +3 -3
  141. package/lib/quoteAttributeValueForBrowser.js +1 -1
  142. package/lib/reactComponentExpect.js +216 -0
  143. package/lib/renderSubtreeIntoContainer.js +1 -1
  144. package/lib/setInnerHTML.js +2 -2
  145. package/lib/setTextContent.js +3 -3
  146. package/lib/shallowCompare.js +1 -1
  147. package/lib/shouldUpdateReactComponent.js +12 -8
  148. package/lib/sliceChildren.js +34 -0
  149. package/lib/traverseAllChildren.js +21 -19
  150. package/lib/update.js +13 -13
  151. package/lib/validateDOMNesting.js +6 -6
  152. package/lib/webcomponents.js +6379 -0
  153. package/package.json +4 -6
  154. package/react.js +2 -0
  155. package/addons/CSSTransitionGroup.js +0 -1
  156. package/addons/LinkedStateMixin.js +0 -1
  157. package/addons/Perf.js +0 -1
  158. package/addons/PureRenderMixin.js +0 -1
  159. package/addons/TestUtils.js +0 -1
  160. package/addons/TransitionGroup.js +0 -1
  161. package/addons/batchedUpdates.js +0 -1
  162. package/addons/cloneWithProps.js +0 -1
  163. package/addons/createFragment.js +0 -1
  164. package/addons/renderSubtreeIntoContainer.js +0 -1
  165. package/addons/shallowCompare.js +0 -1
  166. package/addons/update.js +0 -1
  167. package/dist/JSXTransformer.js +0 -17589
  168. package/lib/CSSCore.js +0 -97
  169. package/lib/EventListener.js +0 -84
  170. package/lib/ExecutionEnvironment.js +0 -38
  171. package/lib/LocalEventTrapMixin.js +0 -46
  172. package/lib/ReactContext.js +0 -32
  173. package/lib/ReactDOMClient.js +0 -85
  174. package/lib/ReactDOMForm.js +0 -47
  175. package/lib/ReactDOMIframe.js +0 -43
  176. package/lib/ReactDOMImg.js +0 -44
  177. package/lib/ReactLifeCycle.js +0 -35
  178. package/lib/camelize.js +0 -32
  179. package/lib/camelizeStyleName.js +0 -40
  180. package/lib/containsNode.js +0 -55
  181. package/lib/createArrayFromMixed.js +0 -85
  182. package/lib/createFullPageComponent.js +0 -51
  183. package/lib/createNodesFromMarkup.js +0 -84
  184. package/lib/emptyFunction.js +0 -38
  185. package/lib/focusNode.js +0 -26
  186. package/lib/getActiveElement.js +0 -29
  187. package/lib/getMarkupWrap.js +0 -115
  188. package/lib/getUnboundedScrollPosition.js +0 -38
  189. package/lib/hyphenate.js +0 -33
  190. package/lib/hyphenateStyleName.js +0 -39
  191. package/lib/invariant.js +0 -49
  192. package/lib/isNode.js +0 -23
  193. package/lib/keyMirror.js +0 -48
  194. package/lib/keyOf.js +0 -35
  195. package/lib/mapObject.js +0 -51
  196. package/lib/performance.js +0 -23
  197. package/lib/performanceNow.js +0 -28
  198. package/lib/shallowEqual.js +0 -48
  199. package/lib/toArray.js +0 -57
  200. package/lib/warning.js +0 -61
package/lib/ReactDOM.js CHANGED
@@ -7,170 +7,86 @@
7
7
  * of patent rights can be found in the PATENTS file in the same directory.
8
8
  *
9
9
  * @providesModule ReactDOM
10
- * @typechecks static-only
11
10
  */
12
11
 
12
+ /* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
13
+
13
14
  'use strict';
14
15
 
15
- var ReactElement = require("./ReactElement");
16
- var ReactElementValidator = require("./ReactElementValidator");
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
+ var ReactUpdates = require('./ReactUpdates');
24
+ var ReactVersion = require('./ReactVersion');
17
25
 
18
- var mapObject = require("./mapObject");
26
+ var findDOMNode = require('./findDOMNode');
27
+ var renderSubtreeIntoContainer = require('./renderSubtreeIntoContainer');
28
+ var warning = require('fbjs/lib/warning');
19
29
 
20
- /**
21
- * Create a factory that creates HTML tag elements.
22
- *
23
- * @param {string} tag Tag name (e.g. `div`).
24
- * @private
25
- */
26
- function createDOMFactory(tag) {
27
- if ('production' !== process.env.NODE_ENV) {
28
- return ReactElementValidator.createFactory(tag);
30
+ ReactDefaultInjection.inject();
31
+
32
+ var render = ReactPerf.measure('React', 'render', ReactMount.render);
33
+
34
+ var React = {
35
+ findDOMNode: findDOMNode,
36
+ render: render,
37
+ unmountComponentAtNode: ReactMount.unmountComponentAtNode,
38
+ version: ReactVersion,
39
+
40
+ /* eslint-disable camelcase */
41
+ unstable_batchedUpdates: ReactUpdates.batchedUpdates,
42
+ unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
43
+ };
44
+
45
+ // Inject the runtime into a devtools global hook regardless of browser.
46
+ // Allows for debugging when the hook is injected on the page.
47
+ /* eslint-enable camelcase */
48
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
49
+ __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
50
+ CurrentOwner: ReactCurrentOwner,
51
+ InstanceHandles: ReactInstanceHandles,
52
+ Mount: ReactMount,
53
+ Reconciler: ReactReconciler,
54
+ TextComponent: ReactDOMTextComponent
55
+ });
56
+ }
57
+
58
+ if (process.env.NODE_ENV !== 'production') {
59
+ var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
60
+ if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
61
+
62
+ // First check if devtools is not installed
63
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
64
+ // If we're in Chrome or Firefox, provide a download link if not installed.
65
+ if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
66
+ console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
67
+ }
68
+ }
69
+
70
+ // If we're in IE8, check to see if we are in compatibility mode and provide
71
+ // information on preventing compatibility mode
72
+ var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
73
+
74
+ process.env.NODE_ENV !== 'production' ? 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;
75
+
76
+ var expectedFeatures = [
77
+ // shims
78
+ 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,
79
+
80
+ // shams
81
+ Object.create, Object.freeze];
82
+
83
+ for (var i = 0; i < expectedFeatures.length; i++) {
84
+ if (!expectedFeatures[i]) {
85
+ console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
86
+ break;
87
+ }
88
+ }
29
89
  }
30
- return ReactElement.createFactory(tag);
31
90
  }
32
91
 
33
- /**
34
- * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.
35
- * This is also accessible via `React.DOM`.
36
- *
37
- * @public
38
- */
39
- var ReactDOM = mapObject({
40
- a: 'a',
41
- abbr: 'abbr',
42
- address: 'address',
43
- area: 'area',
44
- article: 'article',
45
- aside: 'aside',
46
- audio: 'audio',
47
- b: 'b',
48
- base: 'base',
49
- bdi: 'bdi',
50
- bdo: 'bdo',
51
- big: 'big',
52
- blockquote: 'blockquote',
53
- body: 'body',
54
- br: 'br',
55
- button: 'button',
56
- canvas: 'canvas',
57
- caption: 'caption',
58
- cite: 'cite',
59
- code: 'code',
60
- col: 'col',
61
- colgroup: 'colgroup',
62
- data: 'data',
63
- datalist: 'datalist',
64
- dd: 'dd',
65
- del: 'del',
66
- details: 'details',
67
- dfn: 'dfn',
68
- dialog: 'dialog',
69
- div: 'div',
70
- dl: 'dl',
71
- dt: 'dt',
72
- em: 'em',
73
- embed: 'embed',
74
- fieldset: 'fieldset',
75
- figcaption: 'figcaption',
76
- figure: 'figure',
77
- footer: 'footer',
78
- form: 'form',
79
- h1: 'h1',
80
- h2: 'h2',
81
- h3: 'h3',
82
- h4: 'h4',
83
- h5: 'h5',
84
- h6: 'h6',
85
- head: 'head',
86
- header: 'header',
87
- hgroup: 'hgroup',
88
- hr: 'hr',
89
- html: 'html',
90
- i: 'i',
91
- iframe: 'iframe',
92
- img: 'img',
93
- input: 'input',
94
- ins: 'ins',
95
- kbd: 'kbd',
96
- keygen: 'keygen',
97
- label: 'label',
98
- legend: 'legend',
99
- li: 'li',
100
- link: 'link',
101
- main: 'main',
102
- map: 'map',
103
- mark: 'mark',
104
- menu: 'menu',
105
- menuitem: 'menuitem',
106
- meta: 'meta',
107
- meter: 'meter',
108
- nav: 'nav',
109
- noscript: 'noscript',
110
- object: 'object',
111
- ol: 'ol',
112
- optgroup: 'optgroup',
113
- option: 'option',
114
- output: 'output',
115
- p: 'p',
116
- param: 'param',
117
- picture: 'picture',
118
- pre: 'pre',
119
- progress: 'progress',
120
- q: 'q',
121
- rp: 'rp',
122
- rt: 'rt',
123
- ruby: 'ruby',
124
- s: 's',
125
- samp: 'samp',
126
- script: 'script',
127
- section: 'section',
128
- select: 'select',
129
- small: 'small',
130
- source: 'source',
131
- span: 'span',
132
- strong: 'strong',
133
- style: 'style',
134
- sub: 'sub',
135
- summary: 'summary',
136
- sup: 'sup',
137
- table: 'table',
138
- tbody: 'tbody',
139
- td: 'td',
140
- textarea: 'textarea',
141
- tfoot: 'tfoot',
142
- th: 'th',
143
- thead: 'thead',
144
- time: 'time',
145
- title: 'title',
146
- tr: 'tr',
147
- track: 'track',
148
- u: 'u',
149
- ul: 'ul',
150
- 'var': 'var',
151
- video: 'video',
152
- wbr: 'wbr',
153
-
154
- // SVG
155
- circle: 'circle',
156
- clipPath: 'clipPath',
157
- defs: 'defs',
158
- ellipse: 'ellipse',
159
- g: 'g',
160
- line: 'line',
161
- linearGradient: 'linearGradient',
162
- mask: 'mask',
163
- path: 'path',
164
- pattern: 'pattern',
165
- polygon: 'polygon',
166
- polyline: 'polyline',
167
- radialGradient: 'radialGradient',
168
- rect: 'rect',
169
- stop: 'stop',
170
- svg: 'svg',
171
- text: 'text',
172
- tspan: 'tspan'
173
-
174
- }, createDOMFactory);
175
-
176
- module.exports = ReactDOM;
92
+ module.exports = React;
@@ -11,51 +11,40 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var AutoFocusMixin = require("./AutoFocusMixin");
15
- var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
16
- var ReactClass = require("./ReactClass");
17
- var ReactElement = require("./ReactElement");
18
-
19
- var keyMirror = require("./keyMirror");
20
-
21
- var button = ReactElement.createFactory('button');
22
-
23
- var mouseListenerNames = keyMirror({
14
+ var mouseListenerNames = {
24
15
  onClick: true,
25
16
  onDoubleClick: true,
26
17
  onMouseDown: true,
27
18
  onMouseMove: true,
28
19
  onMouseUp: true,
20
+
29
21
  onClickCapture: true,
30
22
  onDoubleClickCapture: true,
31
23
  onMouseDownCapture: true,
32
24
  onMouseMoveCapture: true,
33
25
  onMouseUpCapture: true
34
- });
26
+ };
35
27
 
36
28
  /**
37
29
  * Implements a <button> native component that does not receive mouse events
38
30
  * when `disabled` is set.
39
31
  */
40
- var ReactDOMButton = ReactClass.createClass({
41
- displayName: 'ReactDOMButton',
42
- tagName: 'BUTTON',
43
-
44
- mixins: [AutoFocusMixin, ReactBrowserComponentMixin],
45
-
46
- render: function () {
47
- var props = {};
32
+ var ReactDOMButton = {
33
+ getNativeProps: function (inst, props, context) {
34
+ if (!props.disabled) {
35
+ return props;
36
+ }
48
37
 
49
- // Copy the props; except the mouse listeners if we're disabled
50
- for (var key in this.props) {
51
- if (this.props.hasOwnProperty(key) && (!this.props.disabled || !mouseListenerNames[key])) {
52
- props[key] = this.props[key];
38
+ // Copy the props, except the mouse listeners
39
+ var nativeProps = {};
40
+ for (var key in props) {
41
+ if (props.hasOwnProperty(key) && !mouseListenerNames[key]) {
42
+ nativeProps[key] = props[key];
53
43
  }
54
44
  }
55
45
 
56
- return button(props, this.props.children);
46
+ return nativeProps;
57
47
  }
58
-
59
- });
48
+ };
60
49
 
61
50
  module.exports = ReactDOMButton;
@@ -14,23 +14,33 @@
14
14
 
15
15
  'use strict';
16
16
 
17
- var CSSPropertyOperations = require("./CSSPropertyOperations");
18
- var DOMProperty = require("./DOMProperty");
19
- var DOMPropertyOperations = require("./DOMPropertyOperations");
20
- var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
21
- var ReactComponentBrowserEnvironment = require("./ReactComponentBrowserEnvironment");
22
- var ReactMount = require("./ReactMount");
23
- var ReactMultiChild = require("./ReactMultiChild");
24
- var ReactPerf = require("./ReactPerf");
25
-
26
- var assign = require("./Object.assign");
27
- var escapeTextContentForBrowser = require("./escapeTextContentForBrowser");
28
- var invariant = require("./invariant");
29
- var isEventSupported = require("./isEventSupported");
30
- var keyOf = require("./keyOf");
31
- var shallowEqual = require("./shallowEqual");
32
- var validateDOMNesting = require("./validateDOMNesting");
33
- var warning = require("./warning");
17
+ var AutoFocusUtils = require('./AutoFocusUtils');
18
+ var CSSPropertyOperations = require('./CSSPropertyOperations');
19
+ var DOMProperty = require('./DOMProperty');
20
+ var DOMPropertyOperations = require('./DOMPropertyOperations');
21
+ var EventConstants = require('./EventConstants');
22
+ var ReactBrowserEventEmitter = require('./ReactBrowserEventEmitter');
23
+ var ReactComponentBrowserEnvironment = require('./ReactComponentBrowserEnvironment');
24
+ var ReactDOMButton = require('./ReactDOMButton');
25
+ var ReactDOMInput = require('./ReactDOMInput');
26
+ var ReactDOMOption = require('./ReactDOMOption');
27
+ var ReactDOMSelect = require('./ReactDOMSelect');
28
+ var ReactDOMTextarea = require('./ReactDOMTextarea');
29
+ var ReactMount = require('./ReactMount');
30
+ var ReactMultiChild = require('./ReactMultiChild');
31
+ var ReactPerf = require('./ReactPerf');
32
+ var ReactUpdateQueue = require('./ReactUpdateQueue');
33
+
34
+ var assign = require('./Object.assign');
35
+ var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');
36
+ var invariant = require('fbjs/lib/invariant');
37
+ var isEventSupported = require('./isEventSupported');
38
+ var keyOf = require('fbjs/lib/keyOf');
39
+ var setInnerHTML = require('./setInnerHTML');
40
+ var setTextContent = require('./setTextContent');
41
+ var shallowEqual = require('fbjs/lib/shallowEqual');
42
+ var validateDOMNesting = require('./validateDOMNesting');
43
+ var warning = require('fbjs/lib/warning');
34
44
 
35
45
  var deleteListener = ReactBrowserEventEmitter.deleteListener;
36
46
  var listenTo = ReactBrowserEventEmitter.listenTo;
@@ -43,6 +53,90 @@ var STYLE = keyOf({ style: null });
43
53
 
44
54
  var ELEMENT_NODE_TYPE = 1;
45
55
 
56
+ var canDefineProperty = false;
57
+ try {
58
+ Object.defineProperty({}, 'test', { get: function () {} });
59
+ canDefineProperty = true;
60
+ } catch (e) {}
61
+
62
+ function getDeclarationErrorAddendum(internalInstance) {
63
+ if (internalInstance) {
64
+ var owner = internalInstance._currentElement._owner || null;
65
+ if (owner) {
66
+ var name = owner.getName();
67
+ if (name) {
68
+ return ' This DOM node was rendered by `' + name + '`.';
69
+ }
70
+ }
71
+ }
72
+ return '';
73
+ }
74
+
75
+ var legacyPropsDescriptor;
76
+ if (process.env.NODE_ENV !== 'production') {
77
+ legacyPropsDescriptor = {
78
+ props: {
79
+ enumerable: false,
80
+ get: function () {
81
+ var component = this._reactInternalComponent;
82
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .props of a DOM node; instead, ' + 'recreate the props as `render` did originally or read the DOM ' + 'properties/attributes directly from this node (e.g., ' + 'this.refs.box.className).%s', getDeclarationErrorAddendum(component)) : undefined;
83
+ return component._currentElement.props;
84
+ }
85
+ }
86
+ };
87
+ }
88
+
89
+ function legacyGetDOMNode() {
90
+ if (process.env.NODE_ENV !== 'production') {
91
+ var component = this._reactInternalComponent;
92
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .getDOMNode() of a DOM node; ' + 'instead, use the node directly.%s', getDeclarationErrorAddendum(component)) : undefined;
93
+ }
94
+ return this;
95
+ }
96
+
97
+ function legacyIsMounted() {
98
+ var component = this._reactInternalComponent;
99
+ if (process.env.NODE_ENV !== 'production') {
100
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .isMounted() of a DOM node.%s', getDeclarationErrorAddendum(component)) : undefined;
101
+ }
102
+ return !!component;
103
+ }
104
+
105
+ function legacySetStateEtc() {
106
+ if (process.env.NODE_ENV !== 'production') {
107
+ var component = this._reactInternalComponent;
108
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setState(), .replaceState(), or ' + '.forceUpdate() of a DOM node. This is a no-op.%s', getDeclarationErrorAddendum(component)) : undefined;
109
+ }
110
+ }
111
+
112
+ function legacySetProps(partialProps, callback) {
113
+ var component = this._reactInternalComponent;
114
+ if (process.env.NODE_ENV !== 'production') {
115
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' + 'Instead, call ReactDOM.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
116
+ }
117
+ if (!component) {
118
+ return;
119
+ }
120
+ ReactUpdateQueue.enqueueSetPropsInternal(component, partialProps);
121
+ if (callback) {
122
+ ReactUpdateQueue.enqueueCallbackInternal(component, callback);
123
+ }
124
+ }
125
+
126
+ function legacyReplaceProps(partialProps, callback) {
127
+ var component = this._reactInternalComponent;
128
+ if (process.env.NODE_ENV !== 'production') {
129
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' + 'Instead, call ReactDOM.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
130
+ }
131
+ if (!component) {
132
+ return;
133
+ }
134
+ ReactUpdateQueue.enqueueReplacePropsInternal(component, partialProps);
135
+ if (callback) {
136
+ ReactUpdateQueue.enqueueCallbackInternal(component, callback);
137
+ }
138
+ }
139
+
46
140
  var styleMutationWarning = {};
47
141
 
48
142
  function checkAndWarnForMutatedStyle(style1, style2, component) {
@@ -68,15 +162,11 @@ function checkAndWarnForMutatedStyle(style1, style2, component) {
68
162
 
69
163
  styleMutationWarning[hash] = true;
70
164
 
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;
165
+ process.env.NODE_ENV !== 'production' ? 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
166
  }
73
167
 
74
168
  /**
75
- * Optionally injectable operations for mutating the DOM
76
- */
77
- var BackendIDOperations = null;
78
-
79
- /**
169
+ * @param {object} component
80
170
  * @param {?object} props
81
171
  */
82
172
  function assertValidProps(component, props) {
@@ -84,27 +174,27 @@ function assertValidProps(component, props) {
84
174
  return;
85
175
  }
86
176
  // Note the use of `==` which checks for null or undefined.
87
- if ('production' !== process.env.NODE_ENV) {
177
+ if (process.env.NODE_ENV !== 'production') {
88
178
  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;
179
+ process.env.NODE_ENV !== 'production' ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : undefined;
90
180
  }
91
181
  }
92
182
  if (props.dangerouslySetInnerHTML != 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;
183
+ !(props.children == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : undefined;
184
+ !(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML) ? process.env.NODE_ENV !== 'production' ? 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;
95
185
  }
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;
186
+ if (process.env.NODE_ENV !== 'production') {
187
+ process.env.NODE_ENV !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : undefined;
188
+ process.env.NODE_ENV !== 'production' ? 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;
99
189
  }
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;
190
+ !(props.style == null || typeof props.style === 'object') ? process.env.NODE_ENV !== 'production' ? 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.%s', getDeclarationErrorAddendum(component)) : invariant(false) : undefined;
101
191
  }
102
192
 
103
193
  function enqueuePutListener(id, registrationName, listener, transaction) {
104
- if ('production' !== process.env.NODE_ENV) {
194
+ if (process.env.NODE_ENV !== 'production') {
105
195
  // IE8 has no API for event capturing and the `onScroll` event doesn't
106
196
  // bubble.
107
- 'production' !== process.env.NODE_ENV ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : undefined;
197
+ process.env.NODE_ENV !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : undefined;
108
198
  }
109
199
  var container = ReactMount.findReactContainerForID(id);
110
200
  if (container) {
@@ -123,6 +213,71 @@ function putListener() {
123
213
  ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
124
214
  }
125
215
 
216
+ // There are so many media events, it makes sense to just
217
+ // maintain a list rather than create a `trapBubbledEvent` for each
218
+ var mediaEvents = {
219
+ topAbort: 'abort',
220
+ topCanPlay: 'canplay',
221
+ topCanPlayThrough: 'canplaythrough',
222
+ topDurationChange: 'durationchange',
223
+ topEmptied: 'emptied',
224
+ topEncrypted: 'encrypted',
225
+ topEnded: 'ended',
226
+ topError: 'error',
227
+ topLoadedData: 'loadeddata',
228
+ topLoadedMetadata: 'loadedmetadata',
229
+ topLoadStart: 'loadstart',
230
+ topPause: 'pause',
231
+ topPlay: 'play',
232
+ topPlaying: 'playing',
233
+ topProgress: 'progress',
234
+ topRateChange: 'ratechange',
235
+ topSeeked: 'seeked',
236
+ topSeeking: 'seeking',
237
+ topStalled: 'stalled',
238
+ topSuspend: 'suspend',
239
+ topTimeUpdate: 'timeupdate',
240
+ topVolumeChange: 'volumechange',
241
+ topWaiting: 'waiting'
242
+ };
243
+
244
+ function trapBubbledEventsLocal() {
245
+ var inst = this;
246
+ // If a component renders to null or if another component fatals and causes
247
+ // the state of the tree to be corrupted, `node` here can be null.
248
+ !inst._rootNodeID ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Must be mounted to trap events') : invariant(false) : undefined;
249
+ var node = ReactMount.getNode(inst._rootNodeID);
250
+ !node ? process.env.NODE_ENV !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : invariant(false) : undefined;
251
+
252
+ switch (inst._tag) {
253
+ case 'iframe':
254
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
255
+ break;
256
+ case 'video':
257
+ case 'audio':
258
+
259
+ inst._wrapperState.listeners = [];
260
+ // create listener for each media event
261
+ for (var event in mediaEvents) {
262
+ if (mediaEvents.hasOwnProperty(event)) {
263
+ inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));
264
+ }
265
+ }
266
+
267
+ break;
268
+ case 'img':
269
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
270
+ break;
271
+ case 'form':
272
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];
273
+ break;
274
+ }
275
+ }
276
+
277
+ function postUpdateSelectWrapper() {
278
+ ReactDOMSelect.postUpdateWrapper(this);
279
+ }
280
+
126
281
  // For HTML, certain tags should omit their close tag. We keep a whitelist for
127
282
  // those special cased tags.
128
283
 
@@ -142,9 +297,9 @@ var omittedCloseTags = {
142
297
  'source': true,
143
298
  'track': true,
144
299
  'wbr': true
145
- // NOTE: menuitem's close tag should be omitted, but that causes problems.
146
300
  };
147
301
 
302
+ // NOTE: menuitem's close tag should be omitted, but that causes problems.
148
303
  var newlineEatingTags = {
149
304
  'listing': true,
150
305
  'pre': true,
@@ -168,13 +323,13 @@ var hasOwnProperty = ({}).hasOwnProperty;
168
323
 
169
324
  function validateDangerousTag(tag) {
170
325
  if (!hasOwnProperty.call(validatedTagCache, tag)) {
171
- !VALID_TAG_REGEX.test(tag) ? 'production' !== process.env.NODE_ENV ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : undefined;
326
+ !VALID_TAG_REGEX.test(tag) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : undefined;
172
327
  validatedTagCache[tag] = true;
173
328
  }
174
329
  }
175
330
 
176
331
  function processChildContext(context, inst) {
177
- if ('production' !== process.env.NODE_ENV) {
332
+ if (process.env.NODE_ENV !== 'production') {
178
333
  // Pass down our tag name to child components for validation purposes
179
334
  context = assign({}, context);
180
335
  var info = context[validateDOMNesting.ancestorInfoContextKey];
@@ -183,6 +338,10 @@ function processChildContext(context, inst) {
183
338
  return context;
184
339
  }
185
340
 
341
+ function isCustomComponent(tagName, props) {
342
+ return tagName.indexOf('-') >= 0 || props.is != null;
343
+ }
344
+
186
345
  /**
187
346
  * Creates a new React class that is idempotent and capable of containing other
188
347
  * React components. It accepts event listeners and DOM properties that are
@@ -199,11 +358,14 @@ function processChildContext(context, inst) {
199
358
  */
200
359
  function ReactDOMComponent(tag) {
201
360
  validateDangerousTag(tag);
202
- this._tag = tag;
361
+ this._tag = tag.toLowerCase();
203
362
  this._renderedChildren = null;
204
363
  this._previousStyle = null;
205
364
  this._previousStyleCopy = null;
206
365
  this._rootNodeID = null;
366
+ this._wrapperState = null;
367
+ this._topLevelWrapper = null;
368
+ this._nodeWithLegacyProperties = null;
207
369
  }
208
370
 
209
371
  ReactDOMComponent.displayName = 'ReactDOMComponent';
@@ -227,19 +389,80 @@ ReactDOMComponent.Mixin = {
227
389
  mountComponent: function (rootID, transaction, context) {
228
390
  this._rootNodeID = rootID;
229
391
 
230
- assertValidProps(this, this._currentElement.props);
231
- if ('production' !== process.env.NODE_ENV) {
392
+ var props = this._currentElement.props;
393
+
394
+ switch (this._tag) {
395
+ case 'iframe':
396
+ case 'img':
397
+ case 'form':
398
+ case 'video':
399
+ case 'audio':
400
+ this._wrapperState = {
401
+ listeners: null
402
+ };
403
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
404
+ break;
405
+ case 'button':
406
+ props = ReactDOMButton.getNativeProps(this, props, context);
407
+ break;
408
+ case 'input':
409
+ ReactDOMInput.mountWrapper(this, props, context);
410
+ props = ReactDOMInput.getNativeProps(this, props, context);
411
+ break;
412
+ case 'option':
413
+ ReactDOMOption.mountWrapper(this, props, context);
414
+ props = ReactDOMOption.getNativeProps(this, props, context);
415
+ break;
416
+ case 'select':
417
+ ReactDOMSelect.mountWrapper(this, props, context);
418
+ props = ReactDOMSelect.getNativeProps(this, props, context);
419
+ context = ReactDOMSelect.processChildContext(this, props, context);
420
+ break;
421
+ case 'textarea':
422
+ ReactDOMTextarea.mountWrapper(this, props, context);
423
+ props = ReactDOMTextarea.getNativeProps(this, props, context);
424
+ break;
425
+ }
426
+
427
+ assertValidProps(this, props);
428
+ if (process.env.NODE_ENV !== 'production') {
232
429
  if (context[validateDOMNesting.ancestorInfoContextKey]) {
233
430
  validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
234
431
  }
235
432
  }
236
433
 
237
- var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction);
238
- var tagContent = this._createContentMarkup(transaction, context);
239
- if (!tagContent && omittedCloseTags[this._tag]) {
240
- return tagOpen + '/>';
434
+ var mountImage;
435
+ if (transaction.useCreateElement) {
436
+ var ownerDocument = context[ReactMount.ownerDocumentContextKey];
437
+ var el = ownerDocument.createElement(this._currentElement.type);
438
+ DOMPropertyOperations.setAttributeForID(el, this._rootNodeID);
439
+ // Populate node cache
440
+ ReactMount.getID(el);
441
+ this._updateDOMProperties({}, props, transaction, el);
442
+ this._createInitialChildren(transaction, props, context, el);
443
+ mountImage = el;
444
+ } else {
445
+ var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
446
+ var tagContent = this._createContentMarkup(transaction, props, context);
447
+ if (!tagContent && omittedCloseTags[this._tag]) {
448
+ mountImage = tagOpen + '/>';
449
+ } else {
450
+ mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
451
+ }
241
452
  }
242
- return tagOpen + '>' + tagContent + '</' + this._tag + '>';
453
+
454
+ switch (this._tag) {
455
+ case 'button':
456
+ case 'input':
457
+ case 'select':
458
+ case 'textarea':
459
+ if (props.autoFocus) {
460
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
461
+ }
462
+ break;
463
+ }
464
+
465
+ return mountImage;
243
466
  },
244
467
 
245
468
  /**
@@ -252,11 +475,11 @@ ReactDOMComponent.Mixin = {
252
475
  *
253
476
  * @private
254
477
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
478
+ * @param {object} props
255
479
  * @return {string} Markup of opening tag.
256
480
  */
257
- _createOpenTagMarkupAndPutListeners: function (transaction) {
258
- var props = this._currentElement.props;
259
- var ret = '<' + this._tag;
481
+ _createOpenTagMarkupAndPutListeners: function (transaction, props) {
482
+ var ret = '<' + this._currentElement.type;
260
483
 
261
484
  for (var propKey in props) {
262
485
  if (!props.hasOwnProperty(propKey)) {
@@ -271,7 +494,7 @@ ReactDOMComponent.Mixin = {
271
494
  } else {
272
495
  if (propKey === STYLE) {
273
496
  if (propValue) {
274
- if ('production' !== process.env.NODE_ENV) {
497
+ if (process.env.NODE_ENV !== 'production') {
275
498
  // See `_updateDOMProperties`. style block
276
499
  this._previousStyle = propValue;
277
500
  }
@@ -279,7 +502,12 @@ ReactDOMComponent.Mixin = {
279
502
  }
280
503
  propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
281
504
  }
282
- var markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
505
+ var markup = null;
506
+ if (this._tag != null && isCustomComponent(this._tag, props)) {
507
+ markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
508
+ } else {
509
+ markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
510
+ }
283
511
  if (markup) {
284
512
  ret += ' ' + markup;
285
513
  }
@@ -301,12 +529,12 @@ ReactDOMComponent.Mixin = {
301
529
  *
302
530
  * @private
303
531
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
532
+ * @param {object} props
304
533
  * @param {object} context
305
534
  * @return {string} Content markup.
306
535
  */
307
- _createContentMarkup: function (transaction, context) {
536
+ _createContentMarkup: function (transaction, props, context) {
308
537
  var ret = '';
309
- var props = this._currentElement.props;
310
538
 
311
539
  // Intentional use of != to avoid catching zero/false.
312
540
  var innerHTML = props.dangerouslySetInnerHTML;
@@ -342,6 +570,28 @@ ReactDOMComponent.Mixin = {
342
570
  }
343
571
  },
344
572
 
573
+ _createInitialChildren: function (transaction, props, context, el) {
574
+ // Intentional use of != to avoid catching zero/false.
575
+ var innerHTML = props.dangerouslySetInnerHTML;
576
+ if (innerHTML != null) {
577
+ if (innerHTML.__html != null) {
578
+ setInnerHTML(el, innerHTML.__html);
579
+ }
580
+ } else {
581
+ var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
582
+ var childrenToUse = contentToUse != null ? null : props.children;
583
+ if (contentToUse != null) {
584
+ // TODO: Validate that text is allowed as a child of this node
585
+ setTextContent(el, contentToUse);
586
+ } else if (childrenToUse != null) {
587
+ var mountImages = this.mountChildren(childrenToUse, transaction, processChildContext(context, this));
588
+ for (var i = 0; i < mountImages.length; i++) {
589
+ el.appendChild(mountImages[i]);
590
+ }
591
+ }
592
+ }
593
+ },
594
+
345
595
  /**
346
596
  * Receives a next element and updates the component.
347
597
  *
@@ -367,9 +617,47 @@ ReactDOMComponent.Mixin = {
367
617
  * @overridable
368
618
  */
369
619
  updateComponent: function (transaction, prevElement, nextElement, context) {
370
- assertValidProps(this, this._currentElement.props);
371
- this._updateDOMProperties(prevElement.props, transaction);
372
- this._updateDOMChildren(prevElement.props, transaction, processChildContext(context, this));
620
+ var lastProps = prevElement.props;
621
+ var nextProps = this._currentElement.props;
622
+
623
+ switch (this._tag) {
624
+ case 'button':
625
+ lastProps = ReactDOMButton.getNativeProps(this, lastProps);
626
+ nextProps = ReactDOMButton.getNativeProps(this, nextProps);
627
+ break;
628
+ case 'input':
629
+ ReactDOMInput.updateWrapper(this);
630
+ lastProps = ReactDOMInput.getNativeProps(this, lastProps);
631
+ nextProps = ReactDOMInput.getNativeProps(this, nextProps);
632
+ break;
633
+ case 'option':
634
+ lastProps = ReactDOMOption.getNativeProps(this, lastProps);
635
+ nextProps = ReactDOMOption.getNativeProps(this, nextProps);
636
+ break;
637
+ case 'select':
638
+ lastProps = ReactDOMSelect.getNativeProps(this, lastProps);
639
+ nextProps = ReactDOMSelect.getNativeProps(this, nextProps);
640
+ break;
641
+ case 'textarea':
642
+ ReactDOMTextarea.updateWrapper(this);
643
+ lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
644
+ nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
645
+ break;
646
+ }
647
+
648
+ assertValidProps(this, nextProps);
649
+ this._updateDOMProperties(lastProps, nextProps, transaction, null);
650
+ this._updateDOMChildren(lastProps, nextProps, transaction, processChildContext(context, this));
651
+
652
+ if (!canDefineProperty && this._nodeWithLegacyProperties) {
653
+ this._nodeWithLegacyProperties.props = nextProps;
654
+ }
655
+
656
+ if (this._tag === 'select') {
657
+ // <select> value update needs to occur after <option> children
658
+ // reconciliation
659
+ transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
660
+ }
373
661
  },
374
662
 
375
663
  /**
@@ -385,10 +673,11 @@ ReactDOMComponent.Mixin = {
385
673
  *
386
674
  * @private
387
675
  * @param {object} lastProps
676
+ * @param {object} nextProps
388
677
  * @param {ReactReconcileTransaction} transaction
678
+ * @param {?DOMElement} node
389
679
  */
390
- _updateDOMProperties: function (lastProps, transaction) {
391
- var nextProps = this._currentElement.props;
680
+ _updateDOMProperties: function (lastProps, nextProps, transaction, node) {
392
681
  var propKey;
393
682
  var styleName;
394
683
  var styleUpdates;
@@ -412,8 +701,11 @@ ReactDOMComponent.Mixin = {
412
701
  // listener (e.g., onClick={null})
413
702
  deleteListener(this._rootNodeID, propKey);
414
703
  }
415
- } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
416
- BackendIDOperations.deletePropertyByID(this._rootNodeID, propKey);
704
+ } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
705
+ if (!node) {
706
+ node = ReactMount.getNode(this._rootNodeID);
707
+ }
708
+ DOMPropertyOperations.deleteValueForProperty(node, propKey);
417
709
  }
418
710
  }
419
711
  for (propKey in nextProps) {
@@ -424,7 +716,7 @@ ReactDOMComponent.Mixin = {
424
716
  }
425
717
  if (propKey === STYLE) {
426
718
  if (nextProp) {
427
- if ('production' !== process.env.NODE_ENV) {
719
+ if (process.env.NODE_ENV !== 'production') {
428
720
  checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
429
721
  this._previousStyle = nextProp;
430
722
  }
@@ -457,12 +749,30 @@ ReactDOMComponent.Mixin = {
457
749
  } else if (lastProp) {
458
750
  deleteListener(this._rootNodeID, propKey);
459
751
  }
460
- } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
461
- BackendIDOperations.updatePropertyByID(this._rootNodeID, propKey, nextProp);
752
+ } else if (isCustomComponent(this._tag, nextProps)) {
753
+ if (!node) {
754
+ node = ReactMount.getNode(this._rootNodeID);
755
+ }
756
+ DOMPropertyOperations.setValueForAttribute(node, propKey, nextProp);
757
+ } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
758
+ if (!node) {
759
+ node = ReactMount.getNode(this._rootNodeID);
760
+ }
761
+ // If we're updating to null or undefined, we should remove the property
762
+ // from the DOM node instead of inadvertantly setting to a string. This
763
+ // brings us in line with the same behavior we have on initial render.
764
+ if (nextProp != null) {
765
+ DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
766
+ } else {
767
+ DOMPropertyOperations.deleteValueForProperty(node, propKey);
768
+ }
462
769
  }
463
770
  }
464
771
  if (styleUpdates) {
465
- BackendIDOperations.updateStylesByID(this._rootNodeID, styleUpdates);
772
+ if (!node) {
773
+ node = ReactMount.getNode(this._rootNodeID);
774
+ }
775
+ CSSPropertyOperations.setValueForStyles(node, styleUpdates);
466
776
  }
467
777
  },
468
778
 
@@ -471,11 +781,11 @@ ReactDOMComponent.Mixin = {
471
781
  * children content.
472
782
  *
473
783
  * @param {object} lastProps
784
+ * @param {object} nextProps
474
785
  * @param {ReactReconcileTransaction} transaction
786
+ * @param {object} context
475
787
  */
476
- _updateDOMChildren: function (lastProps, transaction, context) {
477
- var nextProps = this._currentElement.props;
478
-
788
+ _updateDOMChildren: function (lastProps, nextProps, transaction, context) {
479
789
  var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
480
790
  var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
481
791
 
@@ -502,7 +812,7 @@ ReactDOMComponent.Mixin = {
502
812
  }
503
813
  } else if (nextHtml != null) {
504
814
  if (lastHtml !== nextHtml) {
505
- BackendIDOperations.updateInnerHTMLByID(this._rootNodeID, nextHtml);
815
+ this.updateMarkup('' + nextHtml);
506
816
  }
507
817
  } else if (nextChildren != null) {
508
818
  this.updateChildren(nextChildren, transaction, context);
@@ -516,10 +826,75 @@ ReactDOMComponent.Mixin = {
516
826
  * @internal
517
827
  */
518
828
  unmountComponent: function () {
829
+ switch (this._tag) {
830
+ case 'iframe':
831
+ case 'img':
832
+ case 'form':
833
+ case 'video':
834
+ case 'audio':
835
+ var listeners = this._wrapperState.listeners;
836
+ if (listeners) {
837
+ for (var i = 0; i < listeners.length; i++) {
838
+ listeners[i].remove();
839
+ }
840
+ }
841
+ break;
842
+ case 'input':
843
+ ReactDOMInput.unmountWrapper(this);
844
+ break;
845
+ case 'html':
846
+ case 'head':
847
+ case 'body':
848
+ /**
849
+ * Components like <html> <head> and <body> can't be removed or added
850
+ * easily in a cross-browser way, however it's valuable to be able to
851
+ * take advantage of React's reconciliation for styling and <title>
852
+ * management. So we just document it and throw in dangerous cases.
853
+ */
854
+ !false ? process.env.NODE_ENV !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is ' + 'impossible to unmount some top-level components (eg <html>, ' + '<head>, and <body>) reliably and efficiently. To fix this, have a ' + 'single top-level component that never unmounts render these ' + 'elements.', this._tag) : invariant(false) : undefined;
855
+ break;
856
+ }
857
+
519
858
  this.unmountChildren();
520
859
  ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
521
860
  ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
522
861
  this._rootNodeID = null;
862
+ this._wrapperState = null;
863
+ if (this._nodeWithLegacyProperties) {
864
+ var node = this._nodeWithLegacyProperties;
865
+ node._reactInternalComponent = null;
866
+ this._nodeWithLegacyProperties = null;
867
+ }
868
+ },
869
+
870
+ getPublicInstance: function () {
871
+ if (!this._nodeWithLegacyProperties) {
872
+ var node = ReactMount.getNode(this._rootNodeID);
873
+
874
+ node._reactInternalComponent = this;
875
+ node.getDOMNode = legacyGetDOMNode;
876
+ node.isMounted = legacyIsMounted;
877
+ node.setState = legacySetStateEtc;
878
+ node.replaceState = legacySetStateEtc;
879
+ node.forceUpdate = legacySetStateEtc;
880
+ node.setProps = legacySetProps;
881
+ node.replaceProps = legacyReplaceProps;
882
+
883
+ if (process.env.NODE_ENV !== 'production') {
884
+ if (canDefineProperty) {
885
+ Object.defineProperties(node, legacyPropsDescriptor);
886
+ } else {
887
+ // updateComponent will update this property on subsequent renders
888
+ node.props = this._currentElement.props;
889
+ }
890
+ } else {
891
+ // updateComponent will update this property on subsequent renders
892
+ node.props = this._currentElement.props;
893
+ }
894
+
895
+ this._nodeWithLegacyProperties = node;
896
+ }
897
+ return this._nodeWithLegacyProperties;
523
898
  }
524
899
 
525
900
  };
@@ -531,10 +906,4 @@ ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
531
906
 
532
907
  assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
533
908
 
534
- ReactDOMComponent.injection = {
535
- injectIDOperations: function (IDOperations) {
536
- ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
537
- }
538
- };
539
-
540
909
  module.exports = ReactDOMComponent;