Remove event pooling in the modern system (#18969)
Dominic Gannaway committed
May 21, 2020 at 13:54 UTC
4a3f779d67d7d7f69cb2340c788826b86b34ce05
7 files changed
+412
-361
packages/legacy-events/SyntheticEvent.js
+92
-71
@@ -157,7 +157,10 @@ Object.assign(SyntheticEvent.prototype, {
157
* won't be added back into the pool.
158
*/
159
persist: function() {
160
- this.isPersistent = functionThatReturnsTrue;
160
+ // Modern event system doesn't use pooling.
161
+ if (!enableModernEventSystem) {
162
+ this.isPersistent = functionThatReturnsTrue;
163
+ }
164
},
165
166
/**
@@ -165,65 +168,68 @@ Object.assign(SyntheticEvent.prototype, {
168
*
169
* @return {boolean} True if this should not be released, false otherwise.
170
*/
168
- isPersistent: functionThatReturnsFalse,
171
+ isPersistent: enableModernEventSystem
172
+ ? functionThatReturnsTrue
173
+ : functionThatReturnsFalse,
174
175
/**
176
* `PooledClass` looks for `destructor` on each instance it releases.
177
*/
178
destructor: function() {
174
- const Interface = this.constructor.Interface;
175
- for (const propName in Interface) {
179
+ // Modern event system doesn't use pooling.
180
+ if (!enableModernEventSystem) {
181
+ const Interface = this.constructor.Interface;
182
+ for (const propName in Interface) {
183
+ if (__DEV__) {
184
+ Object.defineProperty(
185
+ this,
186
+ propName,
187
+ getPooledWarningPropertyDefinition(propName, Interface[propName]),
188
+ );
189
+ } else {
190
+ this[propName] = null;
191
+ }
192
+ }
193
+ this.dispatchConfig = null;
194
+ this._targetInst = null;
195
+ this.nativeEvent = null;
196
+ this.isDefaultPrevented = functionThatReturnsFalse;
197
+ this.isPropagationStopped = functionThatReturnsFalse;
198
+ this._dispatchListeners = null;
199
+ this._dispatchInstances = null;
200
if (__DEV__) {
201
Object.defineProperty(
202
this,
179
- propName,
180
- getPooledWarningPropertyDefinition(propName, Interface[propName]),
203
+ 'nativeEvent',
204
+ getPooledWarningPropertyDefinition('nativeEvent', null),
205
);
182
- } else {
183
- this[propName] = null;
184
- }
185
- }
186
- this.dispatchConfig = null;
187
- this._targetInst = null;
188
- this.nativeEvent = null;
189
- this.isDefaultPrevented = functionThatReturnsFalse;
190
- this.isPropagationStopped = functionThatReturnsFalse;
191
- if (!enableModernEventSystem) {
192
- this._dispatchListeners = null;
193
- this._dispatchInstances = null;
194
- }
195
- if (__DEV__) {
196
- Object.defineProperty(
197
- this,
198
- 'nativeEvent',
199
- getPooledWarningPropertyDefinition('nativeEvent', null),
200
- );
201
- Object.defineProperty(
202
- this,
203
- 'isDefaultPrevented',
204
- getPooledWarningPropertyDefinition(
206
+ Object.defineProperty(
207
+ this,
208
'isDefaultPrevented',
206
- functionThatReturnsFalse,
207
- ),
208
- );
209
- Object.defineProperty(
210
- this,
211
- 'isPropagationStopped',
212
- getPooledWarningPropertyDefinition(
209
+ getPooledWarningPropertyDefinition(
210
+ 'isDefaultPrevented',
211
+ functionThatReturnsFalse,
212
+ ),
213
+ );
214
+ Object.defineProperty(
215
+ this,
216
'isPropagationStopped',
214
- functionThatReturnsFalse,
215
- ),
216
- );
217
- Object.defineProperty(
218
- this,
219
- 'preventDefault',
220
- getPooledWarningPropertyDefinition('preventDefault', () => {}),
221
- );
222
- Object.defineProperty(
223
- this,
224
- 'stopPropagation',
225
- getPooledWarningPropertyDefinition('stopPropagation', () => {}),
226
- );
217
+ getPooledWarningPropertyDefinition(
218
+ 'isPropagationStopped',
219
+ functionThatReturnsFalse,
220
+ ),
221
+ );
222
+ Object.defineProperty(
223
+ this,
224
+ 'preventDefault',
225
+ getPooledWarningPropertyDefinition('preventDefault', () => {}),
226
+ );
227
+ Object.defineProperty(
228
+ this,
229
+ 'stopPropagation',
230
+ getPooledWarningPropertyDefinition('stopPropagation', () => {}),
231
+ );
232
+ }
233
}
234
},
235
});
@@ -303,18 +309,26 @@ function getPooledWarningPropertyDefinition(propName, getVal) {
309
}
310
}
311
306
-function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
312
+function createOrGetPooledEvent(
313
+ dispatchConfig,
314
+ targetInst,
315
+ nativeEvent,
316
+ nativeInst,
317
+) {
318
const EventConstructor = this;
308
- if (EventConstructor.eventPool.length) {
309
- const instance = EventConstructor.eventPool.pop();
310
- EventConstructor.call(
311
- instance,
312
- dispatchConfig,
313
- targetInst,
314
- nativeEvent,
315
- nativeInst,
316
- );
317
- return instance;
319
+ // Modern event system doesn't use pooling.
320
+ if (!enableModernEventSystem) {
321
+ if (EventConstructor.eventPool.length) {
322
+ const instance = EventConstructor.eventPool.pop();
323
+ EventConstructor.call(
324
+ instance,
325
+ dispatchConfig,
326
+ targetInst,
327
+ nativeEvent,
328
+ nativeInst,
329
+ );
330
+ return instance;
331
+ }
332
}
333
return new EventConstructor(
334
dispatchConfig,
@@ -325,21 +339,28 @@ function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
339
}
340
341
function releasePooledEvent(event) {
328
- const EventConstructor = this;
329
- invariant(
330
- event instanceof EventConstructor,
331
- 'Trying to release an event instance into a pool of a different type.',
332
- );
333
- event.destructor();
334
- if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
335
- EventConstructor.eventPool.push(event);
342
+ // Modern event system doesn't use pooling.
343
+ if (!enableModernEventSystem) {
344
+ const EventConstructor = this;
345
+ invariant(
346
+ event instanceof EventConstructor,
347
+ 'Trying to release an event instance into a pool of a different type.',
348
+ );
349
+ event.destructor();
350
+ if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
351
+ EventConstructor.eventPool.push(event);
352
+ }
353
}
354
}
355
356
function addEventPoolingTo(EventConstructor) {
340
- EventConstructor.eventPool = [];
341
- EventConstructor.getPooled = getPooledEvent;
342
- EventConstructor.release = releasePooledEvent;
357
+ EventConstructor.getPooled = createOrGetPooledEvent;
358
+
359
+ // Modern event system doesn't use pooling.
360
+ if (!enableModernEventSystem) {
361
+ EventConstructor.eventPool = [];
362
+ EventConstructor.release = releasePooledEvent;
363
+ }
364
}
365
366
export default SyntheticEvent;
packages/react-dom/src/events/DOMModernPluginEventSystem.js
+1
-4
@@ -207,10 +207,7 @@ export function dispatchEventsInBatch(dispatchQueue: DispatchQueue): void {
207
const dispatchQueueItem: DispatchQueueItem = dispatchQueue[i];
208
const {event, capture, bubble} = dispatchQueueItem;
209
executeDispatchesInOrder(event, capture, bubble);
210
- // Release the event from the pool if needed
211
- if (!event.isPersistent()) {
212
- event.constructor.release(event);
213
- }
210
+ // Modern event system doesn't use pooling.
211
}
212
// This would be a good time to rethrow if any of the event handlers threw.
213
rethrowCaughtError();
packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js
+21
@@ -78,6 +78,27 @@ describe('DOMModernPluginEventSystem', () => {
78
endNativeEventListenerClearDown();
79
});
80
81
+ it('does not pool events', () => {
82
+ const buttonRef = React.createRef();
83
+ const log = [];
84
+ const onClick = jest.fn(e => log.push(e));
85
+
86
+ function Test() {
87
+ return <button ref={buttonRef} onClick={onClick} />;
88
+ }
89
+
90
+ ReactDOM.render(<Test />, container);
91
+
92
+ let buttonElement = buttonRef.current;
93
+ dispatchClickEvent(buttonElement);
94
+ expect(onClick).toHaveBeenCalledTimes(1);
95
+ dispatchClickEvent(buttonElement);
96
+ expect(onClick).toHaveBeenCalledTimes(2);
97
+ expect(log[0]).not.toBe(log[1]);
98
+ expect(log[0].type).toBe('click');
99
+ expect(log[1].type).toBe('click');
100
+ });
101
+
102
it('handle propagation of click events', () => {
103
const buttonRef = React.createRef();
104
const divRef = React.createRef();
packages/react-dom/src/events/__tests__/SyntheticClipboardEvent-test.js
+39
-36
@@ -11,6 +11,7 @@
11
12
let React;
13
let ReactDOM;
14
+const ReactFeatureFlags = require('shared/ReactFeatureFlags');
15
16
describe('SyntheticClipboardEvent', () => {
17
let container;
@@ -117,41 +118,43 @@ describe('SyntheticClipboardEvent', () => {
118
expect(expectedCount).toBe(3);
119
});
120
120
- it('is able to `persist`', () => {
121
- const persistentEvents = [];
122
- const eventHandler = event => {
123
- expect(event.isPersistent()).toBe(false);
124
- event.persist();
125
- expect(event.isPersistent()).toBe(true);
126
- persistentEvents.push(event);
127
- };
128
-
129
- const div = ReactDOM.render(
130
- <div
131
- onCopy={eventHandler}
132
- onCut={eventHandler}
133
- onPaste={eventHandler}
134
- />,
135
- container,
136
- );
137
-
138
- let event;
139
- event = document.createEvent('Event');
140
- event.initEvent('copy', true, true);
141
- div.dispatchEvent(event);
142
-
143
- event = document.createEvent('Event');
144
- event.initEvent('cut', true, true);
145
- div.dispatchEvent(event);
146
-
147
- event = document.createEvent('Event');
148
- event.initEvent('paste', true, true);
149
- div.dispatchEvent(event);
150
-
151
- expect(persistentEvents.length).toBe(3);
152
- expect(persistentEvents[0].type).toBe('copy');
153
- expect(persistentEvents[1].type).toBe('cut');
154
- expect(persistentEvents[2].type).toBe('paste');
155
- });
121
+ if (!ReactFeatureFlags.enableModernEventSystem) {
122
+ it('is able to `persist`', () => {
123
+ const persistentEvents = [];
124
+ const eventHandler = event => {
125
+ expect(event.isPersistent()).toBe(false);
126
+ event.persist();
127
+ expect(event.isPersistent()).toBe(true);
128
+ persistentEvents.push(event);
129
+ };
130
+
131
+ const div = ReactDOM.render(
132
+ <div
133
+ onCopy={eventHandler}
134
+ onCut={eventHandler}
135
+ onPaste={eventHandler}
136
+ />,
137
+ container,
138
+ );
139
+
140
+ let event;
141
+ event = document.createEvent('Event');
142
+ event.initEvent('copy', true, true);
143
+ div.dispatchEvent(event);
144
+
145
+ event = document.createEvent('Event');
146
+ event.initEvent('cut', true, true);
147
+ div.dispatchEvent(event);
148
+
149
+ event = document.createEvent('Event');
150
+ event.initEvent('paste', true, true);
151
+ div.dispatchEvent(event);
152
+
153
+ expect(persistentEvents.length).toBe(3);
154
+ expect(persistentEvents[0].type).toBe('copy');
155
+ expect(persistentEvents[1].type).toBe('cut');
156
+ expect(persistentEvents[2].type).toBe('paste');
157
+ });
158
+ }
159
});
160
});
packages/react-dom/src/events/__tests__/SyntheticEvent-test.js
+191
-188
@@ -11,6 +11,7 @@
11
12
let React;
13
let ReactDOM;
14
+const ReactFeatureFlags = require('shared/ReactFeatureFlags');
15
16
describe('SyntheticEvent', () => {
17
let container;
@@ -99,223 +100,225 @@ describe('SyntheticEvent', () => {
100
expect(expectedCount).toBe(1);
101
});
102
102
- it('should be able to `persist`', () => {
103
- let expectedCount = 0;
104
- let syntheticEvent;
105
-
106
- const eventHandler = e => {
107
- expect(e.isPersistent()).toBe(false);
108
- e.persist();
109
- syntheticEvent = e;
110
- expect(e.isPersistent()).toBe(true);
111
-
112
- expectedCount++;
113
- };
114
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
115
-
116
- const event = document.createEvent('Event');
117
- event.initEvent('click', true, true);
118
- node.dispatchEvent(event);
119
-
120
- expect(syntheticEvent.type).toBe('click');
121
- expect(syntheticEvent.bubbles).toBe(true);
122
- expect(syntheticEvent.cancelable).toBe(true);
123
- expect(expectedCount).toBe(1);
124
- });
103
+ if (!ReactFeatureFlags.enableModernEventSystem) {
104
+ it('should be able to `persist`', () => {
105
+ let expectedCount = 0;
106
+ let syntheticEvent;
107
+
108
+ const eventHandler = e => {
109
+ expect(e.isPersistent()).toBe(false);
110
+ e.persist();
111
+ syntheticEvent = e;
112
+ expect(e.isPersistent()).toBe(true);
113
+
114
+ expectedCount++;
115
+ };
116
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
117
+
118
+ const event = document.createEvent('Event');
119
+ event.initEvent('click', true, true);
120
+ node.dispatchEvent(event);
121
+
122
+ expect(syntheticEvent.type).toBe('click');
123
+ expect(syntheticEvent.bubbles).toBe(true);
124
+ expect(syntheticEvent.cancelable).toBe(true);
125
+ expect(expectedCount).toBe(1);
126
+ });
127
126
- it('should be nullified and log warnings if the synthetic event has not been persisted', () => {
127
- let expectedCount = 0;
128
- let syntheticEvent;
128
+ it('should be nullified and log warnings if the synthetic event has not been persisted', () => {
129
+ let expectedCount = 0;
130
+ let syntheticEvent;
131
130
- const eventHandler = e => {
131
- syntheticEvent = e;
132
+ const eventHandler = e => {
133
+ syntheticEvent = e;
134
133
- expectedCount++;
134
- };
135
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
135
+ expectedCount++;
136
+ };
137
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
138
137
- const event = document.createEvent('Event');
138
- event.initEvent('click', true, true);
139
- node.dispatchEvent(event);
139
+ const event = document.createEvent('Event');
140
+ event.initEvent('click', true, true);
141
+ node.dispatchEvent(event);
142
141
- const getExpectedWarning = property =>
142
- 'Warning: This synthetic event is reused for performance reasons. If ' +
143
- `you're seeing this, you're accessing the property \`${property}\` on a ` +
144
- 'released/nullified synthetic event. This is set to null. If you must ' +
145
- 'keep the original synthetic event around, use event.persist(). ' +
146
- 'See https://fb.me/react-event-pooling for more information.';
147
-
148
- // once for each property accessed
149
- expect(() =>
150
- expect(syntheticEvent.type).toBe(null),
151
- ).toErrorDev(getExpectedWarning('type'), {withoutStack: true});
152
- expect(() =>
153
- expect(syntheticEvent.nativeEvent).toBe(null),
154
- ).toErrorDev(getExpectedWarning('nativeEvent'), {withoutStack: true});
155
- expect(() =>
156
- expect(syntheticEvent.target).toBe(null),
157
- ).toErrorDev(getExpectedWarning('target'), {withoutStack: true});
143
+ const getExpectedWarning = property =>
144
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
145
+ `you're seeing this, you're accessing the property \`${property}\` on a ` +
146
+ 'released/nullified synthetic event. This is set to null. If you must ' +
147
+ 'keep the original synthetic event around, use event.persist(). ' +
148
+ 'See https://fb.me/react-event-pooling for more information.';
149
+
150
+ // once for each property accessed
151
+ expect(() =>
152
+ expect(syntheticEvent.type).toBe(null),
153
+ ).toErrorDev(getExpectedWarning('type'), {withoutStack: true});
154
+ expect(() =>
155
+ expect(syntheticEvent.nativeEvent).toBe(null),
156
+ ).toErrorDev(getExpectedWarning('nativeEvent'), {withoutStack: true});
157
+ expect(() =>
158
+ expect(syntheticEvent.target).toBe(null),
159
+ ).toErrorDev(getExpectedWarning('target'), {withoutStack: true});
160
+
161
+ expect(expectedCount).toBe(1);
162
+ });
163
159
- expect(expectedCount).toBe(1);
160
- });
164
+ it('should warn when setting properties of a synthetic event that has not been persisted', () => {
165
+ let expectedCount = 0;
166
+ let syntheticEvent;
167
162
- it('should warn when setting properties of a synthetic event that has not been persisted', () => {
163
- let expectedCount = 0;
164
- let syntheticEvent;
168
+ const eventHandler = e => {
169
+ syntheticEvent = e;
170
166
- const eventHandler = e => {
167
- syntheticEvent = e;
171
+ expectedCount++;
172
+ };
173
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
174
169
- expectedCount++;
170
- };
171
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
175
+ const event = document.createEvent('Event');
176
+ event.initEvent('click', true, true);
177
+ node.dispatchEvent(event);
178
173
- const event = document.createEvent('Event');
174
- event.initEvent('click', true, true);
175
- node.dispatchEvent(event);
179
+ expect(() => {
180
+ syntheticEvent.type = 'MouseEvent';
181
+ }).toErrorDev(
182
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
183
+ "you're seeing this, you're setting the property `type` on a " +
184
+ 'released/nullified synthetic event. This is effectively a no-op. If you must ' +
185
+ 'keep the original synthetic event around, use event.persist(). ' +
186
+ 'See https://fb.me/react-event-pooling for more information.',
187
+ {withoutStack: true},
188
+ );
189
+ expect(expectedCount).toBe(1);
190
+ });
191
177
- expect(() => {
178
- syntheticEvent.type = 'MouseEvent';
179
- }).toErrorDev(
180
- 'Warning: This synthetic event is reused for performance reasons. If ' +
181
- "you're seeing this, you're setting the property `type` on a " +
182
- 'released/nullified synthetic event. This is effectively a no-op. If you must ' +
183
- 'keep the original synthetic event around, use event.persist(). ' +
184
- 'See https://fb.me/react-event-pooling for more information.',
185
- {withoutStack: true},
186
- );
187
- expect(expectedCount).toBe(1);
188
- });
192
+ it('should warn when calling `preventDefault` if the synthetic event has not been persisted', () => {
193
+ let expectedCount = 0;
194
+ let syntheticEvent;
195
190
- it('should warn when calling `preventDefault` if the synthetic event has not been persisted', () => {
191
- let expectedCount = 0;
192
- let syntheticEvent;
196
+ const eventHandler = e => {
197
+ syntheticEvent = e;
198
+ expectedCount++;
199
+ };
200
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
201
194
- const eventHandler = e => {
195
- syntheticEvent = e;
196
- expectedCount++;
197
- };
198
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
202
+ const event = document.createEvent('Event');
203
+ event.initEvent('click', true, true);
204
+ node.dispatchEvent(event);
205
200
- const event = document.createEvent('Event');
201
- event.initEvent('click', true, true);
202
- node.dispatchEvent(event);
206
+ expect(() =>
207
+ syntheticEvent.preventDefault(),
208
+ ).toErrorDev(
209
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
210
+ "you're seeing this, you're accessing the method `preventDefault` on a " +
211
+ 'released/nullified synthetic event. This is a no-op function. If you must ' +
212
+ 'keep the original synthetic event around, use event.persist(). ' +
213
+ 'See https://fb.me/react-event-pooling for more information.',
214
+ {withoutStack: true},
215
+ );
216
+ expect(expectedCount).toBe(1);
217
+ });
218
204
- expect(() =>
205
- syntheticEvent.preventDefault(),
206
- ).toErrorDev(
207
- 'Warning: This synthetic event is reused for performance reasons. If ' +
208
- "you're seeing this, you're accessing the method `preventDefault` on a " +
209
- 'released/nullified synthetic event. This is a no-op function. If you must ' +
210
- 'keep the original synthetic event around, use event.persist(). ' +
211
- 'See https://fb.me/react-event-pooling for more information.',
212
- {withoutStack: true},
213
- );
214
- expect(expectedCount).toBe(1);
215
- });
219
+ it('should warn when calling `stopPropagation` if the synthetic event has not been persisted', () => {
220
+ let expectedCount = 0;
221
+ let syntheticEvent;
222
217
- it('should warn when calling `stopPropagation` if the synthetic event has not been persisted', () => {
218
- let expectedCount = 0;
219
- let syntheticEvent;
223
+ const eventHandler = e => {
224
+ syntheticEvent = e;
225
+ expectedCount++;
226
+ };
227
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
228
221
- const eventHandler = e => {
222
- syntheticEvent = e;
223
- expectedCount++;
224
- };
225
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
229
+ const event = document.createEvent('Event');
230
+ event.initEvent('click', true, true);
231
227
- const event = document.createEvent('Event');
228
- event.initEvent('click', true, true);
232
+ node.dispatchEvent(event);
233
230
- node.dispatchEvent(event);
234
+ expect(() =>
235
+ syntheticEvent.stopPropagation(),
236
+ ).toErrorDev(
237
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
238
+ "you're seeing this, you're accessing the method `stopPropagation` on a " +
239
+ 'released/nullified synthetic event. This is a no-op function. If you must ' +
240
+ 'keep the original synthetic event around, use event.persist(). ' +
241
+ 'See https://fb.me/react-event-pooling for more information.',
242
+ {withoutStack: true},
243
+ );
244
+ expect(expectedCount).toBe(1);
245
+ });
246
232
- expect(() =>
233
- syntheticEvent.stopPropagation(),
234
- ).toErrorDev(
235
- 'Warning: This synthetic event is reused for performance reasons. If ' +
236
- "you're seeing this, you're accessing the method `stopPropagation` on a " +
237
- 'released/nullified synthetic event. This is a no-op function. If you must ' +
238
- 'keep the original synthetic event around, use event.persist(). ' +
239
- 'See https://fb.me/react-event-pooling for more information.',
240
- {withoutStack: true},
241
- );
242
- expect(expectedCount).toBe(1);
243
- });
247
+ it('should warn when calling `isPropagationStopped` if the synthetic event has not been persisted', () => {
248
+ let expectedCount = 0;
249
+ let syntheticEvent;
250
245
- it('should warn when calling `isPropagationStopped` if the synthetic event has not been persisted', () => {
246
- let expectedCount = 0;
247
- let syntheticEvent;
251
+ const eventHandler = e => {
252
+ syntheticEvent = e;
253
+ expectedCount++;
254
+ };
255
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
256
249
- const eventHandler = e => {
250
- syntheticEvent = e;
251
- expectedCount++;
252
- };
253
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
257
+ const event = document.createEvent('Event');
258
+ event.initEvent('click', true, true);
259
+ node.dispatchEvent(event);
260
255
- const event = document.createEvent('Event');
256
- event.initEvent('click', true, true);
257
- node.dispatchEvent(event);
261
+ expect(() =>
262
+ expect(syntheticEvent.isPropagationStopped()).toBe(false),
263
+ ).toErrorDev(
264
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
265
+ "you're seeing this, you're accessing the method `isPropagationStopped` on a " +
266
+ 'released/nullified synthetic event. This is a no-op function. If you must ' +
267
+ 'keep the original synthetic event around, use event.persist(). ' +
268
+ 'See https://fb.me/react-event-pooling for more information.',
269
+ {withoutStack: true},
270
+ );
271
+ expect(expectedCount).toBe(1);
272
+ });
273
259
- expect(() =>
260
- expect(syntheticEvent.isPropagationStopped()).toBe(false),
261
- ).toErrorDev(
262
- 'Warning: This synthetic event is reused for performance reasons. If ' +
263
- "you're seeing this, you're accessing the method `isPropagationStopped` on a " +
264
- 'released/nullified synthetic event. This is a no-op function. If you must ' +
265
- 'keep the original synthetic event around, use event.persist(). ' +
266
- 'See https://fb.me/react-event-pooling for more information.',
267
- {withoutStack: true},
268
- );
269
- expect(expectedCount).toBe(1);
270
- });
274
+ it('should warn when calling `isDefaultPrevented` if the synthetic event has not been persisted', () => {
275
+ let expectedCount = 0;
276
+ let syntheticEvent;
277
272
- it('should warn when calling `isDefaultPrevented` if the synthetic event has not been persisted', () => {
273
- let expectedCount = 0;
274
- let syntheticEvent;
278
+ const eventHandler = e => {
279
+ syntheticEvent = e;
280
+ expectedCount++;
281
+ };
282
+ const node = ReactDOM.render(<div onClick={eventHandler} />, container);
283
276
- const eventHandler = e => {
277
- syntheticEvent = e;
278
- expectedCount++;
279
- };
280
- const node = ReactDOM.render(<div onClick={eventHandler} />, container);
284
+ const event = document.createEvent('Event');
285
+ event.initEvent('click', true, true);
286
+ node.dispatchEvent(event);
287
282
- const event = document.createEvent('Event');
283
- event.initEvent('click', true, true);
284
- node.dispatchEvent(event);
288
+ expect(() =>
289
+ expect(syntheticEvent.isDefaultPrevented()).toBe(false),
290
+ ).toErrorDev(
291
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
292
+ "you're seeing this, you're accessing the method `isDefaultPrevented` on a " +
293
+ 'released/nullified synthetic event. This is a no-op function. If you must ' +
294
+ 'keep the original synthetic event around, use event.persist(). ' +
295
+ 'See https://fb.me/react-event-pooling for more information.',
296
+ {withoutStack: true},
297
+ );
298
+ expect(expectedCount).toBe(1);
299
+ });
300
286
- expect(() =>
287
- expect(syntheticEvent.isDefaultPrevented()).toBe(false),
288
- ).toErrorDev(
289
- 'Warning: This synthetic event is reused for performance reasons. If ' +
290
- "you're seeing this, you're accessing the method `isDefaultPrevented` on a " +
291
- 'released/nullified synthetic event. This is a no-op function. If you must ' +
292
- 'keep the original synthetic event around, use event.persist(). ' +
293
- 'See https://fb.me/react-event-pooling for more information.',
294
- {withoutStack: true},
295
- );
296
- expect(expectedCount).toBe(1);
297
- });
301
+ it('should properly log warnings when events simulated with rendered components', () => {
302
+ let event;
303
+ function assignEvent(e) {
304
+ event = e;
305
+ }
306
+ const node = ReactDOM.render(<div onClick={assignEvent} />, container);
307
+ node.click();
308
299
- it('should properly log warnings when events simulated with rendered components', () => {
300
- let event;
301
- function assignEvent(e) {
302
- event = e;
303
- }
304
- const node = ReactDOM.render(<div onClick={assignEvent} />, container);
305
- node.click();
306
-
307
- // access a property to cause the warning
308
- expect(() => {
309
- event.nativeEvent; // eslint-disable-line no-unused-expressions
310
- }).toErrorDev(
311
- 'Warning: This synthetic event is reused for performance reasons. If ' +
312
- "you're seeing this, you're accessing the property `nativeEvent` on a " +
313
- 'released/nullified synthetic event. This is set to null. If you must ' +
314
- 'keep the original synthetic event around, use event.persist(). ' +
315
- 'See https://fb.me/react-event-pooling for more information.',
316
- {withoutStack: true},
317
- );
318
- });
309
+ // access a property to cause the warning
310
+ expect(() => {
311
+ event.nativeEvent; // eslint-disable-line no-unused-expressions
312
+ }).toErrorDev(
313
+ 'Warning: This synthetic event is reused for performance reasons. If ' +
314
+ "you're seeing this, you're accessing the property `nativeEvent` on a " +
315
+ 'released/nullified synthetic event. This is set to null. If you must ' +
316
+ 'keep the original synthetic event around, use event.persist(). ' +
317
+ 'See https://fb.me/react-event-pooling for more information.',
318
+ {withoutStack: true},
319
+ );
320
+ });
321
+ }
322
323
// TODO: we might want to re-add a warning like this in the future,
324
// but it shouldn't use Proxies because they make debugging difficult.
packages/react-dom/src/events/__tests__/SyntheticKeyboardEvent-test.js
+46
-43
@@ -11,6 +11,7 @@
11
12
let React;
13
let ReactDOM;
14
+const ReactFeatureFlags = require('shared/ReactFeatureFlags');
15
16
describe('SyntheticKeyboardEvent', () => {
17
let container;
@@ -547,49 +548,51 @@ describe('SyntheticKeyboardEvent', () => {
548
expect(expectedCount).toBe(3);
549
});
550
550
- it('is able to `persist`', () => {
551
- const persistentEvents = [];
552
- const eventHandler = event => {
553
- expect(event.isPersistent()).toBe(false);
554
- event.persist();
555
- expect(event.isPersistent()).toBe(true);
556
- persistentEvents.push(event);
557
- };
558
- const div = ReactDOM.render(
559
- <div
560
- onKeyDown={eventHandler}
561
- onKeyUp={eventHandler}
562
- onKeyPress={eventHandler}
563
- />,
564
- container,
565
- );
551
+ if (!ReactFeatureFlags.enableModernEventSystem) {
552
+ it('is able to `persist`', () => {
553
+ const persistentEvents = [];
554
+ const eventHandler = event => {
555
+ expect(event.isPersistent()).toBe(false);
556
+ event.persist();
557
+ expect(event.isPersistent()).toBe(true);
558
+ persistentEvents.push(event);
559
+ };
560
+ const div = ReactDOM.render(
561
+ <div
562
+ onKeyDown={eventHandler}
563
+ onKeyUp={eventHandler}
564
+ onKeyPress={eventHandler}
565
+ />,
566
+ container,
567
+ );
568
567
- div.dispatchEvent(
568
- new KeyboardEvent('keydown', {
569
- keyCode: 40,
570
- bubbles: true,
571
- cancelable: true,
572
- }),
573
- );
574
- div.dispatchEvent(
575
- new KeyboardEvent('keyup', {
576
- keyCode: 40,
577
- bubbles: true,
578
- cancelable: true,
579
- }),
580
- );
581
- div.dispatchEvent(
582
- new KeyboardEvent('keypress', {
583
- charCode: 40,
584
- keyCode: 40,
585
- bubbles: true,
586
- cancelable: true,
587
- }),
588
- );
589
- expect(persistentEvents.length).toBe(3);
590
- expect(persistentEvents[0].type).toBe('keydown');
591
- expect(persistentEvents[1].type).toBe('keyup');
592
- expect(persistentEvents[2].type).toBe('keypress');
593
- });
569
+ div.dispatchEvent(
570
+ new KeyboardEvent('keydown', {
571
+ keyCode: 40,
572
+ bubbles: true,
573
+ cancelable: true,
574
+ }),
575
+ );
576
+ div.dispatchEvent(
577
+ new KeyboardEvent('keyup', {
578
+ keyCode: 40,
579
+ bubbles: true,
580
+ cancelable: true,
581
+ }),
582
+ );
583
+ div.dispatchEvent(
584
+ new KeyboardEvent('keypress', {
585
+ charCode: 40,
586
+ keyCode: 40,
587
+ bubbles: true,
588
+ cancelable: true,
589
+ }),
590
+ );
591
+ expect(persistentEvents.length).toBe(3);
592
+ expect(persistentEvents[0].type).toBe('keydown');
593
+ expect(persistentEvents[1].type).toBe('keyup');
594
+ expect(persistentEvents[2].type).toBe('keypress');
595
+ });
596
+ }
597
});
598
});
packages/react-dom/src/events/__tests__/SyntheticWheelEvent-test.js
+22
-19
@@ -11,6 +11,7 @@
11
12
let React;
13
let ReactDOM;
14
+const ReactFeatureFlags = require('shared/ReactFeatureFlags');
15
16
describe('SyntheticWheelEvent', () => {
17
let container;
@@ -113,23 +114,25 @@ describe('SyntheticWheelEvent', () => {
114
expect(events.length).toBe(2);
115
});
116
116
- it('should be able to `persist`', () => {
117
- const events = [];
118
- const onWheel = event => {
119
- expect(event.isPersistent()).toBe(false);
120
- event.persist();
121
- expect(event.isPersistent()).toBe(true);
122
- events.push(event);
123
- };
124
- ReactDOM.render(<div onWheel={onWheel} />, container);
125
-
126
- container.firstChild.dispatchEvent(
127
- new MouseEvent('wheel', {
128
- bubbles: true,
129
- }),
130
- );
131
-
132
- expect(events.length).toBe(1);
133
- expect(events[0].type).toBe('wheel');
134
- });
117
+ if (!ReactFeatureFlags.enableModernEventSystem) {
118
+ it('should be able to `persist`', () => {
119
+ const events = [];
120
+ const onWheel = event => {
121
+ expect(event.isPersistent()).toBe(false);
122
+ event.persist();
123
+ expect(event.isPersistent()).toBe(true);
124
+ events.push(event);
125
+ };
126
+ ReactDOM.render(<div onWheel={onWheel} />, container);
127
+
128
+ container.firstChild.dispatchEvent(
129
+ new MouseEvent('wheel', {
130
+ bubbles: true,
131
+ }),
132
+ );
133
+
134
+ expect(events.length).toBe(1);
135
+ expect(events[0].type).toBe('wheel');
136
+ });
137
+ }
138
});