react-test-renderer 15.5.0 → 15.5.4

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 (168) hide show
  1. package/lib/ReactShallowRenderer.js +6 -0
  2. package/lib/shallow/ARIADOMPropertyConfig.js +73 -0
  3. package/lib/shallow/AutoFocusUtils.js +23 -0
  4. package/lib/shallow/BeforeInputEventPlugin.js +384 -0
  5. package/lib/shallow/CSSProperty.js +147 -0
  6. package/lib/shallow/CSSPropertyOperations.js +208 -0
  7. package/lib/shallow/CallbackQueue.js +118 -0
  8. package/lib/shallow/ChangeEventPlugin.js +345 -0
  9. package/lib/shallow/DOMChildrenOperations.js +224 -0
  10. package/lib/shallow/DOMLazyTree.js +117 -0
  11. package/lib/shallow/DOMNamespaces.js +19 -0
  12. package/lib/shallow/DOMProperty.js +209 -0
  13. package/lib/shallow/DOMPropertyOperations.js +236 -0
  14. package/lib/shallow/Danger.js +47 -0
  15. package/lib/shallow/DefaultEventPluginOrder.js +25 -0
  16. package/lib/shallow/EnterLeaveEventPlugin.js +99 -0
  17. package/lib/shallow/EventConstants.js +91 -0
  18. package/lib/shallow/EventPluginHub.js +277 -0
  19. package/lib/shallow/EventPluginRegistry.js +254 -0
  20. package/lib/shallow/EventPluginUtils.js +225 -0
  21. package/lib/shallow/EventPropagators.js +133 -0
  22. package/lib/shallow/FallbackCompositionState.js +94 -0
  23. package/lib/shallow/HTMLDOMPropertyConfig.js +235 -0
  24. package/lib/shallow/KeyEscapeUtils.js +58 -0
  25. package/lib/shallow/LinkedValueUtils.js +137 -0
  26. package/lib/shallow/PluginModuleType.js +12 -0
  27. package/lib/shallow/PooledClass.js +111 -0
  28. package/lib/shallow/ReactBrowserEventEmitter.js +327 -0
  29. package/lib/shallow/ReactChildFiber.js +243 -0
  30. package/lib/shallow/ReactChildReconciler.js +153 -0
  31. package/lib/shallow/ReactComponentBrowserEnvironment.js +29 -0
  32. package/lib/shallow/ReactComponentEnvironment.js +45 -0
  33. package/lib/shallow/ReactCompositeComponent.js +901 -0
  34. package/lib/shallow/ReactCoroutine.js +80 -0
  35. package/lib/shallow/ReactDOM.js +110 -0
  36. package/lib/shallow/ReactDOMComponent.js +1000 -0
  37. package/lib/shallow/ReactDOMComponentFlags.js +17 -0
  38. package/lib/shallow/ReactDOMComponentTree.js +194 -0
  39. package/lib/shallow/ReactDOMContainerInfo.js +32 -0
  40. package/lib/shallow/ReactDOMEmptyComponent.js +59 -0
  41. package/lib/shallow/ReactDOMFeatureFlags.js +18 -0
  42. package/lib/shallow/ReactDOMFiber.js +97 -0
  43. package/lib/shallow/ReactDOMIDOperations.js +33 -0
  44. package/lib/shallow/ReactDOMInput.js +284 -0
  45. package/lib/shallow/ReactDOMInvalidARIAHook.js +92 -0
  46. package/lib/shallow/ReactDOMNullInputValuePropHook.js +42 -0
  47. package/lib/shallow/ReactDOMOption.js +122 -0
  48. package/lib/shallow/ReactDOMSelect.js +199 -0
  49. package/lib/shallow/ReactDOMSelection.js +211 -0
  50. package/lib/shallow/ReactDOMServer.js +25 -0
  51. package/lib/shallow/ReactDOMTextComponent.js +163 -0
  52. package/lib/shallow/ReactDOMTextarea.js +159 -0
  53. package/lib/shallow/ReactDOMTreeTraversal.js +135 -0
  54. package/lib/shallow/ReactDOMUnknownPropertyHook.js +111 -0
  55. package/lib/shallow/ReactDebugTool.js +358 -0
  56. package/lib/shallow/ReactDefaultBatchingStrategy.js +67 -0
  57. package/lib/shallow/ReactDefaultInjection.js +85 -0
  58. package/lib/shallow/ReactElementSymbol.js +19 -0
  59. package/lib/shallow/ReactEmptyComponent.js +29 -0
  60. package/lib/shallow/ReactErrorUtils.js +75 -0
  61. package/lib/shallow/ReactEventEmitterMixin.js +32 -0
  62. package/lib/shallow/ReactEventListener.js +154 -0
  63. package/lib/shallow/ReactFeatureFlags.js +21 -0
  64. package/lib/shallow/ReactFiber.js +190 -0
  65. package/lib/shallow/ReactFiberBeginWork.js +380 -0
  66. package/lib/shallow/ReactFiberCommitWork.js +78 -0
  67. package/lib/shallow/ReactFiberCompleteWork.js +208 -0
  68. package/lib/shallow/ReactFiberReconciler.js +64 -0
  69. package/lib/shallow/ReactFiberRoot.js +29 -0
  70. package/lib/shallow/ReactFiberScheduler.js +331 -0
  71. package/lib/shallow/ReactFiberUpdateQueue.js +77 -0
  72. package/lib/shallow/ReactHostComponent.js +67 -0
  73. package/lib/shallow/ReactHostOperationHistoryHook.js +33 -0
  74. package/lib/shallow/ReactInjection.js +33 -0
  75. package/lib/shallow/ReactInputSelection.js +123 -0
  76. package/lib/shallow/ReactInstanceMap.js +47 -0
  77. package/lib/shallow/ReactInstanceType.js +12 -0
  78. package/lib/shallow/ReactInstrumentation.js +23 -0
  79. package/lib/shallow/ReactInvalidSetStateWarningHook.js +36 -0
  80. package/lib/shallow/ReactMarkupChecksum.js +49 -0
  81. package/lib/shallow/ReactMount.js +537 -0
  82. package/lib/shallow/ReactMultiChild.js +449 -0
  83. package/lib/shallow/ReactMultiChildUpdateTypes.js +18 -0
  84. package/lib/shallow/ReactNodeTypes.js +39 -0
  85. package/lib/shallow/ReactOwner.js +93 -0
  86. package/lib/shallow/ReactPerf.js +500 -0
  87. package/lib/shallow/ReactPriorityLevel.js +20 -0
  88. package/lib/shallow/ReactPropTypeLocationNames.js +24 -0
  89. package/lib/shallow/ReactPropTypeLocations.js +12 -0
  90. package/lib/shallow/ReactPropTypesSecret.js +16 -0
  91. package/lib/shallow/ReactReconcileTransaction.js +177 -0
  92. package/lib/shallow/ReactReconciler.js +167 -0
  93. package/lib/shallow/ReactRef.js +88 -0
  94. package/lib/shallow/ReactReifiedYield.js +30 -0
  95. package/lib/shallow/ReactServerBatchingStrategy.js +21 -0
  96. package/lib/shallow/ReactServerRendering.js +89 -0
  97. package/lib/shallow/ReactServerRenderingTransaction.js +89 -0
  98. package/lib/shallow/ReactServerUpdateQueue.js +138 -0
  99. package/lib/shallow/ReactShallowRenderer.js +150 -0
  100. package/lib/shallow/ReactSimpleEmptyComponent.js +36 -0
  101. package/lib/shallow/ReactSyntheticEventType.js +14 -0
  102. package/lib/shallow/ReactTestEmptyComponent.js +36 -0
  103. package/lib/shallow/ReactTestMount.js +131 -0
  104. package/lib/shallow/ReactTestReconcileTransaction.js +128 -0
  105. package/lib/shallow/ReactTestRenderer.js +139 -0
  106. package/lib/shallow/ReactTestTextComponent.js +40 -0
  107. package/lib/shallow/ReactTypeOfWork.js +23 -0
  108. package/lib/shallow/ReactTypes.js +12 -0
  109. package/lib/shallow/ReactUpdateQueue.js +235 -0
  110. package/lib/shallow/ReactUpdates.js +250 -0
  111. package/lib/shallow/ReactVersion.js +13 -0
  112. package/lib/shallow/ResponderEventPlugin.js +507 -0
  113. package/lib/shallow/ResponderSyntheticEvent.js +38 -0
  114. package/lib/shallow/ResponderTouchHistoryStore.js +183 -0
  115. package/lib/shallow/SVGDOMPropertyConfig.js +301 -0
  116. package/lib/shallow/SelectEventPlugin.js +190 -0
  117. package/lib/shallow/SimpleEventPlugin.js +227 -0
  118. package/lib/shallow/SyntheticAnimationEvent.js +38 -0
  119. package/lib/shallow/SyntheticClipboardEvent.js +37 -0
  120. package/lib/shallow/SyntheticCompositionEvent.js +35 -0
  121. package/lib/shallow/SyntheticDragEvent.js +35 -0
  122. package/lib/shallow/SyntheticEvent.js +267 -0
  123. package/lib/shallow/SyntheticFocusEvent.js +35 -0
  124. package/lib/shallow/SyntheticInputEvent.js +36 -0
  125. package/lib/shallow/SyntheticKeyboardEvent.js +83 -0
  126. package/lib/shallow/SyntheticMouseEvent.js +71 -0
  127. package/lib/shallow/SyntheticTouchEvent.js +44 -0
  128. package/lib/shallow/SyntheticTransitionEvent.js +38 -0
  129. package/lib/shallow/SyntheticUIEvent.js +58 -0
  130. package/lib/shallow/SyntheticWheelEvent.js +53 -0
  131. package/lib/shallow/TapEventPlugin.js +115 -0
  132. package/lib/shallow/TouchHistoryMath.js +98 -0
  133. package/lib/shallow/Transaction.js +224 -0
  134. package/lib/shallow/ViewportMetrics.js +26 -0
  135. package/lib/shallow/accumulate.js +45 -0
  136. package/lib/shallow/accumulateInto.js +57 -0
  137. package/lib/shallow/adler32.js +43 -0
  138. package/lib/shallow/canDefineProperty.js +25 -0
  139. package/lib/shallow/checkReactTypeSpec.js +86 -0
  140. package/lib/shallow/createMicrosoftUnsafeLocalFunction.js +31 -0
  141. package/lib/shallow/dangerousStyleValue.js +78 -0
  142. package/lib/shallow/deprecated.js +56 -0
  143. package/lib/shallow/escapeTextContentForBrowser.js +122 -0
  144. package/lib/shallow/findDOMNode.js +59 -0
  145. package/lib/shallow/flattenChildren.js +75 -0
  146. package/lib/shallow/forEachAccumulated.js +30 -0
  147. package/lib/shallow/getEventCharCode.js +49 -0
  148. package/lib/shallow/getEventKey.js +101 -0
  149. package/lib/shallow/getEventModifierState.js +42 -0
  150. package/lib/shallow/getEventTarget.js +34 -0
  151. package/lib/shallow/getHostComponentFromComposite.js +29 -0
  152. package/lib/shallow/getIteratorFn.js +40 -0
  153. package/lib/shallow/getNodeForCharacterOffset.js +73 -0
  154. package/lib/shallow/getTextContentAccessor.js +32 -0
  155. package/lib/shallow/getVendorPrefixedEventName.js +100 -0
  156. package/lib/shallow/instantiateReactComponent.js +128 -0
  157. package/lib/shallow/isEventSupported.js +59 -0
  158. package/lib/shallow/isTextInputElement.js +50 -0
  159. package/lib/shallow/quoteAttributeValueForBrowser.js +25 -0
  160. package/lib/shallow/reactProdInvariant.js +38 -0
  161. package/lib/shallow/renderSubtreeIntoContainer.js +15 -0
  162. package/lib/shallow/setInnerHTML.js +97 -0
  163. package/lib/shallow/setTextContent.js +51 -0
  164. package/lib/shallow/shouldUpdateReactComponent.js +41 -0
  165. package/lib/shallow/traverseAllChildren.js +175 -0
  166. package/lib/shallow/validateDOMNesting.js +376 -0
  167. package/package.json +1 -1
  168. package/shallow.js +1 -1
