react 15.0.3-alpha.2 → 15.2.0-rc.2
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/dist/react-with-addons.js +3324 -2009
- package/dist/react-with-addons.min.js +7 -6
- package/dist/react.js +2736 -2005
- package/dist/react.min.js +6 -6
- package/lib/CSSPropertyOperations.js +5 -5
- package/lib/CallbackQueue.js +3 -2
- package/lib/DOMChildrenOperations.js +42 -7
- package/lib/DOMLazyTree.js +9 -3
- package/lib/DOMProperty.js +6 -4
- package/lib/DOMPropertyOperations.js +35 -12
- package/lib/Danger.js +10 -8
- package/lib/DisabledInputUtils.js +5 -5
- package/lib/EventPluginHub.js +8 -2
- package/lib/EventPluginRegistry.js +13 -7
- package/lib/EventPluginUtils.js +3 -1
- package/lib/HTMLDOMPropertyConfig.js +1 -2
- package/lib/LinkedStateMixin.js +1 -0
- package/lib/LinkedValueUtils.js +5 -3
- package/lib/NativeMethodsMixin.js +6 -4
- package/lib/PooledClass.js +3 -1
- package/lib/React.js +1 -1
- package/lib/ReactCSSTransitionGroup.js +5 -0
- package/lib/ReactCSSTransitionGroupChild.js +15 -8
- package/lib/ReactChildReconciler.js +15 -6
- package/lib/ReactChildren.js +9 -1
- package/lib/ReactClass.js +15 -13
- package/lib/ReactComponent.js +3 -6
- package/lib/ReactComponentBrowserEnvironment.js +0 -5
- package/lib/ReactComponentEnvironment.js +3 -1
- package/lib/ReactComponentTreeDevtool.js +223 -0
- package/lib/ReactComponentTreeTestUtils.js +87 -0
- package/lib/ReactComponentWithPureRenderMixin.js +2 -0
- package/lib/ReactCompositeComponent.js +208 -119
- package/lib/ReactDOM.js +3 -6
- package/lib/ReactDOMButton.js +2 -2
- package/lib/ReactDOMComponent.js +162 -68
- package/lib/ReactDOMComponentTree.js +23 -21
- package/lib/ReactDOMDebugTool.js +7 -1
- package/lib/ReactDOMEmptyComponent.js +9 -9
- package/lib/ReactDOMFactories.js +1 -1
- package/lib/ReactDOMIDOperations.js +0 -5
- package/lib/ReactDOMInput.js +56 -18
- package/lib/ReactDOMOption.js +40 -26
- package/lib/ReactDOMSelect.js +3 -3
- package/lib/ReactDOMTextComponent.js +28 -26
- package/lib/ReactDOMTextarea.js +59 -32
- package/lib/ReactDOMTreeTraversal.js +18 -16
- package/lib/ReactDOMUnknownPropertyDevtool.js +65 -17
- package/lib/ReactDebugTool.js +250 -11
- package/lib/ReactDefaultInjection.js +2 -11
- package/lib/ReactElement.js +90 -25
- package/lib/ReactElementValidator.js +26 -81
- package/lib/ReactEventListener.js +2 -2
- package/lib/ReactFragment.js +8 -3
- package/lib/{ReactNativeComponent.js → ReactHostComponent.js} +10 -29
- package/lib/ReactHostOperationHistoryDevtool.js +37 -0
- package/lib/ReactInjection.js +2 -4
- package/lib/ReactInstanceHandles.js +8 -6
- package/lib/ReactLink.js +3 -0
- package/lib/ReactMount.js +43 -20
- package/lib/ReactMultiChild.js +51 -8
- package/lib/ReactNativeAttributePayload.js +5 -2
- package/lib/ReactNativeBaseComponent.js +7 -7
- package/lib/ReactNativeBridgeEventPlugin.js +1 -1
- package/lib/ReactNativeComponentTree.js +8 -6
- package/lib/ReactNativeDOMIDOperations.js +4 -8
- package/lib/ReactNativeDefaultInjection.js +9 -7
- package/lib/ReactNativeGlobalResponderHandler.js +1 -1
- package/lib/ReactNativeMount.js +25 -8
- package/lib/ReactNativeTagHandles.js +3 -1
- package/lib/ReactNativeTextComponent.js +18 -9
- package/lib/ReactNativeTreeTraversal.js +11 -11
- package/lib/ReactNodeTypes.js +5 -3
- package/lib/ReactNoop.js +76 -0
- package/lib/ReactOwner.js +4 -2
- package/lib/ReactPerf.js +473 -75
- package/lib/ReactPropTypes.js +23 -0
- package/lib/ReactReconcileTransaction.js +1 -1
- package/lib/ReactReconciler.js +57 -11
- package/lib/ReactServerRendering.js +24 -3
- package/lib/ReactSimpleEmptyComponent.js +4 -4
- package/lib/ReactTestMount.js +126 -0
- package/lib/ReactTestReconcileTransaction.js +100 -0
- package/lib/ReactTestRenderer.js +133 -0
- package/lib/ReactTestUtils.js +25 -10
- package/lib/ReactTransitionChildMapping.js +7 -1
- package/lib/ReactTransitionGroup.js +44 -5
- package/lib/ReactUpdateQueue.js +9 -1
- package/lib/ReactUpdates.js +30 -11
- package/lib/ReactVersion.js +1 -1
- package/lib/ReactWithAddons.js +1 -1
- package/lib/ResponderEventPlugin.js +8 -6
- package/lib/ResponderTouchHistoryStore.js +6 -4
- package/lib/SimpleEventPlugin.js +3 -1
- package/lib/SyntheticEvent.js +2 -3
- package/lib/SyntheticUIEvent.js +1 -1
- package/lib/Transaction.js +4 -2
- package/lib/accumulate.js +3 -1
- package/lib/accumulateInto.js +3 -1
- package/lib/checkReactTypeSpec.js +71 -0
- package/lib/createReactNativeComponentClass.js +2 -2
- package/lib/dangerousStyleValue.js +3 -1
- package/lib/escapeTextContentForBrowser.js +96 -12
- package/lib/findDOMNode.js +8 -4
- package/lib/findNodeHandle.js +5 -3
- package/lib/flattenChildren.js +13 -4
- package/lib/{getNativeComponentFromComposite.js → getHostComponentFromComposite.js} +4 -4
- package/lib/instantiateReactComponent.js +44 -10
- package/lib/onlyChild.js +10 -5
- package/lib/reactComponentExpect.js +3 -3
- package/lib/reactProdInvariant.js +38 -0
- package/lib/setInnerHTML.js +17 -1
- package/lib/setTextContent.js +8 -0
- package/lib/shallowCompare.js +1 -0
- package/lib/traverseAllChildren.js +3 -1
- package/lib/update.js +16 -11
- package/package.json +2 -2
- package/lib/MetaMatchers.js +0 -118
- package/lib/ReactDebugInstanceMap.js +0 -102
- package/lib/ReactDefaultPerf.js +0 -316
- package/lib/ReactDefaultPerfAnalysis.js +0 -210
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
var _prodInvariant = require('./reactProdInvariant');
|
|
15
|
+
|
|
14
16
|
var DOMProperty = require('./DOMProperty');
|
|
15
17
|
var ReactDOMComponentFlags = require('./ReactDOMComponentFlags');
|
|
16
18
|
|
|
@@ -22,13 +24,13 @@ var Flags = ReactDOMComponentFlags;
|
|
|
22
24
|
var internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
|
-
* Drill down (through composites and empty components) until we get a
|
|
26
|
-
*
|
|
27
|
+
* Drill down (through composites and empty components) until we get a host or
|
|
28
|
+
* host text component.
|
|
27
29
|
*
|
|
28
30
|
* This is pretty polymorphic but unavoidable with the current structure we have
|
|
29
31
|
* for `_renderedChildren`.
|
|
30
32
|
*/
|
|
31
|
-
function
|
|
33
|
+
function getRenderedHostOrTextFromComponent(component) {
|
|
32
34
|
var rendered;
|
|
33
35
|
while (rendered = component._renderedComponent) {
|
|
34
36
|
component = rendered;
|
|
@@ -37,25 +39,25 @@ function getRenderedNativeOrTextFromComponent(component) {
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
|
-
* Populate `
|
|
42
|
+
* Populate `_hostNode` on the rendered host/text component with the given
|
|
41
43
|
* DOM node. The passed `inst` can be a composite.
|
|
42
44
|
*/
|
|
43
45
|
function precacheNode(inst, node) {
|
|
44
|
-
var
|
|
45
|
-
|
|
46
|
-
node[internalInstanceKey] =
|
|
46
|
+
var hostInst = getRenderedHostOrTextFromComponent(inst);
|
|
47
|
+
hostInst._hostNode = node;
|
|
48
|
+
node[internalInstanceKey] = hostInst;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
function uncacheNode(inst) {
|
|
50
|
-
var node = inst.
|
|
52
|
+
var node = inst._hostNode;
|
|
51
53
|
if (node) {
|
|
52
54
|
delete node[internalInstanceKey];
|
|
53
|
-
inst.
|
|
55
|
+
inst._hostNode = null;
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
|
-
* Populate `
|
|
60
|
+
* Populate `_hostNode` on each child of `inst`, assuming that the children
|
|
59
61
|
* match up with the DOM (element) children of `node`.
|
|
60
62
|
*
|
|
61
63
|
* We cache entire levels at once to avoid an n^2 problem where we access the
|
|
@@ -79,7 +81,7 @@ function precacheChildNodes(inst, node) {
|
|
|
79
81
|
continue;
|
|
80
82
|
}
|
|
81
83
|
var childInst = children[name];
|
|
82
|
-
var childID =
|
|
84
|
+
var childID = getRenderedHostOrTextFromComponent(childInst)._domID;
|
|
83
85
|
if (childID == null) {
|
|
84
86
|
// We're currently unmounting this child in ReactMultiChild; skip it.
|
|
85
87
|
continue;
|
|
@@ -92,7 +94,7 @@ function precacheChildNodes(inst, node) {
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
// We reached the end of the DOM children without finding an ID match.
|
|
95
|
-
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) :
|
|
97
|
+
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;
|
|
96
98
|
}
|
|
97
99
|
inst._flags |= Flags.hasCachedChildNodes;
|
|
98
100
|
}
|
|
@@ -137,7 +139,7 @@ function getClosestInstanceFromNode(node) {
|
|
|
137
139
|
*/
|
|
138
140
|
function getInstanceFromNode(node) {
|
|
139
141
|
var inst = getClosestInstanceFromNode(node);
|
|
140
|
-
if (inst != null && inst.
|
|
142
|
+
if (inst != null && inst._hostNode === node) {
|
|
141
143
|
return inst;
|
|
142
144
|
} else {
|
|
143
145
|
return null;
|
|
@@ -151,27 +153,27 @@ function getInstanceFromNode(node) {
|
|
|
151
153
|
function getNodeFromInstance(inst) {
|
|
152
154
|
// Without this first invariant, passing a non-DOM-component triggers the next
|
|
153
155
|
// invariant for a missing parent, which is super confusing.
|
|
154
|
-
!(inst.
|
|
156
|
+
!(inst._hostNode !== undefined) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;
|
|
155
157
|
|
|
156
|
-
if (inst.
|
|
157
|
-
return inst.
|
|
158
|
+
if (inst._hostNode) {
|
|
159
|
+
return inst._hostNode;
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
// Walk up the tree until we find an ancestor whose DOM node we have cached.
|
|
161
163
|
var parents = [];
|
|
162
|
-
while (!inst.
|
|
164
|
+
while (!inst._hostNode) {
|
|
163
165
|
parents.push(inst);
|
|
164
|
-
!inst.
|
|
165
|
-
inst = inst.
|
|
166
|
+
!inst._hostParent ? process.env.NODE_ENV !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;
|
|
167
|
+
inst = inst._hostParent;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
// Now parents contains each ancestor that does *not* have a cached native
|
|
169
171
|
// node, and `inst` is the deepest ancestor that does.
|
|
170
172
|
for (; parents.length; inst = parents.pop()) {
|
|
171
|
-
precacheChildNodes(inst, inst.
|
|
173
|
+
precacheChildNodes(inst, inst._hostNode);
|
|
172
174
|
}
|
|
173
175
|
|
|
174
|
-
return inst.
|
|
176
|
+
return inst._hostNode;
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
var ReactDOMComponentTree = {
|
package/lib/ReactDOMDebugTool.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
var ReactDOMUnknownPropertyDevtool = require('./ReactDOMUnknownPropertyDevtool');
|
|
15
|
+
var ReactDebugTool = require('./ReactDebugTool');
|
|
15
16
|
|
|
16
17
|
var warning = require('fbjs/lib/warning');
|
|
17
18
|
|
|
@@ -26,7 +27,7 @@ function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
|
|
|
26
27
|
handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);
|
|
27
28
|
}
|
|
28
29
|
} catch (e) {
|
|
29
|
-
process.env.NODE_ENV !== 'production' ? warning(
|
|
30
|
+
process.env.NODE_ENV !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\n' + e.stack) : void 0;
|
|
30
31
|
handlerDoesThrowForEvent[handlerFunctionName] = true;
|
|
31
32
|
}
|
|
32
33
|
});
|
|
@@ -35,9 +36,11 @@ function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
|
|
|
35
36
|
|
|
36
37
|
var ReactDOMDebugTool = {
|
|
37
38
|
addDevtool: function (devtool) {
|
|
39
|
+
ReactDebugTool.addDevtool(devtool);
|
|
38
40
|
eventHandlers.push(devtool);
|
|
39
41
|
},
|
|
40
42
|
removeDevtool: function (devtool) {
|
|
43
|
+
ReactDebugTool.removeDevtool(devtool);
|
|
41
44
|
for (var i = 0; i < eventHandlers.length; i++) {
|
|
42
45
|
if (eventHandlers[i] === devtool) {
|
|
43
46
|
eventHandlers.splice(i, 1);
|
|
@@ -53,6 +56,9 @@ var ReactDOMDebugTool = {
|
|
|
53
56
|
},
|
|
54
57
|
onDeleteValueForProperty: function (node, name) {
|
|
55
58
|
emitEvent('onDeleteValueForProperty', node, name);
|
|
59
|
+
},
|
|
60
|
+
onTestEvent: function () {
|
|
61
|
+
emitEvent('onTestEvent');
|
|
56
62
|
}
|
|
57
63
|
};
|
|
58
64
|
|
|
@@ -20,21 +20,21 @@ var ReactDOMEmptyComponent = function (instantiate) {
|
|
|
20
20
|
// ReactCompositeComponent uses this:
|
|
21
21
|
this._currentElement = null;
|
|
22
22
|
// ReactDOMComponentTree uses these:
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
23
|
+
this._hostNode = null;
|
|
24
|
+
this._hostParent = null;
|
|
25
|
+
this._hostContainerInfo = null;
|
|
26
26
|
this._domID = null;
|
|
27
27
|
};
|
|
28
28
|
_assign(ReactDOMEmptyComponent.prototype, {
|
|
29
|
-
mountComponent: function (transaction,
|
|
30
|
-
var domID =
|
|
29
|
+
mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
|
|
30
|
+
var domID = hostContainerInfo._idCounter++;
|
|
31
31
|
this._domID = domID;
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
32
|
+
this._hostParent = hostParent;
|
|
33
|
+
this._hostContainerInfo = hostContainerInfo;
|
|
34
34
|
|
|
35
35
|
var nodeValue = ' react-empty: ' + this._domID + ' ';
|
|
36
36
|
if (transaction.useCreateElement) {
|
|
37
|
-
var ownerDocument =
|
|
37
|
+
var ownerDocument = hostContainerInfo._ownerDocument;
|
|
38
38
|
var node = ownerDocument.createComment(nodeValue);
|
|
39
39
|
ReactDOMComponentTree.precacheNode(this, node);
|
|
40
40
|
return DOMLazyTree(node);
|
|
@@ -49,7 +49,7 @@ _assign(ReactDOMEmptyComponent.prototype, {
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
receiveComponent: function () {},
|
|
52
|
-
|
|
52
|
+
getHostNode: function () {
|
|
53
53
|
return ReactDOMComponentTree.getNodeFromInstance(this);
|
|
54
54
|
},
|
|
55
55
|
unmountComponent: function () {
|
package/lib/ReactDOMFactories.js
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
var ReactElement = require('./ReactElement');
|
|
15
|
-
var ReactElementValidator = require('./ReactElementValidator');
|
|
16
15
|
|
|
17
16
|
var mapObject = require('fbjs/lib/mapObject');
|
|
18
17
|
|
|
@@ -24,6 +23,7 @@ var mapObject = require('fbjs/lib/mapObject');
|
|
|
24
23
|
*/
|
|
25
24
|
function createDOMFactory(tag) {
|
|
26
25
|
if (process.env.NODE_ENV !== 'production') {
|
|
26
|
+
var ReactElementValidator = require('./ReactElementValidator');
|
|
27
27
|
return ReactElementValidator.createFactory(tag);
|
|
28
28
|
}
|
|
29
29
|
return ReactElement.createFactory(tag);
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
|
|
14
14
|
var DOMChildrenOperations = require('./DOMChildrenOperations');
|
|
15
15
|
var ReactDOMComponentTree = require('./ReactDOMComponentTree');
|
|
16
|
-
var ReactPerf = require('./ReactPerf');
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Operations used to process updates to DOM nodes.
|
|
@@ -32,8 +31,4 @@ var ReactDOMIDOperations = {
|
|
|
32
31
|
}
|
|
33
32
|
};
|
|
34
33
|
|
|
35
|
-
ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
|
|
36
|
-
dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
|
|
37
|
-
});
|
|
38
|
-
|
|
39
34
|
module.exports = ReactDOMIDOperations;
|
package/lib/ReactDOMInput.js
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var _prodInvariant = require('./reactProdInvariant'),
|
|
15
|
+
_assign = require('object-assign');
|
|
15
16
|
|
|
16
17
|
var DisabledInputUtils = require('./DisabledInputUtils');
|
|
17
18
|
var DOMPropertyOperations = require('./DOMPropertyOperations');
|
|
@@ -45,8 +46,13 @@ function warnIfValueIsNull(props) {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
function isControlled(props) {
|
|
50
|
+
var usesChecked = props.type === 'checkbox' || props.type === 'radio';
|
|
51
|
+
return usesChecked ? props.checked !== undefined : props.value !== undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
48
54
|
/**
|
|
49
|
-
* Implements an <input>
|
|
55
|
+
* Implements an <input> host component that allows setting these optional
|
|
50
56
|
* props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
|
|
51
57
|
*
|
|
52
58
|
* If `checked` or `value` are not supplied (or null/undefined), user actions
|
|
@@ -62,15 +68,15 @@ function warnIfValueIsNull(props) {
|
|
|
62
68
|
* @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
|
|
63
69
|
*/
|
|
64
70
|
var ReactDOMInput = {
|
|
65
|
-
|
|
71
|
+
getHostProps: function (inst, props) {
|
|
66
72
|
var value = LinkedValueUtils.getValue(props);
|
|
67
73
|
var checked = LinkedValueUtils.getChecked(props);
|
|
68
74
|
|
|
69
|
-
var
|
|
75
|
+
var hostProps = _assign({
|
|
70
76
|
// Make sure we set .type before any other properties (setting .value
|
|
71
77
|
// before .type means .value is lost in IE11 and below)
|
|
72
78
|
type: undefined
|
|
73
|
-
}, DisabledInputUtils.
|
|
79
|
+
}, DisabledInputUtils.getHostProps(inst, props), {
|
|
74
80
|
defaultChecked: undefined,
|
|
75
81
|
defaultValue: undefined,
|
|
76
82
|
value: value != null ? value : inst._wrapperState.initialValue,
|
|
@@ -78,13 +84,15 @@ var ReactDOMInput = {
|
|
|
78
84
|
onChange: inst._wrapperState.onChange
|
|
79
85
|
});
|
|
80
86
|
|
|
81
|
-
return
|
|
87
|
+
return hostProps;
|
|
82
88
|
},
|
|
83
89
|
|
|
84
90
|
mountWrapper: function (inst, props) {
|
|
85
91
|
if (process.env.NODE_ENV !== 'production') {
|
|
86
92
|
LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);
|
|
87
93
|
|
|
94
|
+
var owner = inst._currentElement._owner;
|
|
95
|
+
|
|
88
96
|
if (props.valueLink !== undefined && !didWarnValueLink) {
|
|
89
97
|
process.env.NODE_ENV !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
|
|
90
98
|
didWarnValueLink = true;
|
|
@@ -94,11 +102,11 @@ var ReactDOMInput = {
|
|
|
94
102
|
didWarnCheckedLink = true;
|
|
95
103
|
}
|
|
96
104
|
if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
|
|
97
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
|
|
105
|
+
process.env.NODE_ENV !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
|
98
106
|
didWarnCheckedDefaultChecked = true;
|
|
99
107
|
}
|
|
100
108
|
if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
|
|
101
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
|
|
109
|
+
process.env.NODE_ENV !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
|
102
110
|
didWarnValueDefaultValue = true;
|
|
103
111
|
}
|
|
104
112
|
warnIfValueIsNull(props);
|
|
@@ -106,14 +114,14 @@ var ReactDOMInput = {
|
|
|
106
114
|
|
|
107
115
|
var defaultValue = props.defaultValue;
|
|
108
116
|
inst._wrapperState = {
|
|
109
|
-
initialChecked: props.
|
|
110
|
-
initialValue:
|
|
117
|
+
initialChecked: props.checked != null ? props.checked : props.defaultChecked,
|
|
118
|
+
initialValue: props.value != null ? props.value : defaultValue,
|
|
111
119
|
listeners: null,
|
|
112
120
|
onChange: _handleChange.bind(inst)
|
|
113
121
|
};
|
|
114
122
|
|
|
115
123
|
if (process.env.NODE_ENV !== 'production') {
|
|
116
|
-
inst._wrapperState.controlled = props
|
|
124
|
+
inst._wrapperState.controlled = isControlled(props);
|
|
117
125
|
}
|
|
118
126
|
},
|
|
119
127
|
|
|
@@ -123,16 +131,14 @@ var ReactDOMInput = {
|
|
|
123
131
|
if (process.env.NODE_ENV !== 'production') {
|
|
124
132
|
warnIfValueIsNull(props);
|
|
125
133
|
|
|
126
|
-
var
|
|
127
|
-
var defaultValue = props.defaultChecked || props.defaultValue;
|
|
128
|
-
var controlled = props.checked !== undefined || props.value !== undefined;
|
|
134
|
+
var controlled = isControlled(props);
|
|
129
135
|
var owner = inst._currentElement._owner;
|
|
130
136
|
|
|
131
|
-
if (
|
|
137
|
+
if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
|
|
132
138
|
process.env.NODE_ENV !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
|
133
139
|
didWarnUncontrolledToControlled = true;
|
|
134
140
|
}
|
|
135
|
-
if (inst._wrapperState.controlled &&
|
|
141
|
+
if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
|
|
136
142
|
process.env.NODE_ENV !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
|
|
137
143
|
didWarnControlledToUncontrolled = true;
|
|
138
144
|
}
|
|
@@ -144,12 +150,44 @@ var ReactDOMInput = {
|
|
|
144
150
|
DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
|
|
145
151
|
}
|
|
146
152
|
|
|
153
|
+
var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
|
147
154
|
var value = LinkedValueUtils.getValue(props);
|
|
148
155
|
if (value != null) {
|
|
156
|
+
|
|
149
157
|
// Cast `value` to a string to ensure the value is set correctly. While
|
|
150
158
|
// browsers typically do this as necessary, jsdom doesn't.
|
|
151
|
-
|
|
159
|
+
var newValue = '' + value;
|
|
160
|
+
|
|
161
|
+
// To avoid side effects (such as losing text selection), only set value if changed
|
|
162
|
+
if (newValue !== node.value) {
|
|
163
|
+
node.value = newValue;
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
if (props.value == null && props.defaultValue != null) {
|
|
167
|
+
node.defaultValue = '' + props.defaultValue;
|
|
168
|
+
}
|
|
169
|
+
if (props.checked == null && props.defaultChecked != null) {
|
|
170
|
+
node.defaultChecked = !!props.defaultChecked;
|
|
171
|
+
}
|
|
152
172
|
}
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
postMountWrapper: function (inst) {
|
|
176
|
+
// This is in postMount because we need access to the DOM node, which is not
|
|
177
|
+
// available until after the component has mounted.
|
|
178
|
+
var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
|
179
|
+
node.value = node.value; // Detach value from defaultValue
|
|
180
|
+
|
|
181
|
+
// Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
|
|
182
|
+
// this is needed to work around a chrome bug where setting defaultChecked
|
|
183
|
+
// will sometimes influence the value of checked (even after detachment).
|
|
184
|
+
// Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
|
|
185
|
+
// We need to temporarily unset name to avoid disrupting radio button groups.
|
|
186
|
+
var name = node.name;
|
|
187
|
+
node.name = undefined;
|
|
188
|
+
node.defaultChecked = !node.defaultChecked;
|
|
189
|
+
node.defaultChecked = !node.defaultChecked;
|
|
190
|
+
node.name = name;
|
|
153
191
|
}
|
|
154
192
|
};
|
|
155
193
|
|
|
@@ -190,7 +228,7 @@ function _handleChange(event) {
|
|
|
190
228
|
// That's probably okay; we don't support it just as we don't support
|
|
191
229
|
// mixing React radio buttons with non-React ones.
|
|
192
230
|
var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
|
|
193
|
-
!otherInstance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the
|
|
231
|
+
!otherInstance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;
|
|
194
232
|
// If this is a controlled radio button group, forcing the input that
|
|
195
233
|
// was previously checked to update will cause it to be come re-checked
|
|
196
234
|
// as appropriate.
|
package/lib/ReactDOMOption.js
CHANGED
|
@@ -18,12 +18,33 @@ var ReactDOMComponentTree = require('./ReactDOMComponentTree');
|
|
|
18
18
|
var ReactDOMSelect = require('./ReactDOMSelect');
|
|
19
19
|
|
|
20
20
|
var warning = require('fbjs/lib/warning');
|
|
21
|
+
var didWarnInvalidOptionChildren = false;
|
|
22
|
+
|
|
23
|
+
function flattenChildren(children) {
|
|
24
|
+
var content = '';
|
|
25
|
+
|
|
26
|
+
// Flatten children and warn if they aren't strings or numbers;
|
|
27
|
+
// invalid types are ignored.
|
|
28
|
+
ReactChildren.forEach(children, function (child) {
|
|
29
|
+
if (child == null) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (typeof child === 'string' || typeof child === 'number') {
|
|
33
|
+
content += child;
|
|
34
|
+
} else if (!didWarnInvalidOptionChildren) {
|
|
35
|
+
didWarnInvalidOptionChildren = true;
|
|
36
|
+
process.env.NODE_ENV !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return content;
|
|
41
|
+
}
|
|
21
42
|
|
|
22
43
|
/**
|
|
23
|
-
* Implements an <option>
|
|
44
|
+
* Implements an <option> host component that warns when `selected` is set.
|
|
24
45
|
*/
|
|
25
46
|
var ReactDOMOption = {
|
|
26
|
-
mountWrapper: function (inst, props,
|
|
47
|
+
mountWrapper: function (inst, props, hostParent) {
|
|
27
48
|
// TODO (yungsters): Remove support for `selected` in <option>.
|
|
28
49
|
if (process.env.NODE_ENV !== 'production') {
|
|
29
50
|
process.env.NODE_ENV !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;
|
|
@@ -31,11 +52,11 @@ var ReactDOMOption = {
|
|
|
31
52
|
|
|
32
53
|
// Look up whether this option is 'selected'
|
|
33
54
|
var selectValue = null;
|
|
34
|
-
if (
|
|
35
|
-
var selectParent =
|
|
55
|
+
if (hostParent != null) {
|
|
56
|
+
var selectParent = hostParent;
|
|
36
57
|
|
|
37
58
|
if (selectParent._tag === 'optgroup') {
|
|
38
|
-
selectParent = selectParent.
|
|
59
|
+
selectParent = selectParent._hostParent;
|
|
39
60
|
}
|
|
40
61
|
|
|
41
62
|
if (selectParent != null && selectParent._tag === 'select') {
|
|
@@ -47,17 +68,23 @@ var ReactDOMOption = {
|
|
|
47
68
|
// or missing (e.g., for <datalist>), we don't change props.selected
|
|
48
69
|
var selected = null;
|
|
49
70
|
if (selectValue != null) {
|
|
71
|
+
var value;
|
|
72
|
+
if (props.value != null) {
|
|
73
|
+
value = props.value + '';
|
|
74
|
+
} else {
|
|
75
|
+
value = flattenChildren(props.children);
|
|
76
|
+
}
|
|
50
77
|
selected = false;
|
|
51
78
|
if (Array.isArray(selectValue)) {
|
|
52
79
|
// multiple
|
|
53
80
|
for (var i = 0; i < selectValue.length; i++) {
|
|
54
|
-
if ('' + selectValue[i] ===
|
|
81
|
+
if ('' + selectValue[i] === value) {
|
|
55
82
|
selected = true;
|
|
56
83
|
break;
|
|
57
84
|
}
|
|
58
85
|
}
|
|
59
86
|
} else {
|
|
60
|
-
selected = '' + selectValue ===
|
|
87
|
+
selected = '' + selectValue === value;
|
|
61
88
|
}
|
|
62
89
|
}
|
|
63
90
|
|
|
@@ -73,35 +100,22 @@ var ReactDOMOption = {
|
|
|
73
100
|
}
|
|
74
101
|
},
|
|
75
102
|
|
|
76
|
-
|
|
77
|
-
var
|
|
103
|
+
getHostProps: function (inst, props) {
|
|
104
|
+
var hostProps = _assign({ selected: undefined, children: undefined }, props);
|
|
78
105
|
|
|
79
106
|
// Read state only from initial mount because <select> updates value
|
|
80
107
|
// manually; we need the initial state only for server rendering
|
|
81
108
|
if (inst._wrapperState.selected != null) {
|
|
82
|
-
|
|
109
|
+
hostProps.selected = inst._wrapperState.selected;
|
|
83
110
|
}
|
|
84
111
|
|
|
85
|
-
var content =
|
|
86
|
-
|
|
87
|
-
// Flatten children and warn if they aren't strings or numbers;
|
|
88
|
-
// invalid types are ignored.
|
|
89
|
-
ReactChildren.forEach(props.children, function (child) {
|
|
90
|
-
if (child == null) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (typeof child === 'string' || typeof child === 'number') {
|
|
94
|
-
content += child;
|
|
95
|
-
} else {
|
|
96
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
112
|
+
var content = flattenChildren(props.children);
|
|
99
113
|
|
|
100
114
|
if (content) {
|
|
101
|
-
|
|
115
|
+
hostProps.children = content;
|
|
102
116
|
}
|
|
103
117
|
|
|
104
|
-
return
|
|
118
|
+
return hostProps;
|
|
105
119
|
}
|
|
106
120
|
|
|
107
121
|
};
|