react 0.14.0-alpha2 → 0.14.0-beta3

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 (196) hide show
  1. package/README.md +5 -2
  2. package/addons.js +6 -3
  3. package/dist/JSXTransformer.js +634 -274
  4. package/dist/react-with-addons.js +5350 -4954
  5. package/dist/react-with-addons.min.js +6 -6
  6. package/dist/react.js +4777 -4408
  7. package/dist/react.min.js +6 -5
  8. package/lib/{AutoFocusMixin.js → AutoFocusUtils.js} +15 -5
  9. package/lib/BeforeInputEventPlugin.js +13 -13
  10. package/lib/CSSProperty.js +3 -0
  11. package/lib/CSSPropertyOperations.js +13 -13
  12. package/lib/CallbackQueue.js +4 -4
  13. package/lib/ChangeEventPlugin.js +16 -14
  14. package/lib/DOMChildrenOperations.js +10 -6
  15. package/lib/DOMProperty.js +82 -117
  16. package/lib/DOMPropertyOperations.js +78 -33
  17. package/lib/Danger.js +14 -14
  18. package/lib/DefaultEventPluginOrder.js +2 -2
  19. package/lib/EnterLeaveEventPlugin.js +8 -8
  20. package/lib/EventConstants.js +23 -1
  21. package/lib/EventPluginHub.js +13 -13
  22. package/lib/EventPluginRegistry.js +8 -8
  23. package/lib/EventPluginUtils.js +17 -17
  24. package/lib/EventPropagators.js +7 -7
  25. package/lib/FallbackCompositionState.js +3 -3
  26. package/lib/HTMLDOMPropertyConfig.js +13 -3
  27. package/lib/LinkedStateMixin.js +2 -2
  28. package/lib/LinkedValueUtils.js +50 -38
  29. package/lib/MetaMatchers.js +118 -0
  30. package/lib/OrderedMap.js +453 -0
  31. package/lib/PooledClass.js +14 -2
  32. package/lib/React.js +6 -6
  33. package/lib/ReactBrowserComponentMixin.js +4 -4
  34. package/lib/ReactBrowserEventEmitter.js +30 -7
  35. package/lib/ReactCSSTransitionGroup.js +16 -5
  36. package/lib/ReactCSSTransitionGroupChild.js +20 -11
  37. package/lib/ReactChildReconciler.js +25 -18
  38. package/lib/ReactChildren.js +9 -9
  39. package/lib/ReactClass.js +65 -83
  40. package/lib/ReactComponent.js +22 -17
  41. package/lib/ReactComponentBrowserEnvironment.js +2 -2
  42. package/lib/ReactComponentEnvironment.js +2 -2
  43. package/lib/ReactComponentWithPureRenderMixin.js +3 -3
  44. package/lib/ReactCompositeComponent.js +80 -111
  45. package/lib/ReactDOM.js +72 -158
  46. package/lib/ReactDOMButton.js +15 -26
  47. package/lib/ReactDOMComponent.js +378 -56
  48. package/lib/ReactDOMFactories.js +177 -0
  49. package/lib/ReactDOMIDOperations.js +23 -23
  50. package/lib/ReactDOMInput.js +83 -99
  51. package/lib/ReactDOMOption.js +25 -45
  52. package/lib/ReactDOMSelect.js +88 -98
  53. package/lib/ReactDOMSelection.js +3 -3
  54. package/lib/ReactDOMServer.js +2 -2
  55. package/lib/ReactDOMTextComponent.js +11 -11
  56. package/lib/ReactDOMTextarea.js +48 -61
  57. package/lib/ReactDefaultBatchingStrategy.js +4 -4
  58. package/lib/ReactDefaultInjection.js +24 -71
  59. package/lib/ReactDefaultPerf.js +7 -7
  60. package/lib/ReactDefaultPerfAnalysis.js +6 -9
  61. package/lib/ReactElement.js +22 -83
  62. package/lib/ReactElementValidator.js +48 -117
  63. package/lib/ReactEmptyComponent.js +4 -4
  64. package/lib/ReactErrorUtils.js +1 -1
  65. package/lib/ReactEventEmitterMixin.js +3 -4
  66. package/lib/ReactEventListener.js +57 -12
  67. package/lib/ReactFragment.js +22 -17
  68. package/lib/ReactInjection.js +11 -11
  69. package/lib/ReactInputSelection.js +8 -7
  70. package/lib/ReactInstanceHandles.js +12 -12
  71. package/lib/ReactIsomorphic.js +11 -11
  72. package/lib/ReactLink.js +1 -1
  73. package/lib/ReactMarkupChecksum.js +6 -2
  74. package/lib/ReactMount.js +88 -88
  75. package/lib/ReactMultiChild.js +83 -22
  76. package/lib/ReactMultiChildUpdateTypes.js +2 -1
  77. package/lib/ReactNativeComponent.js +3 -8
  78. package/lib/ReactNoopUpdateQueue.js +118 -0
  79. package/lib/ReactOwner.js +3 -3
  80. package/lib/ReactPerf.js +2 -2
  81. package/lib/ReactPropTransferer.js +3 -3
  82. package/lib/ReactPropTypeLocationNames.js +1 -1
  83. package/lib/ReactPropTypeLocations.js +1 -1
  84. package/lib/ReactPropTypes.js +49 -11
  85. package/lib/ReactReconcileTransaction.js +8 -8
  86. package/lib/ReactReconciler.js +18 -20
  87. package/lib/ReactRef.js +1 -1
  88. package/lib/ReactServerBatchingStrategy.js +23 -0
  89. package/lib/ReactServerRendering.js +22 -9
  90. package/lib/ReactServerRenderingTransaction.js +7 -7
  91. package/lib/ReactTestUtils.js +80 -58
  92. package/lib/ReactTransitionChildMapping.js +2 -2
  93. package/lib/ReactTransitionEvents.js +1 -1
  94. package/lib/ReactTransitionGroup.js +5 -6
  95. package/lib/ReactUpdateQueue.js +61 -36
  96. package/lib/ReactUpdates.js +14 -17
  97. package/lib/ReactWithAddons.js +14 -16
  98. package/lib/ResponderEventPlugin.js +514 -0
  99. package/lib/ResponderSyntheticEvent.js +40 -0
  100. package/lib/ResponderTouchHistoryStore.js +180 -0
  101. package/lib/SVGDOMPropertyConfig.js +1 -1
  102. package/lib/SelectEventPlugin.js +14 -15
  103. package/lib/SimpleEventPlugin.js +205 -29
  104. package/lib/SyntheticClipboardEvent.js +3 -3
  105. package/lib/SyntheticCompositionEvent.js +3 -3
  106. package/lib/SyntheticDragEvent.js +3 -3
  107. package/lib/SyntheticEvent.js +9 -8
  108. package/lib/SyntheticFocusEvent.js +3 -3
  109. package/lib/SyntheticInputEvent.js +3 -3
  110. package/lib/SyntheticKeyboardEvent.js +6 -6
  111. package/lib/SyntheticMouseEvent.js +5 -5
  112. package/lib/SyntheticTouchEvent.js +4 -4
  113. package/lib/SyntheticUIEvent.js +4 -4
  114. package/lib/SyntheticWheelEvent.js +3 -3
  115. package/lib/TapEventPlugin.js +119 -0
  116. package/lib/Transaction.js +16 -10
  117. package/lib/accumulate.js +44 -0
  118. package/lib/accumulateInto.js +2 -2
  119. package/lib/adler32.js +19 -7
  120. package/lib/cloneWithProps.js +12 -7
  121. package/lib/createHierarchyRenderer.js +85 -0
  122. package/lib/dangerousStyleValue.js +1 -1
  123. package/lib/deprecated.js +47 -0
  124. package/lib/findDOMNode.js +11 -12
  125. package/lib/flattenChildren.js +4 -4
  126. package/lib/forEachAccumulated.js +1 -1
  127. package/lib/getEventCharCode.js +1 -1
  128. package/lib/getEventKey.js +1 -1
  129. package/lib/getEventModifierState.js +0 -1
  130. package/lib/getTestDocument.js +28 -0
  131. package/lib/getTextContentAccessor.js +1 -1
  132. package/lib/instantiateReactComponent.js +24 -20
  133. package/lib/isEventSupported.js +1 -1
  134. package/lib/isTextInputElement.js +2 -1
  135. package/lib/joinClasses.js +1 -1
  136. package/lib/onlyChild.js +3 -3
  137. package/lib/quoteAttributeValueForBrowser.js +1 -1
  138. package/lib/reactComponentExpect.js +210 -0
  139. package/lib/renderSubtreeIntoContainer.js +1 -1
  140. package/lib/setInnerHTML.js +2 -2
  141. package/lib/setTextContent.js +3 -3
  142. package/lib/shallowCompare.js +1 -1
  143. package/lib/sliceChildren.js +51 -0
  144. package/lib/traverseAllChildren.js +15 -14
  145. package/lib/update.js +13 -13
  146. package/lib/validateDOMNesting.js +14 -6
  147. package/lib/webcomponents.js +6379 -0
  148. package/package.json +4 -6
  149. package/react.js +53 -1
  150. package/addons/CSSTransitionGroup.js +0 -1
  151. package/addons/LinkedStateMixin.js +0 -1
  152. package/addons/Perf.js +0 -1
  153. package/addons/PureRenderMixin.js +0 -1
  154. package/addons/TestUtils.js +0 -1
  155. package/addons/TransitionGroup.js +0 -1
  156. package/addons/batchedUpdates.js +0 -1
  157. package/addons/cloneWithProps.js +0 -1
  158. package/addons/createFragment.js +0 -1
  159. package/addons/renderSubtreeIntoContainer.js +0 -1
  160. package/addons/shallowCompare.js +0 -1
  161. package/addons/update.js +0 -1
  162. package/lib/CSSCore.js +0 -97
  163. package/lib/EventListener.js +0 -84
  164. package/lib/ExecutionEnvironment.js +0 -38
  165. package/lib/LocalEventTrapMixin.js +0 -46
  166. package/lib/ReactContext.js +0 -32
  167. package/lib/ReactDOMClient.js +0 -85
  168. package/lib/ReactDOMForm.js +0 -47
  169. package/lib/ReactDOMIframe.js +0 -43
  170. package/lib/ReactDOMImg.js +0 -44
  171. package/lib/ReactLifeCycle.js +0 -35
  172. package/lib/camelize.js +0 -32
  173. package/lib/camelizeStyleName.js +0 -40
  174. package/lib/containsNode.js +0 -55
  175. package/lib/createArrayFromMixed.js +0 -85
  176. package/lib/createFullPageComponent.js +0 -51
  177. package/lib/createNodesFromMarkup.js +0 -84
  178. package/lib/emptyFunction.js +0 -38
  179. package/lib/emptyObject.js +0 -20
  180. package/lib/focusNode.js +0 -26
  181. package/lib/getActiveElement.js +0 -29
  182. package/lib/getMarkupWrap.js +0 -115
  183. package/lib/getUnboundedScrollPosition.js +0 -38
  184. package/lib/hyphenate.js +0 -33
  185. package/lib/hyphenateStyleName.js +0 -39
  186. package/lib/invariant.js +0 -49
  187. package/lib/isNode.js +0 -23
  188. package/lib/isTextNode.js +0 -25
  189. package/lib/keyMirror.js +0 -48
  190. package/lib/keyOf.js +0 -35
  191. package/lib/mapObject.js +0 -51
  192. package/lib/performance.js +0 -23
  193. package/lib/performanceNow.js +0 -28
  194. package/lib/shallowEqual.js +0 -48
  195. package/lib/toArray.js +0 -57
  196. package/lib/warning.js +0 -61