@@ -0,0 +1,1000 @@
1
+ /**
2
+ * Copyright 2013-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ */
10
+
11
+ /* global hasOwnProperty:true */
12
+
13
+ 'use strict';
14
+
15
+ var _prodInvariant = require('./reactProdInvariant'),
16
+ _assign = require('object-assign');
17
+
18
+ var AutoFocusUtils = require('./AutoFocusUtils');
19
+ var CSSPropertyOperations = require('./CSSPropertyOperations');
20
+ var DOMLazyTree = require('./DOMLazyTree');
21
+ var DOMNamespaces = require('./DOMNamespaces');
22
+ var DOMProperty = require('./DOMProperty');
23
+ var DOMPropertyOperations = require('./DOMPropertyOperations');
24
+ var EventPluginHub = require('./EventPluginHub');
25
+ var EventPluginRegistry = require('./EventPluginRegistry');
26
+ var ReactBrowserEventEmitter = require('./ReactBrowserEventEmitter');
27
+ var ReactDOMComponentFlags = require('./ReactDOMComponentFlags');
28
+ var ReactDOMComponentTree = require('./ReactDOMComponentTree');
29
+ var ReactDOMInput = require('./ReactDOMInput');
30
+ var ReactDOMOption = require('./ReactDOMOption');
31
+ var ReactDOMSelect = require('./ReactDOMSelect');
32
+ var ReactDOMTextarea = require('./ReactDOMTextarea');
33
+ var ReactInstrumentation = require('./ReactInstrumentation');
34
+ var ReactMultiChild = require('./ReactMultiChild');
35
+ var ReactServerRenderingTransaction = require('./ReactServerRenderingTransaction');
36
+
37
+ var emptyFunction = require('fbjs/lib/emptyFunction');
38
+ var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');
39
+ var invariant = require('fbjs/lib/invariant');
40
+ var isEventSupported = require('./isEventSupported');
41
+ var shallowEqual = require('fbjs/lib/shallowEqual');
42
+ var validateDOMNesting = require('./validateDOMNesting');
43
+ var warning = require('fbjs/lib/warning');
44
+
45
+ var Flags = ReactDOMComponentFlags;
46
+ var deleteListener = EventPluginHub.deleteListener;
47
+ var getNode = ReactDOMComponentTree.getNodeFromInstance;
48
+ var listenTo = ReactBrowserEventEmitter.listenTo;
49
+ var registrationNameModules = EventPluginRegistry.registrationNameModules;
50
+
51
+ // For quickly matching children type, to test if can be treated as content.
52
+ var CONTENT_TYPES = { 'string': true, 'number': true };
53
+
54
+ var STYLE = 'style';
55
+ var HTML = '__html';
56
+ var RESERVED_PROPS = {
57
+ children: null,
58
+ dangerouslySetInnerHTML: null,
59
+ suppressContentEditableWarning: null
60
+ };
61
+
62
+ // Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).
63
+ var DOC_FRAGMENT_TYPE = 11;
64
+
65
+ function getDeclarationErrorAddendum(internalInstance) {
66
+ if (internalInstance) {
67
+ var owner = internalInstance._currentElement._owner || null;
68
+ if (owner) {
69
+ var name = owner.getName();
70
+ if (name) {
71
+ return ' This DOM node was rendered by `' + name + '`.';
72
+ }
73
+ }
74
+ }
75
+ return '';
76
+ }
77
+
78
+ function friendlyStringify(obj) {
79
+ if (typeof obj === 'object') {
80
+ if (Array.isArray(obj)) {
81
+ return '[' + obj.map(friendlyStringify).join(', ') + ']';
82
+ } else {
83
+ var pairs = [];
84
+ for (var key in obj) {
85
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
86
+ var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? key : JSON.stringify(key);
87
+ pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));
88
+ }
89
+ }
90
+ return '{' + pairs.join(', ') + '}';
91
+ }
92
+ } else if (typeof obj === 'string') {
93
+ return JSON.stringify(obj);
94
+ } else if (typeof obj === 'function') {
95
+ return '[function object]';
96
+ }
97
+ // Differs from JSON.stringify in that undefined because undefined and that
98
+ // inf and nan don't become null
99
+ return String(obj);
100
+ }
101
+
102
+ var styleMutationWarning = {};
103
+
104
+ function checkAndWarnForMutatedStyle(style1, style2, component) {
105
+ if (style1 == null || style2 == null) {
106
+ return;
107
+ }
108
+ if (shallowEqual(style1, style2)) {
109
+ return;
110
+ }
111
+
112
+ var componentName = component._tag;
113
+ var owner = component._currentElement._owner;
114
+ var ownerName;
115
+ if (owner) {
116
+ ownerName = owner.getName();
117
+ }
118
+
119
+ var hash = ownerName + '|' + componentName;
120
+
121
+ if (styleMutationWarning.hasOwnProperty(hash)) {
122
+ return;
123
+ }
124
+
125
+ styleMutationWarning[hash] = true;
126
+
127
+ 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 + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;
128
+ }
129
+
130
+ /**
131
+ * @param {object} component
132
+ * @param {?object} props
133
+ */
134
+ function assertValidProps(component, props) {
135
+ if (!props) {
136
+ return;
137
+ }
138
+ // Note the use of `==` which checks for null or undefined.
139
+ if (voidElementTags[component._tag]) {
140
+ !(props.children == null && props.dangerouslySetInnerHTML == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;
141
+ }
142
+ if (props.dangerouslySetInnerHTML != null) {
143
+ !(props.children == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;
144
+ !(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.') : _prodInvariant('61') : void 0;
145
+ }
146
+ if (process.env.NODE_ENV !== 'production') {
147
+ process.env.NODE_ENV !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;
148
+ process.env.NODE_ENV !== 'production' ? warning(props.suppressContentEditableWarning || !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.') : void 0;
149
+ process.env.NODE_ENV !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;
150
+ }
151
+ !(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)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;
152
+ }
153
+
154
+ function enqueuePutListener(inst, registrationName, listener, transaction) {
155
+ if (transaction instanceof ReactServerRenderingTransaction) {
156
+ return;
157
+ }
158
+ if (process.env.NODE_ENV !== 'production') {
159
+ // IE8 has no API for event capturing and the `onScroll` event doesn't
160
+ // bubble.
161
+ process.env.NODE_ENV !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : void 0;
162
+ }
163
+ var containerInfo = inst._hostContainerInfo;
164
+ var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
165
+ var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
166
+ listenTo(registrationName, doc);
167
+ transaction.getReactMountReady().enqueue(putListener, {
168
+ inst: inst,
169
+ registrationName: registrationName,
170
+ listener: listener
171
+ });
172
+ }
173
+
174
+ function putListener() {
175
+ var listenerToPut = this;
176
+ EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);
177
+ }
178
+
179
+ function inputPostMount() {
180
+ var inst = this;
181
+ ReactDOMInput.postMountWrapper(inst);
182
+ }
183
+
184
+ function textareaPostMount() {
185
+ var inst = this;
186
+ ReactDOMTextarea.postMountWrapper(inst);
187
+ }
188
+
189
+ function optionPostMount() {
190
+ var inst = this;
191
+ ReactDOMOption.postMountWrapper(inst);
192
+ }
193
+
194
+ var setAndValidateContentChildDev = emptyFunction;
195
+ if (process.env.NODE_ENV !== 'production') {
196
+ setAndValidateContentChildDev = function (content) {
197
+ var hasExistingContent = this._contentDebugID != null;
198
+ var debugID = this._debugID;
199
+ // This ID represents the inlined child that has no backing instance:
200
+ var contentDebugID = -debugID;
201
+
202
+ if (content == null) {
203
+ if (hasExistingContent) {
204
+ ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);
205
+ }
206
+ this._contentDebugID = null;
207
+ return;
208
+ }
209
+
210
+ validateDOMNesting(null, String(content), this, this._ancestorInfo);
211
+ this._contentDebugID = contentDebugID;
212
+ if (hasExistingContent) {
213
+ ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);
214
+ ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);
215
+ } else {
216
+ ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content, debugID);
217
+ ReactInstrumentation.debugTool.onMountComponent(contentDebugID);
218
+ ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);
219
+ }
220
+ };
221
+ }
222
+
223
+ // There are so many media events, it makes sense to just
224
+ // maintain a list rather than create a `trapBubbledEvent` for each
225
+ var mediaEvents = {
226
+ topAbort: 'abort',
227
+ topCanPlay: 'canplay',
228
+ topCanPlayThrough: 'canplaythrough',
229
+ topDurationChange: 'durationchange',
230
+ topEmptied: 'emptied',
231
+ topEncrypted: 'encrypted',
232
+ topEnded: 'ended',
233
+ topError: 'error',
234
+ topLoadedData: 'loadeddata',
235
+ topLoadedMetadata: 'loadedmetadata',
236
+ topLoadStart: 'loadstart',
237
+ topPause: 'pause',
238
+ topPlay: 'play',
239
+ topPlaying: 'playing',
240
+ topProgress: 'progress',
241
+ topRateChange: 'ratechange',
242
+ topSeeked: 'seeked',
243
+ topSeeking: 'seeking',
244
+ topStalled: 'stalled',
245
+ topSuspend: 'suspend',
246
+ topTimeUpdate: 'timeupdate',
247
+ topVolumeChange: 'volumechange',
248
+ topWaiting: 'waiting'
249
+ };
250
+
251
+ function trapBubbledEventsLocal() {
252
+ var inst = this;
253
+ // If a component renders to null or if another component fatals and causes
254
+ // the state of the tree to be corrupted, `node` here can be null.
255
+ !inst._rootNodeID ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;
256
+ var node = getNode(inst);
257
+ !node ? process.env.NODE_ENV !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;
258
+
259
+ switch (inst._tag) {
260
+ case 'iframe':
261
+ case 'object':
262
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node)];
263
+ break;
264
+ case 'video':
265
+ case 'audio':
266
+
267
+ inst._wrapperState.listeners = [];
268
+ // Create listener for each media event
269
+ for (var event in mediaEvents) {
270
+ if (mediaEvents.hasOwnProperty(event)) {
271
+ inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(event, mediaEvents[event], node));
272
+ }
273
+ }
274
+ break;
275
+ case 'source':
276
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node)];
277
+ break;
278
+ case 'img':
279
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topError', 'error', node), ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', node)];
280
+ break;
281
+ case 'form':
282
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topReset', 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent('topSubmit', 'submit', node)];
283
+ break;
284
+ case 'input':
285
+ case 'select':
286
+ case 'textarea':
287
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent('topInvalid', 'invalid', node)];
288
+ break;
289
+ }
290
+ }
291
+
292
+ function postUpdateSelectWrapper() {
293
+ ReactDOMSelect.postUpdateWrapper(this);
294
+ }
295
+
296
+ // For HTML, certain tags should omit their close tag. We keep a whitelist for
297
+ // those special-case tags.
298
+
299
+ var omittedCloseTags = {
300
+ 'area': true,
301
+ 'base': true,
302
+ 'br': true,
303
+ 'col': true,
304
+ 'embed': true,
305
+ 'hr': true,
306
+ 'img': true,
307
+ 'input': true,
308
+ 'keygen': true,
309
+ 'link': true,
310
+ 'meta': true,
311
+ 'param': true,
312
+ 'source': true,
313
+ 'track': true,
314
+ 'wbr': true
315
+ };
316
+
317
+ var newlineEatingTags = {
318
+ 'listing': true,
319
+ 'pre': true,
320
+ 'textarea': true
321
+ };
322
+
323
+ // For HTML, certain tags cannot have children. This has the same purpose as
324
+ // `omittedCloseTags` except that `menuitem` should still have its closing tag.
325
+
326
+ var voidElementTags = _assign({
327
+ 'menuitem': true
328
+ }, omittedCloseTags);
329
+
330
+ // We accept any tag to be rendered but since this gets injected into arbitrary
331
+ // HTML, we want to make sure that it's a safe tag.
332
+ // http://www.w3.org/TR/REC-xml/#NT-Name
333
+
334
+ var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
335
+ var validatedTagCache = {};
336
+ var hasOwnProperty = {}.hasOwnProperty;
337
+
338
+ function validateDangerousTag(tag) {
339
+ if (!hasOwnProperty.call(validatedTagCache, tag)) {
340
+ !VALID_TAG_REGEX.test(tag) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;
341
+ validatedTagCache[tag] = true;
342
+ }
343
+ }
344
+
345
+ function isCustomComponent(tagName, props) {
346
+ return tagName.indexOf('-') >= 0 || props.is != null;
347
+ }
348
+
349
+ var globalIdCounter = 1;
350
+
351
+ /**
352
+ * Creates a new React class that is idempotent and capable of containing other
353
+ * React components. It accepts event listeners and DOM properties that are
354
+ * valid according to `DOMProperty`.
355
+ *
356
+ * - Event listeners: `onClick`, `onMouseDown`, etc.
357
+ * - DOM properties: `className`, `name`, `title`, etc.
358
+ *
359
+ * The `style` property functions differently from the DOM API. It accepts an
360
+ * object mapping of style properties to values.
361
+ *
362
+ * @constructor ReactDOMComponent
363
+ * @extends ReactMultiChild
364
+ */
365
+ function ReactDOMComponent(element) {
366
+ var tag = element.type;
367
+ validateDangerousTag(tag);
368
+ this._currentElement = element;
369
+ this._tag = tag.toLowerCase();
370
+ this._namespaceURI = null;
371
+ this._renderedChildren = null;
372
+ this._previousStyle = null;
373
+ this._previousStyleCopy = null;
374
+ this._hostNode = null;
375
+ this._hostParent = null;
376
+ this._rootNodeID = 0;
377
+ this._domID = 0;
378
+ this._hostContainerInfo = null;
379
+ this._wrapperState = null;
380
+ this._topLevelWrapper = null;
381
+ this._flags = 0;
382
+ if (process.env.NODE_ENV !== 'production') {
383
+ this._ancestorInfo = null;
384
+ setAndValidateContentChildDev.call(this, null);
385
+ }
386
+ }
387
+
388
+ ReactDOMComponent.displayName = 'ReactDOMComponent';
389
+
390
+ ReactDOMComponent.Mixin = {
391
+
392
+ /**
393
+ * Generates root tag markup then recurses. This method has side effects and
394
+ * is not idempotent.
395
+ *
396
+ * @internal
397
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
398
+ * @param {?ReactDOMComponent} the parent component instance
399
+ * @param {?object} info about the host container
400
+ * @param {object} context
401
+ * @return {string} The computed markup.
402
+ */
403
+ mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
404
+ this._rootNodeID = globalIdCounter++;
405
+ this._domID = hostContainerInfo._idCounter++;
406
+ this._hostParent = hostParent;
407
+ this._hostContainerInfo = hostContainerInfo;
408
+
409
+ var props = this._currentElement.props;
410
+
411
+ switch (this._tag) {
412
+ case 'audio':
413
+ case 'form':
414
+ case 'iframe':
415
+ case 'img':
416
+ case 'link':
417
+ case 'object':
418
+ case 'source':
419
+ case 'video':
420
+ this._wrapperState = {
421
+ listeners: null
422
+ };
423
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
424
+ break;
425
+ case 'input':
426
+ ReactDOMInput.mountWrapper(this, props, hostParent);
427
+ props = ReactDOMInput.getHostProps(this, props);
428
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
429
+ break;
430
+ case 'option':
431
+ ReactDOMOption.mountWrapper(this, props, hostParent);
432
+ props = ReactDOMOption.getHostProps(this, props);
433
+ break;
434
+ case 'select':
435
+ ReactDOMSelect.mountWrapper(this, props, hostParent);
436
+ props = ReactDOMSelect.getHostProps(this, props);
437
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
438
+ break;
439
+ case 'textarea':
440
+ ReactDOMTextarea.mountWrapper(this, props, hostParent);
441
+ props = ReactDOMTextarea.getHostProps(this, props);
442
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
443
+ break;
444
+ }
445
+
446
+ assertValidProps(this, props);
447
+
448
+ // We create tags in the namespace of their parent container, except HTML
449
+ // tags get no namespace.
450
+ var namespaceURI;
451
+ var parentTag;
452
+ if (hostParent != null) {
453
+ namespaceURI = hostParent._namespaceURI;
454
+ parentTag = hostParent._tag;
455
+ } else if (hostContainerInfo._tag) {
456
+ namespaceURI = hostContainerInfo._namespaceURI;
457
+ parentTag = hostContainerInfo._tag;
458
+ }
459
+ if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {
460
+ namespaceURI = DOMNamespaces.html;
461
+ }
462
+ if (namespaceURI === DOMNamespaces.html) {
463
+ if (this._tag === 'svg') {
464
+ namespaceURI = DOMNamespaces.svg;
465
+ } else if (this._tag === 'math') {
466
+ namespaceURI = DOMNamespaces.mathml;
467
+ }
468
+ }
469
+ this._namespaceURI = namespaceURI;
470
+
471
+ if (process.env.NODE_ENV !== 'production') {
472
+ var parentInfo;
473
+ if (hostParent != null) {
474
+ parentInfo = hostParent._ancestorInfo;
475
+ } else if (hostContainerInfo._tag) {
476
+ parentInfo = hostContainerInfo._ancestorInfo;
477
+ }
478
+ if (parentInfo) {
479
+ // parentInfo should always be present except for the top-level
480
+ // component when server rendering
481
+ validateDOMNesting(this._tag, null, this, parentInfo);
482
+ }
483
+ this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);
484
+ }
485
+
486
+ var mountImage;
487
+ if (transaction.useCreateElement) {
488
+ var ownerDocument = hostContainerInfo._ownerDocument;
489
+ var el;
490
+ if (namespaceURI === DOMNamespaces.html) {
491
+ if (this._tag === 'script') {
492
+ // Create the script via .innerHTML so its "parser-inserted" flag is
493
+ // set to true and it does not execute
494
+ var div = ownerDocument.createElement('div');
495
+ var type = this._currentElement.type;
496
+ div.innerHTML = '<' + type + '></' + type + '>';
497
+ el = div.removeChild(div.firstChild);
498
+ } else if (props.is) {
499
+ el = ownerDocument.createElement(this._currentElement.type, props.is);
500
+ } else {
501
+ // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.
502
+ // See discussion in https://github.com/facebook/react/pull/6896
503
+ // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
504
+ el = ownerDocument.createElement(this._currentElement.type);
505
+ }
506
+ } else {
507
+ el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);
508
+ }
509
+ ReactDOMComponentTree.precacheNode(this, el);
510
+ this._flags |= Flags.hasCachedChildNodes;
511
+ if (!this._hostParent) {
512
+ DOMPropertyOperations.setAttributeForRoot(el);
513
+ }
514
+ this._updateDOMProperties(null, props, transaction);
515
+ var lazyTree = DOMLazyTree(el);
516
+ this._createInitialChildren(transaction, props, context, lazyTree);
517
+ mountImage = lazyTree;
518
+ } else {
519
+ var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
520
+ var tagContent = this._createContentMarkup(transaction, props, context);
521
+ if (!tagContent && omittedCloseTags[this._tag]) {
522
+ mountImage = tagOpen + '/>';
523
+ } else {
524
+ mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
525
+ }
526
+ }
527
+
528
+ switch (this._tag) {
529
+ case 'input':
530
+ transaction.getReactMountReady().enqueue(inputPostMount, this);
531
+ if (props.autoFocus) {
532
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
533
+ }
534
+ break;
535
+ case 'textarea':
536
+ transaction.getReactMountReady().enqueue(textareaPostMount, this);
537
+ if (props.autoFocus) {
538
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
539
+ }
540
+ break;
541
+ case 'select':
542
+ if (props.autoFocus) {
543
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
544
+ }
545
+ break;
546
+ case 'button':
547
+ if (props.autoFocus) {
548
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
549
+ }
550
+ break;
551
+ case 'option':
552
+ transaction.getReactMountReady().enqueue(optionPostMount, this);
553
+ break;
554
+ }
555
+
556
+ return mountImage;
557
+ },
558
+
559
+ /**
560
+ * Creates markup for the open tag and all attributes.
561
+ *
562
+ * This method has side effects because events get registered.
563
+ *
564
+ * Iterating over object properties is faster than iterating over arrays.
565
+ * @see http://jsperf.com/obj-vs-arr-iteration
566
+ *
567
+ * @private
568
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
569
+ * @param {object} props
570
+ * @return {string} Markup of opening tag.
571
+ */
572
+ _createOpenTagMarkupAndPutListeners: function (transaction, props) {
573
+ var ret = '<' + this._currentElement.type;
574
+
575
+ for (var propKey in props) {
576
+ if (!props.hasOwnProperty(propKey)) {
577
+ continue;
578
+ }
579
+ var propValue = props[propKey];
580
+ if (propValue == null) {
581
+ continue;
582
+ }
583
+ if (registrationNameModules.hasOwnProperty(propKey)) {
584
+ if (propValue) {
585
+ enqueuePutListener(this, propKey, propValue, transaction);
586
+ }
587
+ } else {
588
+ if (propKey === STYLE) {
589
+ if (propValue) {
590
+ if (process.env.NODE_ENV !== 'production') {
591
+ // See `_updateDOMProperties`. style block
592
+ this._previousStyle = propValue;
593
+ }
594
+ propValue = this._previousStyleCopy = _assign({}, props.style);
595
+ }
596
+ propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);
597
+ }
598
+ var markup = null;
599
+ if (this._tag != null && isCustomComponent(this._tag, props)) {
600
+ if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
601
+ markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
602
+ }
603
+ } else {
604
+ markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
605
+ }
606
+ if (markup) {
607
+ ret += ' ' + markup;
608
+ }
609
+ }
610
+ }
611
+
612
+ // For static pages, no need to put React ID and checksum. Saves lots of
613
+ // bytes.
614
+ if (transaction.renderToStaticMarkup) {
615
+ return ret;
616
+ }
617
+
618
+ if (!this._hostParent) {
619
+ ret += ' ' + DOMPropertyOperations.createMarkupForRoot();
620
+ }
621
+ ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);
622
+ return ret;
623
+ },
624
+
625
+ /**
626
+ * Creates markup for the content between the tags.
627
+ *
628
+ * @private
629
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
630
+ * @param {object} props
631
+ * @param {object} context
632
+ * @return {string} Content markup.
633
+ */
634
+ _createContentMarkup: function (transaction, props, context) {
635
+ var ret = '';
636
+
637
+ // Intentional use of != to avoid catching zero/false.
638
+ var innerHTML = props.dangerouslySetInnerHTML;
639
+ if (innerHTML != null) {
640
+ if (innerHTML.__html != null) {
641
+ ret = innerHTML.__html;
642
+ }
643
+ } else {
644
+ var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
645
+ var childrenToUse = contentToUse != null ? null : props.children;
646
+ if (contentToUse != null) {
647
+ // TODO: Validate that text is allowed as a child of this node
648
+ ret = escapeTextContentForBrowser(contentToUse);
649
+ if (process.env.NODE_ENV !== 'production') {
650
+ setAndValidateContentChildDev.call(this, contentToUse);
651
+ }
652
+ } else if (childrenToUse != null) {
653
+ var mountImages = this.mountChildren(childrenToUse, transaction, context);
654
+ ret = mountImages.join('');
655
+ }
656
+ }
657
+ if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
658
+ // text/html ignores the first character in these tags if it's a newline
659
+ // Prefer to break application/xml over text/html (for now) by adding
660
+ // a newline specifically to get eaten by the parser. (Alternately for
661
+ // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
662
+ // \r is normalized out by HTMLTextAreaElement#value.)
663
+ // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
664
+ // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
665
+ // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
666
+ // See: Parsing of "textarea" "listing" and "pre" elements
667
+ // from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
668
+ return '\n' + ret;
669
+ } else {
670
+ return ret;
671
+ }
672
+ },
673
+
674
+ _createInitialChildren: function (transaction, props, context, lazyTree) {
675
+ // Intentional use of != to avoid catching zero/false.
676
+ var innerHTML = props.dangerouslySetInnerHTML;
677
+ if (innerHTML != null) {
678
+ if (innerHTML.__html != null) {
679
+ DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);
680
+ }
681
+ } else {
682
+ var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
683
+ var childrenToUse = contentToUse != null ? null : props.children;
684
+ // TODO: Validate that text is allowed as a child of this node
685
+ if (contentToUse != null) {
686
+ // Avoid setting textContent when the text is empty. In IE11 setting
687
+ // textContent on a text area will cause the placeholder to not
688
+ // show within the textarea until it has been focused and blurred again.
689
+ // https://github.com/facebook/react/issues/6731#issuecomment-254874553
690
+ if (contentToUse !== '') {
691
+ if (process.env.NODE_ENV !== 'production') {
692
+ setAndValidateContentChildDev.call(this, contentToUse);
693
+ }
694
+ DOMLazyTree.queueText(lazyTree, contentToUse);
695
+ }
696
+ } else if (childrenToUse != null) {
697
+ var mountImages = this.mountChildren(childrenToUse, transaction, context);
698
+ for (var i = 0; i < mountImages.length; i++) {
699
+ DOMLazyTree.queueChild(lazyTree, mountImages[i]);
700
+ }
701
+ }
702
+ }
703
+ },
704
+
705
+ /**
706
+ * Receives a next element and updates the component.
707
+ *
708
+ * @internal
709
+ * @param {ReactElement} nextElement
710
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
711
+ * @param {object} context
712
+ */
713
+ receiveComponent: function (nextElement, transaction, context) {
714
+ var prevElement = this._currentElement;
715
+ this._currentElement = nextElement;
716
+ this.updateComponent(transaction, prevElement, nextElement, context);
717
+ },
718
+
719
+ /**
720
+ * Updates a DOM component after it has already been allocated and
721
+ * attached to the DOM. Reconciles the root DOM node, then recurses.
722
+ *
723
+ * @param {ReactReconcileTransaction} transaction
724
+ * @param {ReactElement} prevElement
725
+ * @param {ReactElement} nextElement
726
+ * @internal
727
+ * @overridable
728
+ */
729
+ updateComponent: function (transaction, prevElement, nextElement, context) {
730
+ var lastProps = prevElement.props;
731
+ var nextProps = this._currentElement.props;
732
+
733
+ switch (this._tag) {
734
+ case 'input':
735
+ lastProps = ReactDOMInput.getHostProps(this, lastProps);
736
+ nextProps = ReactDOMInput.getHostProps(this, nextProps);
737
+ break;
738
+ case 'option':
739
+ lastProps = ReactDOMOption.getHostProps(this, lastProps);
740
+ nextProps = ReactDOMOption.getHostProps(this, nextProps);
741
+ break;
742
+ case 'select':
743
+ lastProps = ReactDOMSelect.getHostProps(this, lastProps);
744
+ nextProps = ReactDOMSelect.getHostProps(this, nextProps);
745
+ break;
746
+ case 'textarea':
747
+ lastProps = ReactDOMTextarea.getHostProps(this, lastProps);
748
+ nextProps = ReactDOMTextarea.getHostProps(this, nextProps);
749
+ break;
750
+ }
751
+
752
+ assertValidProps(this, nextProps);
753
+ this._updateDOMProperties(lastProps, nextProps, transaction);
754
+ this._updateDOMChildren(lastProps, nextProps, transaction, context);
755
+
756
+ switch (this._tag) {
757
+ case 'input':
758
+ // Update the wrapper around inputs *after* updating props. This has to
759
+ // happen after `_updateDOMProperties`. Otherwise HTML5 input validations
760
+ // raise warnings and prevent the new value from being assigned.
761
+ ReactDOMInput.updateWrapper(this);
762
+ break;
763
+ case 'textarea':
764
+ ReactDOMTextarea.updateWrapper(this);
765
+ break;
766
+ case 'select':
767
+ // <select> value update needs to occur after <option> children
768
+ // reconciliation
769
+ transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
770
+ break;
771
+ }
772
+ },
773
+
774
+ /**
775
+ * Reconciles the properties by detecting differences in property values and
776
+ * updating the DOM as necessary. This function is probably the single most
777
+ * critical path for performance optimization.
778
+ *
779
+ * TODO: Benchmark whether checking for changed values in memory actually
780
+ * improves performance (especially statically positioned elements).
781
+ * TODO: Benchmark the effects of putting this at the top since 99% of props
782
+ * do not change for a given reconciliation.
783
+ * TODO: Benchmark areas that can be improved with caching.
784
+ *
785
+ * @private
786
+ * @param {object} lastProps
787
+ * @param {object} nextProps
788
+ * @param {?DOMElement} node
789
+ */
790
+ _updateDOMProperties: function (lastProps, nextProps, transaction) {
791
+ var propKey;
792
+ var styleName;
793
+ var styleUpdates;
794
+ for (propKey in lastProps) {
795
+ if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
796
+ continue;
797
+ }
798
+ if (propKey === STYLE) {
799
+ var lastStyle = this._previousStyleCopy;
800
+ for (styleName in lastStyle) {
801
+ if (lastStyle.hasOwnProperty(styleName)) {
802
+ styleUpdates = styleUpdates || {};
803
+ styleUpdates[styleName] = '';
804
+ }
805
+ }
806
+ this._previousStyleCopy = null;
807
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
808
+ if (lastProps[propKey]) {
809
+ // Only call deleteListener if there was a listener previously or
810
+ // else willDeleteListener gets called when there wasn't actually a
811
+ // listener (e.g., onClick={null})
812
+ deleteListener(this, propKey);
813
+ }
814
+ } else if (isCustomComponent(this._tag, lastProps)) {
815
+ if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
816
+ DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);
817
+ }
818
+ } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
819
+ DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);
820
+ }
821
+ }
822
+ for (propKey in nextProps) {
823
+ var nextProp = nextProps[propKey];
824
+ var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;
825
+ if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
826
+ continue;
827
+ }
828
+ if (propKey === STYLE) {
829
+ if (nextProp) {
830
+ if (process.env.NODE_ENV !== 'production') {
831
+ checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
832
+ this._previousStyle = nextProp;
833
+ }
834
+ nextProp = this._previousStyleCopy = _assign({}, nextProp);
835
+ } else {
836
+ this._previousStyleCopy = null;
837
+ }
838
+ if (lastProp) {
839
+ // Unset styles on `lastProp` but not on `nextProp`.
840
+ for (styleName in lastProp) {
841
+ if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
842
+ styleUpdates = styleUpdates || {};
843
+ styleUpdates[styleName] = '';
844
+ }
845
+ }
846
+ // Update styles that changed since `lastProp`.
847
+ for (styleName in nextProp) {
848
+ if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
849
+ styleUpdates = styleUpdates || {};
850
+ styleUpdates[styleName] = nextProp[styleName];
851
+ }
852
+ }
853
+ } else {
854
+ // Relies on `updateStylesByID` not mutating `styleUpdates`.
855
+ styleUpdates = nextProp;
856
+ }
857
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
858
+ if (nextProp) {
859
+ enqueuePutListener(this, propKey, nextProp, transaction);
860
+ } else if (lastProp) {
861
+ deleteListener(this, propKey);
862
+ }
863
+ } else if (isCustomComponent(this._tag, nextProps)) {
864
+ if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
865
+ DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);
866
+ }
867
+ } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
868
+ var node = getNode(this);
869
+ // If we're updating to null or undefined, we should remove the property
870
+ // from the DOM node instead of inadvertently setting to a string. This
871
+ // brings us in line with the same behavior we have on initial render.
872
+ if (nextProp != null) {
873
+ DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
874
+ } else {
875
+ DOMPropertyOperations.deleteValueForProperty(node, propKey);
876
+ }
877
+ }
878
+ }
879
+ if (styleUpdates) {
880
+ CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);
881
+ }
882
+ },
883
+
884
+ /**
885
+ * Reconciles the children with the various properties that affect the
886
+ * children content.
887
+ *
888
+ * @param {object} lastProps
889
+ * @param {object} nextProps
890
+ * @param {ReactReconcileTransaction} transaction
891
+ * @param {object} context
892
+ */
893
+ _updateDOMChildren: function (lastProps, nextProps, transaction, context) {
894
+ var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
895
+ var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
896
+
897
+ var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
898
+ var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;
899
+
900
+ // Note the use of `!=` which checks for null or undefined.
901
+ var lastChildren = lastContent != null ? null : lastProps.children;
902
+ var nextChildren = nextContent != null ? null : nextProps.children;
903
+
904
+ // If we're switching from children to content/html or vice versa, remove
905
+ // the old content
906
+ var lastHasContentOrHtml = lastContent != null || lastHtml != null;
907
+ var nextHasContentOrHtml = nextContent != null || nextHtml != null;
908
+ if (lastChildren != null && nextChildren == null) {
909
+ this.updateChildren(null, transaction, context);
910
+ } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
911
+ this.updateTextContent('');
912
+ if (process.env.NODE_ENV !== 'production') {
913
+ ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
914
+ }
915
+ }
916
+
917
+ if (nextContent != null) {
918
+ if (lastContent !== nextContent) {
919
+ this.updateTextContent('' + nextContent);
920
+ if (process.env.NODE_ENV !== 'production') {
921
+ setAndValidateContentChildDev.call(this, nextContent);
922
+ }
923
+ }
924
+ } else if (nextHtml != null) {
925
+ if (lastHtml !== nextHtml) {
926
+ this.updateMarkup('' + nextHtml);
927
+ }
928
+ if (process.env.NODE_ENV !== 'production') {
929
+ ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
930
+ }
931
+ } else if (nextChildren != null) {
932
+ if (process.env.NODE_ENV !== 'production') {
933
+ setAndValidateContentChildDev.call(this, null);
934
+ }
935
+
936
+ this.updateChildren(nextChildren, transaction, context);
937
+ }
938
+ },
939
+
940
+ getHostNode: function () {
941
+ return getNode(this);
942
+ },
943
+
944
+ /**
945
+ * Destroys all event registrations for this instance. Does not remove from
946
+ * the DOM. That must be done by the parent.
947
+ *
948
+ * @internal
949
+ */
950
+ unmountComponent: function (safely) {
951
+ switch (this._tag) {
952
+ case 'audio':
953
+ case 'form':
954
+ case 'iframe':
955
+ case 'img':
956
+ case 'link':
957
+ case 'object':
958
+ case 'source':
959
+ case 'video':
960
+ var listeners = this._wrapperState.listeners;
961
+ if (listeners) {
962
+ for (var i = 0; i < listeners.length; i++) {
963
+ listeners[i].remove();
964
+ }
965
+ }
966
+ break;
967
+ case 'html':
968
+ case 'head':
969
+ case 'body':
970
+ /**
971
+ * Components like <html> <head> and <body> can't be removed or added
972
+ * easily in a cross-browser way, however it's valuable to be able to
973
+ * take advantage of React's reconciliation for styling and <title>
974
+ * management. So we just document it and throw in dangerous cases.
975
+ */
976
+ !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) : _prodInvariant('66', this._tag) : void 0;
977
+ break;
978
+ }
979
+
980
+ this.unmountChildren(safely);
981
+ ReactDOMComponentTree.uncacheNode(this);
982
+ EventPluginHub.deleteAllListeners(this);
983
+ this._rootNodeID = 0;
984
+ this._domID = 0;
985
+ this._wrapperState = null;
986
+
987
+ if (process.env.NODE_ENV !== 'production') {
988
+ setAndValidateContentChildDev.call(this, null);
989
+ }
990
+ },
991
+
992
+ getPublicInstance: function () {
993
+ return getNode(this);
994
+ }
995
+
996
+ };
997
+
998
+ _assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
999
+
1000
+ module.exports = ReactDOMComponent;