react 15.1.0 → 15.2.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 +2685 -1842
- package/dist/react-with-addons.min.js +6 -6
- package/dist/react.js +2400 -1691
- 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 +5 -12
- package/lib/DOMPropertyOperations.js +21 -15
- package/lib/Danger.js +5 -101
- 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/KeyEscapeUtils.js +2 -1
- package/lib/LinkedValueUtils.js +5 -3
- package/lib/NativeMethodsMixin.js +6 -4
- package/lib/PooledClass.js +4 -2
- package/lib/React.js +1 -1
- package/lib/ReactCSSTransitionGroupChild.js +15 -8
- package/lib/ReactChildReconciler.js +17 -8
- package/lib/ReactClass.js +14 -13
- package/lib/ReactComponent.js +3 -6
- package/lib/ReactComponentEnvironment.js +3 -1
- package/lib/ReactComponentTreeDevtool.js +89 -16
- package/lib/ReactComponentTreeTestUtils.js +87 -0
- package/lib/ReactCompositeComponent.js +87 -117
- 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 +17 -11
- package/lib/ReactDOMEmptyComponent.js +9 -9
- package/lib/ReactDOMFactories.js +1 -1
- package/lib/ReactDOMFiber.js +78 -0
- package/lib/ReactDOMInput.js +64 -26
- package/lib/ReactDOMInstrumentation.js +7 -2
- package/lib/ReactDOMNullInputValuePropDevtool.js +43 -0
- package/lib/ReactDOMOption.js +40 -26
- package/lib/ReactDOMSelect.js +3 -16
- package/lib/ReactDOMTextComponent.js +21 -20
- package/lib/ReactDOMTextarea.js +59 -46
- package/lib/ReactDOMTreeTraversal.js +18 -16
- package/lib/ReactDOMUnknownPropertyDevtool.js +65 -17
- package/lib/ReactDebugTool.js +148 -95
- 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/ReactFeatureFlags.js +1 -0
- 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/ReactInstrumentation.js +7 -2
- package/lib/ReactMount.js +38 -32
- package/lib/ReactMultiChild.js +38 -11
- 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 +3 -14
- package/lib/ReactNativeReconcileTransaction.js +16 -0
- package/lib/ReactNativeTagHandles.js +3 -1
- package/lib/ReactNativeTextComponent.js +10 -9
- package/lib/ReactNativeTreeTraversal.js +11 -11
- package/lib/ReactNodeTypes.js +6 -3
- package/lib/ReactNoop.js +173 -0
- package/lib/ReactNoopUpdateQueue.js +6 -5
- package/lib/ReactOwner.js +4 -2
- package/lib/ReactPerf.js +83 -7
- package/lib/ReactPropTypes.js +23 -0
- package/lib/ReactReconcileTransaction.js +17 -1
- package/lib/ReactReconciler.js +12 -7
- package/lib/ReactServerRendering.js +5 -7
- package/lib/ReactServerRenderingTransaction.js +17 -0
- package/lib/ReactServerUpdateQueue.js +141 -0
- package/lib/ReactSimpleEmptyComponent.js +4 -4
- package/lib/ReactTestMount.js +115 -0
- package/lib/ReactTestReconcileTransaction.js +108 -0
- package/lib/ReactTestRenderer.js +133 -0
- package/lib/ReactTestUtils.js +17 -10
- package/lib/ReactTransitionChildMapping.js +7 -1
- package/lib/ReactTransitionGroup.js +41 -6
- package/lib/ReactUpdateQueue.js +13 -3
- package/lib/ReactUpdates.js +10 -18
- package/lib/ReactVersion.js +1 -1
- package/lib/ResponderEventPlugin.js +9 -7
- package/lib/ResponderTouchHistoryStore.js +99 -95
- 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 +17 -15
- package/lib/accumulateInto.js +11 -12
- package/lib/adler32.js +1 -0
- package/lib/checkReactTypeSpec.js +73 -0
- package/lib/createReactNativeComponentClass.js +2 -2
- package/lib/dangerousStyleValue.js +3 -1
- package/lib/deprecated.js +7 -1
- package/lib/escapeTextContentForBrowser.js +96 -12
- package/lib/findDOMNode.js +6 -4
- package/lib/findNodeHandle.js +5 -3
- package/lib/flattenChildren.js +22 -10
- package/lib/forEachAccumulated.js +3 -2
- package/lib/{getNativeComponentFromComposite.js → getHostComponentFromComposite.js} +4 -4
- package/lib/getIteratorFn.js +1 -0
- package/lib/instantiateReactComponent.js +21 -19
- package/lib/isTextInputElement.js +11 -1
- package/lib/onlyChild.js +3 -1
- package/lib/reactComponentExpect.js +3 -3
- package/lib/reactProdInvariant.js +39 -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
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
var ReactDOMNullInputValuePropDevtool = require('./ReactDOMNullInputValuePropDevtool');
|
|
14
15
|
var ReactDOMUnknownPropertyDevtool = require('./ReactDOMUnknownPropertyDevtool');
|
|
16
|
+
var ReactDebugTool = require('./ReactDebugTool');
|
|
15
17
|
|
|
16
18
|
var warning = require('fbjs/lib/warning');
|
|
17
19
|
|
|
@@ -19,25 +21,25 @@ var eventHandlers = [];
|
|
|
19
21
|
var handlerDoesThrowForEvent = {};
|
|
20
22
|
|
|
21
23
|
function emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);
|
|
27
|
-
}
|
|
28
|
-
} catch (e) {
|
|
29
|
-
process.env.NODE_ENV !== 'production' ? warning(!handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e.message) : void 0;
|
|
30
|
-
handlerDoesThrowForEvent[handlerFunctionName] = true;
|
|
24
|
+
eventHandlers.forEach(function (handler) {
|
|
25
|
+
try {
|
|
26
|
+
if (handler[handlerFunctionName]) {
|
|
27
|
+
handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);
|
|
31
28
|
}
|
|
32
|
-
})
|
|
33
|
-
|
|
29
|
+
} catch (e) {
|
|
30
|
+
process.env.NODE_ENV !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\n' + e.stack) : void 0;
|
|
31
|
+
handlerDoesThrowForEvent[handlerFunctionName] = true;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
var ReactDOMDebugTool = {
|
|
37
37
|
addDevtool: function (devtool) {
|
|
38
|
+
ReactDebugTool.addDevtool(devtool);
|
|
38
39
|
eventHandlers.push(devtool);
|
|
39
40
|
},
|
|
40
41
|
removeDevtool: function (devtool) {
|
|
42
|
+
ReactDebugTool.removeDevtool(devtool);
|
|
41
43
|
for (var i = 0; i < eventHandlers.length; i++) {
|
|
42
44
|
if (eventHandlers[i] === devtool) {
|
|
43
45
|
eventHandlers.splice(i, 1);
|
|
@@ -53,9 +55,13 @@ var ReactDOMDebugTool = {
|
|
|
53
55
|
},
|
|
54
56
|
onDeleteValueForProperty: function (node, name) {
|
|
55
57
|
emitEvent('onDeleteValueForProperty', node, name);
|
|
58
|
+
},
|
|
59
|
+
onTestEvent: function () {
|
|
60
|
+
emitEvent('onTestEvent');
|
|
56
61
|
}
|
|
57
62
|
};
|
|
58
63
|
|
|
59
64
|
ReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);
|
|
65
|
+
ReactDOMDebugTool.addDevtool(ReactDOMNullInputValuePropDevtool);
|
|
60
66
|
|
|
61
67
|
module.exports = ReactDOMDebugTool;
|
|
@@ -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);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*
|
|
9
|
+
* @providesModule ReactDOMFiber
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
var ReactFiberReconciler = require('./ReactFiberReconciler');
|
|
16
|
+
|
|
17
|
+
function recursivelyAppendChildren(parent, child) {
|
|
18
|
+
if (!child) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
/* $FlowFixMe: Element should have this property. */
|
|
22
|
+
if (child.nodeType === 1) {
|
|
23
|
+
/* $FlowFixMe: Refinement issue. I don't know how to express different. */
|
|
24
|
+
parent.appendChild(child);
|
|
25
|
+
} else {
|
|
26
|
+
/* As a result of the refinement issue this type isn't known. */
|
|
27
|
+
var node = child;
|
|
28
|
+
do {
|
|
29
|
+
recursivelyAppendChildren(parent, node.output);
|
|
30
|
+
} while (node = node.sibling);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var DOMRenderer = ReactFiberReconciler({
|
|
35
|
+
updateContainer: function (container, children) {
|
|
36
|
+
container.innerHTML = '';
|
|
37
|
+
recursivelyAppendChildren(container, children);
|
|
38
|
+
},
|
|
39
|
+
createInstance: function (type, props, children) {
|
|
40
|
+
var domElement = document.createElement(type);
|
|
41
|
+
recursivelyAppendChildren(domElement, children);
|
|
42
|
+
if (typeof props.children === 'string') {
|
|
43
|
+
domElement.textContent = props.children;
|
|
44
|
+
}
|
|
45
|
+
return domElement;
|
|
46
|
+
},
|
|
47
|
+
prepareUpdate: function (domElement, oldProps, newProps, children) {
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
commitUpdate: function (domElement, oldProps, newProps, children) {
|
|
51
|
+
domElement.innerHTML = '';
|
|
52
|
+
recursivelyAppendChildren(domElement, children);
|
|
53
|
+
if (typeof newProps.children === 'string') {
|
|
54
|
+
domElement.textContent = newProps.children;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
deleteInstance: function (instance) {
|
|
58
|
+
// Noop
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
scheduleHighPriCallback: window.requestAnimationFrame,
|
|
63
|
+
|
|
64
|
+
scheduleLowPriCallback: window.requestIdleCallback
|
|
65
|
+
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
var ReactDOM = {
|
|
69
|
+
render: function (element, container) {
|
|
70
|
+
if (!container._reactRootContainer) {
|
|
71
|
+
container._reactRootContainer = DOMRenderer.mountContainer(element, container);
|
|
72
|
+
} else {
|
|
73
|
+
DOMRenderer.updateContainer(element, container._reactRootContainer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
module.exports = ReactDOM;
|
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');
|
|
@@ -24,7 +25,6 @@ var warning = require('fbjs/lib/warning');
|
|
|
24
25
|
|
|
25
26
|
var didWarnValueLink = false;
|
|
26
27
|
var didWarnCheckedLink = false;
|
|
27
|
-
var didWarnValueNull = false;
|
|
28
28
|
var didWarnValueDefaultValue = false;
|
|
29
29
|
var didWarnCheckedDefaultChecked = false;
|
|
30
30
|
var didWarnControlledToUncontrolled = false;
|
|
@@ -37,16 +37,13 @@ function forceUpdateIfMounted() {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
didWarnValueNull = true;
|
|
45
|
-
}
|
|
40
|
+
function isControlled(props) {
|
|
41
|
+
var usesChecked = props.type === 'checkbox' || props.type === 'radio';
|
|
42
|
+
return usesChecked ? props.checked !== undefined : props.value !== undefined;
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
/**
|
|
49
|
-
* Implements an <input>
|
|
46
|
+
* Implements an <input> host component that allows setting these optional
|
|
50
47
|
* props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
|
|
51
48
|
*
|
|
52
49
|
* If `checked` or `value` are not supplied (or null/undefined), user actions
|
|
@@ -62,15 +59,15 @@ function warnIfValueIsNull(props) {
|
|
|
62
59
|
* @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
|
|
63
60
|
*/
|
|
64
61
|
var ReactDOMInput = {
|
|
65
|
-
|
|
62
|
+
getHostProps: function (inst, props) {
|
|
66
63
|
var value = LinkedValueUtils.getValue(props);
|
|
67
64
|
var checked = LinkedValueUtils.getChecked(props);
|
|
68
65
|
|
|
69
|
-
var
|
|
66
|
+
var hostProps = _assign({
|
|
70
67
|
// Make sure we set .type before any other properties (setting .value
|
|
71
68
|
// before .type means .value is lost in IE11 and below)
|
|
72
69
|
type: undefined
|
|
73
|
-
}, DisabledInputUtils.
|
|
70
|
+
}, DisabledInputUtils.getHostProps(inst, props), {
|
|
74
71
|
defaultChecked: undefined,
|
|
75
72
|
defaultValue: undefined,
|
|
76
73
|
value: value != null ? value : inst._wrapperState.initialValue,
|
|
@@ -78,7 +75,7 @@ var ReactDOMInput = {
|
|
|
78
75
|
onChange: inst._wrapperState.onChange
|
|
79
76
|
});
|
|
80
77
|
|
|
81
|
-
return
|
|
78
|
+
return hostProps;
|
|
82
79
|
},
|
|
83
80
|
|
|
84
81
|
mountWrapper: function (inst, props) {
|
|
@@ -103,19 +100,18 @@ var ReactDOMInput = {
|
|
|
103
100
|
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;
|
|
104
101
|
didWarnValueDefaultValue = true;
|
|
105
102
|
}
|
|
106
|
-
warnIfValueIsNull(props);
|
|
107
103
|
}
|
|
108
104
|
|
|
109
105
|
var defaultValue = props.defaultValue;
|
|
110
106
|
inst._wrapperState = {
|
|
111
|
-
initialChecked: props.
|
|
112
|
-
initialValue:
|
|
107
|
+
initialChecked: props.checked != null ? props.checked : props.defaultChecked,
|
|
108
|
+
initialValue: props.value != null ? props.value : defaultValue,
|
|
113
109
|
listeners: null,
|
|
114
110
|
onChange: _handleChange.bind(inst)
|
|
115
111
|
};
|
|
116
112
|
|
|
117
113
|
if (process.env.NODE_ENV !== 'production') {
|
|
118
|
-
inst._wrapperState.controlled = props
|
|
114
|
+
inst._wrapperState.controlled = isControlled(props);
|
|
119
115
|
}
|
|
120
116
|
},
|
|
121
117
|
|
|
@@ -123,18 +119,14 @@ var ReactDOMInput = {
|
|
|
123
119
|
var props = inst._currentElement.props;
|
|
124
120
|
|
|
125
121
|
if (process.env.NODE_ENV !== 'production') {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
var initialValue = inst._wrapperState.initialChecked || inst._wrapperState.initialValue;
|
|
129
|
-
var defaultValue = props.defaultChecked || props.defaultValue;
|
|
130
|
-
var controlled = props.checked !== undefined || props.value !== undefined;
|
|
122
|
+
var controlled = isControlled(props);
|
|
131
123
|
var owner = inst._currentElement._owner;
|
|
132
124
|
|
|
133
|
-
if (
|
|
125
|
+
if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
|
|
134
126
|
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
127
|
didWarnUncontrolledToControlled = true;
|
|
136
128
|
}
|
|
137
|
-
if (inst._wrapperState.controlled &&
|
|
129
|
+
if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
|
|
138
130
|
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
131
|
didWarnControlledToUncontrolled = true;
|
|
140
132
|
}
|
|
@@ -146,11 +138,57 @@ var ReactDOMInput = {
|
|
|
146
138
|
DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
|
|
147
139
|
}
|
|
148
140
|
|
|
141
|
+
var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
|
149
142
|
var value = LinkedValueUtils.getValue(props);
|
|
150
143
|
if (value != null) {
|
|
144
|
+
|
|
151
145
|
// Cast `value` to a string to ensure the value is set correctly. While
|
|
152
146
|
// browsers typically do this as necessary, jsdom doesn't.
|
|
153
|
-
|
|
147
|
+
var newValue = '' + value;
|
|
148
|
+
|
|
149
|
+
// To avoid side effects (such as losing text selection), only set value if changed
|
|
150
|
+
if (newValue !== node.value) {
|
|
151
|
+
node.value = newValue;
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
if (props.value == null && props.defaultValue != null) {
|
|
155
|
+
node.defaultValue = '' + props.defaultValue;
|
|
156
|
+
}
|
|
157
|
+
if (props.checked == null && props.defaultChecked != null) {
|
|
158
|
+
node.defaultChecked = !!props.defaultChecked;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
postMountWrapper: function (inst) {
|
|
164
|
+
var props = inst._currentElement.props;
|
|
165
|
+
|
|
166
|
+
// This is in postMount because we need access to the DOM node, which is not
|
|
167
|
+
// available until after the component has mounted.
|
|
168
|
+
var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
|
169
|
+
|
|
170
|
+
// Detach value from defaultValue. We won't do anything if we're working on
|
|
171
|
+
// submit or reset inputs as those values & defaultValues are linked. They
|
|
172
|
+
// are not resetable nodes so this operation doesn't matter and actually
|
|
173
|
+
// removes browser-default values (eg "Submit Query") when no value is
|
|
174
|
+
// provided.
|
|
175
|
+
if (props.type !== 'submit' && props.type !== 'reset') {
|
|
176
|
+
node.value = node.value;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
|
|
180
|
+
// this is needed to work around a chrome bug where setting defaultChecked
|
|
181
|
+
// will sometimes influence the value of checked (even after detachment).
|
|
182
|
+
// Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
|
|
183
|
+
// We need to temporarily unset name to avoid disrupting radio button groups.
|
|
184
|
+
var name = node.name;
|
|
185
|
+
if (name !== '') {
|
|
186
|
+
node.name = '';
|
|
187
|
+
}
|
|
188
|
+
node.defaultChecked = !node.defaultChecked;
|
|
189
|
+
node.defaultChecked = !node.defaultChecked;
|
|
190
|
+
if (name !== '') {
|
|
191
|
+
node.name = name;
|
|
154
192
|
}
|
|
155
193
|
}
|
|
156
194
|
};
|
|
@@ -192,7 +230,7 @@ function _handleChange(event) {
|
|
|
192
230
|
// That's probably okay; we don't support it just as we don't support
|
|
193
231
|
// mixing React radio buttons with non-React ones.
|
|
194
232
|
var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
|
|
195
|
-
!otherInstance ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the
|
|
233
|
+
!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
234
|
// If this is a controlled radio button group, forcing the input that
|
|
197
235
|
// was previously checked to update will cause it to be come re-checked
|
|
198
236
|
// as appropriate.
|