package/lib/ReactDOM.js CHANGED
@@ -7,170 +7,84 @@
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');
17
24
 
18
- var mapObject = require("./mapObject");
25
+ var findDOMNode = require('./findDOMNode');
26
+ var renderSubtreeIntoContainer = require('./renderSubtreeIntoContainer');
27
+ var warning = require('fbjs/lib/warning');
19
28
 
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);
29
+ ReactDefaultInjection.inject();
30
+
31
+ var render = ReactPerf.measure('React', 'render', ReactMount.render);
32
+
33
+ var React = {
34
+ findDOMNode: findDOMNode,
35
+ render: render,
36
+ unmountComponentAtNode: ReactMount.unmountComponentAtNode,
37
+
38
+ /* eslint-disable camelcase */
39
+ unstable_batchedUpdates: ReactUpdates.batchedUpdates,
40
+ unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
41
+ };
42
+
43
+ // Inject the runtime into a devtools global hook regardless of browser.
44
+ // Allows for debugging when the hook is injected on the page.
45
+ /* eslint-enable camelcase */
46
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
47
+ __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
48
+ CurrentOwner: ReactCurrentOwner,
49
+ InstanceHandles: ReactInstanceHandles,
50
+ Mount: ReactMount,
51
+ Reconciler: ReactReconciler,
52
+ TextComponent: ReactDOMTextComponent
53
+ });
54
+ }
55
+
56
+ if (process.env.NODE_ENV !== 'production') {
57
+ var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
58
+ if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
59
+
60
+ // If we're in Chrome, look for the devtools marker and provide a download
61
+ // link if not installed.
62
+ if (navigator.userAgent.indexOf('Chrome') > -1) {
63
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
64
+ console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
65
+ }
66
+ }
67
+
68
+ // If we're in IE8, check to see if we are in combatibility mode and provide
69
+ // information on preventing compatibility mode
70
+ var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
71
+
72
+ 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;
73
+
74
+ var expectedFeatures = [
75
+ // shims
76
+ 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,
77
+
78
+ // shams
79
+ Object.create, Object.freeze];
80
+
81
+ for (var i = 0; i < expectedFeatures.length; i++) {
82
+ if (!expectedFeatures[i]) {
83
+ console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
84
+ break;
85
+ }
86
+ }
29
87
  }
