diff --git a/packages/legacy-events/EventBatching.js b/packages/legacy-events/EventBatching.js index bffc978ad6e21..bcdb065a41514 100644 --- a/packages/legacy-events/EventBatching.js +++ b/packages/legacy-events/EventBatching.js @@ -7,6 +7,7 @@ */ import invariant from 'shared/invariant'; +import {enableModernEventSystem} from 'shared/ReactFeatureFlags'; import {rethrowCaughtError} from 'shared/ReactErrorUtils'; import type {ReactSyntheticEvent} from './ReactSyntheticEventType'; @@ -30,8 +31,11 @@ const executeDispatchesAndRelease = function(event: ReactSyntheticEvent) { if (event) { executeDispatchesInOrder(event); - if (!event.isPersistent()) { - event.constructor.release(event); + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + if (!event.isPersistent()) { + event.constructor.release(event); + } } } }; diff --git a/packages/legacy-events/ResponderEventPlugin.js b/packages/legacy-events/ResponderEventPlugin.js index a1e9ae7f0affa..2a9d502882924 100644 --- a/packages/legacy-events/ResponderEventPlugin.js +++ b/packages/legacy-events/ResponderEventPlugin.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +import {enableModernEventSystem} from 'shared/ReactFeatureFlags'; import {getLowestCommonAncestor, isAncestor} from 'shared/ReactTreeTraversal'; import { @@ -378,8 +379,11 @@ function setResponderAndExtractTransfer( accumulateTwoPhaseDispatches(shouldSetEvent); } const wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent); - if (!shouldSetEvent.isPersistent()) { - shouldSetEvent.constructor.release(shouldSetEvent); + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + if (!shouldSetEvent.isPersistent()) { + shouldSetEvent.constructor.release(shouldSetEvent); + } } if (!wantsResponderInst || wantsResponderInst === responderInst) { @@ -409,8 +413,12 @@ function setResponderAndExtractTransfer( const shouldSwitch = !hasDispatches(terminationRequestEvent) || executeDirectDispatch(terminationRequestEvent); - if (!terminationRequestEvent.isPersistent()) { - terminationRequestEvent.constructor.release(terminationRequestEvent); + + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + if (!terminationRequestEvent.isPersistent()) { + terminationRequestEvent.constructor.release(terminationRequestEvent); + } } if (shouldSwitch) { diff --git a/packages/legacy-events/SyntheticEvent.js b/packages/legacy-events/SyntheticEvent.js index ca7a5cf4074f2..50bcc837bfe8b 100644 --- a/packages/legacy-events/SyntheticEvent.js +++ b/packages/legacy-events/SyntheticEvent.js @@ -9,6 +9,8 @@ import invariant from 'shared/invariant'; +import {enableModernEventSystem} from 'shared/ReactFeatureFlags'; + const EVENT_POOL_SIZE = 10; /** @@ -152,7 +154,10 @@ Object.assign(SyntheticEvent.prototype, { * won't be added back into the pool. */ persist: function() { - this.isPersistent = functionThatReturnsTrue; + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + this.isPersistent = functionThatReturnsTrue; + } }, /** @@ -160,63 +165,68 @@ Object.assign(SyntheticEvent.prototype, { * * @return {boolean} True if this should not be released, false otherwise. */ - isPersistent: functionThatReturnsFalse, + isPersistent: enableModernEventSystem + ? functionThatReturnsTrue + : functionThatReturnsFalse, /** * `PooledClass` looks for `destructor` on each instance it releases. */ destructor: function() { - const Interface = this.constructor.Interface; - for (const propName in Interface) { + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + const Interface = this.constructor.Interface; + for (const propName in Interface) { + if (__DEV__) { + Object.defineProperty( + this, + propName, + getPooledWarningPropertyDefinition(propName, Interface[propName]), + ); + } else { + this[propName] = null; + } + } + this.dispatchConfig = null; + this._targetInst = null; + this.nativeEvent = null; + this.isDefaultPrevented = functionThatReturnsFalse; + this.isPropagationStopped = functionThatReturnsFalse; + this._dispatchListeners = null; + this._dispatchInstances = null; if (__DEV__) { Object.defineProperty( this, - propName, - getPooledWarningPropertyDefinition(propName, Interface[propName]), + 'nativeEvent', + getPooledWarningPropertyDefinition('nativeEvent', null), ); - } else { - this[propName] = null; - } - } - this.dispatchConfig = null; - this._targetInst = null; - this.nativeEvent = null; - this.isDefaultPrevented = functionThatReturnsFalse; - this.isPropagationStopped = functionThatReturnsFalse; - this._dispatchListeners = null; - this._dispatchInstances = null; - if (__DEV__) { - Object.defineProperty( - this, - 'nativeEvent', - getPooledWarningPropertyDefinition('nativeEvent', null), - ); - Object.defineProperty( - this, - 'isDefaultPrevented', - getPooledWarningPropertyDefinition( + Object.defineProperty( + this, 'isDefaultPrevented', - functionThatReturnsFalse, - ), - ); - Object.defineProperty( - this, - 'isPropagationStopped', - getPooledWarningPropertyDefinition( + getPooledWarningPropertyDefinition( + 'isDefaultPrevented', + functionThatReturnsFalse, + ), + ); + Object.defineProperty( + this, 'isPropagationStopped', - functionThatReturnsFalse, - ), - ); - Object.defineProperty( - this, - 'preventDefault', - getPooledWarningPropertyDefinition('preventDefault', () => {}), - ); - Object.defineProperty( - this, - 'stopPropagation', - getPooledWarningPropertyDefinition('stopPropagation', () => {}), - ); + getPooledWarningPropertyDefinition( + 'isPropagationStopped', + functionThatReturnsFalse, + ), + ); + Object.defineProperty( + this, + 'preventDefault', + getPooledWarningPropertyDefinition('preventDefault', () => {}), + ); + Object.defineProperty( + this, + 'stopPropagation', + getPooledWarningPropertyDefinition('stopPropagation', () => {}), + ); + } } }, }); @@ -296,18 +306,26 @@ function getPooledWarningPropertyDefinition(propName, getVal) { } } -function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { +function createOrGetPooledEvent( + dispatchConfig, + targetInst, + nativeEvent, + nativeInst, +) { const EventConstructor = this; - if (EventConstructor.eventPool.length) { - const instance = EventConstructor.eventPool.pop(); - EventConstructor.call( - instance, - dispatchConfig, - targetInst, - nativeEvent, - nativeInst, - ); - return instance; + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + if (EventConstructor.eventPool.length) { + const instance = EventConstructor.eventPool.pop(); + EventConstructor.call( + instance, + dispatchConfig, + targetInst, + nativeEvent, + nativeInst, + ); + return instance; + } } return new EventConstructor( dispatchConfig, @@ -318,21 +336,28 @@ function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) { } function releasePooledEvent(event) { - const EventConstructor = this; - invariant( - event instanceof EventConstructor, - 'Trying to release an event instance into a pool of a different type.', - ); - event.destructor(); - if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { - EventConstructor.eventPool.push(event); + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + const EventConstructor = this; + invariant( + event instanceof EventConstructor, + 'Trying to release an event instance into a pool of a different type.', + ); + event.destructor(); + if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) { + EventConstructor.eventPool.push(event); + } } } function addEventPoolingTo(EventConstructor) { - EventConstructor.eventPool = []; - EventConstructor.getPooled = getPooledEvent; - EventConstructor.release = releasePooledEvent; + EventConstructor.getPooled = createOrGetPooledEvent; + + // Modern event system doesn't use pooling. + if (!enableModernEventSystem) { + EventConstructor.eventPool = []; + EventConstructor.release = releasePooledEvent; + } } export default SyntheticEvent; diff --git a/packages/react-dom/src/events/DOMModernPluginEventSystem.js b/packages/react-dom/src/events/DOMModernPluginEventSystem.js index 32c56b15c62fb..075bb6dd3bfea 100644 --- a/packages/react-dom/src/events/DOMModernPluginEventSystem.js +++ b/packages/react-dom/src/events/DOMModernPluginEventSystem.js @@ -132,10 +132,7 @@ function dispatchEventsForPlugins( for (let i = 0; i < syntheticEvents.length; i++) { const syntheticEvent = syntheticEvents[i]; executeDispatchesInOrder(syntheticEvent); - // Release the event from the pool if needed - if (!syntheticEvent.isPersistent()) { - syntheticEvent.constructor.release(syntheticEvent); - } + // This doesn't call release because modern system doesn't use pooling. } } diff --git a/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js b/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js index 009b74ef69bdc..f06f03353c8ab 100644 --- a/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js +++ b/packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js @@ -169,4 +169,25 @@ describe('DOMModernPluginEventSystem', () => { expect(log).toEqual([]); expect(onDivClick).toHaveBeenCalledTimes(0); }); + + it('does not pool events', () => { + const buttonRef = React.createRef(); + const log = []; + const onClick = jest.fn(e => log.push(e)); + + function Test() { + return