@samitouri / QOS-React / commits / 94505b9613

Don't use EventListener Fork in Modern WWW Builds (#18333)

* Move unsubscribe fork to EventListener That way we can statically compile out more of these indirections. * Don't use the EventListener fork for Modern WWW builds

Sebastian Markbåge committed Mar 18, 2020 at 06:13 UTC 94505b961332d9295c3f6da33d51219d126bf04f
4 files changed +60 -44
packages/react-dom/src/events/EventListener.js
+17 -4
@@ -11,16 +11,18 @@ export function addEventBubbleListener(
11 target: EventTarget,
12 eventType: string,
13 listener: Function,
14 -): void {
14 +): Function {
15 target.addEventListener(eventType, listener, false);
16 + return listener;
17 }
18
19 export function addEventCaptureListener(
20 target: EventTarget,
21 eventType: string,
22 listener: Function,
22 -): void {
23 +): Function {
24 target.addEventListener(eventType, listener, true);
25 + return listener;
26 }
27
28 export function addEventCaptureListenerWithPassiveFlag(
@@ -28,11 +30,12 @@ export function addEventCaptureListenerWithPassiveFlag(
30 eventType: string,
31 listener: Function,
32 passive: boolean,
31 -): void {
33 +): Function {
34 target.addEventListener(eventType, listener, {
35 capture: true,
36 passive,
37 });
38 + return listener;
39 }
40
41 export function addEventBubbleListenerWithPassiveFlag(
@@ -40,8 +43,18 @@ export function addEventBubbleListenerWithPassiveFlag(
43 eventType: string,
44 listener: Function,
45 passive: boolean,
43 -): void {
46 +): Function {
47 target.addEventListener(eventType, listener, {
48 passive,
49 });
50 + return listener;
51 +}
52 +
53 +export function removeEventListener(
54 + target: EventTarget,
55 + eventType: string,
56 + listener: Function,
57 + capture: boolean,
58 +): void {
59 + target.removeEventListener(eventType, listener, capture);
60 }
packages/react-dom/src/events/ReactDOMEventListener.js
+18 -38
@@ -49,6 +49,7 @@ import {
49 addEventCaptureListener,
50 addEventCaptureListenerWithPassiveFlag,
51 addEventBubbleListenerWithPassiveFlag,
52 + removeEventListener,
53 } from './EventListener';
54 import getEventTarget from './getEventTarget';
55 import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
@@ -108,7 +109,6 @@ export function addResponderEventSystemEvent(
109 } else {
110 eventFlags |= IS_ACTIVE;
111 }
111 - let fbListener;
112 // Check if interactive and wrap in discreteUpdates
113 const listener = dispatchEvent.bind(
114 null,
@@ -117,19 +117,15 @@ export function addResponderEventSystemEvent(
117 document,
118 );
119 if (passiveBrowserEventsSupported) {
120 - fbListener = addEventCaptureListenerWithPassiveFlag(
120 + return addEventCaptureListenerWithPassiveFlag(
121 document,
122 topLevelType,
123 listener,
124 passive,
125 );
126 } else {
127 - fbListener = addEventCaptureListener(document, topLevelType, listener);
127 + return addEventCaptureListener(document, topLevelType, listener);
128 }
129 - // If we have an fbListener, then use that.
130 - // We'll only have one if we use the forked
131 - // EventListener-www module in FB builds.
132 - return fbListener || listener;
129 }
130
131 export function addTrappedEventListener(
@@ -184,8 +180,8 @@ export function addTrappedEventListener(
180 const validTargetContainer = ((targetContainer: any): EventTarget);
181
182 const rawEventName = getRawEventName(topLevelType);
187 - let fbListener;
183
184 + let unsubscribeListener;
185 // When legacyFBSupport is enabled, it's for when we
186 // want to add a one time event listener to a container.
187 // This should only be used with enableLegacyFBPrimerSupport
@@ -203,28 +199,26 @@ export function addTrappedEventListener(
199 try {
200 return originalListener.apply(this, p);
201 } finally {
206 - if (fbListener) {
207 - fbListener.remove();
208 - } else {
209 - validTargetContainer.removeEventListener(
210 - ((rawEventName: any): string),
211 - (listener: any),
212 - );
213 - }
202 + removeEventListener(
203 + validTargetContainer,
204 + rawEventName,
205 + unsubscribeListener,
206 + capture,
207 + );
208 }
209 };
210 }
211 if (capture) {
212 if (enableUseEventAPI && passive !== undefined) {
213 // This is only used with passive is either true or false.
220 - fbListener = addEventCaptureListenerWithPassiveFlag(
214 + unsubscribeListener = addEventCaptureListenerWithPassiveFlag(
215 validTargetContainer,
216 rawEventName,
217 listener,
218 passive,
219 );
220 } else {
227 - fbListener = addEventCaptureListener(
221 + unsubscribeListener = addEventCaptureListener(
222 validTargetContainer,
223 rawEventName,
224 listener,
@@ -233,24 +227,21 @@ export function addTrappedEventListener(
227 } else {
228 if (enableUseEventAPI && passive !== undefined) {
229 // This is only used with passive is either true or false.
236 - fbListener = addEventBubbleListenerWithPassiveFlag(
230 + unsubscribeListener = addEventBubbleListenerWithPassiveFlag(
231 validTargetContainer,
232 rawEventName,
233 listener,
234 passive,
235 );
236 } else {
243 - fbListener = addEventBubbleListener(
237 + unsubscribeListener = addEventBubbleListener(
238 validTargetContainer,
239 rawEventName,
240 listener,
241 );
242 }
243 }
250 - // If we have an fbListener, then use that.
251 - // We'll only have one if we use the forked
252 - // EventListener-www module in FB builds.
253 - return fbListener || listener;
244 + return unsubscribeListener;
245 }
246
247 export function removeTrappedEventListener(
@@ -259,20 +250,9 @@ export function removeTrappedEventListener(
250 capture: boolean,
251 listener: any => void,
252 passive: void | boolean,
262 -) {
263 - if (listener.remove != null) {
264 - listener.remove();
265 - } else {
266 - const rawEventName = getRawEventName(topLevelType);
267 - if (passiveBrowserEventsSupported) {
268 - targetContainer.removeEventListener(rawEventName, listener, {
269 - capture,
270 - passive,
271 - });
272 - } else {
273 - targetContainer.removeEventListener(rawEventName, listener, capture);
274 - }
275 - }
253 +): void {
254 + const rawEventName = getRawEventName(topLevelType);
255 + removeEventListener(targetContainer, rawEventName, listener, capture);
256 }
257
258 function dispatchDiscreteEvent(
packages/react-dom/src/events/forks/EventListener-www.js
+9
@@ -56,6 +56,15 @@ export function addEventBubbleListenerWithPassiveFlag(
56 );
57 }
58
59 +export function removeEventListener(
60 + target: EventTarget,
61 + eventType: string,
62 + listener: Function,
63 + capture: boolean,
64 +) {
65 + listener.remove();
66 +}
67 +
68 // Flow magic to verify the exports of this file match the original version.
69 // eslint-disable-next-line no-unused-vars
70 type Check<_X, Y: _X, X: Y = _X> = null;
scripts/rollup/forks.js
+16 -2
@@ -19,6 +19,15 @@ const {
19 } = bundleTypes;
20 const {RENDERER, RECONCILER} = moduleTypes;
21
22 +const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL;
23 +
24 +// Default to building in experimental mode. If the release channel is set via
25 +// an environment variable, then check if it's "experimental".
26 +const __EXPERIMENTAL__ =
27 + typeof RELEASE_CHANNEL === 'string'
28 + ? RELEASE_CHANNEL === 'experimental'
29 + : true;
30 +
31 // If you need to replace a file with another file for a specific environment,
32 // add it to this list with the logic for choosing the right replacement.
33 const forks = Object.freeze({
@@ -442,8 +451,13 @@ const forks = Object.freeze({
451 case FB_WWW_DEV:
452 case FB_WWW_PROD:
453 case FB_WWW_PROFILING:
445 - // Use the www fork which is integrated with TimeSlice profiling.
446 - return 'react-dom/src/events/forks/EventListener-www.js';
454 + if (__EXPERIMENTAL__) {
455 + // In modern builds we don't use the indirection. We just use raw DOM.
456 + return null;
457 + } else {
458 + // Use the www fork which is integrated with TimeSlice profiling.
459 + return 'react-dom/src/events/forks/EventListener-www.js';
460 + }
461 default:
462 return null;
463 }