30
- return ReactElement.createFactory(tag);
31
88
  }
32
89
 
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;
90
+ 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,31 @@
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 shallowEqual = require('fbjs/lib/shallowEqual');
40
+ var validateDOMNesting = require('./validateDOMNesting');
41
+ var warning = require('fbjs/lib/warning');
34
42
 
35
43
  var deleteListener = ReactBrowserEventEmitter.deleteListener;
36
44
  var listenTo = ReactBrowserEventEmitter.listenTo;
@@ -43,6 +51,90 @@ var STYLE = keyOf({ style: null });
43
51
 
44
52
  var ELEMENT_NODE_TYPE = 1;
45
53
 
54
+ var canDefineProperty = false;
55
+ try {
56
+ Object.defineProperty({}, 'test', { get: function () {} });
57
+ canDefineProperty = true;
58
+ } catch (e) {}
59
+
60
+ function getDeclarationErrorAddendum(internalInstance) {
61
+ if (internalInstance) {
62
+ var owner = internalInstance._currentElement._owner || null;
63
+ if (owner) {
64
+ var name = owner.getName();
65
+ if (name) {
66
+ return ' This DOM node was rendered by `' + name + '`.';
67
+ }
68
+ }
69
+ }
70
+ return '';
71
+ }
72
+
73
+ var legacyPropsDescriptor;
74
+ if (process.env.NODE_ENV !== 'production') {
75
+ legacyPropsDescriptor = {
76
+ props: {
77
+ enumerable: false,
78
+ get: function () {
79
+ var component = this._reactInternalComponent;
80
+ 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;
81
+ return component._currentElement.props;
82
+ }
83
+ }
84
+ };
85
+ }
86
+
87
+ function legacyGetDOMNode() {
88
+ if (process.env.NODE_ENV !== 'production') {
89
+ var component = this._reactInternalComponent;
90
+ 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;
91
+ }
92
+ return this;
93
+ }
94
+
95
+ function legacyIsMounted() {
96
+ var component = this._reactInternalComponent;
97
+ if (process.env.NODE_ENV !== 'production') {
98
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .isMounted() of a DOM node.%s', getDeclarationErrorAddendum(component)) : undefined;
99
+ }
100
+ return !!component;
101
+ }
102
+
103
+ function legacySetStateEtc() {
104
+ if (process.env.NODE_ENV !== 'production') {
105
+ var component = this._reactInternalComponent;
106
+ 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;
107
+ }
108
+ }
109
+
110
+ function legacySetProps(partialProps, callback) {
111
+ var component = this._reactInternalComponent;
112
+ if (process.env.NODE_ENV !== 'production') {
113
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' + 'Instead, call React.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
114
+ }
115
+ if (!component) {
116
+ return;
117
+ }
118
+ ReactUpdateQueue.enqueueSetPropsInternal(component, partialProps);
119
+ if (callback) {
120
+ ReactUpdateQueue.enqueueCallbackInternal(component, callback);
121
+ }
122
+ }
123
+
124
+ function legacyReplaceProps(partialProps, callback) {
125
+ var component = this._reactInternalComponent;
126
+ if (process.env.NODE_ENV !== 'production') {
127
+ process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' + 'Instead, call React.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
128
+ }
129
+ if (!component) {
130
+ return;
131
+ }
132
+ ReactUpdateQueue.enqueueReplacePropsInternal(component, partialProps);
133
+ if (callback) {
134
+ ReactUpdateQueue.enqueueCallbackInternal(component, callback);
135
+ }
136
+ }
137
+
46
138
  var styleMutationWarning = {};
