From 41e4bfb41a7244adece3ad77e789459876fe0b92 Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Thu, 17 Sep 2015 17:36:11 -0700 Subject: [PATCH 1/2] Don't install npm 3 on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 36b070a99df5d..814850ee9bd01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ before_install: echo "Only docs were updated, stopping build process." exit fi - npm install -g npm + npm install -g npm@latest-2 script: - | if [ "$TEST_TYPE" = build_website ]; then From 45f85a6cc5707cd798aba350ae4f6dbe99ede6dc Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Thu, 17 Sep 2015 17:27:56 -0700 Subject: [PATCH 2/2] Just ignore events on unmounted components Fixes #4865 and also seems to fixes #3790. --- src/renderers/dom/client/ReactMount.js | 11 ++- .../__tests__/ReactEventIndependence-test.js | 70 +++++++++++++++++++ 2 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 src/renderers/dom/client/__tests__/ReactEventIndependence-test.js diff --git a/src/renderers/dom/client/ReactMount.js b/src/renderers/dom/client/ReactMount.js index 875ec61408a7e..899eb879fac9d 100644 --- a/src/renderers/dom/client/ReactMount.js +++ b/src/renderers/dom/client/ReactMount.js @@ -392,12 +392,11 @@ function findFirstReactDOMImpl(node) { do { lastID = internalGetID(current); current = current.parentNode; - invariant( - current != null, - 'findFirstReactDOMImpl(...): Unexpected detached subtree found when ' + - 'traversing DOM from node `%s`.', - nodeID - ); + if (current == null) { + // The passed-in node has been detached from the container it was + // originally rendered into. + return null; + } } while (lastID !== reactRootID); if (current === containersByReactRootID[reactRootID]) { diff --git a/src/renderers/dom/client/__tests__/ReactEventIndependence-test.js b/src/renderers/dom/client/__tests__/ReactEventIndependence-test.js new file mode 100644 index 0000000000000..621118cfd4be3 --- /dev/null +++ b/src/renderers/dom/client/__tests__/ReactEventIndependence-test.js @@ -0,0 +1,70 @@ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @emails react-core + */ + +'use strict'; + +var React; +var ReactDOM; +var ReactTestUtils; + +describe('ReactEventIndependence', function() { + beforeEach(function() { + require('mock-modules').dumpCache(); + + React = require('React'); + ReactDOM = require('ReactDOM'); + ReactTestUtils = require('ReactTestUtils'); + }); + + it('does not crash with other react inside', function() { + var clicks = 0; + var div = ReactTestUtils.renderIntoDocument( +
clicks++} + dangerouslySetInnerHTML={{ + __html: '
', + }} + /> + ); + ReactTestUtils.SimulateNative.click(div.firstChild); + expect(clicks).toBe(1); + }); + + it('does not crash with other react outside', function() { + var clicks = 0; + var outer = document.createElement('div'); + outer.setAttribute('data-reactid', '.z'); + var inner = ReactDOM.render( + , + outer + ); + ReactTestUtils.SimulateNative.click(inner); + expect(clicks).toBe(1); + }); + + it('does not when event fired on unmounted tree', function() { + var clicks = 0; + var container = document.createElement('div'); + var button = ReactDOM.render( + , + container + ); + + // Now we unmount the component, as if caused by a non-React event handler + // for the same click we're about to simulate, like closing a layer: + ReactDOM.unmountComponentAtNode(container); + ReactTestUtils.SimulateNative.click(button); + + // Since the tree is unmounted, we don't dispatch the click event. + expect(clicks).toBe(0); + }); + +});