diff --git a/packages/events/SyntheticEvent.js b/packages/events/SyntheticEvent.js index eeeca14a880b3..a4f6285d96fc7 100644 --- a/packages/events/SyntheticEvent.js +++ b/packages/events/SyntheticEvent.js @@ -70,6 +70,8 @@ function SyntheticEvent( delete this.nativeEvent; delete this.preventDefault; delete this.stopPropagation; + delete this.isDefaultPrevented; + delete this.isPropagationStopped; } this.dispatchConfig = dispatchConfig; @@ -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__) { @@ -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', diff --git a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js index 4e9c8502f46f5..5b1c9e0844002 100644 --- a/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js +++ b/packages/react-dom/src/events/__tests__/SyntheticEvent-test.js @@ -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(
, 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(
, 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) {