47
139
 
48
140
  function checkAndWarnForMutatedStyle(style1, style2, component) {
@@ -68,7 +160,7 @@ function checkAndWarnForMutatedStyle(style1, style2, component) {
68
160
 
69
161
  styleMutationWarning[hash] = true;
70
162
 
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;
163
+ 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
164
  }
73
165
 
74
166
  /**
@@ -77,6 +169,7 @@ function checkAndWarnForMutatedStyle(style1, style2, component) {
77
169
  var BackendIDOperations = null;
78
170
 
79
171
  /**
172
+ * @param {object} component
80
173
  * @param {?object} props
81
174
  */
82
175
  function assertValidProps(component, props) {
@@ -84,27 +177,27 @@ function assertValidProps(component, props) {
84
177
  return;
85
178
  }
86
179
  // Note the use of `==` which checks for null or undefined.
87
- if ('production' !== process.env.NODE_ENV) {
180
+ if (process.env.NODE_ENV !== 'production') {
88
181
  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;
182
+ 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
183
  }
91
184
  }
92
185
  if (props.dangerouslySetInnerHTML != 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);
186
+ !(props.children == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : undefined;
187
+ !(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
188
  }
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;
189
+ if (process.env.NODE_ENV !== 'production') {
190
+ process.env.NODE_ENV !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : undefined;
191
+ 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
192
  }
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');
193
+ !(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.') : invariant(false) : undefined;
101
194
  }
102
195
 
103
196
  function enqueuePutListener(id, registrationName, listener, transaction) {
104
- if ('production' !== process.env.NODE_ENV) {
197
+ if (process.env.NODE_ENV !== 'production') {
105
198
  // IE8 has no API for event capturing and the `onScroll` event doesn't
106
199
  // bubble.
107
- 'production' !== process.env.NODE_ENV ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : null;
200
+ process.env.NODE_ENV !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : undefined;
108
201
  }
109
202
  var container = ReactMount.findReactContainerForID(id);
110
203
  if (container) {
@@ -123,6 +216,71 @@ function putListener() {
123
216
  ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
124
217
  }
125
218
 
219
+ // There are so many media events, it makes sense to just
220
+ // maintain a list rather than create a `trapBubbledEvent` for each
221
+ var mediaEvents = {
222
+ topAbort: 'abort',
223
+ topCanPlay: 'canplay',
224
+ topCanPlayThrough: 'canplaythrough',
225
+ topDurationChange: 'durationchange',
226
+ topEmptied: 'emptied',
227
+ topEncrypted: 'encrypted',
228
+ topEnded: 'ended',
229
+ topError: 'error',
230
+ topLoadedData: 'loadeddata',
231
+ topLoadedMetadata: 'loadedmetadata',
232
+ topLoadStart: 'loadstart',
233
+ topPause: 'pause',
234
+ topPlay: 'play',
235
+ topPlaying: 'playing',
236
+ topProgress: 'progress',
237
+ topRateChange: 'ratechange',
238
+ topSeeked: 'seeked',
239
+ topSeeking: 'seeking',
240
+ topStalled: 'stalled',
241
+ topSuspend: 'suspend',
242
+ topTimeUpdate: 'timeupdate',
243
+ topVolumeChange: 'volumechange',
244
+ topWaiting: 'waiting'
245
+ };
246
+
247
+ function trapBubbledEventsLocal() {
248
+ var inst = this;
249
+ // If a component renders to null or if another component fatals and causes
250
+ // the state of the tree to be corrupted, `node` here can be null.
251
+ !inst._rootNodeID ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Must be mounted to trap events') : invariant(false) : undefined;
252
+ var node = ReactMount.getNode(inst._rootNodeID);
253
+ !node ? process.env.NODE_ENV !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : invariant(false) : undefined;
254
+
255
+ switch (inst._tag) {
256
+ case 'iframe':
257
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
258
+ break;
259
+ case 'video':
260
+ case 'audio':
261
+
262
+ inst._wrapperState.listeners = [];
263
+ // create listener for each media event
264
+ for (var event in mediaEvents) {
265
+ if (mediaEvents.hasOwnProperty(event)) {
266
+ inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));
267
+ }
268
+ }
269
+
270
+ break;
271
+ case 'img':
272
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
273
+ break;
274
+ case 'form':
275
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];
276
+ break;
277
+ }
278
+ }
279
+
280
+ function postUpdateSelectWrapper() {
281
+ ReactDOMSelect.postUpdateWrapper(this);
282
+ }
283
+
126
284
  // For HTML, certain tags should omit their close tag. We keep a whitelist for
127
285
  // those special cased tags.
128
286
 
@@ -142,9 +300,9 @@ var omittedCloseTags = {
142
300
  'source': true,
143
301
  'track': true,
144
302
  'wbr': true
145
- // NOTE: menuitem's close tag should be omitted, but that causes problems.
146
303
  };
147
304
 
305
+ // NOTE: menuitem's close tag should be omitted, but that causes problems.
148
306
  var newlineEatingTags = {
149
307
  'listing': true,
150
308
  'pre': true,
@@ -168,13 +326,13 @@ var hasOwnProperty = ({}).hasOwnProperty;
168
326
 
169
327
  function validateDangerousTag(tag) {
170
328
  if (!hasOwnProperty.call(validatedTagCache, tag)) {
171
- 'production' !== process.env.NODE_ENV ? invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag) : invariant(VALID_TAG_REGEX.test(tag));
329
+ !VALID_TAG_REGEX.test(tag) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : undefined;
172
330
  validatedTagCache[tag] = true;
173
331
  }
174
332
  }
175
333
 
176
334
  function processChildContext(context, inst) {
177
- if ('production' !== process.env.NODE_ENV) {
335
+ if (process.env.NODE_ENV !== 'production') {
178
336
  // Pass down our tag name to child components for validation purposes
179
337
  context = assign({}, context);
180
338
  var info = context[validateDOMNesting.ancestorInfoContextKey];
@@ -183,6 +341,10 @@ function processChildContext(context, inst) {
183
341
  return context;
184
342
  }
185
343
 
344
+ function isCustomComponent(tagName, props) {
345
+ return tagName.indexOf('-') >= 0 || props.is != null;
346
+ }
347
+
186
348
  /**
187
349
  * Creates a new React class that is idempotent and capable of containing other
188
350
  * React components. It accepts event listeners and DOM properties that are
@@ -199,11 +361,14 @@ function processChildContext(context, inst) {
199
361
  */
200
362
  function ReactDOMComponent(tag) {
201
363
  validateDangerousTag(tag);
202
- this._tag = tag;
364
+ this._tag = tag.toLowerCase();
203
365
  this._renderedChildren = null;
204
366
  this._previousStyle = null;
205
367
  this._previousStyleCopy = null;
206
368
  this._rootNodeID = null;
369
+ this._wrapperState = null;
370
+ this._topLevelWrapper = null;
371
+ this._nodeWithLegacyProperties = null;
207
372
  }
208
373
 
209
374
  ReactDOMComponent.displayName = 'ReactDOMComponent';
@@ -227,19 +392,66 @@ ReactDOMComponent.Mixin = {
227
392
  mountComponent: function (rootID, transaction, context) {
228
393
  this._rootNodeID = rootID;
229
394
 
230
- assertValidProps(this, this._currentElement.props);
231
- if ('production' !== process.env.NODE_ENV) {
395
+ var props = this._currentElement.props;
396
+
397
+ switch (this._tag) {
398
+ case 'iframe':
399
+ case 'img':
400
+ case 'form':
401
+ case 'video':
402
+ case 'audio':
403
+ this._wrapperState = {
404
+ listeners: null
405
+ };
406
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
407
+ break;
408
+ case 'button':
409
+ props = ReactDOMButton.getNativeProps(this, props, context);
410
+ break;
411
+ case 'input':
412
+ ReactDOMInput.mountWrapper(this, props, context);
413
+ props = ReactDOMInput.getNativeProps(this, props, context);
414
+ break;
415
+ case 'option':
416
+ ReactDOMOption.mountWrapper(this, props, context);
417
+ props = ReactDOMOption.getNativeProps(this, props, context);
418
+ break;
419
+ case 'select':
420
+ ReactDOMSelect.mountWrapper(this, props, context);
421
+ props = ReactDOMSelect.getNativeProps(this, props, context);
422
+ context = ReactDOMSelect.processChildContext(this, props, context);
423
+ break;
424
+ case 'textarea':
425
+ ReactDOMTextarea.mountWrapper(this, props, context);
426
+ props = ReactDOMTextarea.getNativeProps(this, props, context);
427
+ break;
428
+ }
429
+
430
+ assertValidProps(this, props);
431
+ if (process.env.NODE_ENV !== 'production') {
232
432
  if (context[validateDOMNesting.ancestorInfoContextKey]) {
233
433
  validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
234
434
  }
235
435
  }
236
436
 
237
- var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction);
238
- var tagContent = this._createContentMarkup(transaction, context);
437
+ var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
438
+ var tagContent = this._createContentMarkup(transaction, props, context);
439
+
440
+ switch (this._tag) {
441
+ case 'button':
442
+ case 'input':
443
+ case 'select':
444
+ case 'textarea':
445
+ if (props.autoFocus) {
446
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
447
+ }
448
+ break;
449
+ }
450
+
239
451
  if (!tagContent && omittedCloseTags[this._tag]) {
240
452
  return tagOpen + '/>';
241
453
  }
242
- return tagOpen + '>' + tagContent + '</' + this._tag + '>';
454
+ return tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
243
455
  },
244
456
 
245
457
  /**
@@ -252,11 +464,11 @@ ReactDOMComponent.Mixin = {
252
464
  *
253
465
  * @private
254
466
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
467
+ * @param {object} props
255
468
  * @return {string} Markup of opening tag.
256
469
  */
257
- _createOpenTagMarkupAndPutListeners: function (transaction) {
258
- var props = this._currentElement.props;
259
- var ret = '<' + this._tag;
470
+ _createOpenTagMarkupAndPutListeners: function (transaction, props) {
471
+ var ret = '<' + this._currentElement.type;
260
472
 
261
473
  for (var propKey in props) {
262
474
  if (!props.hasOwnProperty(propKey)) {
@@ -271,7 +483,7 @@ ReactDOMComponent.Mixin = {
271
483
  } else {
272
484
  if (propKey === STYLE) {
273
485
  if (propValue) {
274
- if ('production' !== process.env.NODE_ENV) {
486
+ if (process.env.NODE_ENV !== 'production') {
275
487
  // See `_updateDOMProperties`. style block
276
488
  this._previousStyle = propValue;
277
489
  }
@@ -279,7 +491,12 @@ ReactDOMComponent.Mixin = {
279
491
  }
280
492
  propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
281
493
  }
282
- var markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
494
+ var markup = null;
495
+ if (this._tag != null && isCustomComponent(this._tag, props)) {
496
+ markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
497
+ } else {
498
+ markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
499
+ }
283
500
  if (markup) {
284
501
  ret += ' ' + markup;
285
502
  }
@@ -301,12 +518,12 @@ ReactDOMComponent.Mixin = {
301
518
  *
302
519
  * @private
303
520
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
521
+ * @param {object} props
304
522
  * @param {object} context
305
523
  * @return {string} Content markup.
306
524
  */
307
- _createContentMarkup: function (transaction, context) {
525
+ _createContentMarkup: function (transaction, props, context) {
308
526
  var ret = '';
309
- var props = this._currentElement.props;
310
527
 
311
528
  // Intentional use of != to avoid catching zero/false.
312
529
  var innerHTML = props.dangerouslySetInnerHTML;
@@ -367,9 +584,47 @@ ReactDOMComponent.Mixin = {
367
584
  * @overridable
368
585
  */
369
586
  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));
587
+ var lastProps = prevElement.props;
588
+ var nextProps = this._currentElement.props;
589
+
590
+ switch (this._tag) {
591
+ case 'button':
592
+ lastProps = ReactDOMButton.getNativeProps(this, lastProps);
593
+ nextProps = ReactDOMButton.getNativeProps(this, nextProps);
594
+ break;
595
+ case 'input':
596
+ ReactDOMInput.updateWrapper(this);
597
+ lastProps = ReactDOMInput.getNativeProps(this, lastProps);
598
+ nextProps = ReactDOMInput.getNativeProps(this, nextProps);
599
+ break;
600
+ case 'option':
601
+ lastProps = ReactDOMOption.getNativeProps(this, lastProps);
602
+ nextProps = ReactDOMOption.getNativeProps(this, nextProps);
603
+ break;
604
+ case 'select':
605
+ lastProps = ReactDOMSelect.getNativeProps(this, lastProps);
606
+ nextProps = ReactDOMSelect.getNativeProps(this, nextProps);
607
+ break;
608
+ case 'textarea':
609
+ ReactDOMTextarea.updateWrapper(this);
610
+ lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
611
+ nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
612
+ break;
613
+ }
614
+
615
+ assertValidProps(this, nextProps);
616
+ this._updateDOMProperties(lastProps, nextProps, transaction);
617
+ this._updateDOMChildren(lastProps, nextProps, transaction, processChildContext(context, this));
618
+
619
+ if (!canDefineProperty && this._nodeWithLegacyProperties) {
620
+ this._nodeWithLegacyProperties.props = nextProps;
621
+ }
622
+
623
+ if (this._tag === 'select') {
624
+ // <select> value update needs to occur after <option> children
625
+ // reconciliation
626
+ transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
627
+ }
373
628
  },
374
629
 
375
630
  /**
@@ -385,10 +640,10 @@ ReactDOMComponent.Mixin = {
385
640
  *
386
641
  * @private
387
642
  * @param {object} lastProps
643
+ * @param {object} nextProps
388
644
  * @param {ReactReconcileTransaction} transaction
389
645
  */
390
- _updateDOMProperties: function (lastProps, transaction) {
391
- var nextProps = this._currentElement.props;
646
+ _updateDOMProperties: function (lastProps, nextProps, transaction) {
392
647
  var propKey;
393
648
  var styleName;
394
649
  var styleUpdates;
@@ -412,7 +667,7 @@ ReactDOMComponent.Mixin = {
412
667
  // listener (e.g., onClick={null})
413
668
  deleteListener(this._rootNodeID, propKey);
414
669
  }
415
- } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
670
+ } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
416
671
  BackendIDOperations.deletePropertyByID(this._rootNodeID, propKey);
417
672
  }
418
673
  }
@@ -424,7 +679,7 @@ ReactDOMComponent.Mixin = {
424
679
  }
425
680
  if (propKey === STYLE) {
426
681
  if (nextProp) {
427
- if ('production' !== process.env.NODE_ENV) {
682
+ if (process.env.NODE_ENV !== 'production') {
428
683
  checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
429
684
  this._previousStyle = nextProp;
430
685
  }
@@ -457,7 +712,9 @@ ReactDOMComponent.Mixin = {
457
712
  } else if (lastProp) {
458
713
  deleteListener(this._rootNodeID, propKey);
459
714
  }
460
- } else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
715
+ } else if (isCustomComponent(this._tag, nextProps)) {
716
+ BackendIDOperations.updateAttributeByID(this._rootNodeID, propKey, nextProp);
717
+ } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
461
718
  BackendIDOperations.updatePropertyByID(this._rootNodeID, propKey, nextProp);
462
719
  }
463
720
  }
@@ -471,11 +728,11 @@ ReactDOMComponent.Mixin = {
471
728
  * children content.
472
729
  *
473
730
  * @param {object} lastProps
731
+ * @param {object} nextProps
474
732
  * @param {ReactReconcileTransaction} transaction
733
+ * @param {object} context
475
734
  */
476
- _updateDOMChildren: function (lastProps, transaction, context) {
477
- var nextProps = this._currentElement.props;
478
-
735
+ _updateDOMChildren: function (lastProps, nextProps, transaction, context) {
479
736
  var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
480
737
  var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
481
738
 
@@ -502,7 +759,7 @@ ReactDOMComponent.Mixin = {
502
759
  }
503
760
  } else if (nextHtml != null) {
504
761
  if (lastHtml !== nextHtml) {
505
- BackendIDOperations.updateInnerHTMLByID(this._rootNodeID, nextHtml);
762
+ this.updateMarkup('' + nextHtml);
506
763
  }
507
764
  } else if (nextChildren != null) {
508
765
  this.updateChildren(nextChildren, transaction, context);
@@ -516,10 +773,75 @@ ReactDOMComponent.Mixin = {
516
773
  * @internal
517
774
  */
518
775
  unmountComponent: function () {
776
+ switch (this._tag) {
777
+ case 'iframe':
778
+ case 'img':
779
+ case 'form':
780
+ case 'video':
781
+ case 'audio':
782
+ var listeners = this._wrapperState.listeners;
783
+ if (listeners) {
784
+ for (var i = 0; i < listeners.length; i++) {
785
+ listeners[i].remove();
786
+ }
787
+ }
788
+ break;
789
+ case 'input':
790
+ ReactDOMInput.unmountWrapper(this);
791
+ break;
792
+ case 'html':
793
+ case 'head':
794
+ case 'body':
795
+ /**
796
+ * Components like <html> <head> and <body> can't be removed or added
797
+ * easily in a cross-browser way, however it's valuable to be able to
798
+ * take advantage of React's reconciliation for styling and <title>
799
+ * management. So we just document it and throw in dangerous cases.
800
+ */
801
+ !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;
802
+ break;
803
+ }
804
+
519
805
  this.unmountChildren();
520
806
  ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
521
807
  ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
522
808
  this._rootNodeID = null;
809
+ this._wrapperState = null;
810
+ if (this._nodeWithLegacyProperties) {
811
+ var node = this._nodeWithLegacyProperties;
812
+ node._reactInternalComponent = null;
813
+ this._nodeWithLegacyProperties = null;
814
+ }
815
+ },
816
+
817
+ getPublicInstance: function () {
818
+ if (!this._nodeWithLegacyProperties) {
819
+ var node = ReactMount.getNode(this._rootNodeID);
820
+
821
+ node._reactInternalComponent = this;
822
+ node.getDOMNode = legacyGetDOMNode;
823
+ node.isMounted = legacyIsMounted;
824
+ node.setState = legacySetStateEtc;
825
+ node.replaceState = legacySetStateEtc;
826
+ node.forceUpdate = legacySetStateEtc;
827
+ node.setProps = legacySetProps;
828
+ node.replaceProps = legacyReplaceProps;
829
+
830
+ if (process.env.NODE_ENV !== 'production') {
831
+ if (canDefineProperty) {
832
+ Object.defineProperties(node, legacyPropsDescriptor);
833
+ } else {
834
+ // updateComponent will update this property on subsequent renders
835
+ node.props = this._currentElement.props;
836
+ }
837
+ } else {
838
+ // updateComponent will update this property on subsequent renders
839
+ node.props = this._currentElement.props;
840
+ }
841
+
842
+ this._nodeWithLegacyProperties = node;
843
+ }
844
+ return this._nodeWithLegacyProperties;
523
845
  }
524
846
 
525
847
  };