react 15.3.2 → 15.4.0-rc.4
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 +3864 -21390
- package/dist/react-with-addons.min.js +3 -6
- package/dist/react.js +2639 -19486
- package/dist/react.min.js +2 -6
- package/lib/KeyEscapeUtils.js +0 -1
- package/lib/LinkedStateMixin.js +1 -3
- package/lib/PooledClass.js +3 -1
- package/lib/React.js +0 -1
- package/lib/ReactAddonsDOMDependencies.js +35 -0
- package/lib/ReactAddonsDOMDependenciesUMDShim.js +31 -0
- package/lib/ReactCSSTransitionGroup.js +60 -43
- package/lib/ReactCSSTransitionGroupChild.js +2 -3
- package/lib/ReactChildren.js +0 -1
- package/lib/ReactClass.js +38 -54
- package/lib/ReactComponent.js +0 -1
- package/lib/ReactComponentTreeDevtool.js +0 -1
- package/lib/ReactComponentTreeHook.js +84 -101
- package/lib/{DOMNamespaces.js → ReactComponentTreeHookUMDShim.js} +4 -7
- package/lib/ReactComponentWithPureRenderMixin.js +0 -1
- package/lib/ReactCurrentOwner.js +1 -2
- package/lib/{renderSubtreeIntoContainer.js → ReactCurrentOwnerUMDShim.js} +5 -4
- package/lib/ReactDOMFactories.js +0 -1
- package/lib/ReactElement.js +6 -14
- package/lib/ReactElementSymbol.js +19 -0
- package/lib/{ReactDOMComponentFlags.js → ReactElementType.js} +3 -9
- package/lib/ReactElementValidator.js +1 -3
- package/lib/ReactFragment.js +0 -1
- package/lib/ReactLink.js +0 -1
- package/lib/ReactNoopUpdateQueue.js +0 -1
- package/lib/ReactPropTypeLocationNames.js +1 -1
- package/lib/ReactPropTypeLocations.js +2 -12
- package/lib/ReactPropTypes.js +5 -3
- package/lib/ReactPropTypesSecret.js +1 -1
- package/lib/ReactPureComponent.js +0 -1
- package/lib/ReactStateSetters.js +0 -1
- package/lib/ReactTransitionChildMapping.js +0 -1
- package/lib/ReactTransitionEvents.js +1 -2
- package/lib/ReactTransitionGroup.js +145 -142
- package/lib/ReactUMDEntry.js +11 -6
- package/lib/{ReactDOMFeatureFlags.js → ReactUMDShim.js} +3 -6
- package/lib/ReactVersion.js +1 -2
- package/lib/ReactWithAddons.js +15 -3
- package/lib/ReactWithAddonsUMDEntry.js +11 -6
- package/lib/canDefineProperty.js +2 -1
- package/lib/checkReactTypeSpec.js +0 -1
- package/lib/deprecated.js +0 -1
- package/lib/flattenChildren.js +0 -1
- package/lib/getIteratorFn.js +0 -1
- package/lib/onlyChild.js +0 -1
- package/lib/reactProdInvariant.js +0 -1
- package/lib/shallowCompare.js +1 -2
- package/lib/sliceChildren.js +0 -1
- package/lib/traverseAllChildren.js +11 -3
- package/lib/update.js +6 -8
- package/package.json +1 -1
- package/lib/AutoFocusUtils.js +0 -24
- package/lib/BeforeInputEventPlugin.js +0 -390
- package/lib/CSSProperty.js +0 -148
- package/lib/CSSPropertyOperations.js +0 -205
- package/lib/CallbackQueue.js +0 -106
- package/lib/ChangeEventPlugin.js +0 -325
- package/lib/DOMChildrenOperations.js +0 -194
- package/lib/DOMLazyTree.js +0 -118
- package/lib/DOMProperty.js +0 -206
- package/lib/DOMPropertyOperations.js +0 -221
- package/lib/Danger.js +0 -48
- package/lib/DefaultEventPluginOrder.js +0 -27
- package/lib/DisabledInputUtils.js +0 -50
- package/lib/EnterLeaveEventPlugin.js +0 -105
- package/lib/EventConstants.js +0 -97
- package/lib/EventPluginHub.js +0 -251
- package/lib/EventPluginRegistry.js +0 -247
- package/lib/EventPluginUtils.js +0 -229
- package/lib/EventPropagators.js +0 -137
- package/lib/FallbackCompositionState.js +0 -95
- package/lib/HTMLDOMPropertyConfig.js +0 -212
- package/lib/LinkedValueUtils.js +0 -136
- package/lib/NativeMethodsMixin.js +0 -167
- package/lib/ReactBrowserEventEmitter.js +0 -330
- package/lib/ReactChildReconciler.js +0 -154
- package/lib/ReactChildrenMutationWarningHook.js +0 -54
- package/lib/ReactComponentBrowserEnvironment.js +0 -30
- package/lib/ReactComponentEnvironment.js +0 -45
- package/lib/ReactComponentTreeTestUtils.js +0 -87
- package/lib/ReactCompositeComponent.js +0 -904
- package/lib/ReactDOM.js +0 -110
- package/lib/ReactDOMButton.js +0 -24
- package/lib/ReactDOMComponent.js +0 -1006
- package/lib/ReactDOMComponentTree.js +0 -188
- package/lib/ReactDOMContainerInfo.js +0 -33
- package/lib/ReactDOMEmptyComponent.js +0 -60
- package/lib/ReactDOMFiber.js +0 -76
- package/lib/ReactDOMIDOperations.js +0 -34
- package/lib/ReactDOMInput.js +0 -269
- package/lib/ReactDOMNullInputValuePropHook.js +0 -43
- package/lib/ReactDOMOption.js +0 -123
- package/lib/ReactDOMSelect.js +0 -201
- package/lib/ReactDOMSelection.js +0 -212
- package/lib/ReactDOMServer.js +0 -26
- package/lib/ReactDOMTextComponent.js +0 -164
- package/lib/ReactDOMTextarea.js +0 -155
- package/lib/ReactDOMTreeTraversal.js +0 -136
- package/lib/ReactDOMUnknownPropertyHook.js +0 -112
- package/lib/ReactDebugTool.js +0 -301
- package/lib/ReactDefaultBatchingStrategy.js +0 -68
- package/lib/ReactDefaultInjection.js +0 -84
- package/lib/ReactEmptyComponent.js +0 -30
- package/lib/ReactErrorUtils.js +0 -76
- package/lib/ReactEventEmitterMixin.js +0 -33
- package/lib/ReactEventListener.js +0 -157
- package/lib/ReactFeatureFlags.js +0 -22
- package/lib/ReactHostComponent.js +0 -76
- package/lib/ReactHostOperationHistoryHook.js +0 -37
- package/lib/ReactInjection.js +0 -36
- package/lib/ReactInputSelection.js +0 -124
- package/lib/ReactInstanceHandles.js +0 -302
- package/lib/ReactInstanceMap.js +0 -48
- package/lib/ReactInstrumentation.js +0 -21
- package/lib/ReactInvalidSetStateWarningHook.js +0 -36
- package/lib/ReactMarkupChecksum.js +0 -50
- package/lib/ReactMount.js +0 -534
- package/lib/ReactMultiChild.js +0 -451
- package/lib/ReactMultiChildUpdateTypes.js +0 -32
- package/lib/ReactNative.js +0 -71
- package/lib/ReactNativeAttributePayload.js +0 -371
- package/lib/ReactNativeBaseComponent.js +0 -198
- package/lib/ReactNativeBridgeEventPlugin.js +0 -60
- package/lib/ReactNativeComponentEnvironment.js +0 -31
- package/lib/ReactNativeComponentTree.js +0 -68
- package/lib/ReactNativeContainerInfo.js +0 -21
- package/lib/ReactNativeDOMIDOperations.js +0 -79
- package/lib/ReactNativeDefaultInjection.js +0 -101
- package/lib/ReactNativeEventEmitter.js +0 -191
- package/lib/ReactNativeEventPluginOrder.js +0 -16
- package/lib/ReactNativeGlobalResponderHandler.js +0 -25
- package/lib/ReactNativeMount.js +0 -193
- package/lib/ReactNativePropRegistry.js +0 -52
- package/lib/ReactNativeReconcileTransaction.js +0 -129
- package/lib/ReactNativeTagHandles.js +0 -56
- package/lib/ReactNativeTextComponent.js +0 -71
- package/lib/ReactNativeTreeTraversal.js +0 -127
- package/lib/ReactNodeTypes.js +0 -40
- package/lib/ReactNoop.js +0 -173
- package/lib/ReactOwner.js +0 -94
- package/lib/ReactPerf.js +0 -494
- package/lib/ReactReconcileTransaction.js +0 -178
- package/lib/ReactReconciler.js +0 -168
- package/lib/ReactRef.js +0 -80
- package/lib/ReactServerBatchingStrategy.js +0 -22
- package/lib/ReactServerRendering.js +0 -90
- package/lib/ReactServerRenderingTransaction.js +0 -90
- package/lib/ReactServerUpdateQueue.js +0 -141
- package/lib/ReactSimpleEmptyComponent.js +0 -37
- package/lib/ReactTestMount.js +0 -126
- package/lib/ReactTestReconcileTransaction.js +0 -121
- package/lib/ReactTestRenderer.js +0 -144
- package/lib/ReactTestUtils.js +0 -518
- package/lib/ReactUpdateQueue.js +0 -226
- package/lib/ReactUpdates.js +0 -251
- package/lib/ResponderEventPlugin.js +0 -510
- package/lib/ResponderSyntheticEvent.js +0 -39
- package/lib/ResponderTouchHistoryStore.js +0 -184
- package/lib/SVGDOMPropertyConfig.js +0 -302
- package/lib/SelectEventPlugin.js +0 -196
- package/lib/SimpleEventPlugin.js +0 -635
- package/lib/SyntheticAnimationEvent.js +0 -39
- package/lib/SyntheticClipboardEvent.js +0 -38
- package/lib/SyntheticCompositionEvent.js +0 -36
- package/lib/SyntheticDragEvent.js +0 -36
- package/lib/SyntheticEvent.js +0 -268
- package/lib/SyntheticFocusEvent.js +0 -36
- package/lib/SyntheticInputEvent.js +0 -37
- package/lib/SyntheticKeyboardEvent.js +0 -84
- package/lib/SyntheticMouseEvent.js +0 -72
- package/lib/SyntheticTouchEvent.js +0 -45
- package/lib/SyntheticTransitionEvent.js +0 -39
- package/lib/SyntheticUIEvent.js +0 -59
- package/lib/SyntheticWheelEvent.js +0 -54
- package/lib/TapEventPlugin.js +0 -110
- package/lib/TouchHistoryMath.js +0 -99
- package/lib/Transaction.js +0 -233
- package/lib/ViewportMetrics.js +0 -27
- package/lib/accumulate.js +0 -46
- package/lib/accumulateInto.js +0 -58
- package/lib/adler32.js +0 -44
- package/lib/createMicrosoftUnsafeLocalFunction.js +0 -32
- package/lib/createReactNativeComponentClass.js +0 -42
- package/lib/dangerousStyleValue.js +0 -79
- package/lib/escapeTextContentForBrowser.js +0 -123
- package/lib/findDOMNode.js +0 -60
- package/lib/findNodeHandle.js +0 -91
- package/lib/forEachAccumulated.js +0 -31
- package/lib/getEventCharCode.js +0 -50
- package/lib/getEventKey.js +0 -102
- package/lib/getEventModifierState.js +0 -43
- package/lib/getEventTarget.js +0 -35
- package/lib/getHostComponentFromComposite.js +0 -30
- package/lib/getNodeForCharacterOffset.js +0 -74
- package/lib/getTestDocument.js +0 -21
- package/lib/getTextContentAccessor.js +0 -33
- package/lib/getVendorPrefixedEventName.js +0 -101
- package/lib/instantiateReactComponent.js +0 -119
- package/lib/isEventSupported.js +0 -60
- package/lib/isTextInputElement.js +0 -51
- package/lib/quoteAttributeValueForBrowser.js +0 -26
- package/lib/reactComponentExpect.js +0 -217
- package/lib/setInnerHTML.js +0 -98
- package/lib/setTextContent.js +0 -48
- package/lib/shouldUpdateReactComponent.js +0 -42
- package/lib/validateDOMNesting.js +0 -382
package/lib/setInnerHTML.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
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 setInnerHTML
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
|
|
15
|
-
var DOMNamespaces = require('./DOMNamespaces');
|
|
16
|
-
|
|
17
|
-
var WHITESPACE_TEST = /^[ \r\n\t\f]/;
|
|
18
|
-
var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;
|
|
19
|
-
|
|
20
|
-
var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction');
|
|
21
|
-
|
|
22
|
-
// SVG temp container for IE lacking innerHTML
|
|
23
|
-
var reusableSVGContainer;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Set the innerHTML property of a node, ensuring that whitespace is preserved
|
|
27
|
-
* even in IE8.
|
|
28
|
-
*
|
|
29
|
-
* @param {DOMElement} node
|
|
30
|
-
* @param {string} html
|
|
31
|
-
* @internal
|
|
32
|
-
*/
|
|
33
|
-
var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
|
|
34
|
-
// IE does not have innerHTML for SVG nodes, so instead we inject the
|
|
35
|
-
// new markup in a temp node and then move the child nodes across into
|
|
36
|
-
// the target node
|
|
37
|
-
if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {
|
|
38
|
-
reusableSVGContainer = reusableSVGContainer || document.createElement('div');
|
|
39
|
-
reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
|
|
40
|
-
var svgNode = reusableSVGContainer.firstChild;
|
|
41
|
-
while (svgNode.firstChild) {
|
|
42
|
-
node.appendChild(svgNode.firstChild);
|
|
43
|
-
}
|
|
44
|
-
} else {
|
|
45
|
-
node.innerHTML = html;
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
if (ExecutionEnvironment.canUseDOM) {
|
|
50
|
-
// IE8: When updating a just created node with innerHTML only leading
|
|
51
|
-
// whitespace is removed. When updating an existing node with innerHTML
|
|
52
|
-
// whitespace in root TextNodes is also collapsed.
|
|
53
|
-
// @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
|
|
54
|
-
|
|
55
|
-
// Feature detection; only IE8 is known to behave improperly like this.
|
|
56
|
-
var testElement = document.createElement('div');
|
|
57
|
-
testElement.innerHTML = ' ';
|
|
58
|
-
if (testElement.innerHTML === '') {
|
|
59
|
-
setInnerHTML = function (node, html) {
|
|
60
|
-
// Magic theory: IE8 supposedly differentiates between added and updated
|
|
61
|
-
// nodes when processing innerHTML, innerHTML on updated nodes suffers
|
|
62
|
-
// from worse whitespace behavior. Re-adding a node like this triggers
|
|
63
|
-
// the initial and more favorable whitespace behavior.
|
|
64
|
-
// TODO: What to do on a detached node?
|
|
65
|
-
if (node.parentNode) {
|
|
66
|
-
node.parentNode.replaceChild(node, node);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// We also implement a workaround for non-visible tags disappearing into
|
|
70
|
-
// thin air on IE8, this only happens if there is no visible text
|
|
71
|
-
// in-front of the non-visible tags. Piggyback on the whitespace fix
|
|
72
|
-
// and simply check if any non-visible tags appear in the source.
|
|
73
|
-
if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {
|
|
74
|
-
// Recover leading whitespace by temporarily prepending any character.
|
|
75
|
-
// \uFEFF has the potential advantage of being zero-width/invisible.
|
|
76
|
-
// UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode
|
|
77
|
-
// in hopes that this is preserved even if "\uFEFF" is transformed to
|
|
78
|
-
// the actual Unicode character (by Babel, for example).
|
|
79
|
-
// https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216
|
|
80
|
-
node.innerHTML = String.fromCharCode(0xFEFF) + html;
|
|
81
|
-
|
|
82
|
-
// deleteData leaves an empty `TextNode` which offsets the index of all
|
|
83
|
-
// children. Definitely want to avoid this.
|
|
84
|
-
var textNode = node.firstChild;
|
|
85
|
-
if (textNode.data.length === 1) {
|
|
86
|
-
node.removeChild(textNode);
|
|
87
|
-
} else {
|
|
88
|
-
textNode.deleteData(0, 1);
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
node.innerHTML = html;
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
testElement = null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
module.exports = setInnerHTML;
|
package/lib/setTextContent.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
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 setTextContent
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
|
|
15
|
-
var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');
|
|
16
|
-
var setInnerHTML = require('./setInnerHTML');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Set the textContent property of a node, ensuring that whitespace is preserved
|
|
20
|
-
* even in IE8. innerText is a poor substitute for textContent and, among many
|
|
21
|
-
* issues, inserts <br> instead of the literal newline chars. innerHTML behaves
|
|
22
|
-
* as it should.
|
|
23
|
-
*
|
|
24
|
-
* @param {DOMElement} node
|
|
25
|
-
* @param {string} text
|
|
26
|
-
* @internal
|
|
27
|
-
*/
|
|
28
|
-
var setTextContent = function (node, text) {
|
|
29
|
-
if (text) {
|
|
30
|
-
var firstChild = node.firstChild;
|
|
31
|
-
|
|
32
|
-
if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {
|
|
33
|
-
firstChild.nodeValue = text;
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
node.textContent = text;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
if (ExecutionEnvironment.canUseDOM) {
|
|
41
|
-
if (!('textContent' in document.documentElement)) {
|
|
42
|
-
setTextContent = function (node, text) {
|
|
43
|
-
setInnerHTML(node, escapeTextContentForBrowser(text));
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = setTextContent;
|
|
@@ -1,42 +0,0 @@
|
|
|
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 shouldUpdateReactComponent
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Given a `prevElement` and `nextElement`, determines if the existing
|
|
16
|
-
* instance should be updated as opposed to being destroyed or replaced by a new
|
|
17
|
-
* instance. Both arguments are elements. This ensures that this logic can
|
|
18
|
-
* operate on stateless trees without any backing instance.
|
|
19
|
-
*
|
|
20
|
-
* @param {?object} prevElement
|
|
21
|
-
* @param {?object} nextElement
|
|
22
|
-
* @return {boolean} True if the existing instance should be updated.
|
|
23
|
-
* @protected
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
function shouldUpdateReactComponent(prevElement, nextElement) {
|
|
27
|
-
var prevEmpty = prevElement === null || prevElement === false;
|
|
28
|
-
var nextEmpty = nextElement === null || nextElement === false;
|
|
29
|
-
if (prevEmpty || nextEmpty) {
|
|
30
|
-
return prevEmpty === nextEmpty;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
var prevType = typeof prevElement;
|
|
34
|
-
var nextType = typeof nextElement;
|
|
35
|
-
if (prevType === 'string' || prevType === 'number') {
|
|
36
|
-
return nextType === 'string' || nextType === 'number';
|
|
37
|
-
} else {
|
|
38
|
-
return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
module.exports = shouldUpdateReactComponent;
|
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2015-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 validateDOMNesting
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
var _assign = require('object-assign');
|
|
15
|
-
|
|
16
|
-
var emptyFunction = require('fbjs/lib/emptyFunction');
|
|
17
|
-
var warning = require('fbjs/lib/warning');
|
|
18
|
-
|
|
19
|
-
var validateDOMNesting = emptyFunction;
|
|
20
|
-
|
|
21
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
22
|
-
// This validation code was written based on the HTML5 parsing spec:
|
|
23
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
|
24
|
-
//
|
|
25
|
-
// Note: this does not catch all invalid nesting, nor does it try to (as it's
|
|
26
|
-
// not clear what practical benefit doing so provides); instead, we warn only
|
|
27
|
-
// for cases where the parser will give a parse tree differing from what React
|
|
28
|
-
// intended. For example, <b><div></div></b> is invalid but we don't warn
|
|
29
|
-
// because it still parses correctly; we do warn for other cases like nested
|
|
30
|
-
// <p> tags where the beginning of the second element implicitly closes the
|
|
31
|
-
// first, causing a confusing mess.
|
|
32
|
-
|
|
33
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#special
|
|
34
|
-
var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];
|
|
35
|
-
|
|
36
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
|
37
|
-
var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
|
|
38
|
-
|
|
39
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
|
|
40
|
-
// TODO: Distinguish by namespace here -- for <title>, including it here
|
|
41
|
-
// errs on the side of fewer warnings
|
|
42
|
-
'foreignObject', 'desc', 'title'];
|
|
43
|
-
|
|
44
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
|
|
45
|
-
var buttonScopeTags = inScopeTags.concat(['button']);
|
|
46
|
-
|
|
47
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
|
|
48
|
-
var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
|
|
49
|
-
|
|
50
|
-
var emptyAncestorInfo = {
|
|
51
|
-
current: null,
|
|
52
|
-
|
|
53
|
-
formTag: null,
|
|
54
|
-
aTagInScope: null,
|
|
55
|
-
buttonTagInScope: null,
|
|
56
|
-
nobrTagInScope: null,
|
|
57
|
-
pTagInButtonScope: null,
|
|
58
|
-
|
|
59
|
-
listItemTagAutoclosing: null,
|
|
60
|
-
dlItemTagAutoclosing: null
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
var updatedAncestorInfo = function (oldInfo, tag, instance) {
|
|
64
|
-
var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
|
|
65
|
-
var info = { tag: tag, instance: instance };
|
|
66
|
-
|
|
67
|
-
if (inScopeTags.indexOf(tag) !== -1) {
|
|
68
|
-
ancestorInfo.aTagInScope = null;
|
|
69
|
-
ancestorInfo.buttonTagInScope = null;
|
|
70
|
-
ancestorInfo.nobrTagInScope = null;
|
|
71
|
-
}
|
|
72
|
-
if (buttonScopeTags.indexOf(tag) !== -1) {
|
|
73
|
-
ancestorInfo.pTagInButtonScope = null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// See rules for 'li', 'dd', 'dt' start tags in
|
|
77
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
|
|
78
|
-
if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
|
|
79
|
-
ancestorInfo.listItemTagAutoclosing = null;
|
|
80
|
-
ancestorInfo.dlItemTagAutoclosing = null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
ancestorInfo.current = info;
|
|
84
|
-
|
|
85
|
-
if (tag === 'form') {
|
|
86
|
-
ancestorInfo.formTag = info;
|
|
87
|
-
}
|
|
88
|
-
if (tag === 'a') {
|
|
89
|
-
ancestorInfo.aTagInScope = info;
|
|
90
|
-
}
|
|
91
|
-
if (tag === 'button') {
|
|
92
|
-
ancestorInfo.buttonTagInScope = info;
|
|
93
|
-
}
|
|
94
|
-
if (tag === 'nobr') {
|
|
95
|
-
ancestorInfo.nobrTagInScope = info;
|
|
96
|
-
}
|
|
97
|
-
if (tag === 'p') {
|
|
98
|
-
ancestorInfo.pTagInButtonScope = info;
|
|
99
|
-
}
|
|
100
|
-
if (tag === 'li') {
|
|
101
|
-
ancestorInfo.listItemTagAutoclosing = info;
|
|
102
|
-
}
|
|
103
|
-
if (tag === 'dd' || tag === 'dt') {
|
|
104
|
-
ancestorInfo.dlItemTagAutoclosing = info;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return ancestorInfo;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Returns whether
|
|
112
|
-
*/
|
|
113
|
-
var isTagValidWithParent = function (tag, parentTag) {
|
|
114
|
-
// First, let's check if we're in an unusual parsing mode...
|
|
115
|
-
switch (parentTag) {
|
|
116
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
|
|
117
|
-
case 'select':
|
|
118
|
-
return tag === 'option' || tag === 'optgroup' || tag === '#text';
|
|
119
|
-
case 'optgroup':
|
|
120
|
-
return tag === 'option' || tag === '#text';
|
|
121
|
-
// Strictly speaking, seeing an <option> doesn't mean we're in a <select>
|
|
122
|
-
// but
|
|
123
|
-
case 'option':
|
|
124
|
-
return tag === '#text';
|
|
125
|
-
|
|
126
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
|
|
127
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
|
|
128
|
-
// No special behavior since these rules fall back to "in body" mode for
|
|
129
|
-
// all except special table nodes which cause bad parsing behavior anyway.
|
|
130
|
-
|
|
131
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
|
|
132
|
-
case 'tr':
|
|
133
|
-
return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
134
|
-
|
|
135
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
|
|
136
|
-
case 'tbody':
|
|
137
|
-
case 'thead':
|
|
138
|
-
case 'tfoot':
|
|
139
|
-
return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
140
|
-
|
|
141
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
|
|
142
|
-
case 'colgroup':
|
|
143
|
-
return tag === 'col' || tag === 'template';
|
|
144
|
-
|
|
145
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
|
|
146
|
-
case 'table':
|
|
147
|
-
return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
148
|
-
|
|
149
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
|
|
150
|
-
case 'head':
|
|
151
|
-
return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
152
|
-
|
|
153
|
-
// https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
|
|
154
|
-
case 'html':
|
|
155
|
-
return tag === 'head' || tag === 'body';
|
|
156
|
-
case '#document':
|
|
157
|
-
return tag === 'html';
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Probably in the "in body" parsing mode, so we outlaw only tag combos
|
|
161
|
-
// where the parsing rules cause implicit opens or closes to be added.
|
|
162
|
-
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
|
|
163
|
-
switch (tag) {
|
|
164
|
-
case 'h1':
|
|
165
|
-
case 'h2':
|
|
166
|
-
case 'h3':
|
|
167
|
-
case 'h4':
|
|
168
|
-
case 'h5':
|
|
169
|
-
case 'h6':
|
|
170
|
-
return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
|
|
171
|
-
|
|
172
|
-
case 'rp':
|
|
173
|
-
case 'rt':
|
|
174
|
-
return impliedEndTags.indexOf(parentTag) === -1;
|
|
175
|
-
|
|
176
|
-
case 'body':
|
|
177
|
-
case 'caption':
|
|
178
|
-
case 'col':
|
|
179
|
-
case 'colgroup':
|
|
180
|
-
case 'frame':
|
|
181
|
-
case 'head':
|
|
182
|
-
case 'html':
|
|
183
|
-
case 'tbody':
|
|
184
|
-
case 'td':
|
|
185
|
-
case 'tfoot':
|
|
186
|
-
case 'th':
|
|
187
|
-
case 'thead':
|
|
188
|
-
case 'tr':
|
|
189
|
-
// These tags are only valid with a few parents that have special child
|
|
190
|
-
// parsing rules -- if we're down here, then none of those matched and
|
|
191
|
-
// so we allow it only if we don't know what the parent is, as all other
|
|
192
|
-
// cases are invalid.
|
|
193
|
-
return parentTag == null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return true;
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Returns whether
|
|
201
|
-
*/
|
|
202
|
-
var findInvalidAncestorForTag = function (tag, ancestorInfo) {
|
|
203
|
-
switch (tag) {
|
|
204
|
-
case 'address':
|
|
205
|
-
case 'article':
|
|
206
|
-
case 'aside':
|
|
207
|
-
case 'blockquote':
|
|
208
|
-
case 'center':
|
|
209
|
-
case 'details':
|
|
210
|
-
case 'dialog':
|
|
211
|
-
case 'dir':
|
|
212
|
-
case 'div':
|
|
213
|
-
case 'dl':
|
|
214
|
-
case 'fieldset':
|
|
215
|
-
case 'figcaption':
|
|
216
|
-
case 'figure':
|
|
217
|
-
case 'footer':
|
|
218
|
-
case 'header':
|
|
219
|
-
case 'hgroup':
|
|
220
|
-
case 'main':
|
|
221
|
-
case 'menu':
|
|
222
|
-
case 'nav':
|
|
223
|
-
case 'ol':
|
|
224
|
-
case 'p':
|
|
225
|
-
case 'section':
|
|
226
|
-
case 'summary':
|
|
227
|
-
case 'ul':
|
|
228
|
-
|
|
229
|
-
case 'pre':
|
|
230
|
-
case 'listing':
|
|
231
|
-
|
|
232
|
-
case 'table':
|
|
233
|
-
|
|
234
|
-
case 'hr':
|
|
235
|
-
|
|
236
|
-
case 'xmp':
|
|
237
|
-
|
|
238
|
-
case 'h1':
|
|
239
|
-
case 'h2':
|
|
240
|
-
case 'h3':
|
|
241
|
-
case 'h4':
|
|
242
|
-
case 'h5':
|
|
243
|
-
case 'h6':
|
|
244
|
-
return ancestorInfo.pTagInButtonScope;
|
|
245
|
-
|
|
246
|
-
case 'form':
|
|
247
|
-
return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
|
|
248
|
-
|
|
249
|
-
case 'li':
|
|
250
|
-
return ancestorInfo.listItemTagAutoclosing;
|
|
251
|
-
|
|
252
|
-
case 'dd':
|
|
253
|
-
case 'dt':
|
|
254
|
-
return ancestorInfo.dlItemTagAutoclosing;
|
|
255
|
-
|
|
256
|
-
case 'button':
|
|
257
|
-
return ancestorInfo.buttonTagInScope;
|
|
258
|
-
|
|
259
|
-
case 'a':
|
|
260
|
-
// Spec says something about storing a list of markers, but it sounds
|
|
261
|
-
// equivalent to this check.
|
|
262
|
-
return ancestorInfo.aTagInScope;
|
|
263
|
-
|
|
264
|
-
case 'nobr':
|
|
265
|
-
return ancestorInfo.nobrTagInScope;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return null;
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Given a ReactCompositeComponent instance, return a list of its recursive
|
|
273
|
-
* owners, starting at the root and ending with the instance itself.
|
|
274
|
-
*/
|
|
275
|
-
var findOwnerStack = function (instance) {
|
|
276
|
-
if (!instance) {
|
|
277
|
-
return [];
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
var stack = [];
|
|
281
|
-
do {
|
|
282
|
-
stack.push(instance);
|
|
283
|
-
} while (instance = instance._currentElement._owner);
|
|
284
|
-
stack.reverse();
|
|
285
|
-
return stack;
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
var didWarn = {};
|
|
289
|
-
|
|
290
|
-
validateDOMNesting = function (childTag, childText, childInstance, ancestorInfo) {
|
|
291
|
-
ancestorInfo = ancestorInfo || emptyAncestorInfo;
|
|
292
|
-
var parentInfo = ancestorInfo.current;
|
|
293
|
-
var parentTag = parentInfo && parentInfo.tag;
|
|
294
|
-
|
|
295
|
-
if (childText != null) {
|
|
296
|
-
process.env.NODE_ENV !== 'production' ? warning(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null') : void 0;
|
|
297
|
-
childTag = '#text';
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
|
|
301
|
-
var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
|
|
302
|
-
var problematic = invalidParent || invalidAncestor;
|
|
303
|
-
|
|
304
|
-
if (problematic) {
|
|
305
|
-
var ancestorTag = problematic.tag;
|
|
306
|
-
var ancestorInstance = problematic.instance;
|
|
307
|
-
|
|
308
|
-
var childOwner = childInstance && childInstance._currentElement._owner;
|
|
309
|
-
var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;
|
|
310
|
-
|
|
311
|
-
var childOwners = findOwnerStack(childOwner);
|
|
312
|
-
var ancestorOwners = findOwnerStack(ancestorOwner);
|
|
313
|
-
|
|
314
|
-
var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
|
|
315
|
-
var i;
|
|
316
|
-
|
|
317
|
-
var deepestCommon = -1;
|
|
318
|
-
for (i = 0; i < minStackLen; i++) {
|
|
319
|
-
if (childOwners[i] === ancestorOwners[i]) {
|
|
320
|
-
deepestCommon = i;
|
|
321
|
-
} else {
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
var UNKNOWN = '(unknown)';
|
|
327
|
-
var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
|
|
328
|
-
return inst.getName() || UNKNOWN;
|
|
329
|
-
});
|
|
330
|
-
var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
|
|
331
|
-
return inst.getName() || UNKNOWN;
|
|
332
|
-
});
|
|
333
|
-
var ownerInfo = [].concat(
|
|
334
|
-
// If the parent and child instances have a common owner ancestor, start
|
|
335
|
-
// with that -- otherwise we just start with the parent's owners.
|
|
336
|
-
deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
|
|
337
|
-
// If we're warning about an invalid (non-parent) ancestry, add '...'
|
|
338
|
-
invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');
|
|
339
|
-
|
|
340
|
-
var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;
|
|
341
|
-
if (didWarn[warnKey]) {
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
didWarn[warnKey] = true;
|
|
345
|
-
|
|
346
|
-
var tagDisplayName = childTag;
|
|
347
|
-
var whitespaceInfo = '';
|
|
348
|
-
if (childTag === '#text') {
|
|
349
|
-
if (/\S/.test(childText)) {
|
|
350
|
-
tagDisplayName = 'Text nodes';
|
|
351
|
-
} else {
|
|
352
|
-
tagDisplayName = 'Whitespace text nodes';
|
|
353
|
-
whitespaceInfo = ' Make sure you don\'t have any extra whitespace between tags on ' + 'each line of your source code.';
|
|
354
|
-
}
|
|
355
|
-
} else {
|
|
356
|
-
tagDisplayName = '<' + childTag + '>';
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
if (invalidParent) {
|
|
360
|
-
var info = '';
|
|
361
|
-
if (ancestorTag === 'table' && childTag === 'tr') {
|
|
362
|
-
info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
|
|
363
|
-
}
|
|
364
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s ' + 'See %s.%s', tagDisplayName, ancestorTag, whitespaceInfo, ownerInfo, info) : void 0;
|
|
365
|
-
} else {
|
|
366
|
-
process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;
|
|
372
|
-
|
|
373
|
-
// For testing
|
|
374
|
-
validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
|
|
375
|
-
ancestorInfo = ancestorInfo || emptyAncestorInfo;
|
|
376
|
-
var parentInfo = ancestorInfo.current;
|
|
377
|
-
var parentTag = parentInfo && parentInfo.tag;
|
|
378
|
-
return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
module.exports = validateDOMNesting;
|