react 15.1.0 → 15.2.0-rc.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/dist/react-with-addons.js +2034 -1313
- package/dist/react-with-addons.min.js +7 -6
- package/dist/react.js +1832 -1244
- package/dist/react.min.js +6 -6
- package/lib/CSSPropertyOperations.js +1 -1
- package/lib/CallbackQueue.js +3 -2
- package/lib/DOMChildrenOperations.js +9 -9
- package/lib/DOMLazyTree.js +3 -2
- package/lib/DOMProperty.js +6 -4
- package/lib/DOMPropertyOperations.js +17 -3
- 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/LinkedValueUtils.js +5 -3
- package/lib/NativeMethodsMixin.js +6 -4
- package/lib/PooledClass.js +3 -1
- package/lib/React.js +1 -1
- package/lib/ReactCSSTransitionGroupChild.js +15 -8
- package/lib/ReactChildReconciler.js +15 -6
- package/lib/ReactClass.js +14 -13
- package/lib/ReactComponent.js +3 -6
- package/lib/ReactComponentEnvironment.js +3 -1
- package/lib/ReactComponentTreeDevtool.js +94 -16
- package/lib/ReactComponentTreeTestUtils.js +87 -0
- package/lib/ReactCompositeComponent.js +66 -106
- package/lib/ReactDOM.js +2 -2
- package/lib/ReactDOMButton.js +2 -2
- package/lib/ReactDOMComponent.js +130 -76
- 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/ReactDOMInput.js +52 -16
- package/lib/ReactDOMOption.js +40 -26
- package/lib/ReactDOMSelect.js +3 -3
- package/lib/ReactDOMTextComponent.js +21 -20
- package/lib/ReactDOMTextarea.js +59 -32
- package/lib/ReactDOMTreeTraversal.js +18 -16
- package/lib/ReactDOMUnknownPropertyDevtool.js +41 -15
- package/lib/ReactDebugTool.js +88 -27
- package/lib/ReactDefaultInjection.js +2 -2
- package/lib/ReactElement.js +64 -25
- package/lib/ReactElementValidator.js +26 -81
- package/lib/ReactEventListener.js +2 -2
- package/lib/ReactFragment.js +3 -1
- package/lib/{ReactNativeComponent.js → ReactHostComponent.js} +10 -29
- package/lib/{ReactNativeOperationHistoryDevtool.js → ReactHostOperationHistoryDevtool.js} +5 -5
- package/lib/ReactInjection.js +2 -2
- package/lib/ReactInstanceHandles.js +8 -6
- package/lib/ReactMount.js +24 -16
- package/lib/ReactMultiChild.js +31 -9
- 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 +1 -2
- package/lib/ReactNativeDefaultInjection.js +9 -7
- package/lib/ReactNativeGlobalResponderHandler.js +1 -1
- package/lib/ReactNativeMount.js +1 -1
- package/lib/ReactNativeTagHandles.js +3 -1
- package/lib/ReactNativeTextComponent.js +10 -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 +83 -7
- package/lib/ReactPropTypes.js +23 -0
- package/lib/ReactReconcileTransaction.js +1 -1
- package/lib/ReactReconciler.js +12 -7
- package/lib/ReactServerRendering.js +4 -2
- 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 +17 -10
- package/lib/ReactTransitionChildMapping.js +7 -1
- package/lib/ReactTransitionGroup.js +40 -6
- package/lib/ReactUpdateQueue.js +9 -1
- package/lib/ReactUpdates.js +9 -8
- package/lib/ReactVersion.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 +6 -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 +13 -12
- package/lib/onlyChild.js +3 -1
- 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/traverseAllChildren.js +3 -1
- package/lib/update.js +12 -11
- package/package.json +2 -2
- package/lib/MetaMatchers.js +0 -118
|
@@ -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);
|
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,7 +84,7 @@ 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) {
|
|
@@ -108,14 +114,14 @@ var ReactDOMInput = {
|
|
|
108
114
|
|
|
109
115
|
var defaultValue = props.defaultValue;
|
|
110
116
|
inst._wrapperState = {
|
|
111
|
-
initialChecked: props.
|
|
112
|
-
initialValue:
|
|
117
|
+
initialChecked: props.checked != null ? props.checked : props.defaultChecked,
|
|
118
|
+
initialValue: props.value != null ? props.value : defaultValue,
|
|
113
119
|
listeners: null,
|
|
114
120
|
onChange: _handleChange.bind(inst)
|
|
115
121
|
};
|
|
116
122
|
|
|
117
123
|
if (process.env.NODE_ENV !== 'production') {
|
|
118
|
-
inst._wrapperState.controlled = props
|
|
124
|
+
inst._wrapperState.controlled = isControlled(props);
|
|
119
125
|
}
|
|
120
126
|
},
|
|
121
127
|
|
|
@@ -125,16 +131,14 @@ var ReactDOMInput = {
|
|
|
125
131
|
if (process.env.NODE_ENV !== 'production') {
|
|
126
132
|
warnIfValueIsNull(props);
|
|
127
133
|
|
|
128
|
-
var
|
|
129
|
-
var defaultValue = props.defaultChecked || props.defaultValue;
|
|
130
|
-
var controlled = props.checked !== undefined || props.value !== undefined;
|
|
134
|
+
var controlled = isControlled(props);
|
|
131
135
|
var owner = inst._currentElement._owner;
|
|
132
136
|
|
|
133
|
-
if (
|
|
137
|
+
if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
|
|
134
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;
|
|
135
139
|
didWarnUncontrolledToControlled = true;
|
|
136
140
|
}
|
|
137
|
-
if (inst._wrapperState.controlled &&
|
|
141
|
+
if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
|
|
138
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;
|
|
139
143
|
didWarnControlledToUncontrolled = true;
|
|
140
144
|
}
|
|
@@ -146,12 +150,44 @@ var ReactDOMInput = {
|
|
|
146
150
|
DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
|
|
147
151
|
}
|
|
148
152
|
|
|
153
|
+
var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
|
149
154
|
var value = LinkedValueUtils.getValue(props);
|
|
150
155
|
if (value != null) {
|
|
156
|
+
|
|
151
157
|
// Cast `value` to a string to ensure the value is set correctly. While
|
|
152
158
|
// browsers typically do this as necessary, jsdom doesn't.
|
|
153
|
-
|
|
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
|
+
}
|
|
154
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;
|
|
155
191
|
}
|
|
156
192
|
};
|
|
157
193
|
|
|
@@ -192,7 +228,7 @@ function _handleChange(event) {
|
|
|
192
228
|
// That's probably okay; we don't support it just as we don't support
|
|
193
229
|
// mixing React radio buttons with non-React ones.
|
|
194
230
|
var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
|
|
195
|
-
!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;
|
|
196
232
|
// If this is a controlled radio button group, forcing the input that
|
|
197
233
|
// was previously checked to update will cause it to be come re-checked
|
|
198
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
|
};
|