Skip to content

Commit 5c13e2e

Browse files
authored
Remove Stack (part 4: remove Stack-only branches and types) (#10798)
* Remove findDOMNode injection and inline it * Remove Stack-only code in ReactGenericBatching * Remove Stack-only code branches
1 parent df44527 commit 5c13e2e

30 files changed

+195
-799
lines changed

src/isomorphic/classic/element/ReactCurrentOwner.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
'use strict';
1212

13-
import type {ReactInstance} from 'ReactInstanceType';
1413
import type {Fiber} from 'ReactFiber';
1514

1615
/**
@@ -24,7 +23,7 @@ var ReactCurrentOwner = {
2423
* @internal
2524
* @type {ReactComponent}
2625
*/
27-
current: (null: null | ReactInstance | Fiber),
26+
current: (null: null | Fiber),
2827
};
2928

3029
module.exports = ReactCurrentOwner;

src/renderers/dom/fiber/ReactDOMFiberEntry.js

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
'use strict';
1212

13-
import type {Fiber} from 'ReactFiber';
1413
import type {ReactNodeList} from 'ReactTypes';
1514

1615
require('checkReact');
@@ -28,6 +27,7 @@ var ReactInputSelection = require('ReactInputSelection');
2827
var ReactInstanceMap = require('ReactInstanceMap');
2928
var ReactPortal = require('ReactPortal');
3029
var ReactVersion = require('ReactVersion');
30+
var {ReactCurrentOwner} = require('ReactGlobalSharedState');
3131
var {injectInternals} = require('ReactFiberDevToolsHook');
3232
var {
3333
ELEMENT_NODE,
@@ -38,7 +38,7 @@ var {
3838
} = require('HTMLNodeType');
3939
var {ROOT_ATTRIBUTE_NAME} = require('DOMProperty');
4040

41-
var findDOMNode = require('findDOMNode');
41+
var getComponentName = require('getComponentName');
4242
var invariant = require('fbjs/lib/invariant');
4343

4444
var {getChildNamespace} = DOMNamespaces;
@@ -85,9 +85,6 @@ require('ReactDOMInjection');
8585
ReactControlledComponent.injection.injectFiberControlledHostComponent(
8686
ReactDOMFiberComponent,
8787
);
88-
findDOMNode._injectFiber(function(fiber: Fiber) {
89-
return DOMRenderer.findHostInstance(fiber);
90-
});
9188

9289
type DOMContainer =
9390
| (Element & {
@@ -232,7 +229,7 @@ var DOMRenderer = ReactFiberReconciler({
232229
if (__DEV__) {
233230
// TODO: take namespace into account when validating.
234231
const hostContextDev = ((hostContext: any): HostContextDev);
235-
validateDOMNesting(type, null, null, hostContextDev.ancestorInfo);
232+
validateDOMNesting(type, null, hostContextDev.ancestorInfo);
236233
if (
237234
typeof props.children === 'string' ||
238235
typeof props.children === 'number'
@@ -243,7 +240,7 @@ var DOMRenderer = ReactFiberReconciler({
243240
type,
244241
null,
245242
);
246-
validateDOMNesting(null, string, null, ownAncestorInfo);
243+
validateDOMNesting(null, string, ownAncestorInfo);
247244
}
248245
parentNamespace = hostContextDev.namespace;
249246
} else {
@@ -298,7 +295,7 @@ var DOMRenderer = ReactFiberReconciler({
298295
type,
299296
null,
300297
);
301-
validateDOMNesting(null, string, null, ownAncestorInfo);
298+
validateDOMNesting(null, string, ownAncestorInfo);
302299
}
303300
}
304301
return diffProperties(
@@ -365,7 +362,7 @@ var DOMRenderer = ReactFiberReconciler({
365362
): TextInstance {
366363
if (__DEV__) {
367364
const hostContextDev = ((hostContext: any): HostContextDev);
368-
validateDOMNesting(null, text, null, hostContextDev.ancestorInfo);
365+
validateDOMNesting(null, text, hostContextDev.ancestorInfo);
369366
}
370367
var textNode: TextInstance = createTextNode(text, rootContainerInstance);
371368
precacheFiberNode(internalInstanceHandle, textNode);
@@ -675,6 +672,48 @@ function createPortal(
675672
var ReactDOMFiber = {
676673
createPortal,
677674

675+
findDOMNode(
676+
componentOrElement: Element | ?React$Component<any, any>,
677+
): null | Element | Text {
678+
if (__DEV__) {
679+
var owner = (ReactCurrentOwner.current: any);
680+
if (owner !== null) {
681+
var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
682+
warning(
683+
warnedAboutRefsInRender,
684+
'%s is accessing findDOMNode inside its render(). ' +
685+
'render() should be a pure function of props and state. It should ' +
686+
'never access something that requires stale data from the previous ' +
687+
'render, such as refs. Move this logic to componentDidMount and ' +
688+
'componentDidUpdate instead.',
689+
getComponentName(owner) || 'A component',
690+
);
691+
owner.stateNode._warnedAboutRefsInRender = true;
692+
}
693+
}
694+
if (componentOrElement == null) {
695+
return null;
696+
}
697+
if ((componentOrElement: any).nodeType === ELEMENT_NODE) {
698+
return (componentOrElement: any);
699+
}
700+
701+
var inst = ReactInstanceMap.get(componentOrElement);
702+
if (inst) {
703+
return DOMRenderer.findHostInstance(inst);
704+
}
705+
706+
if (typeof componentOrElement.render === 'function') {
707+
invariant(false, 'Unable to find node on an unmounted component.');
708+
} else {
709+
invariant(
710+
false,
711+
'Element appears to be neither ReactComponent nor DOMNode. Keys: %s',
712+
Object.keys(componentOrElement),
713+
);
714+
}
715+
},
716+
678717
hydrate(element: React$Node, container: DOMContainer, callback: ?Function) {
679718
// TODO: throw or warn if we couldn't hydrate?
680719
return renderSubtreeIntoContainer(null, element, container, true, callback);
@@ -768,8 +807,6 @@ var ReactDOMFiber = {
768807
}
769808
},
770809

771-
findDOMNode: findDOMNode,
772-
773810
// Temporary alias since we already shipped React 16 RC with it.
774811
// TODO: remove in React 17.
775812
unstable_createPortal: createPortal,

src/renderers/dom/shared/ReactDOMComponentFlags.js

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/renderers/dom/shared/ReactDOMComponentTree.js

Lines changed: 2 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -9,116 +9,18 @@
99

1010
'use strict';
1111

12-
var DOMProperty = require('DOMProperty');
13-
var ReactDOMComponentFlags = require('ReactDOMComponentFlags');
1412
var {HostComponent, HostText} = require('ReactTypeOfWork');
15-
var {ELEMENT_NODE, COMMENT_NODE} = require('HTMLNodeType');
1613

1714
var invariant = require('fbjs/lib/invariant');
1815

19-
var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
20-
var Flags = ReactDOMComponentFlags;
21-
2216
var randomKey = Math.random().toString(36).slice(2);
23-
2417
var internalInstanceKey = '__reactInternalInstance$' + randomKey;
25-
2618
var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
2719

28-
/**
29-
* Check if a given node should be cached.
30-
*/
31-
function shouldPrecacheNode(node, nodeID) {
32-
return (
33-
(node.nodeType === ELEMENT_NODE &&
34-
node.getAttribute(ATTR_NAME) === '' + nodeID) ||
35-
(node.nodeType === COMMENT_NODE &&
36-
node.nodeValue === ' react-text: ' + nodeID + ' ') ||
37-
(node.nodeType === COMMENT_NODE &&
38-
node.nodeValue === ' react-empty: ' + nodeID + ' ')
39-
);
40-
}
41-
42-
/**
43-
* Drill down (through composites and empty components) until we get a host or
44-
* host text component.
45-
*
46-
* This is pretty polymorphic but unavoidable with the current structure we have
47-
* for `_renderedChildren`.
48-
*/
49-
function getRenderedHostOrTextFromComponent(component) {
50-
var rendered;
51-
while ((rendered = component._renderedComponent)) {
52-
component = rendered;
53-
}
54-
return component;
55-
}
56-
57-
/**
58-
* Populate `_hostNode` on the rendered host/text component with the given
59-
* DOM node. The passed `inst` can be a composite.
60-
*/
61-
function precacheNode(inst, node) {
62-
var hostInst = getRenderedHostOrTextFromComponent(inst);
63-
hostInst._hostNode = node;
64-
node[internalInstanceKey] = hostInst;
65-
}
66-
6720
function precacheFiberNode(hostInst, node) {
6821
node[internalInstanceKey] = hostInst;
6922
}
7023

71-
function uncacheNode(inst) {
72-
var node = inst._hostNode;
73-
if (node) {
74-
delete node[internalInstanceKey];
75-
inst._hostNode = null;
76-
}
77-
}
78-
79-
/**
80-
* Populate `_hostNode` on each child of `inst`, assuming that the children
81-
* match up with the DOM (element) children of `node`.
82-
*
83-
* We cache entire levels at once to avoid an n^2 problem where we access the
84-
* children of a node sequentially and have to walk from the start to our target
85-
* node every time.
86-
*
87-
* Since we update `_renderedChildren` and the actual DOM at (slightly)
88-
* different times, we could race here and see a newer `_renderedChildren` than
89-
* the DOM nodes we see. To avoid this, ReactMultiChild calls
90-
* `prepareToManageChildren` before we change `_renderedChildren`, at which
91-
* time the container's child nodes are always cached (until it unmounts).
92-
*/
93-
function precacheChildNodes(inst, node) {
94-
if (inst._flags & Flags.hasCachedChildNodes) {
95-
return;
96-
}
97-
var children = inst._renderedChildren;
98-
var childNode = node.firstChild;
99-
outer: for (var name in children) {
100-
if (!children.hasOwnProperty(name)) {
101-
continue;
102-
}
103-
var childInst = children[name];
104-
var childID = getRenderedHostOrTextFromComponent(childInst)._domID;
105-
if (childID === 0) {
106-
// We're currently unmounting this child in ReactMultiChild; skip it.
107-
continue;
108-
}
109-
// We assume the child nodes are in the same order as the child instances.
110-
for (; childNode !== null; childNode = childNode.nextSibling) {
111-
if (shouldPrecacheNode(childNode, childID)) {
112-
precacheNode(childInst, childNode);
113-
continue outer;
114-
}
115-
}
116-
// We reached the end of the DOM children without finding an ID match.
117-
invariant(false, 'Unable to find element with ID %s.', childID);
118-
}
119-
inst._flags |= Flags.hasCachedChildNodes;
120-
}
121-
12224
/**
12325
* Given a DOM node, return the closest ReactDOMComponent or
12426
* ReactDOMTextComponent instance ancestor.
@@ -149,9 +51,6 @@ function getClosestInstanceFromNode(node) {
14951
}
15052
for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
15153
closest = inst;
152-
if (parents.length) {
153-
precacheChildNodes(inst, node);
154-
}
15554
}
15655

15756
return closest;
@@ -166,18 +65,11 @@ function getInstanceFromNode(node) {
16665
if (inst) {
16766
if (inst.tag === HostComponent || inst.tag === HostText) {
16867
return inst;
169-
} else if (inst._hostNode === node) {
170-
return inst;
17168
} else {
17269
return null;
17370
}
17471
}
175-
inst = getClosestInstanceFromNode(node);
176-
if (inst != null && inst._hostNode === node) {
177-
return inst;
178-
} else {
179-
return null;
180-
}
72+
return null;
18173
}
18274

18375
/**
@@ -193,33 +85,7 @@ function getNodeFromInstance(inst) {
19385

19486
// Without this first invariant, passing a non-DOM-component triggers the next
19587
// invariant for a missing parent, which is super confusing.
196-
invariant(
197-
inst._hostNode !== undefined,
198-
'getNodeFromInstance: Invalid argument.',
199-
);
200-
201-
if (inst._hostNode) {
202-
return inst._hostNode;
203-
}
204-
205-
// Walk up the tree until we find an ancestor whose DOM node we have cached.
206-
var parents = [];
207-
while (!inst._hostNode) {
208-
parents.push(inst);
209-
invariant(
210-
inst._hostParent,
211-
'React DOM tree root should always have a node reference.',
212-
);
213-
inst = inst._hostParent;
214-
}
215-
216-
// Now parents contains each ancestor that does *not* have a cached native
217-
// node, and `inst` is the deepest ancestor that does.
218-
for (; parents.length; inst = parents.pop()) {
219-
precacheChildNodes(inst, inst._hostNode);
220-
}
221-
222-
return inst._hostNode;
88+
invariant(false, 'getNodeFromInstance: Invalid argument.');
22389
}
22490

22591
function getFiberCurrentPropsFromNode(node) {
@@ -234,9 +100,6 @@ var ReactDOMComponentTree = {
234100
getClosestInstanceFromNode: getClosestInstanceFromNode,
235101
getInstanceFromNode: getInstanceFromNode,
236102
getNodeFromInstance: getNodeFromInstance,
237-
precacheChildNodes: precacheChildNodes,
238-
precacheNode: precacheNode,
239-
uncacheNode: uncacheNode,
240103
precacheFiberNode: precacheFiberNode,
241104
getFiberCurrentPropsFromNode,
242105
updateFiberProps,

src/renderers/dom/shared/ReactDOMEventListener.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,14 @@ function findRootContainerNode(inst) {
3131
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
3232
// traversal, but caching is difficult to do correctly without using a
3333
// mutation observer to listen for all DOM changes.
34-
if (typeof inst.tag === 'number') {
35-
while (inst.return) {
36-
inst = inst.return;
37-
}
38-
if (inst.tag !== HostRoot) {
39-
// This can happen if we're in a detached tree.
40-
return null;
41-
}
42-
return inst.stateNode.containerInfo;
43-
} else {
44-
while (inst._hostParent) {
45-
inst = inst._hostParent;
46-
}
47-
var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
48-
return rootNode.parentNode;
34+
while (inst.return) {
35+
inst = inst.return;
36+
}
37+
if (inst.tag !== HostRoot) {
38+
// This can happen if we're in a detached tree.
39+
return null;
4940
}
41+
return inst.stateNode.containerInfo;
5042
}
5143

5244
// Used to store ancestor hierarchy in top level callback

src/renderers/dom/shared/ReactDOMFeatureFlags.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
var ReactDOMFeatureFlags = {
1313
fiberAsyncScheduling: false,
14-
useFiber: true,
1514
};
1615

1716
module.exports = ReactDOMFeatureFlags;

0 commit comments

Comments
 (0)