react 15.3.2-rc.1 → 15.4.0-rc.3

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