react 0.14.0-beta2 → 0.14.1
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 +4 -4
- package/addons.js +3 -1
- package/dist/react-with-addons.js +1944 -1375
- package/dist/react-with-addons.min.js +6 -6
- package/dist/react.js +1704 -1250
- package/dist/react.min.js +6 -6
- package/lib/CSSProperty.js +15 -3
- package/lib/CSSPropertyOperations.js +15 -2
- package/lib/ChangeEventPlugin.js +5 -2
- package/lib/DOMChildrenOperations.js +12 -1
- package/lib/DOMPropertyOperations.js +14 -1
- package/lib/Danger.js +9 -4
- package/lib/EnterLeaveEventPlugin.js +13 -5
- package/lib/EventConstants.js +2 -2
- package/lib/EventPluginHub.js +18 -10
- package/lib/EventPluginUtils.js +23 -27
- package/lib/EventPropagators.js +1 -1
- package/lib/FallbackCompositionState.js +6 -0
- package/lib/HTMLDOMPropertyConfig.js +25 -2
- package/lib/PooledClass.js +1 -3
- package/lib/React.js +14 -3
- package/lib/ReactBrowserComponentMixin.js +1 -1
- package/lib/ReactBrowserEventEmitter.js +10 -4
- package/lib/ReactCSSTransitionGroup.js +33 -18
- package/lib/ReactCSSTransitionGroupChild.js +42 -25
- package/lib/ReactChildReconciler.js +3 -5
- package/lib/ReactChildren.js +70 -30
- package/lib/ReactClass.js +6 -6
- package/lib/ReactComponent.js +7 -6
- package/lib/ReactCompositeComponent.js +58 -7
- package/lib/ReactDOM.js +7 -5
- package/lib/ReactDOMComponent.js +140 -46
- package/lib/ReactDOMFeatureFlags.js +18 -0
- package/lib/ReactDOMIDOperations.js +1 -60
- package/lib/ReactDOMInput.js +10 -1
- package/lib/ReactDOMSelect.js +1 -1
- package/lib/ReactDOMSelection.js +16 -0
- package/lib/ReactDOMServer.js +3 -1
- package/lib/ReactDOMTextComponent.js +23 -10
- package/lib/ReactDOMTextarea.js +3 -1
- package/lib/ReactDefaultInjection.js +0 -2
- package/lib/ReactDefaultPerf.js +10 -4
- package/lib/ReactDefaultPerfAnalysis.js +7 -3
- package/lib/ReactElement.js +72 -35
- package/lib/ReactElementValidator.js +31 -75
- package/lib/ReactEmptyComponent.js +25 -61
- package/lib/ReactEmptyComponentRegistry.js +48 -0
- package/lib/ReactErrorUtils.js +55 -9
- package/lib/ReactEventEmitterMixin.js +1 -1
- package/lib/ReactEventListener.js +16 -9
- package/lib/ReactFragment.js +25 -116
- package/lib/ReactInjection.js +0 -2
- package/lib/ReactIsomorphic.js +4 -0
- package/lib/ReactLink.js +1 -1
- package/lib/ReactMount.js +127 -41
- package/lib/ReactMultiChild.js +37 -4
- package/lib/ReactOwner.js +2 -2
- package/lib/ReactPropTransferer.js +1 -1
- package/lib/ReactPropTypes.js +11 -8
- package/lib/ReactReconcileTransaction.js +4 -2
- package/lib/ReactReconciler.js +16 -17
- package/lib/ReactRef.js +13 -1
- package/lib/ReactServerRenderingTransaction.js +1 -0
- package/lib/ReactTestUtils.js +27 -15
- package/lib/ReactTransitionChildMapping.js +3 -6
- package/lib/ReactUpdateQueue.js +4 -4
- package/lib/ReactUpdates.js +1 -1
- package/lib/ReactVersion.js +14 -0
- package/lib/ReactWithAddons.js +10 -1
- package/lib/ResponderEventPlugin.js +1 -1
- package/lib/SelectEventPlugin.js +11 -1
- package/lib/SimpleEventPlugin.js +10 -31
- package/lib/SyntheticEvent.js +15 -1
- package/lib/Transaction.js +1 -1
- package/lib/canDefineProperty.js +24 -0
- package/lib/createHierarchyRenderer.js +1 -1
- package/lib/deprecated.js +3 -2
- package/lib/findDOMNode.js +1 -1
- package/lib/getTestDocument.js +4 -11
- package/lib/instantiateReactComponent.js +3 -5
- package/lib/reactComponentExpect.js +6 -0
- package/lib/shouldUpdateReactComponent.js +12 -8
- package/lib/sliceChildren.js +3 -20
- package/lib/traverseAllChildren.js +15 -9
- package/package.json +2 -2
- package/react.js +1 -51
- package/dist/JSXTransformer.js +0 -17949
- package/lib/joinClasses.js +0 -39
- package/lib/memoizeStringOnly.js +0 -31
package/lib/ReactChildren.js
CHANGED
|
@@ -12,13 +12,18 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
var PooledClass = require('./PooledClass');
|
|
15
|
-
var
|
|
15
|
+
var ReactElement = require('./ReactElement');
|
|
16
16
|
|
|
17
|
+
var emptyFunction = require('fbjs/lib/emptyFunction');
|
|
17
18
|
var traverseAllChildren = require('./traverseAllChildren');
|
|
18
|
-
var warning = require('fbjs/lib/warning');
|
|
19
19
|
|
|
20
20
|
var twoArgumentPooler = PooledClass.twoArgumentPooler;
|
|
21
|
-
var
|
|
21
|
+
var fourArgumentPooler = PooledClass.fourArgumentPooler;
|
|
22
|
+
|
|
23
|
+
var userProvidedKeyEscapeRegex = /\/(?!\/)/g;
|
|
24
|
+
function escapeUserProvidedKey(text) {
|
|
25
|
+
return ('' + text).replace(userProvidedKeyEscapeRegex, '//');
|
|
26
|
+
}
|
|
22
27
|
|
|
23
28
|
/**
|
|
24
29
|
* PooledClass representing the bookkeeping associated with performing a child
|
|
@@ -33,11 +38,18 @@ function ForEachBookKeeping(forEachFunction, forEachContext) {
|
|
|
33
38
|
this.context = forEachContext;
|
|
34
39
|
this.count = 0;
|
|
35
40
|
}
|
|
41
|
+
ForEachBookKeeping.prototype.destructor = function () {
|
|
42
|
+
this.func = null;
|
|
43
|
+
this.context = null;
|
|
44
|
+
this.count = 0;
|
|
45
|
+
};
|
|
36
46
|
PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);
|
|
37
47
|
|
|
38
|
-
function forEachSingleChild(
|
|
39
|
-
var
|
|
40
|
-
|
|
48
|
+
function forEachSingleChild(bookKeeping, child, name) {
|
|
49
|
+
var func = bookKeeping.func;
|
|
50
|
+
var context = bookKeeping.context;
|
|
51
|
+
|
|
52
|
+
func.call(context, child, bookKeeping.count++);
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
/**
|
|
@@ -54,7 +66,6 @@ function forEachChildren(children, forEachFunc, forEachContext) {
|
|
|
54
66
|
if (children == null) {
|
|
55
67
|
return children;
|
|
56
68
|
}
|
|
57
|
-
|
|
58
69
|
var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);
|
|
59
70
|
traverseAllChildren(children, forEachSingleChild, traverseContext);
|
|
60
71
|
ForEachBookKeeping.release(traverseContext);
|
|
@@ -69,27 +80,50 @@ function forEachChildren(children, forEachFunc, forEachContext) {
|
|
|
69
80
|
* @param {!function} mapFunction Function to perform mapping with.
|
|
70
81
|
* @param {?*} mapContext Context to perform mapping with.
|
|
71
82
|
*/
|
|
72
|
-
function MapBookKeeping(mapResult, mapFunction, mapContext) {
|
|
83
|
+
function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {
|
|
73
84
|
this.result = mapResult;
|
|
85
|
+
this.keyPrefix = keyPrefix;
|
|
74
86
|
this.func = mapFunction;
|
|
75
87
|
this.context = mapContext;
|
|
76
88
|
this.count = 0;
|
|
77
89
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
MapBookKeeping.prototype.destructor = function () {
|
|
91
|
+
this.result = null;
|
|
92
|
+
this.keyPrefix = null;
|
|
93
|
+
this.func = null;
|
|
94
|
+
this.context = null;
|
|
95
|
+
this.count = 0;
|
|
96
|
+
};
|
|
97
|
+
PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);
|
|
98
|
+
|
|
99
|
+
function mapSingleChildIntoContext(bookKeeping, child, childKey) {
|
|
100
|
+
var result = bookKeeping.result;
|
|
101
|
+
var keyPrefix = bookKeeping.keyPrefix;
|
|
102
|
+
var func = bookKeeping.func;
|
|
103
|
+
var context = bookKeeping.context;
|
|
104
|
+
|
|
105
|
+
var mappedChild = func.call(context, child, bookKeeping.count++);
|
|
106
|
+
if (Array.isArray(mappedChild)) {
|
|
107
|
+
mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);
|
|
108
|
+
} else if (mappedChild != null) {
|
|
109
|
+
if (ReactElement.isValidElement(mappedChild)) {
|
|
110
|
+
mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,
|
|
111
|
+
// Keep both the (mapped) and old keys if they differ, just as
|
|
112
|
+
// traverseAllChildren used to do for objects as children
|
|
113
|
+
keyPrefix + (mappedChild !== child ? escapeUserProvidedKey(mappedChild.key || '') + '/' : '') + childKey);
|
|
114
|
+
}
|
|
115
|
+
result.push(mappedChild);
|
|
87
116
|
}
|
|
117
|
+
}
|
|
88
118
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
119
|
+
function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
|
|
120
|
+
var escapedPrefix = '';
|
|
121
|
+
if (prefix != null) {
|
|
122
|
+
escapedPrefix = escapeUserProvidedKey(prefix) + '/';
|
|
92
123
|
}
|
|
124
|
+
var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);
|
|
125
|
+
traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
|
|
126
|
+
MapBookKeeping.release(traverseContext);
|
|
93
127
|
}
|
|
94
128
|
|
|
95
129
|
/**
|
|
@@ -98,9 +132,6 @@ function mapSingleChildIntoContext(traverseContext, child, name) {
|
|
|
98
132
|
* The provided mapFunction(child, key, index) will be called for each
|
|
99
133
|
* leaf child.
|
|
100
134
|
*
|
|
101
|
-
* TODO: This may likely break any calls to `ReactChildren.map` that were
|
|
102
|
-
* previously relying on the fact that we guarded against null children.
|
|
103
|
-
*
|
|
104
135
|
* @param {?*} children Children tree container.
|
|
105
136
|
* @param {function(*, int)} func The map function.
|
|
106
137
|
* @param {*} context Context for mapFunction.
|
|
@@ -110,12 +141,9 @@ function mapChildren(children, func, context) {
|
|
|
110
141
|
if (children == null) {
|
|
111
142
|
return children;
|
|
112
143
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
|
|
117
|
-
MapBookKeeping.release(traverseContext);
|
|
118
|
-
return ReactFragment.create(mapResult);
|
|
144
|
+
var result = [];
|
|
145
|
+
mapIntoWithKeyPrefixInternal(children, result, null, func, context);
|
|
146
|
+
return result;
|
|
119
147
|
}
|
|
120
148
|
|
|
121
149
|
function forEachSingleChildDummy(traverseContext, child, name) {
|
|
@@ -133,10 +161,22 @@ function countChildren(children, context) {
|
|
|
133
161
|
return traverseAllChildren(children, forEachSingleChildDummy, null);
|
|
134
162
|
}
|
|
135
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Flatten a children object (typically specified as `props.children`) and
|
|
166
|
+
* return an array with appropriately re-keyed children.
|
|
167
|
+
*/
|
|
168
|
+
function toArray(children) {
|
|
169
|
+
var result = [];
|
|
170
|
+
mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
|
|
136
174
|
var ReactChildren = {
|
|
137
175
|
forEach: forEachChildren,
|
|
138
176
|
map: mapChildren,
|
|
139
|
-
|
|
177
|
+
mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,
|
|
178
|
+
count: countChildren,
|
|
179
|
+
toArray: toArray
|
|
140
180
|
};
|
|
141
181
|
|
|
142
182
|
module.exports = ReactChildren;
|
package/lib/ReactClass.js
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
|
|
14
14
|
var ReactComponent = require('./ReactComponent');
|
|
15
15
|
var ReactElement = require('./ReactElement');
|
|
16
|
-
var ReactErrorUtils = require('./ReactErrorUtils');
|
|
17
16
|
var ReactPropTypeLocations = require('./ReactPropTypeLocations');
|
|
18
17
|
var ReactPropTypeLocationNames = require('./ReactPropTypeLocationNames');
|
|
19
18
|
var ReactNoopUpdateQueue = require('./ReactNoopUpdateQueue');
|
|
@@ -58,7 +57,7 @@ var warnedSetProps = false;
|
|
|
58
57
|
function warnSetProps() {
|
|
59
58
|
if (!warnedSetProps) {
|
|
60
59
|
warnedSetProps = true;
|
|
61
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'setProps(...) and replaceProps(...) are deprecated. ' + 'Instead, call
|
|
60
|
+
process.env.NODE_ENV !== 'production' ? warning(false, 'setProps(...) and replaceProps(...) are deprecated. ' + 'Instead, call render again at the top level.') : undefined;
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -358,9 +357,10 @@ var RESERVED_SPEC_KEYS = {
|
|
|
358
357
|
},
|
|
359
358
|
statics: function (Constructor, statics) {
|
|
360
359
|
mixStaticSpecIntoComponent(Constructor, statics);
|
|
361
|
-
}
|
|
362
|
-
};
|
|
360
|
+
},
|
|
361
|
+
autobind: function () {} };
|
|
363
362
|
|
|
363
|
+
// noop
|
|
364
364
|
function validateTypeDef(Constructor, typeDef, location) {
|
|
365
365
|
for (var propName in typeDef) {
|
|
366
366
|
if (typeDef.hasOwnProperty(propName)) {
|
|
@@ -429,7 +429,7 @@ function mixSpecIntoComponent(Constructor, spec) {
|
|
|
429
429
|
var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
|
|
430
430
|
var isAlreadyDefined = proto.hasOwnProperty(name);
|
|
431
431
|
var isFunction = typeof property === 'function';
|
|
432
|
-
var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined;
|
|
432
|
+
var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;
|
|
433
433
|
|
|
434
434
|
if (shouldAutoBind) {
|
|
435
435
|
if (!proto.__reactAutoBindMap) {
|
|
@@ -593,7 +593,7 @@ function bindAutoBindMethods(component) {
|
|
|
593
593
|
for (var autoBindKey in component.__reactAutoBindMap) {
|
|
594
594
|
if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
|
|
595
595
|
var method = component.__reactAutoBindMap[autoBindKey];
|
|
596
|
-
component[autoBindKey] = bindAutoBindMethod(component,
|
|
596
|
+
component[autoBindKey] = bindAutoBindMethod(component, method);
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
599
|
}
|
package/lib/ReactComponent.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
var ReactNoopUpdateQueue = require('./ReactNoopUpdateQueue');
|
|
15
15
|
|
|
16
|
+
var canDefineProperty = require('./canDefineProperty');
|
|
16
17
|
var emptyObject = require('fbjs/lib/emptyObject');
|
|
17
18
|
var invariant = require('fbjs/lib/invariant');
|
|
18
19
|
var warning = require('fbjs/lib/warning');
|
|
@@ -29,6 +30,8 @@ function ReactComponent(props, context, updater) {
|
|
|
29
30
|
this.updater = updater || ReactNoopUpdateQueue;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
ReactComponent.prototype.isReactComponent = {};
|
|
34
|
+
|
|
32
35
|
/**
|
|
33
36
|
* Sets a subset of the state. Always use this to mutate
|
|
34
37
|
* state. You should treat `this.state` as immutable.
|
|
@@ -93,22 +96,20 @@ ReactComponent.prototype.forceUpdate = function (callback) {
|
|
|
93
96
|
*/
|
|
94
97
|
if (process.env.NODE_ENV !== 'production') {
|
|
95
98
|
var deprecatedAPIs = {
|
|
96
|
-
getDOMNode: ['getDOMNode', 'Use
|
|
99
|
+
getDOMNode: ['getDOMNode', 'Use ReactDOM.findDOMNode(component) instead.'],
|
|
97
100
|
isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
|
|
98
|
-
replaceProps: ['replaceProps', 'Instead, call
|
|
101
|
+
replaceProps: ['replaceProps', 'Instead, call render again at the top level.'],
|
|
99
102
|
replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'],
|
|
100
|
-
setProps: ['setProps', 'Instead, call
|
|
103
|
+
setProps: ['setProps', 'Instead, call render again at the top level.']
|
|
101
104
|
};
|
|
102
105
|
var defineDeprecationWarning = function (methodName, info) {
|
|
103
|
-
|
|
106
|
+
if (canDefineProperty) {
|
|
104
107
|
Object.defineProperty(ReactComponent.prototype, methodName, {
|
|
105
108
|
get: function () {
|
|
106
109
|
process.env.NODE_ENV !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : undefined;
|
|
107
110
|
return undefined;
|
|
108
111
|
}
|
|
109
112
|
});
|
|
110
|
-
} catch (x) {
|
|
111
|
-
// IE will fail on defineProperty (es5-shim/sham too)
|
|
112
113
|
}
|
|
113
114
|
};
|
|
114
115
|
for (var fnName in deprecatedAPIs) {
|
|
@@ -38,6 +38,12 @@ function getDeclarationErrorAddendum(component) {
|
|
|
38
38
|
return '';
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function StatelessComponent(Component) {}
|
|
42
|
+
StatelessComponent.prototype.render = function () {
|
|
43
|
+
var Component = ReactInstanceMap.get(this)._currentElement.type;
|
|
44
|
+
return Component(this.props, this.context, this.updater);
|
|
45
|
+
};
|
|
46
|
+
|
|
41
47
|
/**
|
|
42
48
|
* ------------------ The Life-Cycle of a Composite Component ------------------
|
|
43
49
|
*
|
|
@@ -126,12 +132,43 @@ var ReactCompositeComponentMixin = {
|
|
|
126
132
|
var Component = this._currentElement.type;
|
|
127
133
|
|
|
128
134
|
// Initialize the public class
|
|
129
|
-
var inst
|
|
135
|
+
var inst;
|
|
136
|
+
var renderedElement;
|
|
137
|
+
|
|
138
|
+
// This is a way to detect if Component is a stateless arrow function
|
|
139
|
+
// component, which is not newable. It might not be 100% reliable but is
|
|
140
|
+
// something we can do until we start detecting that Component extends
|
|
141
|
+
// React.Component. We already assume that typeof Component === 'function'.
|
|
142
|
+
var canInstantiate = ('prototype' in Component);
|
|
143
|
+
|
|
144
|
+
if (canInstantiate) {
|
|
145
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
146
|
+
ReactCurrentOwner.current = this;
|
|
147
|
+
try {
|
|
148
|
+
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
|
|
149
|
+
} finally {
|
|
150
|
+
ReactCurrentOwner.current = null;
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!canInstantiate || inst === null || inst === false || ReactElement.isValidElement(inst)) {
|
|
158
|
+
renderedElement = inst;
|
|
159
|
+
inst = new StatelessComponent(Component);
|
|
160
|
+
}
|
|
130
161
|
|
|
131
162
|
if (process.env.NODE_ENV !== 'production') {
|
|
132
163
|
// This will throw later in _renderValidatedComponent, but add an early
|
|
133
164
|
// warning now to help debugging
|
|
134
|
-
|
|
165
|
+
if (inst.render == null) {
|
|
166
|
+
process.env.NODE_ENV !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`, returned ' + 'null/false from a stateless component, or tried to render an ' + 'element whose type is a function that isn\'t a React component.', Component.displayName || Component.name || 'Component') : undefined;
|
|
167
|
+
} else {
|
|
168
|
+
// We support ES6 inheriting from React.Component, the module pattern,
|
|
169
|
+
// and stateless components, but not ES6 classes that don't extend
|
|
170
|
+
process.env.NODE_ENV !== 'production' ? warning(Component.prototype && Component.prototype.isReactComponent || !canInstantiate || !(inst instanceof Component), '%s(...): React component classes must extend React.Component.', Component.displayName || Component.name || 'Component') : undefined;
|
|
171
|
+
}
|
|
135
172
|
}
|
|
136
173
|
|
|
137
174
|
// These should be set up in the constructor, but as a convenience for
|
|
@@ -178,7 +215,10 @@ var ReactCompositeComponentMixin = {
|
|
|
178
215
|
}
|
|
179
216
|
}
|
|
180
217
|
|
|
181
|
-
|
|
218
|
+
// If not a stateless component, we now render
|
|
219
|
+
if (renderedElement === undefined) {
|
|
220
|
+
renderedElement = this._renderValidatedComponent();
|
|
221
|
+
}
|
|
182
222
|
|
|
183
223
|
this._renderedComponent = this._instantiateReactComponent(renderedElement);
|
|
184
224
|
|
|
@@ -205,6 +245,7 @@ var ReactCompositeComponentMixin = {
|
|
|
205
245
|
|
|
206
246
|
ReactReconciler.unmountComponent(this._renderedComponent);
|
|
207
247
|
this._renderedComponent = null;
|
|
248
|
+
this._instance = null;
|
|
208
249
|
|
|
209
250
|
// Reset pending fields
|
|
210
251
|
// Even if this component is scheduled for another update in ReactUpdates,
|
|
@@ -340,7 +381,7 @@ var ReactCompositeComponentMixin = {
|
|
|
340
381
|
}
|
|
341
382
|
if (error instanceof Error) {
|
|
342
383
|
// We may want to extend this logic for similar errors in
|
|
343
|
-
//
|
|
384
|
+
// top-level render calls, so I'm abstracting it away into
|
|
344
385
|
// a function to minimize refactoring in the future
|
|
345
386
|
var addendum = getDeclarationErrorAddendum(this);
|
|
346
387
|
|
|
@@ -583,8 +624,14 @@ var ReactCompositeComponentMixin = {
|
|
|
583
624
|
*/
|
|
584
625
|
attachRef: function (ref, component) {
|
|
585
626
|
var inst = this.getPublicInstance();
|
|
627
|
+
!(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : invariant(false) : undefined;
|
|
628
|
+
var publicComponentInstance = component.getPublicInstance();
|
|
629
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
630
|
+
var componentName = component && component.getName ? component.getName() : 'a component';
|
|
631
|
+
process.env.NODE_ENV !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : undefined;
|
|
632
|
+
}
|
|
586
633
|
var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;
|
|
587
|
-
refs[ref] =
|
|
634
|
+
refs[ref] = publicComponentInstance;
|
|
588
635
|
},
|
|
589
636
|
|
|
590
637
|
/**
|
|
@@ -613,14 +660,18 @@ var ReactCompositeComponentMixin = {
|
|
|
613
660
|
|
|
614
661
|
/**
|
|
615
662
|
* Get the publicly accessible representation of this component - i.e. what
|
|
616
|
-
* is exposed by refs and returned by
|
|
663
|
+
* is exposed by refs and returned by render. Can be null for stateless
|
|
617
664
|
* components.
|
|
618
665
|
*
|
|
619
666
|
* @return {ReactComponent} the public component instance.
|
|
620
667
|
* @internal
|
|
621
668
|
*/
|
|
622
669
|
getPublicInstance: function () {
|
|
623
|
-
|
|
670
|
+
var inst = this._instance;
|
|
671
|
+
if (inst instanceof StatelessComponent) {
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
return inst;
|
|
624
675
|
},
|
|
625
676
|
|
|
626
677
|
// Stub
|
package/lib/ReactDOM.js
CHANGED
|
@@ -21,6 +21,7 @@ var ReactMount = require('./ReactMount');
|
|
|
21
21
|
var ReactPerf = require('./ReactPerf');
|
|
22
22
|
var ReactReconciler = require('./ReactReconciler');
|
|
23
23
|
var ReactUpdates = require('./ReactUpdates');
|
|
24
|
+
var ReactVersion = require('./ReactVersion');
|
|
24
25
|
|
|
25
26
|
var findDOMNode = require('./findDOMNode');
|
|
26
27
|
var renderSubtreeIntoContainer = require('./renderSubtreeIntoContainer');
|
|
@@ -34,6 +35,7 @@ var React = {
|
|
|
34
35
|
findDOMNode: findDOMNode,
|
|
35
36
|
render: render,
|
|
36
37
|
unmountComponentAtNode: ReactMount.unmountComponentAtNode,
|
|
38
|
+
version: ReactVersion,
|
|
37
39
|
|
|
38
40
|
/* eslint-disable camelcase */
|
|
39
41
|
unstable_batchedUpdates: ReactUpdates.batchedUpdates,
|
|
@@ -57,15 +59,15 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
57
59
|
var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
|
|
58
60
|
if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
|
|
59
61
|
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (
|
|
62
|
+
// First check if devtools is not installed
|
|
63
|
+
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
|
|
64
|
+
// If we're in Chrome or Firefox, provide a download link if not installed.
|
|
65
|
+
if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
|
|
64
66
|
console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
// If we're in IE8, check to see if we are in
|
|
70
|
+
// If we're in IE8, check to see if we are in compatibility mode and provide
|
|
69
71
|
// information on preventing compatibility mode
|
|
70
72
|
var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
|
|
71
73
|
|
package/lib/ReactDOMComponent.js
CHANGED
|
@@ -32,10 +32,13 @@ var ReactPerf = require('./ReactPerf');
|
|
|
32
32
|
var ReactUpdateQueue = require('./ReactUpdateQueue');
|
|
33
33
|
|
|
34
34
|
var assign = require('./Object.assign');
|
|
35
|
+
var canDefineProperty = require('./canDefineProperty');
|
|
35
36
|
var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');
|
|
36
37
|
var invariant = require('fbjs/lib/invariant');
|
|
37
38
|
var isEventSupported = require('./isEventSupported');
|
|
38
39
|
var keyOf = require('fbjs/lib/keyOf');
|
|
40
|
+
var setInnerHTML = require('./setInnerHTML');
|
|
41
|
+
var setTextContent = require('./setTextContent');
|
|
39
42
|
var shallowEqual = require('fbjs/lib/shallowEqual');
|
|
40
43
|
var validateDOMNesting = require('./validateDOMNesting');
|
|
41
44
|
var warning = require('fbjs/lib/warning');
|
|
@@ -48,15 +51,10 @@ var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
|
|
|
48
51
|
var CONTENT_TYPES = { 'string': true, 'number': true };
|
|
49
52
|
|
|
50
53
|
var STYLE = keyOf({ style: null });
|
|
54
|
+
var HTML = keyOf({ __html: null });
|
|
51
55
|
|
|
52
56
|
var ELEMENT_NODE_TYPE = 1;
|
|
53
57
|
|
|
54
|
-
var canDefineProperty = false;
|
|
55
|
-
try {
|
|
56
|
-
Object.defineProperty({}, 'test', { get: function () {} });
|
|
57
|
-
canDefineProperty = true;
|
|
58
|
-
} catch (e) {}
|
|
59
|
-
|
|
60
58
|
function getDeclarationErrorAddendum(internalInstance) {
|
|
61
59
|
if (internalInstance) {
|
|
62
60
|
var owner = internalInstance._currentElement._owner || null;
|
|
@@ -110,7 +108,7 @@ function legacySetStateEtc() {
|
|
|
110
108
|
function legacySetProps(partialProps, callback) {
|
|
111
109
|
var component = this._reactInternalComponent;
|
|
112
110
|
if (process.env.NODE_ENV !== 'production') {
|
|
113
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' + 'Instead, call
|
|
111
|
+
process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' + 'Instead, call ReactDOM.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
114
112
|
}
|
|
115
113
|
if (!component) {
|
|
116
114
|
return;
|
|
@@ -124,7 +122,7 @@ function legacySetProps(partialProps, callback) {
|
|
|
124
122
|
function legacyReplaceProps(partialProps, callback) {
|
|
125
123
|
var component = this._reactInternalComponent;
|
|
126
124
|
if (process.env.NODE_ENV !== 'production') {
|
|
127
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' + 'Instead, call
|
|
125
|
+
process.env.NODE_ENV !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' + 'Instead, call ReactDOM.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
128
126
|
}
|
|
129
127
|
if (!component) {
|
|
130
128
|
return;
|
|
@@ -135,6 +133,30 @@ function legacyReplaceProps(partialProps, callback) {
|
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
135
|
|
|
136
|
+
function friendlyStringify(obj) {
|
|
137
|
+
if (typeof obj === 'object') {
|
|
138
|
+
if (Array.isArray(obj)) {
|
|
139
|
+
return '[' + obj.map(friendlyStringify).join(', ') + ']';
|
|
140
|
+
} else {
|
|
141
|
+
var pairs = [];
|
|
142
|
+
for (var key in obj) {
|
|
143
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
144
|
+
var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? key : JSON.stringify(key);
|
|
145
|
+
pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return '{' + pairs.join(', ') + '}';
|
|
149
|
+
}
|
|
150
|
+
} else if (typeof obj === 'string') {
|
|
151
|
+
return JSON.stringify(obj);
|
|
152
|
+
} else if (typeof obj === 'function') {
|
|
153
|
+
return '[function object]';
|
|
154
|
+
}
|
|
155
|
+
// Differs from JSON.stringify in that undefined becauses undefined and that
|
|
156
|
+
// inf and nan don't become null
|
|
157
|
+
return String(obj);
|
|
158
|
+
}
|
|
159
|
+
|
|
138
160
|
var styleMutationWarning = {};
|
|
139
161
|
|
|
140
162
|
function checkAndWarnForMutatedStyle(style1, style2, component) {
|
|
@@ -160,14 +182,9 @@ function checkAndWarnForMutatedStyle(style1, style2, component) {
|
|
|
160
182
|
|
|
161
183
|
styleMutationWarning[hash] = true;
|
|
162
184
|
|
|
163
|
-
process.env.NODE_ENV !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>',
|
|
185
|
+
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)) : undefined;
|
|
164
186
|
}
|
|
165
187
|
|
|
166
|
-
/**
|
|
167
|
-
* Optionally injectable operations for mutating the DOM
|
|
168
|
-
*/
|
|
169
|
-
var BackendIDOperations = null;
|
|
170
|
-
|
|
171
188
|
/**
|
|
172
189
|
* @param {object} component
|
|
173
190
|
* @param {?object} props
|
|
@@ -184,13 +201,13 @@ function assertValidProps(component, props) {
|
|
|
184
201
|
}
|
|
185
202
|
if (props.dangerouslySetInnerHTML != null) {
|
|
186
203
|
!(props.children == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : undefined;
|
|
187
|
-
!(typeof props.dangerouslySetInnerHTML === 'object' &&
|
|
204
|
+
!(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? process.env.NODE_ENV !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(false) : undefined;
|
|
188
205
|
}
|
|
189
206
|
if (process.env.NODE_ENV !== 'production') {
|
|
190
207
|
process.env.NODE_ENV !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : undefined;
|
|
191
208
|
process.env.NODE_ENV !== 'production' ? warning(!props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : undefined;
|
|
192
209
|
}
|
|
193
|
-
!(props.style == null || typeof props.style === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX
|
|
210
|
+
!(props.style == null || typeof props.style === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.%s', getDeclarationErrorAddendum(component)) : invariant(false) : undefined;
|
|
194
211
|
}
|
|
195
212
|
|
|
196
213
|
function enqueuePutListener(id, registrationName, listener, transaction) {
|
|
@@ -224,12 +241,12 @@ var mediaEvents = {
|
|
|
224
241
|
topCanPlayThrough: 'canplaythrough',
|
|
225
242
|
topDurationChange: 'durationchange',
|
|
226
243
|
topEmptied: 'emptied',
|
|
244
|
+
topEncrypted: 'encrypted',
|
|
227
245
|
topEnded: 'ended',
|
|
228
246
|
topError: 'error',
|
|
229
247
|
topLoadedData: 'loadeddata',
|
|
230
248
|
topLoadedMetadata: 'loadedmetadata',
|
|
231
249
|
topLoadStart: 'loadstart',
|
|
232
|
-
topOnEncrypted: 'onencrypted',
|
|
233
250
|
topPause: 'pause',
|
|
234
251
|
topPlay: 'play',
|
|
235
252
|
topPlaying: 'playing',
|
|
@@ -277,6 +294,10 @@ function trapBubbledEventsLocal() {
|
|
|
277
294
|
}
|
|
278
295
|
}
|
|
279
296
|
|
|
297
|
+
function mountReadyInputWrapper() {
|
|
298
|
+
ReactDOMInput.mountReadyWrapper(this);
|
|
299
|
+
}
|
|
300
|
+
|
|
280
301
|
function postUpdateSelectWrapper() {
|
|
281
302
|
ReactDOMSelect.postUpdateWrapper(this);
|
|
282
303
|
}
|
|
@@ -331,13 +352,11 @@ function validateDangerousTag(tag) {
|
|
|
331
352
|
}
|
|
332
353
|
}
|
|
333
354
|
|
|
334
|
-
function
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
context[validateDOMNesting.ancestorInfoContextKey] = validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
|
|
340
|
-
}
|
|
355
|
+
function processChildContextDev(context, inst) {
|
|
356
|
+
// Pass down our tag name to child components for validation purposes
|
|
357
|
+
context = assign({}, context);
|
|
358
|
+
var info = context[validateDOMNesting.ancestorInfoContextKey];
|
|
359
|
+
context[validateDOMNesting.ancestorInfoContextKey] = validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
|
|
341
360
|
return context;
|
|
342
361
|
}
|
|
343
362
|
|
|
@@ -369,6 +388,10 @@ function ReactDOMComponent(tag) {
|
|
|
369
388
|
this._wrapperState = null;
|
|
370
389
|
this._topLevelWrapper = null;
|
|
371
390
|
this._nodeWithLegacyProperties = null;
|
|
391
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
392
|
+
this._unprocessedContextDev = null;
|
|
393
|
+
this._processedContextDev = null;
|
|
394
|
+
}
|
|
372
395
|
}
|
|
373
396
|
|
|
374
397
|
ReactDOMComponent.displayName = 'ReactDOMComponent';
|
|
@@ -434,12 +457,37 @@ ReactDOMComponent.Mixin = {
|
|
|
434
457
|
}
|
|
435
458
|
}
|
|
436
459
|
|
|
437
|
-
|
|
438
|
-
|
|
460
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
461
|
+
this._unprocessedContextDev = context;
|
|
462
|
+
this._processedContextDev = processChildContextDev(context, this);
|
|
463
|
+
context = this._processedContextDev;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
var mountImage;
|
|
467
|
+
if (transaction.useCreateElement) {
|
|
468
|
+
var ownerDocument = context[ReactMount.ownerDocumentContextKey];
|
|
469
|
+
var el = ownerDocument.createElement(this._currentElement.type);
|
|
470
|
+
DOMPropertyOperations.setAttributeForID(el, this._rootNodeID);
|
|
471
|
+
// Populate node cache
|
|
472
|
+
ReactMount.getID(el);
|
|
473
|
+
this._updateDOMProperties({}, props, transaction, el);
|
|
474
|
+
this._createInitialChildren(transaction, props, context, el);
|
|
475
|
+
mountImage = el;
|
|
476
|
+
} else {
|
|
477
|
+
var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
|
|
478
|
+
var tagContent = this._createContentMarkup(transaction, props, context);
|
|
479
|
+
if (!tagContent && omittedCloseTags[this._tag]) {
|
|
480
|
+
mountImage = tagOpen + '/>';
|
|
481
|
+
} else {
|
|
482
|
+
mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
|
|
483
|
+
}
|
|
484
|
+
}
|
|
439
485
|
|
|
440
486
|
switch (this._tag) {
|
|
441
|
-
case 'button':
|
|
442
487
|
case 'input':
|
|
488
|
+
transaction.getReactMountReady().enqueue(mountReadyInputWrapper, this);
|
|
489
|
+
// falls through
|
|
490
|
+
case 'button':
|
|
443
491
|
case 'select':
|
|
444
492
|
case 'textarea':
|
|
445
493
|
if (props.autoFocus) {
|
|
@@ -448,10 +496,7 @@ ReactDOMComponent.Mixin = {
|
|
|
448
496
|
break;
|
|
449
497
|
}
|
|
450
498
|
|
|
451
|
-
|
|
452
|
-
return tagOpen + '/>';
|
|
453
|
-
}
|
|
454
|
-
return tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
|
|
499
|
+
return mountImage;
|
|
455
500
|
},
|
|
456
501
|
|
|
457
502
|
/**
|
|
@@ -479,7 +524,9 @@ ReactDOMComponent.Mixin = {
|
|
|
479
524
|
continue;
|
|
480
525
|
}
|
|
481
526
|
if (registrationNameModules.hasOwnProperty(propKey)) {
|
|
482
|
-
|
|
527
|
+
if (propValue) {
|
|
528
|
+
enqueuePutListener(this._rootNodeID, propKey, propValue, transaction);
|
|
529
|
+
}
|
|
483
530
|
} else {
|
|
484
531
|
if (propKey === STYLE) {
|
|
485
532
|
if (propValue) {
|
|
@@ -538,7 +585,7 @@ ReactDOMComponent.Mixin = {
|
|
|
538
585
|
// TODO: Validate that text is allowed as a child of this node
|
|
539
586
|
ret = escapeTextContentForBrowser(contentToUse);
|
|
540
587
|
} else if (childrenToUse != null) {
|
|
541
|
-
var mountImages = this.mountChildren(childrenToUse, transaction,
|
|
588
|
+
var mountImages = this.mountChildren(childrenToUse, transaction, context);
|
|
542
589
|
ret = mountImages.join('');
|
|
543
590
|
}
|
|
544
591
|
}
|
|
@@ -559,6 +606,28 @@ ReactDOMComponent.Mixin = {
|
|
|
559
606
|
}
|
|
560
607
|
},
|
|
561
608
|
|
|
609
|
+
_createInitialChildren: function (transaction, props, context, el) {
|
|
610
|
+
// Intentional use of != to avoid catching zero/false.
|
|
611
|
+
var innerHTML = props.dangerouslySetInnerHTML;
|
|
612
|
+
if (innerHTML != null) {
|
|
613
|
+
if (innerHTML.__html != null) {
|
|
614
|
+
setInnerHTML(el, innerHTML.__html);
|
|
615
|
+
}
|
|
616
|
+
} else {
|
|
617
|
+
var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
|
|
618
|
+
var childrenToUse = contentToUse != null ? null : props.children;
|
|
619
|
+
if (contentToUse != null) {
|
|
620
|
+
// TODO: Validate that text is allowed as a child of this node
|
|
621
|
+
setTextContent(el, contentToUse);
|
|
622
|
+
} else if (childrenToUse != null) {
|
|
623
|
+
var mountImages = this.mountChildren(childrenToUse, transaction, context);
|
|
624
|
+
for (var i = 0; i < mountImages.length; i++) {
|
|
625
|
+
el.appendChild(mountImages[i]);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
|
|
562
631
|
/**
|
|
563
632
|
* Receives a next element and updates the component.
|
|
564
633
|
*
|
|
@@ -612,9 +681,20 @@ ReactDOMComponent.Mixin = {
|
|
|
612
681
|
break;
|
|
613
682
|
}
|
|
614
683
|
|
|
684
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
685
|
+
// If the context is reference-equal to the old one, pass down the same
|
|
686
|
+
// processed object so the update bailout in ReactReconciler behaves
|
|
687
|
+
// correctly (and identically in dev and prod). See #5005.
|
|
688
|
+
if (this._unprocessedContextDev !== context) {
|
|
689
|
+
this._unprocessedContextDev = context;
|
|
690
|
+
this._processedContextDev = processChildContextDev(context, this);
|
|
691
|
+
}
|
|
692
|
+
context = this._processedContextDev;
|
|
693
|
+
}
|
|
694
|
+
|
|
615
695
|
assertValidProps(this, nextProps);
|
|
616
|
-
this._updateDOMProperties(lastProps, nextProps, transaction);
|
|
617
|
-
this._updateDOMChildren(lastProps, nextProps, transaction,
|
|
696
|
+
this._updateDOMProperties(lastProps, nextProps, transaction, null);
|
|
697
|
+
this._updateDOMChildren(lastProps, nextProps, transaction, context);
|
|
618
698
|
|
|
619
699
|
if (!canDefineProperty && this._nodeWithLegacyProperties) {
|
|
620
700
|
this._nodeWithLegacyProperties.props = nextProps;
|
|
@@ -642,8 +722,9 @@ ReactDOMComponent.Mixin = {
|
|
|
642
722
|
* @param {object} lastProps
|
|
643
723
|
* @param {object} nextProps
|
|
644
724
|
* @param {ReactReconcileTransaction} transaction
|
|
725
|
+
* @param {?DOMElement} node
|
|
645
726
|
*/
|
|
646
|
-
_updateDOMProperties: function (lastProps, nextProps, transaction) {
|
|
727
|
+
_updateDOMProperties: function (lastProps, nextProps, transaction, node) {
|
|
647
728
|
var propKey;
|
|
648
729
|
var styleName;
|
|
649
730
|
var styleUpdates;
|
|
@@ -668,7 +749,10 @@ ReactDOMComponent.Mixin = {
|
|
|
668
749
|
deleteListener(this._rootNodeID, propKey);
|
|
669
750
|
}
|
|
670
751
|
} else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
|
|
671
|
-
|
|
752
|
+
if (!node) {
|
|
753
|
+
node = ReactMount.getNode(this._rootNodeID);
|
|
754
|
+
}
|
|
755
|
+
DOMPropertyOperations.deleteValueForProperty(node, propKey);
|
|
672
756
|
}
|
|
673
757
|
}
|
|
674
758
|
for (propKey in nextProps) {
|
|
@@ -713,13 +797,29 @@ ReactDOMComponent.Mixin = {
|
|
|
713
797
|
deleteListener(this._rootNodeID, propKey);
|
|
714
798
|
}
|
|
715
799
|
} else if (isCustomComponent(this._tag, nextProps)) {
|
|
716
|
-
|
|
800
|
+
if (!node) {
|
|
801
|
+
node = ReactMount.getNode(this._rootNodeID);
|
|
802
|
+
}
|
|
803
|
+
DOMPropertyOperations.setValueForAttribute(node, propKey, nextProp);
|
|
717
804
|
} else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
|
|
718
|
-
|
|
805
|
+
if (!node) {
|
|
806
|
+
node = ReactMount.getNode(this._rootNodeID);
|
|
807
|
+
}
|
|
808
|
+
// If we're updating to null or undefined, we should remove the property
|
|
809
|
+
// from the DOM node instead of inadvertantly setting to a string. This
|
|
810
|
+
// brings us in line with the same behavior we have on initial render.
|
|
811
|
+
if (nextProp != null) {
|
|
812
|
+
DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
|
|
813
|
+
} else {
|
|
814
|
+
DOMPropertyOperations.deleteValueForProperty(node, propKey);
|
|
815
|
+
}
|
|
719
816
|
}
|
|
720
817
|
}
|
|
721
818
|
if (styleUpdates) {
|
|
722
|
-
|
|
819
|
+
if (!node) {
|
|
820
|
+
node = ReactMount.getNode(this._rootNodeID);
|
|
821
|
+
}
|
|
822
|
+
CSSPropertyOperations.setValueForStyles(node, styleUpdates);
|
|
723
823
|
}
|
|
724
824
|
},
|
|
725
825
|
|
|
@@ -853,10 +953,4 @@ ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
|
|
|
853
953
|
|
|
854
954
|
assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
|
|
855
955
|
|
|
856
|
-
ReactDOMComponent.injection = {
|
|
857
|
-
injectIDOperations: function (IDOperations) {
|
|
858
|
-
ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
|
|
859
|
-
}
|
|
860
|
-
};
|
|
861
|
-
|
|
862
956
|
module.exports = ReactDOMComponent;
|