Skip to content

Commit

Permalink
Allow simulated native events to propagate
Browse files Browse the repository at this point in the history
fixes facebook#7211 fixes facebook#6822 fixes facebook#6614

we should make sure it doesn't break facebook#3926 any worse (or works with facebook#8438)
  • Loading branch information
jquense committed Dec 14, 2016
1 parent d186af8 commit ff73f69
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 21 deletions.
30 changes: 20 additions & 10 deletions src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,14 @@ function stopWatchingForChangeEventIE8() {
activeElementInst = null;
}

function getInstIfValueChanged(targetInst) {
if (inputValueTracking.updateValueIfChanged(targetInst)) {
function getInstIfValueChanged(targetInst, nativeEvent) {
var updated = inputValueTracking.updateValueIfChanged(targetInst);
var simulated = (
nativeEvent.simulated === true &&
ChangeEventPlugin._allowSimulatedPassThrough
);

if (updated || simulated) {
return targetInst;
}
}
Expand Down Expand Up @@ -198,7 +204,7 @@ function handlePropertyChange(nativeEvent) {
if (nativeEvent.propertyName !== 'value') {
return;
}
if (getInstIfValueChanged(activeElementInst)) {
if (getInstIfValueChanged(activeElementInst, nativeEvent)) {
manualDispatchChangeEvent(nativeEvent);
}
}
Expand Down Expand Up @@ -233,7 +239,8 @@ function handleEventsForInputEventPolyfill(
// For IE8 and IE9.
function getTargetInstForInputEventPolyfill(
topLevelType,
targetInst
targetInst,
nativeEvent
) {
if (topLevelType === 'topSelectionChange' ||
topLevelType === 'topKeyUp' ||
Expand All @@ -248,7 +255,7 @@ function getTargetInstForInputEventPolyfill(
// keystroke if user does a key repeat (it'll be a little delayed: right
// before the second keystroke). Other input methods (e.g., paste) seem to
// fire selectionchange normally.
return getInstIfValueChanged(activeElementInst);
return getInstIfValueChanged(activeElementInst, nativeEvent);
}
}

Expand All @@ -269,23 +276,25 @@ function shouldUseClickEvent(elem) {

function getTargetInstForClickEvent(
topLevelType,
targetInst
targetInst,
nativeEvent
) {

if (topLevelType === 'topClick') {
return getInstIfValueChanged(targetInst);
return getInstIfValueChanged(targetInst, nativeEvent);
}
}

function getTargetInstForInputOrChangeEvent(
topLevelType,
targetInst
targetInst,
nativeEvent
) {
if (
topLevelType === 'topInput' ||
topLevelType === 'topChange'
) {
return getInstIfValueChanged(targetInst);
return getInstIfValueChanged(targetInst, nativeEvent);
}
}

Expand All @@ -303,6 +312,7 @@ var ChangeEventPlugin = {

eventTypes: eventTypes,

_allowSimulatedPassThrough: true,
_isInputEventSupported: isInputEventSupported,

extractEvents: function(
Expand Down Expand Up @@ -333,7 +343,7 @@ var ChangeEventPlugin = {
}

if (getTargetInstFunc) {
var inst = getTargetInstFunc(topLevelType, targetInst);
var inst = getTargetInstFunc(topLevelType, targetInst, nativeEvent);
if (inst) {
var event = createAndAccumulateChangeEvent(
inst,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ function setUntrackedValue(elem, value) {
}

describe('ChangeEventPlugin', () => {
beforeEach(() => {
ChangeEventPlugin._allowSimulatedPassThrough = false;
});

afterEach(() => {
ChangeEventPlugin._allowSimulatedPassThrough = true;
});

it('should fire change for checkbox input', () => {
var called = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@ describe('ReactDOMInput', () => {
var ReactDOMFeatureFlags;
var ReactLink;
var ReactTestUtils;
var inputValueTracking;

function setUntrackedValue(elem, value) {
var tracker = inputValueTracking._getTrackerFromNode(elem);
var current = tracker.getValue();
elem.value = value;
tracker.setValue(current);
}

beforeEach(() => {
jest.resetModuleRegistry();
Expand All @@ -38,7 +31,6 @@ describe('ReactDOMInput', () => {
ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
ReactLink = require('ReactLink');
ReactTestUtils = require('ReactTestUtils');
inputValueTracking = require('inputValueTracking');
spyOn(console, 'error');
});

Expand Down Expand Up @@ -265,7 +257,7 @@ describe('ReactDOMInput', () => {
var container = document.createElement('div');
var node = ReactDOM.render(stub, container);

setUntrackedValue(node, 'giraffe');
node.value = 'giraffe';

var fakeNativeEvent = new function() {};
fakeNativeEvent.target = node;
Expand Down
4 changes: 2 additions & 2 deletions src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ describe('ReactDOMComponent', () => {

ReactDOM.unmountComponentAtNode(container);

expect(tracker.stopTracking.calls.length).toBe(1);
expect(tracker.stopTracking.calls.count()).toBe(1);
});

it('should clean up input textarea tracking', function() {
Expand All @@ -1166,7 +1166,7 @@ describe('ReactDOMComponent', () => {

ReactDOM.unmountComponentAtNode(container);

expect(tracker.stopTracking.calls.length).toBe(1);
expect(tracker.stopTracking.calls.count()).toBe(1);
});

it('unmounts children before unsetting DOM node info', function() {
Expand Down
1 change: 1 addition & 0 deletions src/test/ReactTestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ var ReactTestUtils = {
*/
simulateNativeEventOnNode: function(topLevelType, node, fakeNativeEvent) {
fakeNativeEvent.target = node;
fakeNativeEvent.simulated = true;
ReactBrowserEventEmitter.ReactEventListener.dispatchEvent(
topLevelType,
fakeNativeEvent
Expand Down

0 comments on commit ff73f69

Please sign in to comment.