react 0.13.1 → 0.14.0-alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/addons.js +7 -0
- package/addons/CSSTransitionGroup.js +1 -0
- package/addons/LinkedStateMixin.js +1 -0
- package/addons/Perf.js +1 -0
- package/addons/PureRenderMixin.js +1 -0
- package/addons/TestUtils.js +1 -0
- package/addons/TransitionGroup.js +1 -0
- package/addons/batchedUpdates.js +1 -0
- package/addons/cloneWithProps.js +1 -0
- package/addons/createFragment.js +1 -0
- package/addons/renderSubtreeIntoContainer.js +1 -0
- package/addons/shallowCompare.js +1 -0
- package/addons/update.js +1 -0
- package/dist/JSXTransformer.js +3336 -1671
- package/dist/react-with-addons.js +3320 -5125
- package/dist/react-with-addons.min.js +6 -6
- package/dist/react.js +2952 -4533
- package/dist/react.min.js +5 -5
- package/lib/AutoFocusMixin.js +4 -3
- package/lib/BeforeInputEventPlugin.js +30 -118
- package/lib/CSSCore.js +12 -23
- package/lib/CSSProperty.js +9 -4
- package/lib/CSSPropertyOperations.js +14 -30
- package/lib/CallbackQueue.js +7 -10
- package/lib/ChangeEventPlugin.js +24 -88
- package/lib/ClientReactRootIndex.js +2 -2
- package/lib/DOMChildrenOperations.js +13 -33
- package/lib/DOMProperty.js +41 -67
- package/lib/DOMPropertyOperations.js +30 -51
- package/lib/Danger.js +19 -62
- package/lib/DefaultEventPluginOrder.js +2 -12
- package/lib/EnterLeaveEventPlugin.js +11 -33
- package/lib/EventConstants.js +2 -2
- package/lib/EventListener.js +11 -13
- package/lib/EventPluginHub.js +44 -47
- package/lib/EventPluginRegistry.js +18 -74
- package/lib/EventPluginUtils.js +27 -38
- package/lib/EventPropagators.js +23 -26
- package/lib/ExecutionEnvironment.js +4 -8
- package/lib/FallbackCompositionState.js +3 -3
- package/lib/HTMLDOMPropertyConfig.js +13 -20
- package/lib/LinkedStateMixin.js +3 -6
- package/lib/LinkedValueUtils.js +34 -64
- package/lib/LocalEventTrapMixin.js +9 -16
- package/lib/Object.assign.js +1 -1
- package/lib/PooledClass.js +8 -11
- package/lib/React.js +9 -129
- package/lib/ReactBrowserComponentMixin.js +9 -2
- package/lib/ReactBrowserEventEmitter.js +26 -82
- package/lib/ReactCSSTransitionGroup.js +13 -24
- package/lib/ReactCSSTransitionGroupChild.js +18 -28
- package/lib/ReactChildReconciler.js +11 -19
- package/lib/ReactChildren.js +21 -28
- package/lib/ReactClass.js +81 -234
- package/lib/ReactComponent.js +17 -33
- package/lib/ReactComponentBrowserEnvironment.js +4 -8
- package/lib/ReactComponentEnvironment.js +6 -12
- package/lib/ReactComponentWithPureRenderMixin.js +4 -5
- package/lib/ReactCompositeComponent.js +85 -297
- package/lib/ReactContext.js +2 -44
- package/lib/ReactCurrentOwner.js +1 -3
- package/lib/ReactDOM.js +4 -2
- package/lib/ReactDOMButton.js +3 -4
- package/lib/ReactDOMClient.js +85 -0
- package/lib/ReactDOMComponent.js +184 -146
- package/lib/ReactDOMForm.js +3 -3
- package/lib/ReactDOMIDOperations.js +11 -22
- package/lib/ReactDOMIframe.js +3 -3
- package/lib/ReactDOMImg.js +3 -3
- package/lib/ReactDOMInput.js +22 -35
- package/lib/ReactDOMOption.js +68 -10
- package/lib/ReactDOMSelect.js +50 -28
- package/lib/ReactDOMSelection.js +5 -20
- package/lib/ReactDOMServer.js +24 -0
- package/lib/ReactDOMTextComponent.js +17 -18
- package/lib/ReactDOMTextarea.js +15 -27
- package/lib/ReactDefaultBatchingStrategy.js +9 -13
- package/lib/ReactDefaultInjection.js +31 -40
- package/lib/ReactDefaultPerf.js +36 -69
- package/lib/ReactDefaultPerfAnalysis.js +8 -14
- package/lib/ReactElement.js +24 -57
- package/lib/ReactElementValidator.js +38 -105
- package/lib/ReactEmptyComponent.js +7 -11
- package/lib/ReactErrorUtils.js +2 -2
- package/lib/ReactEventEmitterMixin.js +3 -12
- package/lib/ReactEventListener.js +16 -38
- package/lib/ReactFragment.js +23 -54
- package/lib/ReactInjection.js +1 -1
- package/lib/ReactInputSelection.js +11 -21
- package/lib/ReactInstanceHandles.js +27 -57
- package/lib/ReactInstanceMap.js +5 -5
- package/lib/ReactIsomorphic.js +70 -0
- package/lib/ReactLifeCycle.js +1 -1
- package/lib/ReactLink.js +2 -4
- package/lib/ReactMarkupChecksum.js +5 -10
- package/lib/ReactMount.js +137 -260
- package/lib/ReactMultiChild.js +19 -45
- package/lib/ReactMultiChildUpdateTypes.js +1 -1
- package/lib/ReactNativeComponent.js +7 -11
- package/lib/ReactOwner.js +7 -24
- package/lib/ReactPerf.js +8 -12
- package/lib/ReactPropTransferer.js +4 -4
- package/lib/ReactPropTypeLocationNames.js +2 -2
- package/lib/ReactPropTypeLocations.js +1 -1
- package/lib/ReactPropTypes.js +29 -61
- package/lib/ReactReconcileTransaction.js +9 -34
- package/lib/ReactReconciler.js +9 -19
- package/lib/ReactRef.js +5 -8
- package/lib/ReactRootIndex.js +2 -2
- package/lib/ReactServerRendering.js +7 -15
- package/lib/ReactServerRenderingTransaction.js +7 -32
- package/lib/ReactStateSetters.js +6 -6
- package/lib/ReactTestUtils.js +93 -165
- package/lib/ReactTransitionChildMapping.js +5 -7
- package/lib/ReactTransitionEvents.js +5 -5
- package/lib/ReactTransitionGroup.js +30 -52
- package/lib/ReactUpdateQueue.js +27 -90
- package/lib/ReactUpdates.js +27 -79
- package/lib/ReactWithAddons.js +7 -6
- package/lib/SVGDOMPropertyConfig.js +41 -4
- package/lib/SelectEventPlugin.js +28 -29
- package/lib/ServerReactRootIndex.js +2 -2
- package/lib/SimpleEventPlugin.js +136 -128
- package/lib/SyntheticClipboardEvent.js +3 -7
- package/lib/SyntheticCompositionEvent.js +3 -9
- package/lib/SyntheticDragEvent.js +1 -1
- package/lib/SyntheticEvent.js +8 -10
- package/lib/SyntheticFocusEvent.js +1 -1
- package/lib/SyntheticInputEvent.js +3 -9
- package/lib/SyntheticKeyboardEvent.js +4 -4
- package/lib/SyntheticMouseEvent.js +8 -14
- package/lib/SyntheticTouchEvent.js +1 -1
- package/lib/SyntheticUIEvent.js +3 -3
- package/lib/SyntheticWheelEvent.js +11 -15
- package/lib/Transaction.js +12 -24
- package/lib/ViewportMetrics.js +2 -2
- package/lib/accumulateInto.js +2 -5
- package/lib/adler32.js +2 -4
- package/lib/camelize.js +4 -2
- package/lib/camelizeStyleName.js +2 -2
- package/lib/cloneWithProps.js +5 -11
- package/lib/containsNode.js +29 -16
- package/lib/createArrayFromMixed.js +17 -16
- package/lib/createFullPageComponent.js +4 -11
- package/lib/createNodesFromMarkup.js +6 -8
- package/lib/dangerousStyleValue.js +2 -3
- package/lib/emptyFunction.js +10 -4
- package/lib/emptyObject.js +1 -1
- package/lib/escapeTextContentForBrowser.js +1 -1
- package/lib/findDOMNode.js +5 -24
- package/lib/flattenChildren.js +4 -10
- package/lib/focusNode.js +2 -3
- package/lib/forEachAccumulated.js +2 -2
- package/lib/getActiveElement.js +4 -2
- package/lib/getEventCharCode.js +1 -1
- package/lib/getEventKey.js +1 -1
- package/lib/getEventModifierState.js +1 -1
- package/lib/getEventTarget.js +1 -1
- package/lib/getIteratorFn.js +2 -4
- package/lib/getMarkupWrap.js +7 -5
- package/lib/getNodeForCharacterOffset.js +1 -1
- package/lib/getTextContentAccessor.js +2 -4
- package/lib/getUnboundedScrollPosition.js +1 -1
- package/lib/hyphenate.js +3 -1
- package/lib/hyphenateStyleName.js +2 -2
- package/lib/instantiateReactComponent.js +14 -37
- package/lib/invariant.js +8 -12
- package/lib/isEventSupported.js +7 -10
- package/lib/isNode.js +4 -6
- package/lib/isTextInputElement.js +2 -4
- package/lib/isTextNode.js +3 -1
- package/lib/joinClasses.js +2 -2
- package/lib/keyMirror.js +3 -6
- package/lib/keyOf.js +4 -3
- package/lib/mapObject.js +1 -1
- package/lib/memoizeStringOnly.js +2 -2
- package/lib/onlyChild.js +2 -5
- package/lib/performance.js +2 -5
- package/lib/performanceNow.js +3 -1
- package/lib/quoteAttributeValueForBrowser.js +1 -1
- package/lib/renderSubtreeIntoContainer.js +16 -0
- package/lib/setInnerHTML.js +11 -8
- package/lib/setTextContent.js +3 -3
- package/lib/shallowCompare.js +24 -0
- package/lib/shallowEqual.js +17 -11
- package/lib/shouldUpdateReactComponent.js +3 -64
- package/lib/toArray.js +8 -19
- package/lib/traverseAllChildren.js +22 -89
- package/lib/update.js +33 -90
- package/lib/validateDOMNesting.js +355 -0
- package/lib/warning.js +17 -15
- package/package.json +3 -3
- package/lib/MobileSafariClickEventPlugin.js +0 -56
- package/lib/ReactPutListenerQueue.js +0 -54
- package/lib/cx.js +0 -52
- package/lib/getReactRootElementInContainer.js +0 -33
package/lib/ReactContext.js
CHANGED
|
@@ -11,11 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var assign = require("./Object.assign");
|
|
15
14
|
var emptyObject = require("./emptyObject");
|
|
16
|
-
var warning = require("./warning");
|
|
17
|
-
|
|
18
|
-
var didWarn = false;
|
|
19
15
|
|
|
20
16
|
/**
|
|
21
17
|
* Keeps track of the current context.
|
|
@@ -29,46 +25,8 @@ var ReactContext = {
|
|
|
29
25
|
* @internal
|
|
30
26
|
* @type {object}
|
|
31
27
|
*/
|
|
32
|
-
current: emptyObject
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Temporarily extends the current context while executing scopedCallback.
|
|
36
|
-
*
|
|
37
|
-
* A typical use case might look like
|
|
38
|
-
*
|
|
39
|
-
* render: function() {
|
|
40
|
-
* var children = ReactContext.withContext({foo: 'foo'}, () => (
|
|
41
|
-
*
|
|
42
|
-
* ));
|
|
43
|
-
* return <div>{children}</div>;
|
|
44
|
-
* }
|
|
45
|
-
*
|
|
46
|
-
* @param {object} newContext New context to merge into the existing context
|
|
47
|
-
* @param {function} scopedCallback Callback to run with the new context
|
|
48
|
-
* @return {ReactComponent|array<ReactComponent>}
|
|
49
|
-
*/
|
|
50
|
-
withContext: function(newContext, scopedCallback) {
|
|
51
|
-
if ("production" !== process.env.NODE_ENV) {
|
|
52
|
-
("production" !== process.env.NODE_ENV ? warning(
|
|
53
|
-
didWarn,
|
|
54
|
-
'withContext is deprecated and will be removed in a future version. ' +
|
|
55
|
-
'Use a wrapper component with getChildContext instead.'
|
|
56
|
-
) : null);
|
|
57
|
-
|
|
58
|
-
didWarn = true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
var result;
|
|
62
|
-
var previousContext = ReactContext.current;
|
|
63
|
-
ReactContext.current = assign({}, previousContext, newContext);
|
|
64
|
-
try {
|
|
65
|
-
result = scopedCallback();
|
|
66
|
-
} finally {
|
|
67
|
-
ReactContext.current = previousContext;
|
|
68
|
-
}
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
28
|
+
current: emptyObject
|
|
71
29
|
|
|
72
30
|
};
|
|
73
31
|
|
|
74
|
-
module.exports = ReactContext;
|
|
32
|
+
module.exports = ReactContext;
|
package/lib/ReactCurrentOwner.js
CHANGED
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
*
|
|
17
17
|
* The current owner is the component who should own any components that are
|
|
18
18
|
* currently being constructed.
|
|
19
|
-
*
|
|
20
|
-
* The depth indicate how many composite components are above this render level.
|
|
21
19
|
*/
|
|
22
20
|
var ReactCurrentOwner = {
|
|
23
21
|
|
|
@@ -29,4 +27,4 @@ var ReactCurrentOwner = {
|
|
|
29
27
|
|
|
30
28
|
};
|
|
31
29
|
|
|
32
|
-
module.exports = ReactCurrentOwner;
|
|
30
|
+
module.exports = ReactCurrentOwner;
|
package/lib/ReactDOM.js
CHANGED
|
@@ -24,7 +24,7 @@ var mapObject = require("./mapObject");
|
|
|
24
24
|
* @private
|
|
25
25
|
*/
|
|
26
26
|
function createDOMFactory(tag) {
|
|
27
|
-
if (
|
|
27
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
28
28
|
return ReactElementValidator.createFactory(tag);
|
|
29
29
|
}
|
|
30
30
|
return ReactElement.createFactory(tag);
|
|
@@ -84,6 +84,7 @@ var ReactDOM = mapObject({
|
|
|
84
84
|
h6: 'h6',
|
|
85
85
|
head: 'head',
|
|
86
86
|
header: 'header',
|
|
87
|
+
hgroup: 'hgroup',
|
|
87
88
|
hr: 'hr',
|
|
88
89
|
html: 'html',
|
|
89
90
|
i: 'i',
|
|
@@ -152,6 +153,7 @@ var ReactDOM = mapObject({
|
|
|
152
153
|
|
|
153
154
|
// SVG
|
|
154
155
|
circle: 'circle',
|
|
156
|
+
clipPath: 'clipPath',
|
|
155
157
|
defs: 'defs',
|
|
156
158
|
ellipse: 'ellipse',
|
|
157
159
|
g: 'g',
|
|
@@ -171,4 +173,4 @@ var ReactDOM = mapObject({
|
|
|
171
173
|
|
|
172
174
|
}, createDOMFactory);
|
|
173
175
|
|
|
174
|
-
module.exports = ReactDOM;
|
|
176
|
+
module.exports = ReactDOM;
|
package/lib/ReactDOMButton.js
CHANGED
|
@@ -43,13 +43,12 @@ var ReactDOMButton = ReactClass.createClass({
|
|
|
43
43
|
|
|
44
44
|
mixins: [AutoFocusMixin, ReactBrowserComponentMixin],
|
|
45
45
|
|
|
46
|
-
render: function() {
|
|
46
|
+
render: function () {
|
|
47
47
|
var props = {};
|
|
48
48
|
|
|
49
49
|
// Copy the props; except the mouse listeners if we're disabled
|
|
50
50
|
for (var key in this.props) {
|
|
51
|
-
if (this.props.hasOwnProperty(key) &&
|
|
52
|
-
(!this.props.disabled || !mouseListenerNames[key])) {
|
|
51
|
+
if (this.props.hasOwnProperty(key) && (!this.props.disabled || !mouseListenerNames[key])) {
|
|
53
52
|
props[key] = this.props[key];
|
|
54
53
|
}
|
|
55
54
|
}
|
|
@@ -59,4 +58,4 @@ var ReactDOMButton = ReactClass.createClass({
|
|
|
59
58
|
|
|
60
59
|
});
|
|
61
60
|
|
|
62
|
-
module.exports = ReactDOMButton;
|
|
61
|
+
module.exports = ReactDOMButton;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2015, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*
|
|
9
|
+
* @providesModule ReactDOMClient
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
17
|
+
var ReactDOMTextComponent = require("./ReactDOMTextComponent");
|
|
18
|
+
var ReactDefaultInjection = require("./ReactDefaultInjection");
|
|
19
|
+
var ReactInstanceHandles = require("./ReactInstanceHandles");
|
|
20
|
+
var ReactMount = require("./ReactMount");
|
|
21
|
+
var ReactPerf = require("./ReactPerf");
|
|
22
|
+
var ReactReconciler = require("./ReactReconciler");
|
|
23
|
+
|
|
24
|
+
var findDOMNode = require("./findDOMNode");
|
|
25
|
+
var warning = require("./warning");
|
|
26
|
+
|
|
27
|
+
ReactDefaultInjection.inject();
|
|
28
|
+
|
|
29
|
+
var render = ReactPerf.measure('React', 'render', ReactMount.render);
|
|
30
|
+
|
|
31
|
+
var React = {
|
|
32
|
+
constructAndRenderComponent: ReactMount.constructAndRenderComponent,
|
|
33
|
+
constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID,
|
|
34
|
+
findDOMNode: findDOMNode,
|
|
35
|
+
render: render,
|
|
36
|
+
unmountComponentAtNode: ReactMount.unmountComponentAtNode
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Inject the runtime into a devtools global hook regardless of browser.
|
|
40
|
+
// Allows for debugging when the hook is injected on the page.
|
|
41
|
+
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
|
|
42
|
+
__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
|
|
43
|
+
CurrentOwner: ReactCurrentOwner,
|
|
44
|
+
InstanceHandles: ReactInstanceHandles,
|
|
45
|
+
Mount: ReactMount,
|
|
46
|
+
Reconciler: ReactReconciler,
|
|
47
|
+
TextComponent: ReactDOMTextComponent
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
52
|
+
var ExecutionEnvironment = require("./ExecutionEnvironment");
|
|
53
|
+
if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
|
|
54
|
+
|
|
55
|
+
// If we're in Chrome, look for the devtools marker and provide a download
|
|
56
|
+
// link if not installed.
|
|
57
|
+
if (navigator.userAgent.indexOf('Chrome') > -1) {
|
|
58
|
+
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
|
|
59
|
+
console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// If we're in IE8, check to see if we are in combatibility mode and provide
|
|
64
|
+
// information on preventing compatibility mode
|
|
65
|
+
var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
|
|
66
|
+
|
|
67
|
+
'production' !== process.env.NODE_ENV ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : null;
|
|
68
|
+
|
|
69
|
+
var expectedFeatures = [
|
|
70
|
+
// shims
|
|
71
|
+
Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim,
|
|
72
|
+
|
|
73
|
+
// shams
|
|
74
|
+
Object.create, Object.freeze];
|
|
75
|
+
|
|
76
|
+
for (var i = 0; i < expectedFeatures.length; i++) {
|
|
77
|
+
if (!expectedFeatures[i]) {
|
|
78
|
+
console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = React;
|
package/lib/ReactDOMComponent.js
CHANGED
|
@@ -18,8 +18,7 @@ var CSSPropertyOperations = require("./CSSPropertyOperations");
|
|
|
18
18
|
var DOMProperty = require("./DOMProperty");
|
|
19
19
|
var DOMPropertyOperations = require("./DOMPropertyOperations");
|
|
20
20
|
var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
|
|
21
|
-
var ReactComponentBrowserEnvironment =
|
|
22
|
-
require("./ReactComponentBrowserEnvironment");
|
|
21
|
+
var ReactComponentBrowserEnvironment = require("./ReactComponentBrowserEnvironment");
|
|
23
22
|
var ReactMount = require("./ReactMount");
|
|
24
23
|
var ReactMultiChild = require("./ReactMultiChild");
|
|
25
24
|
var ReactPerf = require("./ReactPerf");
|
|
@@ -29,6 +28,8 @@ var escapeTextContentForBrowser = require("./escapeTextContentForBrowser");
|
|
|
29
28
|
var invariant = require("./invariant");
|
|
30
29
|
var isEventSupported = require("./isEventSupported");
|
|
31
30
|
var keyOf = require("./keyOf");
|
|
31
|
+
var shallowEqual = require("./shallowEqual");
|
|
32
|
+
var validateDOMNesting = require("./validateDOMNesting");
|
|
32
33
|
var warning = require("./warning");
|
|
33
34
|
|
|
34
35
|
var deleteListener = ReactBrowserEventEmitter.deleteListener;
|
|
@@ -36,12 +37,40 @@ var listenTo = ReactBrowserEventEmitter.listenTo;
|
|
|
36
37
|
var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
|
|
37
38
|
|
|
38
39
|
// For quickly matching children type, to test if can be treated as content.
|
|
39
|
-
var CONTENT_TYPES = {'string': true, 'number': true};
|
|
40
|
+
var CONTENT_TYPES = { 'string': true, 'number': true };
|
|
40
41
|
|
|
41
|
-
var STYLE = keyOf({style: null});
|
|
42
|
+
var STYLE = keyOf({ style: null });
|
|
42
43
|
|
|
43
44
|
var ELEMENT_NODE_TYPE = 1;
|
|
44
45
|
|
|
46
|
+
var styleMutationWarning = {};
|
|
47
|
+
|
|
48
|
+
function checkAndWarnForMutatedStyle(style1, style2, component) {
|
|
49
|
+
if (style1 == null || style2 == null) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (shallowEqual(style1, style2)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var componentName = component._tag;
|
|
57
|
+
var owner = component._currentElement._owner;
|
|
58
|
+
var ownerName;
|
|
59
|
+
if (owner) {
|
|
60
|
+
ownerName = owner.getName();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
var hash = ownerName + '|' + componentName;
|
|
64
|
+
|
|
65
|
+
if (styleMutationWarning.hasOwnProperty(hash)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
styleMutationWarning[hash] = true;
|
|
70
|
+
|
|
71
|
+
'production' !== process.env.NODE_ENV ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', JSON.stringify(style1), JSON.stringify(style2)) : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
45
74
|
/**
|
|
46
75
|
* Optionally injectable operations for mutating the DOM
|
|
47
76
|
*/
|
|
@@ -50,66 +79,48 @@ var BackendIDOperations = null;
|
|
|
50
79
|
/**
|
|
51
80
|
* @param {?object} props
|
|
52
81
|
*/
|
|
53
|
-
function assertValidProps(props) {
|
|
82
|
+
function assertValidProps(component, props) {
|
|
54
83
|
if (!props) {
|
|
55
84
|
return;
|
|
56
85
|
}
|
|
57
86
|
// Note the use of `==` which checks for null or undefined.
|
|
87
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
88
|
+
if (voidElementTags[component._tag]) {
|
|
89
|
+
'production' !== process.env.NODE_ENV ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.', component._tag) : null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
58
92
|
if (props.dangerouslySetInnerHTML != null) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
'Can only set one of `children` or `props.dangerouslySetInnerHTML`.'
|
|
62
|
-
) : invariant(props.children == null));
|
|
63
|
-
("production" !== process.env.NODE_ENV ? invariant(
|
|
64
|
-
props.dangerouslySetInnerHTML.__html != null,
|
|
65
|
-
'`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
|
|
66
|
-
'Please visit http://fb.me/react-invariant-dangerously-set-inner-html ' +
|
|
67
|
-
'for more information.'
|
|
68
|
-
) : invariant(props.dangerouslySetInnerHTML.__html != null));
|
|
93
|
+
'production' !== process.env.NODE_ENV ? invariant(props.children == null, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(props.children == null);
|
|
94
|
+
'production' !== process.env.NODE_ENV ? invariant(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(typeof props.dangerouslySetInnerHTML === 'object' && '__html' in props.dangerouslySetInnerHTML);
|
|
69
95
|
}
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
'Directly setting property `innerHTML` is not permitted. ' +
|
|
74
|
-
'For more information, lookup documentation on `dangerouslySetInnerHTML`.'
|
|
75
|
-
) : null);
|
|
76
|
-
("production" !== process.env.NODE_ENV ? warning(
|
|
77
|
-
!props.contentEditable || props.children == null,
|
|
78
|
-
'A component is `contentEditable` and contains `children` managed by ' +
|
|
79
|
-
'React. It is now your responsibility to guarantee that none of ' +
|
|
80
|
-
'those nodes are unexpectedly modified or duplicated. This is ' +
|
|
81
|
-
'probably not intentional.'
|
|
82
|
-
) : null);
|
|
96
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
97
|
+
'production' !== process.env.NODE_ENV ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : null;
|
|
98
|
+
'production' !== process.env.NODE_ENV ? warning(!props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : null;
|
|
83
99
|
}
|
|
84
|
-
|
|
85
|
-
props.style == null || typeof props.style === 'object',
|
|
86
|
-
'The `style` prop expects a mapping from style properties to values, ' +
|
|
87
|
-
'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' +
|
|
88
|
-
'using JSX.'
|
|
89
|
-
) : invariant(props.style == null || typeof props.style === 'object'));
|
|
100
|
+
'production' !== process.env.NODE_ENV ? invariant(props.style == null || typeof props.style === 'object', 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.') : invariant(props.style == null || typeof props.style === 'object');
|
|
90
101
|
}
|
|
91
102
|
|
|
92
|
-
function
|
|
93
|
-
if (
|
|
103
|
+
function enqueuePutListener(id, registrationName, listener, transaction) {
|
|
104
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
94
105
|
// IE8 has no API for event capturing and the `onScroll` event doesn't
|
|
95
106
|
// bubble.
|
|
96
|
-
|
|
97
|
-
registrationName !== 'onScroll' || isEventSupported('scroll', true),
|
|
98
|
-
'This browser doesn\'t support the `onScroll` event'
|
|
99
|
-
) : null);
|
|
107
|
+
'production' !== process.env.NODE_ENV ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : null;
|
|
100
108
|
}
|
|
101
109
|
var container = ReactMount.findReactContainerForID(id);
|
|
102
110
|
if (container) {
|
|
103
|
-
var doc = container.nodeType === ELEMENT_NODE_TYPE ?
|
|
104
|
-
container.ownerDocument :
|
|
105
|
-
container;
|
|
111
|
+
var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
|
|
106
112
|
listenTo(registrationName, doc);
|
|
107
113
|
}
|
|
108
|
-
transaction.
|
|
109
|
-
id,
|
|
110
|
-
registrationName,
|
|
111
|
-
listener
|
|
112
|
-
);
|
|
114
|
+
transaction.getReactMountReady().enqueue(putListener, {
|
|
115
|
+
id: id,
|
|
116
|
+
registrationName: registrationName,
|
|
117
|
+
listener: listener
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function putListener() {
|
|
122
|
+
var listenerToPut = this;
|
|
123
|
+
ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
// For HTML, certain tags should omit their close tag. We keep a whitelist for
|
|
@@ -134,21 +145,44 @@ var omittedCloseTags = {
|
|
|
134
145
|
// NOTE: menuitem's close tag should be omitted, but that causes problems.
|
|
135
146
|
};
|
|
136
147
|
|
|
137
|
-
|
|
148
|
+
var newlineEatingTags = {
|
|
149
|
+
'listing': true,
|
|
150
|
+
'pre': true,
|
|
151
|
+
'textarea': true
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// For HTML, certain tags cannot have children. This has the same purpose as
|
|
155
|
+
// `omittedCloseTags` except that `menuitem` should still have its closing tag.
|
|
156
|
+
|
|
157
|
+
var voidElementTags = assign({
|
|
158
|
+
'menuitem': true
|
|
159
|
+
}, omittedCloseTags);
|
|
160
|
+
|
|
161
|
+
// We accept any tag to be rendered but since this gets injected into arbitrary
|
|
138
162
|
// HTML, we want to make sure that it's a safe tag.
|
|
139
163
|
// http://www.w3.org/TR/REC-xml/#NT-Name
|
|
140
164
|
|
|
141
165
|
var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
|
|
142
166
|
var validatedTagCache = {};
|
|
143
|
-
var hasOwnProperty = {}.hasOwnProperty;
|
|
167
|
+
var hasOwnProperty = ({}).hasOwnProperty;
|
|
144
168
|
|
|
145
169
|
function validateDangerousTag(tag) {
|
|
146
170
|
if (!hasOwnProperty.call(validatedTagCache, tag)) {
|
|
147
|
-
|
|
171
|
+
'production' !== process.env.NODE_ENV ? invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag) : invariant(VALID_TAG_REGEX.test(tag));
|
|
148
172
|
validatedTagCache[tag] = true;
|
|
149
173
|
}
|
|
150
174
|
}
|
|
151
175
|
|
|
176
|
+
function processChildContext(context, inst) {
|
|
177
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
178
|
+
// Pass down our tag name to child components for validation purposes
|
|
179
|
+
context = assign({}, context);
|
|
180
|
+
var info = context[validateDOMNesting.ancestorInfoContextKey];
|
|
181
|
+
context[validateDOMNesting.ancestorInfoContextKey] = validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
|
|
182
|
+
}
|
|
183
|
+
return context;
|
|
184
|
+
}
|
|
185
|
+
|
|
152
186
|
/**
|
|
153
187
|
* Creates a new React class that is idempotent and capable of containing other
|
|
154
188
|
* React components. It accepts event listeners and DOM properties that are
|
|
@@ -167,6 +201,7 @@ function ReactDOMComponent(tag) {
|
|
|
167
201
|
validateDangerousTag(tag);
|
|
168
202
|
this._tag = tag;
|
|
169
203
|
this._renderedChildren = null;
|
|
204
|
+
this._previousStyle = null;
|
|
170
205
|
this._previousStyleCopy = null;
|
|
171
206
|
this._rootNodeID = null;
|
|
172
207
|
}
|
|
@@ -175,7 +210,7 @@ ReactDOMComponent.displayName = 'ReactDOMComponent';
|
|
|
175
210
|
|
|
176
211
|
ReactDOMComponent.Mixin = {
|
|
177
212
|
|
|
178
|
-
construct: function(element) {
|
|
213
|
+
construct: function (element) {
|
|
179
214
|
this._currentElement = element;
|
|
180
215
|
},
|
|
181
216
|
|
|
@@ -186,17 +221,25 @@ ReactDOMComponent.Mixin = {
|
|
|
186
221
|
* @internal
|
|
187
222
|
* @param {string} rootID The root DOM ID for this node.
|
|
188
223
|
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
224
|
+
* @param {object} context
|
|
189
225
|
* @return {string} The computed markup.
|
|
190
226
|
*/
|
|
191
|
-
mountComponent: function(rootID, transaction, context) {
|
|
227
|
+
mountComponent: function (rootID, transaction, context) {
|
|
192
228
|
this._rootNodeID = rootID;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
229
|
+
|
|
230
|
+
assertValidProps(this, this._currentElement.props);
|
|
231
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
232
|
+
if (context[validateDOMNesting.ancestorInfoContextKey]) {
|
|
233
|
+
validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction);
|
|
238
|
+
var tagContent = this._createContentMarkup(transaction, context);
|
|
239
|
+
if (!tagContent && omittedCloseTags[this._tag]) {
|
|
240
|
+
return tagOpen + '/>';
|
|
241
|
+
}
|
|
242
|
+
return tagOpen + '>' + tagContent + '</' + this._tag + '>';
|
|
200
243
|
},
|
|
201
244
|
|
|
202
245
|
/**
|
|
@@ -211,7 +254,7 @@ ReactDOMComponent.Mixin = {
|
|
|
211
254
|
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
212
255
|
* @return {string} Markup of opening tag.
|
|
213
256
|
*/
|
|
214
|
-
_createOpenTagMarkupAndPutListeners: function(transaction) {
|
|
257
|
+
_createOpenTagMarkupAndPutListeners: function (transaction) {
|
|
215
258
|
var props = this._currentElement.props;
|
|
216
259
|
var ret = '<' + this._tag;
|
|
217
260
|
|
|
@@ -224,16 +267,19 @@ ReactDOMComponent.Mixin = {
|
|
|
224
267
|
continue;
|
|
225
268
|
}
|
|
226
269
|
if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
227
|
-
|
|
270
|
+
enqueuePutListener(this._rootNodeID, propKey, propValue, transaction);
|
|
228
271
|
} else {
|
|
229
272
|
if (propKey === STYLE) {
|
|
230
273
|
if (propValue) {
|
|
274
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
275
|
+
// See `_updateDOMProperties`. style block
|
|
276
|
+
this._previousStyle = propValue;
|
|
277
|
+
}
|
|
231
278
|
propValue = this._previousStyleCopy = assign({}, props.style);
|
|
232
279
|
}
|
|
233
280
|
propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
|
|
234
281
|
}
|
|
235
|
-
var markup =
|
|
236
|
-
DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
|
|
282
|
+
var markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
|
|
237
283
|
if (markup) {
|
|
238
284
|
ret += ' ' + markup;
|
|
239
285
|
}
|
|
@@ -243,11 +289,11 @@ ReactDOMComponent.Mixin = {
|
|
|
243
289
|
// For static pages, no need to put React ID and checksum. Saves lots of
|
|
244
290
|
// bytes.
|
|
245
291
|
if (transaction.renderToStaticMarkup) {
|
|
246
|
-
return ret
|
|
292
|
+
return ret;
|
|
247
293
|
}
|
|
248
294
|
|
|
249
295
|
var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID);
|
|
250
|
-
return ret + ' ' + markupForID
|
|
296
|
+
return ret + ' ' + markupForID;
|
|
251
297
|
},
|
|
252
298
|
|
|
253
299
|
/**
|
|
@@ -258,44 +304,53 @@ ReactDOMComponent.Mixin = {
|
|
|
258
304
|
* @param {object} context
|
|
259
305
|
* @return {string} Content markup.
|
|
260
306
|
*/
|
|
261
|
-
_createContentMarkup: function(transaction, context) {
|
|
262
|
-
var
|
|
263
|
-
if (this._tag === 'listing' ||
|
|
264
|
-
this._tag === 'pre' ||
|
|
265
|
-
this._tag === 'textarea') {
|
|
266
|
-
// Add an initial newline because browsers ignore the first newline in
|
|
267
|
-
// a <listing>, <pre>, or <textarea> as an "authoring convenience" -- see
|
|
268
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody.
|
|
269
|
-
prefix = '\n';
|
|
270
|
-
}
|
|
271
|
-
|
|
307
|
+
_createContentMarkup: function (transaction, context) {
|
|
308
|
+
var ret = '';
|
|
272
309
|
var props = this._currentElement.props;
|
|
273
310
|
|
|
274
311
|
// Intentional use of != to avoid catching zero/false.
|
|
275
312
|
var innerHTML = props.dangerouslySetInnerHTML;
|
|
276
313
|
if (innerHTML != null) {
|
|
277
314
|
if (innerHTML.__html != null) {
|
|
278
|
-
|
|
315
|
+
ret = innerHTML.__html;
|
|
279
316
|
}
|
|
280
317
|
} else {
|
|
281
|
-
var contentToUse =
|
|
282
|
-
CONTENT_TYPES[typeof props.children] ? props.children : null;
|
|
318
|
+
var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
|
|
283
319
|
var childrenToUse = contentToUse != null ? null : props.children;
|
|
284
320
|
if (contentToUse != null) {
|
|
285
|
-
|
|
321
|
+
// TODO: Validate that text is allowed as a child of this node
|
|
322
|
+
ret = escapeTextContentForBrowser(contentToUse);
|
|
286
323
|
} else if (childrenToUse != null) {
|
|
287
|
-
var mountImages = this.mountChildren(
|
|
288
|
-
|
|
289
|
-
transaction,
|
|
290
|
-
context
|
|
291
|
-
);
|
|
292
|
-
return prefix + mountImages.join('');
|
|
324
|
+
var mountImages = this.mountChildren(childrenToUse, transaction, processChildContext(context, this));
|
|
325
|
+
ret = mountImages.join('');
|
|
293
326
|
}
|
|
294
327
|
}
|
|
295
|
-
|
|
328
|
+
if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
|
|
329
|
+
// text/html ignores the first character in these tags if it's a newline
|
|
330
|
+
// Prefer to break application/xml over text/html (for now) by adding
|
|
331
|
+
// a newline specifically to get eaten by the parser. (Alternately for
|
|
332
|
+
// textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
|
|
333
|
+
// \r is normalized out by HTMLTextAreaElement#value.)
|
|
334
|
+
// See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
|
|
335
|
+
// See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
|
|
336
|
+
// See: <http://www.w3.org/TR/html5/syntax.html#newlines>
|
|
337
|
+
// See: Parsing of "textarea" "listing" and "pre" elements
|
|
338
|
+
// from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
|
|
339
|
+
return '\n' + ret;
|
|
340
|
+
} else {
|
|
341
|
+
return ret;
|
|
342
|
+
}
|
|
296
343
|
},
|
|
297
344
|
|
|
298
|
-
|
|
345
|
+
/**
|
|
346
|
+
* Receives a next element and updates the component.
|
|
347
|
+
*
|
|
348
|
+
* @internal
|
|
349
|
+
* @param {ReactElement} nextElement
|
|
350
|
+
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
351
|
+
* @param {object} context
|
|
352
|
+
*/
|
|
353
|
+
receiveComponent: function (nextElement, transaction, context) {
|
|
299
354
|
var prevElement = this._currentElement;
|
|
300
355
|
this._currentElement = nextElement;
|
|
301
356
|
this.updateComponent(transaction, prevElement, nextElement, context);
|
|
@@ -311,10 +366,10 @@ ReactDOMComponent.Mixin = {
|
|
|
311
366
|
* @internal
|
|
312
367
|
* @overridable
|
|
313
368
|
*/
|
|
314
|
-
updateComponent: function(transaction, prevElement, nextElement, context) {
|
|
315
|
-
assertValidProps(this._currentElement.props);
|
|
369
|
+
updateComponent: function (transaction, prevElement, nextElement, context) {
|
|
370
|
+
assertValidProps(this, this._currentElement.props);
|
|
316
371
|
this._updateDOMProperties(prevElement.props, transaction);
|
|
317
|
-
this._updateDOMChildren(prevElement.props, transaction, context);
|
|
372
|
+
this._updateDOMChildren(prevElement.props, transaction, processChildContext(context, this));
|
|
318
373
|
},
|
|
319
374
|
|
|
320
375
|
/**
|
|
@@ -332,14 +387,13 @@ ReactDOMComponent.Mixin = {
|
|
|
332
387
|
* @param {object} lastProps
|
|
333
388
|
* @param {ReactReconcileTransaction} transaction
|
|
334
389
|
*/
|
|
335
|
-
_updateDOMProperties: function(lastProps, transaction) {
|
|
390
|
+
_updateDOMProperties: function (lastProps, transaction) {
|
|
336
391
|
var nextProps = this._currentElement.props;
|
|
337
392
|
var propKey;
|
|
338
393
|
var styleName;
|
|
339
394
|
var styleUpdates;
|
|
340
395
|
for (propKey in lastProps) {
|
|
341
|
-
if (nextProps.hasOwnProperty(propKey) ||
|
|
342
|
-
!lastProps.hasOwnProperty(propKey)) {
|
|
396
|
+
if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey)) {
|
|
343
397
|
continue;
|
|
344
398
|
}
|
|
345
399
|
if (propKey === STYLE) {
|
|
@@ -352,41 +406,43 @@ ReactDOMComponent.Mixin = {
|
|
|
352
406
|
}
|
|
353
407
|
this._previousStyleCopy = null;
|
|
354
408
|
} else if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
);
|
|
409
|
+
if (lastProps[propKey]) {
|
|
410
|
+
// Only call deleteListener if there was a listener previously or
|
|
411
|
+
// else willDeleteListener gets called when there wasn't actually a
|
|
412
|
+
// listener (e.g., onClick={null})
|
|
413
|
+
deleteListener(this._rootNodeID, propKey);
|
|
414
|
+
}
|
|
415
|
+
} else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
|
|
416
|
+
BackendIDOperations.deletePropertyByID(this._rootNodeID, propKey);
|
|
363
417
|
}
|
|
364
418
|
}
|
|
365
419
|
for (propKey in nextProps) {
|
|
366
420
|
var nextProp = nextProps[propKey];
|
|
367
|
-
var lastProp = propKey === STYLE ?
|
|
368
|
-
this._previousStyleCopy :
|
|
369
|
-
lastProps[propKey];
|
|
421
|
+
var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps[propKey];
|
|
370
422
|
if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) {
|
|
371
423
|
continue;
|
|
372
424
|
}
|
|
373
425
|
if (propKey === STYLE) {
|
|
374
426
|
if (nextProp) {
|
|
427
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
428
|
+
checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
|
|
429
|
+
this._previousStyle = nextProp;
|
|
430
|
+
}
|
|
375
431
|
nextProp = this._previousStyleCopy = assign({}, nextProp);
|
|
432
|
+
} else {
|
|
433
|
+
this._previousStyleCopy = null;
|
|
376
434
|
}
|
|
377
435
|
if (lastProp) {
|
|
378
436
|
// Unset styles on `lastProp` but not on `nextProp`.
|
|
379
437
|
for (styleName in lastProp) {
|
|
380
|
-
if (lastProp.hasOwnProperty(styleName) &&
|
|
381
|
-
(!nextProp || !nextProp.hasOwnProperty(styleName))) {
|
|
438
|
+
if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
|
|
382
439
|
styleUpdates = styleUpdates || {};
|
|
383
440
|
styleUpdates[styleName] = '';
|
|
384
441
|
}
|
|
385
442
|
}
|
|
386
443
|
// Update styles that changed since `lastProp`.
|
|
387
444
|
for (styleName in nextProp) {
|
|
388
|
-
if (nextProp.hasOwnProperty(styleName) &&
|
|
389
|
-
lastProp[styleName] !== nextProp[styleName]) {
|
|
445
|
+
if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
|
|
390
446
|
styleUpdates = styleUpdates || {};
|
|
391
447
|
styleUpdates[styleName] = nextProp[styleName];
|
|
392
448
|
}
|
|
@@ -396,22 +452,17 @@ ReactDOMComponent.Mixin = {
|
|
|
396
452
|
styleUpdates = nextProp;
|
|
397
453
|
}
|
|
398
454
|
} else if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
nextProp
|
|
407
|
-
);
|
|
455
|
+
if (nextProp) {
|
|
456
|
+
enqueuePutListener(this._rootNodeID, propKey, nextProp, transaction);
|
|
457
|
+
} else if (lastProp) {
|
|
458
|
+
deleteListener(this._rootNodeID, propKey);
|
|
459
|
+
}
|
|
460
|
+
} else if (DOMProperty.isStandardName[propKey] || DOMProperty.isCustomAttribute(propKey)) {
|
|
461
|
+
BackendIDOperations.updatePropertyByID(this._rootNodeID, propKey, nextProp);
|
|
408
462
|
}
|
|
409
463
|
}
|
|
410
464
|
if (styleUpdates) {
|
|
411
|
-
BackendIDOperations.updateStylesByID(
|
|
412
|
-
this._rootNodeID,
|
|
413
|
-
styleUpdates
|
|
414
|
-
);
|
|
465
|
+
BackendIDOperations.updateStylesByID(this._rootNodeID, styleUpdates);
|
|
415
466
|
}
|
|
416
467
|
},
|
|
417
468
|
|
|
@@ -422,20 +473,14 @@ ReactDOMComponent.Mixin = {
|
|
|
422
473
|
* @param {object} lastProps
|
|
423
474
|
* @param {ReactReconcileTransaction} transaction
|
|
424
475
|
*/
|
|
425
|
-
_updateDOMChildren: function(lastProps, transaction, context) {
|
|
476
|
+
_updateDOMChildren: function (lastProps, transaction, context) {
|
|
426
477
|
var nextProps = this._currentElement.props;
|
|
427
478
|
|
|
428
|
-
var lastContent =
|
|
429
|
-
|
|
430
|
-
var nextContent =
|
|
431
|
-
CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
|
|
479
|
+
var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
|
|
480
|
+
var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
|
|
432
481
|
|
|
433
|
-
var lastHtml =
|
|
434
|
-
|
|
435
|
-
lastProps.dangerouslySetInnerHTML.__html;
|
|
436
|
-
var nextHtml =
|
|
437
|
-
nextProps.dangerouslySetInnerHTML &&
|
|
438
|
-
nextProps.dangerouslySetInnerHTML.__html;
|
|
482
|
+
var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;
|
|
483
|
+
var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;
|
|
439
484
|
|
|
440
485
|
// Note the use of `!=` which checks for null or undefined.
|
|
441
486
|
var lastChildren = lastContent != null ? null : lastProps.children;
|
|
@@ -457,10 +502,7 @@ ReactDOMComponent.Mixin = {
|
|
|
457
502
|
}
|
|
458
503
|
} else if (nextHtml != null) {
|
|
459
504
|
if (lastHtml !== nextHtml) {
|
|
460
|
-
BackendIDOperations.updateInnerHTMLByID(
|
|
461
|
-
this._rootNodeID,
|
|
462
|
-
nextHtml
|
|
463
|
-
);
|
|
505
|
+
BackendIDOperations.updateInnerHTMLByID(this._rootNodeID, nextHtml);
|
|
464
506
|
}
|
|
465
507
|
} else if (nextChildren != null) {
|
|
466
508
|
this.updateChildren(nextChildren, transaction, context);
|
|
@@ -473,7 +515,7 @@ ReactDOMComponent.Mixin = {
|
|
|
473
515
|
*
|
|
474
516
|
* @internal
|
|
475
517
|
*/
|
|
476
|
-
unmountComponent: function() {
|
|
518
|
+
unmountComponent: function () {
|
|
477
519
|
this.unmountChildren();
|
|
478
520
|
ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
|
|
479
521
|
ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
|
|
@@ -487,16 +529,12 @@ ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
|
|
|
487
529
|
updateComponent: 'updateComponent'
|
|
488
530
|
});
|
|
489
531
|
|
|
490
|
-
assign(
|
|
491
|
-
ReactDOMComponent.prototype,
|
|
492
|
-
ReactDOMComponent.Mixin,
|
|
493
|
-
ReactMultiChild.Mixin
|
|
494
|
-
);
|
|
532
|
+
assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
|
|
495
533
|
|
|
496
534
|
ReactDOMComponent.injection = {
|
|
497
|
-
injectIDOperations: function(IDOperations) {
|
|
535
|
+
injectIDOperations: function (IDOperations) {
|
|
498
536
|
ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
|
|
499
537
|
}
|
|
500
538
|
};
|
|
501
539
|
|
|
502
|
-
module.exports = ReactDOMComponent;
|
|
540
|
+
module.exports = ReactDOMComponent;
|