diff --git a/scripts/fiber/tests-failing.txt b/scripts/fiber/tests-failing.txt index c5979c37a4..fb1508577d 100644 --- a/scripts/fiber/tests-failing.txt +++ b/scripts/fiber/tests-failing.txt @@ -42,9 +42,6 @@ src/renderers/dom/shared/__tests__/ReactDOMTextComponent-test.js * can reconcile text arbitrarily split into multiple nodes * can reconcile text arbitrarily split into multiple nodes on some substitutions only -src/renderers/dom/shared/__tests__/ReactEventIndependence-test.js -* does not when event fired on unmounted tree - src/renderers/dom/shared/__tests__/ReactEventListener-test.js * should batch between handlers from different roots diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 27de2c82c3..4dfb816a3a 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -640,6 +640,7 @@ src/renderers/dom/shared/__tests__/ReactDOMTextComponent-test.js src/renderers/dom/shared/__tests__/ReactEventIndependence-test.js * does not crash with other react inside * does not crash with other react outside +* does not when event fired on unmounted tree src/renderers/dom/shared/__tests__/ReactEventListener-test.js * should dispatch events from outside React tree diff --git a/src/renderers/dom/shared/ReactEventListener.js b/src/renderers/dom/shared/ReactEventListener.js index d9044a13bf..2856f7de3b 100644 --- a/src/renderers/dom/shared/ReactEventListener.js +++ b/src/renderers/dom/shared/ReactEventListener.js @@ -16,33 +16,38 @@ var ExecutionEnvironment = require('ExecutionEnvironment'); var PooledClass = require('PooledClass'); var ReactDOMComponentTree = require('ReactDOMComponentTree'); var ReactGenericBatching = require('ReactGenericBatching'); +var ReactTypeOfWork = require('ReactTypeOfWork'); var getEventTarget = require('getEventTarget'); var getUnboundedScrollPosition = require('getUnboundedScrollPosition'); +var { HostContainer } = ReactTypeOfWork; + /** * Find the deepest React component completely containing the root of the * passed-in instance (for use when entire React trees are nested within each * other). If React trees are not nested, returns null. */ -function findParent(inst) { +function findRootContainerNode(inst) { // TODO: It may be a good idea to cache this to prevent unnecessary DOM // traversal, but caching is difficult to do correctly without using a // mutation observer to listen for all DOM changes. - var container; if (typeof inst.tag === 'number') { while (inst.return) { inst = inst.return; } - container = inst.stateNode.containerInfo; + if (inst.tag !== HostContainer) { + // This can happen if we're in a detached tree. + return null; + } + return inst.stateNode.containerInfo; } else { while (inst._hostParent) { inst = inst._hostParent; } var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst); - container = rootNode.parentNode; + return rootNode.parentNode; } - return ReactDOMComponentTree.getClosestInstanceFromNode(container); } // Used to store ancestor hierarchy in top level callback @@ -74,8 +79,18 @@ function handleTopLevelImpl(bookKeeping) { // inconsistencies with ReactMount's node cache. See #1105. var ancestor = targetInst; do { + if (!ancestor) { + bookKeeping.ancestors.push(ancestor); + break; + } + var root = findRootContainerNode(ancestor); + if (!root) { + break; + } bookKeeping.ancestors.push(ancestor); - ancestor = ancestor && findParent(ancestor); + ancestor = ReactDOMComponentTree.getClosestInstanceFromNode( + root + ); } while (ancestor); for (var i = 0; i < bookKeeping.ancestors.length; i++) {