@samitouri / QOS-React-2 / commits / 8ce7b7120c

ReactMount now never expects invalid nodes in its cache

It never really made sense for us to have "invalid" nodes in the cache -- when we unmount things, we should always remove them from the cache properly. Now that swapping composite types doesn't repopulate the cache, we should be okay to now assume that everything in the cache is good.

Ben Alpert committed Sep 26, 2015 at 15:11 UTC 8ce7b7120cff9f46237fef73120c9ddca25e30fc
1 file changed +34 -24
src/renderers/dom/client/ReactMount.js
+34 -24
@@ -100,7 +100,7 @@ function getReactRootElementInContainer(container) {
100 */
101 function getReactRootID(container) {
102 var rootElement = getReactRootElementInContainer(container);
103 - return rootElement && ReactMount.getID(rootElement);
103 + return rootElement && internalGetID(rootElement);
104 }
105
106 /**
@@ -116,20 +116,12 @@ function getReactRootID(container) {
116 function getID(node) {
117 var id = internalGetID(node);
118 if (id) {
119 - if (nodeCache.hasOwnProperty(id)) {
120 - var cached = nodeCache[id];
121 - if (cached !== node) {
122 - invariant(
123 - !isValid(cached, id),
124 - 'ReactMount: Two valid but unequal nodes with the same `%s`: %s',
125 - ATTR_NAME, id
126 - );
127 -
128 - nodeCache[id] = node;
129 - }
130 - } else {
131 - nodeCache[id] = node;
132 - }
119 + invariant(
120 + !nodeCache.hasOwnProperty(id) || nodeCache[id] === node,
121 + 'ReactMount: Two unequal nodes with the same `%s`: %s',
122 + ATTR_NAME, id
123 + );
124 + nodeCache[id] = node;
125 }
126
127 return id;
@@ -157,6 +149,25 @@ function setID(node, id) {
149 nodeCache[id] = node;
150 }
151
152 +/**
153 + * Finds the node with the supplied ID if present in the cache.
154 + */
155 +function getNodeIfCached(id) {
156 + var node = nodeCache[id];
157 + // TODO: Since this "isValid" business is now just a sanity check, we can
158 + // probably drop it with no consequences.
159 + invariant(
160 + !node || isValid(node, id),
161 + 'ReactMount: Cached node with `%s`: %s is missing from the document. ' +
162 + 'This probably means the DOM was unexpectedly mutated -- when removing ' +
163 + 'React-rendered children from the DOM, rerender without those children ' +
164 + 'or call ReactDOM.unmountComponentAtNode on the container to unmount an ' +
165 + 'entire subtree.',
166 + ATTR_NAME, id
167 + );
168 + return node;
169 +}
170 +
171 /**
172 * Finds the node with the supplied React-generated DOM ID.
173 *
@@ -165,10 +176,12 @@ function setID(node, id) {
176 * @internal
177 */
178 function getNode(id) {
168 - if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) {
169 - nodeCache[id] = ReactMount.findReactNodeByID(id);
179 + var node = getNodeIfCached(id);
180 + if (node) {
181 + return node;
182 + } else {
183 + return nodeCache[id] = ReactMount.findReactNodeByID(id);
184 }
171 - return nodeCache[id];
185 }
186
187 /**
@@ -183,10 +196,7 @@ function getNodeFromInstance(instance) {
196 if (ReactEmptyComponentRegistry.isNullComponentID(id)) {
197 return null;
198 }
186 - if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) {
187 - nodeCache[id] = ReactMount.findReactNodeByID(id);
188 - }
189 - return nodeCache[id];
199 + return getNode(id);
200 }
201
202 /**
@@ -227,8 +237,8 @@ function purgeID(id) {
237
238 var deepestNodeSoFar = null;
239 function findDeepestCachedAncestorImpl(ancestorID) {
230 - var ancestor = nodeCache[ancestorID];
231 - if (ancestor && isValid(ancestor, ancestorID)) {
240 + var ancestor = getNodeIfCached(ancestorID);
241 + if (ancestor) {
242 deepestNodeSoFar = ancestor;
243 } else {
244 // This node isn't populated in the cache, so presumably none of its