react-test-renderer 15.5.0 → 15.5.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/lib/ReactShallowRenderer.js +6 -0
- package/lib/shallow/ARIADOMPropertyConfig.js +73 -0
- package/lib/shallow/AutoFocusUtils.js +23 -0
- package/lib/shallow/BeforeInputEventPlugin.js +384 -0
- package/lib/shallow/CSSProperty.js +147 -0
- package/lib/shallow/CSSPropertyOperations.js +208 -0
- package/lib/shallow/CallbackQueue.js +118 -0
- package/lib/shallow/ChangeEventPlugin.js +345 -0
- package/lib/shallow/DOMChildrenOperations.js +224 -0
- package/lib/shallow/DOMLazyTree.js +117 -0
- package/lib/shallow/DOMNamespaces.js +19 -0
- package/lib/shallow/DOMProperty.js +209 -0
- package/lib/shallow/DOMPropertyOperations.js +236 -0
- package/lib/shallow/Danger.js +47 -0
- package/lib/shallow/DefaultEventPluginOrder.js +25 -0
- package/lib/shallow/EnterLeaveEventPlugin.js +99 -0
- package/lib/shallow/EventConstants.js +91 -0
- package/lib/shallow/EventPluginHub.js +277 -0
- package/lib/shallow/EventPluginRegistry.js +254 -0
- package/lib/shallow/EventPluginUtils.js +225 -0
- package/lib/shallow/EventPropagators.js +133 -0
- package/lib/shallow/FallbackCompositionState.js +94 -0
- package/lib/shallow/HTMLDOMPropertyConfig.js +235 -0
- package/lib/shallow/KeyEscapeUtils.js +58 -0
- package/lib/shallow/LinkedValueUtils.js +137 -0
- package/lib/shallow/PluginModuleType.js +12 -0
- package/lib/shallow/PooledClass.js +111 -0
- package/lib/shallow/ReactBrowserEventEmitter.js +327 -0
- package/lib/shallow/ReactChildFiber.js +243 -0
- package/lib/shallow/ReactChildReconciler.js +153 -0
- package/lib/shallow/ReactComponentBrowserEnvironment.js +29 -0
- package/lib/shallow/ReactComponentEnvironment.js +45 -0
- package/lib/shallow/ReactCompositeComponent.js +901 -0
- package/lib/shallow/ReactCoroutine.js +80 -0
- package/lib/shallow/ReactDOM.js +110 -0
- package/lib/shallow/ReactDOMComponent.js +1000 -0
- package/lib/shallow/ReactDOMComponentFlags.js +17 -0
- package/lib/shallow/ReactDOMComponentTree.js +194 -0
- package/lib/shallow/ReactDOMContainerInfo.js +32 -0
- package/lib/shallow/ReactDOMEmptyComponent.js +59 -0
- package/lib/shallow/ReactDOMFeatureFlags.js +18 -0
- package/lib/shallow/ReactDOMFiber.js +97 -0
- package/lib/shallow/ReactDOMIDOperations.js +33 -0
- package/lib/shallow/ReactDOMInput.js +284 -0
- package/lib/shallow/ReactDOMInvalidARIAHook.js +92 -0
- package/lib/shallow/ReactDOMNullInputValuePropHook.js +42 -0
- package/lib/shallow/ReactDOMOption.js +122 -0
- package/lib/shallow/ReactDOMSelect.js +199 -0
- package/lib/shallow/ReactDOMSelection.js +211 -0
- package/lib/shallow/ReactDOMServer.js +25 -0
- package/lib/shallow/ReactDOMTextComponent.js +163 -0
- package/lib/shallow/ReactDOMTextarea.js +159 -0
- package/lib/shallow/ReactDOMTreeTraversal.js +135 -0
- package/lib/shallow/ReactDOMUnknownPropertyHook.js +111 -0
- package/lib/shallow/ReactDebugTool.js +358 -0
- package/lib/shallow/ReactDefaultBatchingStrategy.js +67 -0
- package/lib/shallow/ReactDefaultInjection.js +85 -0
- package/lib/shallow/ReactElementSymbol.js +19 -0
- package/lib/shallow/ReactEmptyComponent.js +29 -0
- package/lib/shallow/ReactErrorUtils.js +75 -0
- package/lib/shallow/ReactEventEmitterMixin.js +32 -0
- package/lib/shallow/ReactEventListener.js +154 -0
- package/lib/shallow/ReactFeatureFlags.js +21 -0
- package/lib/shallow/ReactFiber.js +190 -0
- package/lib/shallow/ReactFiberBeginWork.js +380 -0
- package/lib/shallow/ReactFiberCommitWork.js +78 -0
- package/lib/shallow/ReactFiberCompleteWork.js +208 -0
- package/lib/shallow/ReactFiberReconciler.js +64 -0
- package/lib/shallow/ReactFiberRoot.js +29 -0
- package/lib/shallow/ReactFiberScheduler.js +331 -0
- package/lib/shallow/ReactFiberUpdateQueue.js +77 -0
- package/lib/shallow/ReactHostComponent.js +67 -0
- package/lib/shallow/ReactHostOperationHistoryHook.js +33 -0
- package/lib/shallow/ReactInjection.js +33 -0
- package/lib/shallow/ReactInputSelection.js +123 -0
- package/lib/shallow/ReactInstanceMap.js +47 -0
- package/lib/shallow/ReactInstanceType.js +12 -0
- package/lib/shallow/ReactInstrumentation.js +23 -0
- package/lib/shallow/ReactInvalidSetStateWarningHook.js +36 -0
- package/lib/shallow/ReactMarkupChecksum.js +49 -0
- package/lib/shallow/ReactMount.js +537 -0
- package/lib/shallow/ReactMultiChild.js +449 -0
- package/lib/shallow/ReactMultiChildUpdateTypes.js +18 -0
- package/lib/shallow/ReactNodeTypes.js +39 -0
- package/lib/shallow/ReactOwner.js +93 -0
- package/lib/shallow/ReactPerf.js +500 -0
- package/lib/shallow/ReactPriorityLevel.js +20 -0
- package/lib/shallow/ReactPropTypeLocationNames.js +24 -0
- package/lib/shallow/ReactPropTypeLocations.js +12 -0
- package/lib/shallow/ReactPropTypesSecret.js +16 -0
- package/lib/shallow/ReactReconcileTransaction.js +177 -0
- package/lib/shallow/ReactReconciler.js +167 -0
- package/lib/shallow/ReactRef.js +88 -0
- package/lib/shallow/ReactReifiedYield.js +30 -0
- package/lib/shallow/ReactServerBatchingStrategy.js +21 -0
- package/lib/shallow/ReactServerRendering.js +89 -0
- package/lib/shallow/ReactServerRenderingTransaction.js +89 -0
- package/lib/shallow/ReactServerUpdateQueue.js +138 -0
- package/lib/shallow/ReactShallowRenderer.js +150 -0
- package/lib/shallow/ReactSimpleEmptyComponent.js +36 -0
- package/lib/shallow/ReactSyntheticEventType.js +14 -0
- package/lib/shallow/ReactTestEmptyComponent.js +36 -0
- package/lib/shallow/ReactTestMount.js +131 -0
- package/lib/shallow/ReactTestReconcileTransaction.js +128 -0
- package/lib/shallow/ReactTestRenderer.js +139 -0
- package/lib/shallow/ReactTestTextComponent.js +40 -0
- package/lib/shallow/ReactTypeOfWork.js +23 -0
- package/lib/shallow/ReactTypes.js +12 -0
- package/lib/shallow/ReactUpdateQueue.js +235 -0
- package/lib/shallow/ReactUpdates.js +250 -0
- package/lib/shallow/ReactVersion.js +13 -0
- package/lib/shallow/ResponderEventPlugin.js +507 -0
- package/lib/shallow/ResponderSyntheticEvent.js +38 -0
- package/lib/shallow/ResponderTouchHistoryStore.js +183 -0
- package/lib/shallow/SVGDOMPropertyConfig.js +301 -0
- package/lib/shallow/SelectEventPlugin.js +190 -0
- package/lib/shallow/SimpleEventPlugin.js +227 -0
- package/lib/shallow/SyntheticAnimationEvent.js +38 -0
- package/lib/shallow/SyntheticClipboardEvent.js +37 -0
- package/lib/shallow/SyntheticCompositionEvent.js +35 -0
- package/lib/shallow/SyntheticDragEvent.js +35 -0
- package/lib/shallow/SyntheticEvent.js +267 -0
- package/lib/shallow/SyntheticFocusEvent.js +35 -0
- package/lib/shallow/SyntheticInputEvent.js +36 -0
- package/lib/shallow/SyntheticKeyboardEvent.js +83 -0
- package/lib/shallow/SyntheticMouseEvent.js +71 -0
- package/lib/shallow/SyntheticTouchEvent.js +44 -0
- package/lib/shallow/SyntheticTransitionEvent.js +38 -0
- package/lib/shallow/SyntheticUIEvent.js +58 -0
- package/lib/shallow/SyntheticWheelEvent.js +53 -0
- package/lib/shallow/TapEventPlugin.js +115 -0
- package/lib/shallow/TouchHistoryMath.js +98 -0
- package/lib/shallow/Transaction.js +224 -0
- package/lib/shallow/ViewportMetrics.js +26 -0
- package/lib/shallow/accumulate.js +45 -0
- package/lib/shallow/accumulateInto.js +57 -0
- package/lib/shallow/adler32.js +43 -0
- package/lib/shallow/canDefineProperty.js +25 -0
- package/lib/shallow/checkReactTypeSpec.js +86 -0
- package/lib/shallow/createMicrosoftUnsafeLocalFunction.js +31 -0
- package/lib/shallow/dangerousStyleValue.js +78 -0
- package/lib/shallow/deprecated.js +56 -0
- package/lib/shallow/escapeTextContentForBrowser.js +122 -0
- package/lib/shallow/findDOMNode.js +59 -0
- package/lib/shallow/flattenChildren.js +75 -0
- package/lib/shallow/forEachAccumulated.js +30 -0
- package/lib/shallow/getEventCharCode.js +49 -0
- package/lib/shallow/getEventKey.js +101 -0
- package/lib/shallow/getEventModifierState.js +42 -0
- package/lib/shallow/getEventTarget.js +34 -0
- package/lib/shallow/getHostComponentFromComposite.js +29 -0
- package/lib/shallow/getIteratorFn.js +40 -0
- package/lib/shallow/getNodeForCharacterOffset.js +73 -0
- package/lib/shallow/getTextContentAccessor.js +32 -0
- package/lib/shallow/getVendorPrefixedEventName.js +100 -0
- package/lib/shallow/instantiateReactComponent.js +128 -0
- package/lib/shallow/isEventSupported.js +59 -0
- package/lib/shallow/isTextInputElement.js +50 -0
- package/lib/shallow/quoteAttributeValueForBrowser.js +25 -0
- package/lib/shallow/reactProdInvariant.js +38 -0
- package/lib/shallow/renderSubtreeIntoContainer.js +15 -0
- package/lib/shallow/setInnerHTML.js +97 -0
- package/lib/shallow/setTextContent.js +51 -0
- package/lib/shallow/shouldUpdateReactComponent.js +41 -0
- package/lib/shallow/traverseAllChildren.js +175 -0
- package/lib/shallow/validateDOMNesting.js +376 -0
- package/package.json +1 -1
- package/shallow.js +1 -1
|
@@ -0,0 +1,175 @@
|
|
|
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
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
var _prodInvariant = require('./reactProdInvariant');
|
|
14
|
+
|
|
15
|
+
var ReactCurrentOwner = require('react/lib/ReactCurrentOwner');
|
|
16
|
+
var REACT_ELEMENT_TYPE = require('./ReactElementSymbol');
|
|
17
|
+
|
|
18
|
+
var getIteratorFn = require('./getIteratorFn');
|
|
19
|
+
var invariant = require('fbjs/lib/invariant');
|
|
20
|
+
var KeyEscapeUtils = require('./KeyEscapeUtils');
|
|
21
|
+
var warning = require('fbjs/lib/warning');
|
|
22
|
+
|
|
23
|
+
var SEPARATOR = '.';
|
|
24
|
+
var SUBSEPARATOR = ':';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* This is inlined from ReactElement since this file is shared between
|
|
28
|
+
* isomorphic and renderers. We could extract this to a
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* TODO: Test that a single child and an array with one item have the same key
|
|
34
|
+
* pattern.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
var didWarnAboutMaps = false;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generate a key string that identifies a component within a set.
|
|
41
|
+
*
|
|
42
|
+
* @param {*} component A component that could contain a manual key.
|
|
43
|
+
* @param {number} index Index that is used if a manual key is not provided.
|
|
44
|
+
* @return {string}
|
|
45
|
+
*/
|
|
46
|
+
function getComponentKey(component, index) {
|
|
47
|
+
// Do some typechecking here since we call this blindly. We want to ensure
|
|
48
|
+
// that we don't block potential future ES APIs.
|
|
49
|
+
if (component && typeof component === 'object' && component.key != null) {
|
|
50
|
+
// Explicit key
|
|
51
|
+
return KeyEscapeUtils.escape(component.key);
|
|
52
|
+
}
|
|
53
|
+
// Implicit key determined by the index in the set
|
|
54
|
+
return index.toString(36);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {?*} children Children tree container.
|
|
59
|
+
* @param {!string} nameSoFar Name of the key path so far.
|
|
60
|
+
* @param {!function} callback Callback to invoke with each child found.
|
|
61
|
+
* @param {?*} traverseContext Used to pass information throughout the traversal
|
|
62
|
+
* process.
|
|
63
|
+
* @return {!number} The number of children in this subtree.
|
|
64
|
+
*/
|
|
65
|
+
function traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {
|
|
66
|
+
var type = typeof children;
|
|
67
|
+
|
|
68
|
+
if (type === 'undefined' || type === 'boolean') {
|
|
69
|
+
// All of the above are perceived as null.
|
|
70
|
+
children = null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (children === null || type === 'string' || type === 'number' ||
|
|
74
|
+
// The following is inlined from ReactElement. This means we can optimize
|
|
75
|
+
// some checks. React Fiber also inlines this logic for similar purposes.
|
|
76
|
+
type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE) {
|
|
77
|
+
callback(traverseContext, children,
|
|
78
|
+
// If it's the only child, treat the name as if it was wrapped in an array
|
|
79
|
+
// so that it's consistent if the number of children grows.
|
|
80
|
+
nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);
|
|
81
|
+
return 1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
var child;
|
|
85
|
+
var nextName;
|
|
86
|
+
var subtreeCount = 0; // Count of children found in the current subtree.
|
|
87
|
+
var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;
|
|
88
|
+
|
|
89
|
+
if (Array.isArray(children)) {
|
|
90
|
+
for (var i = 0; i < children.length; i++) {
|
|
91
|
+
child = children[i];
|
|
92
|
+
nextName = nextNamePrefix + getComponentKey(child, i);
|
|
93
|
+
subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
var iteratorFn = getIteratorFn(children);
|
|
97
|
+
if (iteratorFn) {
|
|
98
|
+
var iterator = iteratorFn.call(children);
|
|
99
|
+
var step;
|
|
100
|
+
if (iteratorFn !== children.entries) {
|
|
101
|
+
var ii = 0;
|
|
102
|
+
while (!(step = iterator.next()).done) {
|
|
103
|
+
child = step.value;
|
|
104
|
+
nextName = nextNamePrefix + getComponentKey(child, ii++);
|
|
105
|
+
subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
109
|
+
var mapsAsChildrenAddendum = '';
|
|
110
|
+
if (ReactCurrentOwner.current) {
|
|
111
|
+
var mapsAsChildrenOwnerName = ReactCurrentOwner.current.getName();
|
|
112
|
+
if (mapsAsChildrenOwnerName) {
|
|
113
|
+
mapsAsChildrenAddendum = ' Check the render method of `' + mapsAsChildrenOwnerName + '`.';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
process.env.NODE_ENV !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.%s', mapsAsChildrenAddendum) : void 0;
|
|
117
|
+
didWarnAboutMaps = true;
|
|
118
|
+
}
|
|
119
|
+
// Iterator will provide entry [k,v] tuples rather than values.
|
|
120
|
+
while (!(step = iterator.next()).done) {
|
|
121
|
+
var entry = step.value;
|
|
122
|
+
if (entry) {
|
|
123
|
+
child = entry[1];
|
|
124
|
+
nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);
|
|
125
|
+
subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} else if (type === 'object') {
|
|
130
|
+
var addendum = '';
|
|
131
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
132
|
+
addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';
|
|
133
|
+
if (children._isReactElement) {
|
|
134
|
+
addendum = ' It looks like you\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.';
|
|
135
|
+
}
|
|
136
|
+
if (ReactCurrentOwner.current) {
|
|
137
|
+
var name = ReactCurrentOwner.current.getName();
|
|
138
|
+
if (name) {
|
|
139
|
+
addendum += ' Check the render method of `' + name + '`.';
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
var childrenString = String(children);
|
|
144
|
+
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return subtreeCount;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Traverses children that are typically specified as `props.children`, but
|
|
153
|
+
* might also be specified through attributes:
|
|
154
|
+
*
|
|
155
|
+
* - `traverseAllChildren(this.props.children, ...)`
|
|
156
|
+
* - `traverseAllChildren(this.props.leftPanelChildren, ...)`
|
|
157
|
+
*
|
|
158
|
+
* The `traverseContext` is an optional argument that is passed through the
|
|
159
|
+
* entire traversal. It can be used to store accumulations or anything else that
|
|
160
|
+
* the callback might find relevant.
|
|
161
|
+
*
|
|
162
|
+
* @param {?*} children Children tree object.
|
|
163
|
+
* @param {!function} callback To invoke upon traversing each child.
|
|
164
|
+
* @param {?*} traverseContext Context for traversal.
|
|
165
|
+
* @return {!number} The number of children in this subtree.
|
|
166
|
+
*/
|
|
167
|
+
function traverseAllChildren(children, callback, traverseContext) {
|
|
168
|
+
if (children == null) {
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return traverseAllChildrenImpl(children, '', callback, traverseContext);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = traverseAllChildren;
|
|
@@ -0,0 +1,376 @@
|
|
|
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
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
var _assign = require('object-assign');
|
|
14
|
+
|
|
15
|
+
var emptyFunction = require('fbjs/lib/emptyFunction');
|
|
16
|
+
var warning = require('fbjs/lib/warning');
|
|
17
|
+
|
|
18
|
+
var validateDOMNesting = emptyFunction;
|
|
19
|
+
|
|
20
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
21
|
+
// This validation code was written based on the HTML5 parsing spec:
|
|
22
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
|
23
|
+
//
|
|
24
|
+
// Note: this does not catch all invalid nesting, nor does it try to (as it's
|
|
25
|
+
// not clear what practical benefit doing so provides); instead, we warn only
|
|
26
|
+
// for cases where the parser will give a parse tree differing from what React
|
|
27
|
+
// intended. For example, <b><div></div></b> is invalid but we don't warn
|
|
28
|
+
// because it still parses correctly; we do warn for other cases like nested
|
|
29
|
+
// <p> tags where the beginning of the second element implicitly closes the
|
|
30
|
+
// first, causing a confusing mess.
|
|
31
|
+
|
|
32
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#special
|
|
33
|
+
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'];
|
|
34
|
+
|
|
35
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
|
|
36
|
+
var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
|
|
37
|
+
|
|
38
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
|
|
39
|
+
// TODO: Distinguish by namespace here -- for <title>, including it here
|
|
40
|
+
// errs on the side of fewer warnings
|
|
41
|
+
'foreignObject', 'desc', 'title'];
|
|
42
|
+
|
|
43
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
|
|
44
|
+
var buttonScopeTags = inScopeTags.concat(['button']);
|
|
45
|
+
|
|
46
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
|
|
47
|
+
var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
|
|
48
|
+
|
|
49
|
+
var emptyAncestorInfo = {
|
|
50
|
+
current: null,
|
|
51
|
+
|
|
52
|
+
formTag: null,
|
|
53
|
+
aTagInScope: null,
|
|
54
|
+
buttonTagInScope: null,
|
|
55
|
+
nobrTagInScope: null,
|
|
56
|
+
pTagInButtonScope: null,
|
|
57
|
+
|
|
58
|
+
listItemTagAutoclosing: null,
|
|
59
|
+
dlItemTagAutoclosing: null
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
var updatedAncestorInfo = function (oldInfo, tag, instance) {
|
|
63
|
+
var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
|
|
64
|
+
var info = { tag: tag, instance: instance };
|
|
65
|
+
|
|
66
|
+
if (inScopeTags.indexOf(tag) !== -1) {
|
|
67
|
+
ancestorInfo.aTagInScope = null;
|
|
68
|
+
ancestorInfo.buttonTagInScope = null;
|
|
69
|
+
ancestorInfo.nobrTagInScope = null;
|
|
70
|
+
}
|
|
71
|
+
if (buttonScopeTags.indexOf(tag) !== -1) {
|
|
72
|
+
ancestorInfo.pTagInButtonScope = null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// See rules for 'li', 'dd', 'dt' start tags in
|
|
76
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
|
|
77
|
+
if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
|
|
78
|
+
ancestorInfo.listItemTagAutoclosing = null;
|
|
79
|
+
ancestorInfo.dlItemTagAutoclosing = null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
ancestorInfo.current = info;
|
|
83
|
+
|
|
84
|
+
if (tag === 'form') {
|
|
85
|
+
ancestorInfo.formTag = info;
|
|
86
|
+
}
|
|
87
|
+
if (tag === 'a') {
|
|
88
|
+
ancestorInfo.aTagInScope = info;
|
|
89
|
+
}
|
|
90
|
+
if (tag === 'button') {
|
|
91
|
+
ancestorInfo.buttonTagInScope = info;
|
|
92
|
+
}
|
|
93
|
+
if (tag === 'nobr') {
|
|
94
|
+
ancestorInfo.nobrTagInScope = info;
|
|
95
|
+
}
|
|
96
|
+
if (tag === 'p') {
|
|
97
|
+
ancestorInfo.pTagInButtonScope = info;
|
|
98
|
+
}
|
|
99
|
+
if (tag === 'li') {
|
|
100
|
+
ancestorInfo.listItemTagAutoclosing = info;
|
|
101
|
+
}
|
|
102
|
+
if (tag === 'dd' || tag === 'dt') {
|
|
103
|
+
ancestorInfo.dlItemTagAutoclosing = info;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return ancestorInfo;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Returns whether
|
|
111
|
+
*/
|
|
112
|
+
var isTagValidWithParent = function (tag, parentTag) {
|
|
113
|
+
// First, let's check if we're in an unusual parsing mode...
|
|
114
|
+
switch (parentTag) {
|
|
115
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
|
|
116
|
+
case 'select':
|
|
117
|
+
return tag === 'option' || tag === 'optgroup' || tag === '#text';
|
|
118
|
+
case 'optgroup':
|
|
119
|
+
return tag === 'option' || tag === '#text';
|
|
120
|
+
// Strictly speaking, seeing an <option> doesn't mean we're in a <select>
|
|
121
|
+
// but
|
|
122
|
+
case 'option':
|
|
123
|
+
return tag === '#text';
|
|
124
|
+
|
|
125
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
|
|
126
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
|
|
127
|
+
// No special behavior since these rules fall back to "in body" mode for
|
|
128
|
+
// all except special table nodes which cause bad parsing behavior anyway.
|
|
129
|
+
|
|
130
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
|
|
131
|
+
case 'tr':
|
|
132
|
+
return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
133
|
+
|
|
134
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
|
|
135
|
+
case 'tbody':
|
|
136
|
+
case 'thead':
|
|
137
|
+
case 'tfoot':
|
|
138
|
+
return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
139
|
+
|
|
140
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
|
|
141
|
+
case 'colgroup':
|
|
142
|
+
return tag === 'col' || tag === 'template';
|
|
143
|
+
|
|
144
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
|
|
145
|
+
case 'table':
|
|
146
|
+
return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
147
|
+
|
|
148
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
|
|
149
|
+
case 'head':
|
|
150
|
+
return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
|
|
151
|
+
|
|
152
|
+
// https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
|
|
153
|
+
case 'html':
|
|
154
|
+
return tag === 'head' || tag === 'body';
|
|
155
|
+
case '#document':
|
|
156
|
+
return tag === 'html';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Probably in the "in body" parsing mode, so we outlaw only tag combos
|
|
160
|
+
// where the parsing rules cause implicit opens or closes to be added.
|
|
161
|
+
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
|
|
162
|
+
switch (tag) {
|
|
163
|
+
case 'h1':
|
|
164
|
+
case 'h2':
|
|
165
|
+
case 'h3':
|
|
166
|
+
case 'h4':
|
|
167
|
+
case 'h5':
|
|
168
|
+
case 'h6':
|
|
169
|
+
return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
|
|
170
|
+
|
|
171
|
+
case 'rp':
|
|
172
|
+
case 'rt':
|
|
173
|
+
return impliedEndTags.indexOf(parentTag) === -1;
|
|
174
|
+
|
|
175
|
+
case 'body':
|
|
176
|
+
case 'caption':
|
|
177
|
+
case 'col':
|
|
178
|
+
case 'colgroup':
|
|
179
|
+
case 'frame':
|
|
180
|
+
case 'head':
|
|
181
|
+
case 'html':
|
|
182
|
+
case 'tbody':
|
|
183
|
+
case 'td':
|
|
184
|
+
case 'tfoot':
|
|
185
|
+
case 'th':
|
|
186
|
+
case 'thead':
|
|
187
|
+
case 'tr':
|
|
188
|
+
// These tags are only valid with a few parents that have special child
|
|
189
|
+
// parsing rules -- if we're down here, then none of those matched and
|
|
190
|
+
// so we allow it only if we don't know what the parent is, as all other
|
|
191
|
+
// cases are invalid.
|
|
192
|
+
return parentTag == null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return true;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Returns whether
|
|
200
|
+
*/
|
|
201
|
+
var findInvalidAncestorForTag = function (tag, ancestorInfo) {
|
|
202
|
+
switch (tag) {
|
|
203
|
+
case 'address':
|
|
204
|
+
case 'article':
|
|
205
|
+
case 'aside':
|
|
206
|
+
case 'blockquote':
|
|
207
|
+
case 'center':
|
|
208
|
+
case 'details':
|
|
209
|
+
case 'dialog':
|
|
210
|
+
case 'dir':
|
|
211
|
+
case 'div':
|
|
212
|
+
case 'dl':
|
|
213
|
+
case 'fieldset':
|
|
214
|
+
case 'figcaption':
|
|
215
|
+
case 'figure':
|
|
216
|
+
case 'footer':
|
|
217
|
+
case 'header':
|
|
218
|
+
case 'hgroup':
|
|
219
|
+
case 'main':
|
|
220
|
+
case 'menu':
|
|
221
|
+
case 'nav':
|
|
222
|
+
case 'ol':
|
|
223
|
+
case 'p':
|
|
224
|
+
case 'section':
|
|
225
|
+
case 'summary':
|
|
226
|
+
case 'ul':
|
|
227
|
+
case 'pre':
|
|
228
|
+
case 'listing':
|
|
229
|
+
case 'table':
|
|
230
|
+
case 'hr':
|
|
231
|
+
case 'xmp':
|
|
232
|
+
case 'h1':
|
|
233
|
+
case 'h2':
|
|
234
|
+
case 'h3':
|
|
235
|
+
case 'h4':
|
|
236
|
+
case 'h5':
|
|
237
|
+
case 'h6':
|
|
238
|
+
return ancestorInfo.pTagInButtonScope;
|
|
239
|
+
|
|
240
|
+
case 'form':
|
|
241
|
+
return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
|
|
242
|
+
|
|
243
|
+
case 'li':
|
|
244
|
+
return ancestorInfo.listItemTagAutoclosing;
|
|
245
|
+
|
|
246
|
+
case 'dd':
|
|
247
|
+
case 'dt':
|
|
248
|
+
return ancestorInfo.dlItemTagAutoclosing;
|
|
249
|
+
|
|
250
|
+
case 'button':
|
|
251
|
+
return ancestorInfo.buttonTagInScope;
|
|
252
|
+
|
|
253
|
+
case 'a':
|
|
254
|
+
// Spec says something about storing a list of markers, but it sounds
|
|
255
|
+
// equivalent to this check.
|
|
256
|
+
return ancestorInfo.aTagInScope;
|
|
257
|
+
|
|
258
|
+
case 'nobr':
|
|
259
|
+
return ancestorInfo.nobrTagInScope;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return null;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Given a ReactCompositeComponent instance, return a list of its recursive
|
|
267
|
+
* owners, starting at the root and ending with the instance itself.
|
|
268
|
+
*/
|
|
269
|
+
var findOwnerStack = function (instance) {
|
|
270
|
+
if (!instance) {
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
var stack = [];
|
|
275
|
+
do {
|
|
276
|
+
stack.push(instance);
|
|
277
|
+
} while (instance = instance._currentElement._owner);
|
|
278
|
+
stack.reverse();
|
|
279
|
+
return stack;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
var didWarn = {};
|
|
283
|
+
|
|
284
|
+
validateDOMNesting = function (childTag, childText, childInstance, ancestorInfo) {
|
|
285
|
+
ancestorInfo = ancestorInfo || emptyAncestorInfo;
|
|
286
|
+
var parentInfo = ancestorInfo.current;
|
|
287
|
+
var parentTag = parentInfo && parentInfo.tag;
|
|
288
|
+
|
|
289
|
+
if (childText != null) {
|
|
290
|
+
process.env.NODE_ENV !== 'production' ? warning(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null') : void 0;
|
|
291
|
+
childTag = '#text';
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
|
|
295
|
+
var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
|
|
296
|
+
var problematic = invalidParent || invalidAncestor;
|
|
297
|
+
|
|
298
|
+
if (problematic) {
|
|
299
|
+
var ancestorTag = problematic.tag;
|
|
300
|
+
var ancestorInstance = problematic.instance;
|
|
301
|
+
|
|
302
|
+
var childOwner = childInstance && childInstance._currentElement._owner;
|
|
303
|
+
var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;
|
|
304
|
+
|
|
305
|
+
var childOwners = findOwnerStack(childOwner);
|
|
306
|
+
var ancestorOwners = findOwnerStack(ancestorOwner);
|
|
307
|
+
|
|
308
|
+
var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
|
|
309
|
+
var i;
|
|
310
|
+
|
|
311
|
+
var deepestCommon = -1;
|
|
312
|
+
for (i = 0; i < minStackLen; i++) {
|
|
313
|
+
if (childOwners[i] === ancestorOwners[i]) {
|
|
314
|
+
deepestCommon = i;
|
|
315
|
+
} else {
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
var UNKNOWN = '(unknown)';
|
|
321
|
+
var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
|
|
322
|
+
return inst.getName() || UNKNOWN;
|
|
323
|
+
});
|
|
324
|
+
var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
|
|
325
|
+
return inst.getName() || UNKNOWN;
|
|
326
|
+
});
|
|
327
|
+
var ownerInfo = [].concat(
|
|
328
|
+
// If the parent and child instances have a common owner ancestor, start
|
|
329
|
+
// with that -- otherwise we just start with the parent's owners.
|
|
330
|
+
deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
|
|
331
|
+
// If we're warning about an invalid (non-parent) ancestry, add '...'
|
|
332
|
+
invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');
|
|
333
|
+
|
|
334
|
+
var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;
|
|
335
|
+
if (didWarn[warnKey]) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
didWarn[warnKey] = true;
|
|
339
|
+
|
|
340
|
+
var tagDisplayName = childTag;
|
|
341
|
+
var whitespaceInfo = '';
|
|
342
|
+
if (childTag === '#text') {
|
|
343
|
+
if (/\S/.test(childText)) {
|
|
344
|
+
tagDisplayName = 'Text nodes';
|
|
345
|
+
} else {
|
|
346
|
+
tagDisplayName = 'Whitespace text nodes';
|
|
347
|
+
whitespaceInfo = ' Make sure you don\'t have any extra whitespace between tags on ' + 'each line of your source code.';
|
|
348
|
+
}
|
|
349
|
+
} else {
|
|
350
|
+
tagDisplayName = '<' + childTag + '>';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (invalidParent) {
|
|
354
|
+
var info = '';
|
|
355
|
+
if (ancestorTag === 'table' && childTag === 'tr') {
|
|
356
|
+
info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
|
|
357
|
+
}
|
|
358
|
+
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;
|
|
359
|
+
} else {
|
|
360
|
+
process.env.NODE_ENV !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;
|
|
366
|
+
|
|
367
|
+
// For testing
|
|
368
|
+
validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
|
|
369
|
+
ancestorInfo = ancestorInfo || emptyAncestorInfo;
|
|
370
|
+
var parentInfo = ancestorInfo.current;
|
|
371
|
+
var parentTag = parentInfo && parentInfo.tag;
|
|
372
|
+
return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
module.exports = validateDOMNesting;
|
package/package.json
CHANGED
package/shallow.js
CHANGED