Skip to content

Commit

Permalink
Fix isDefaultPrevented and isPropagationStopped to not get nulled
Browse files Browse the repository at this point in the history
This was a bug introduced by facebook#5947. It's very confusing that they become nulled while stopPropagation/preventDefault don't.
  • Loading branch information
gaearon committed Jul 17, 2018
1 parent ac71c29 commit 3c97680
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
16 changes: 14 additions & 2 deletions packages/events/SyntheticEvent.js
Expand Up @@ -70,6 +70,8 @@ function SyntheticEvent(
delete this.nativeEvent;
delete this.preventDefault;
delete this.stopPropagation;
delete this.isDefaultPrevented;
delete this.isPropagationStopped;
}

this.dispatchConfig = dispatchConfig;
Expand Down Expand Up @@ -180,8 +182,8 @@ Object.assign(SyntheticEvent.prototype, {
this.dispatchConfig = null;
this._targetInst = null;
this.nativeEvent = null;
this.isDefaultPrevented = null;
this.isPropagationStopped = null;
this.isDefaultPrevented = functionThatReturnsFalse;
this.isPropagationStopped = functionThatReturnsFalse;
this._dispatchListeners = null;
this._dispatchInstances = null;
if (__DEV__) {
Expand All @@ -190,6 +192,16 @@ Object.assign(SyntheticEvent.prototype, {
'nativeEvent',
getPooledWarningPropertyDefinition('nativeEvent', null),
);
Object.defineProperty(
this,
'isDefaultPrevented',
getPooledWarningPropertyDefinition('isDefaultPrevented', functionThatReturnsFalse),
);
Object.defineProperty(
this,
'isPropagationStopped',
getPooledWarningPropertyDefinition('isPropagationStopped', functionThatReturnsFalse),
);
Object.defineProperty(
this,
'preventDefault',
Expand Down
52 changes: 52 additions & 0 deletions packages/react-dom/src/events/__tests__/SyntheticEvent-test.js
Expand Up @@ -249,6 +249,58 @@ describe('SyntheticEvent', () => {
expect(expectedCount).toBe(1);
});

it('should warn when calling `isPropagationStopped` if the synthetic event has not been persisted', () => {
let node;
let expectedCount = 0;
let syntheticEvent;

const eventHandler = e => {
syntheticEvent = e;
expectedCount++;
};
node = ReactDOM.render(<div onClick={eventHandler} />, container);

const event = document.createEvent('Event');
event.initEvent('click', true, true);
node.dispatchEvent(event);

expect(() => expect(syntheticEvent.isPropagationStopped()).toBe(false)).toWarnDev(
'Warning: This synthetic event is reused for performance reasons. If ' +
"you're seeing this, you're accessing the method `isPropagationStopped` on a " +
'released/nullified synthetic event. This is a no-op function. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
{withoutStack: true},
);
expect(expectedCount).toBe(1);
});

it('should warn when calling `isDefaultPrevented` if the synthetic event has not been persisted', () => {
let node;
let expectedCount = 0;
let syntheticEvent;

const eventHandler = e => {
syntheticEvent = e;
expectedCount++;
};
node = ReactDOM.render(<div onClick={eventHandler} />, container);

const event = document.createEvent('Event');
event.initEvent('click', true, true);
node.dispatchEvent(event);

expect(() => expect(syntheticEvent.isDefaultPrevented()).toBe(false)).toWarnDev(
'Warning: This synthetic event is reused for performance reasons. If ' +
"you're seeing this, you're accessing the method `isDefaultPrevented` on a " +
'released/nullified synthetic event. This is a no-op function. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
{withoutStack: true},
);
expect(expectedCount).toBe(1);
});

it('should properly log warnings when events simulated with rendered components', () => {
let event;
function assignEvent(e) {
Expand Down

0 comments on commit 3c97680

Please sign in to comment.