Skip to content

Commit 0a00804

Browse files
authored
Remove Array.from() from hot path (#19908)
* Remove Array.from() from hot path * Fix build Don't declare block variables inside loops
1 parent 1890159 commit 0a00804

File tree

2 files changed

+54
-83
lines changed

2 files changed

+54
-83
lines changed

packages/react-dom/src/events/DOMPluginEventSystem.js

Lines changed: 51 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,9 @@ export function accumulateSinglePhaseListeners(
726726
inCapturePhase: boolean,
727727
accumulateTargetOnly: boolean,
728728
): void {
729-
const bubbled = event._reactName;
730-
const captured = bubbled !== null ? bubbled + 'Capture' : null;
729+
const bubbleName = event._reactName;
730+
const captureName = bubbleName !== null ? bubbleName + 'Capture' : null;
731+
const reactEventName = inCapturePhase ? captureName : bubbleName;
731732
const listeners: Array<DispatchListener> = [];
732733

733734
let instance = targetFiber;
@@ -739,48 +740,34 @@ export function accumulateSinglePhaseListeners(
739740
const {stateNode, tag} = instance;
740741
// Handle listeners that are on HostComponents (i.e. <div>)
741742
if (tag === HostComponent && stateNode !== null) {
742-
const currentTarget = stateNode;
743-
lastHostComponent = currentTarget;
744-
// For Event Handle listeners
745-
if (enableCreateEventHandleAPI) {
746-
const eventHandlerlisteners = getEventHandlerListeners(currentTarget);
743+
lastHostComponent = stateNode;
747744

748-
if (eventHandlerlisteners !== null) {
749-
const eventHandlerlistenersArr = Array.from(eventHandlerlisteners);
750-
for (let i = 0; i < eventHandlerlistenersArr.length; i++) {
751-
const {
752-
callback,
753-
capture: isCapturePhaseListener,
754-
type,
755-
} = eventHandlerlistenersArr[i];
756-
if (type === targetType) {
757-
if (isCapturePhaseListener && inCapturePhase) {
758-
listeners.push(
759-
createDispatchListener(instance, callback, currentTarget),
760-
);
761-
} else if (!isCapturePhaseListener && !inCapturePhase) {
762-
listeners.push(
763-
createDispatchListener(instance, callback, currentTarget),
764-
);
765-
}
745+
// createEventHandle listeners
746+
if (enableCreateEventHandleAPI) {
747+
const eventHandlerListeners = getEventHandlerListeners(
748+
lastHostComponent,
749+
);
750+
if (eventHandlerListeners !== null) {
751+
eventHandlerListeners.forEach(entry => {
752+
if (entry.type === targetType && entry.capture === inCapturePhase) {
753+
listeners.push(
754+
createDispatchListener(
755+
instance,
756+
entry.callback,
757+
(lastHostComponent: any),
758+
),
759+
);
766760
}
767-
}
768-
}
769-
}
770-
// Standard React on* listeners, i.e. onClick prop
771-
if (captured !== null && inCapturePhase) {
772-
const captureListener = getListener(instance, captured);
773-
if (captureListener != null) {
774-
listeners.push(
775-
createDispatchListener(instance, captureListener, currentTarget),
776-
);
761+
});
777762
}
778763
}
779-
if (bubbled !== null && !inCapturePhase) {
780-
const bubbleListener = getListener(instance, bubbled);
781-
if (bubbleListener != null) {
764+
765+
// Standard React on* listeners, i.e. onClick or onClickCapture
766+
if (reactEventName !== null) {
767+
const listener = getListener(instance, reactEventName);
768+
if (listener != null) {
782769
listeners.push(
783-
createDispatchListener(instance, bubbleListener, currentTarget),
770+
createDispatchListener(instance, listener, lastHostComponent),
784771
);
785772
}
786773
}
@@ -791,32 +778,23 @@ export function accumulateSinglePhaseListeners(
791778
lastHostComponent !== null &&
792779
stateNode !== null
793780
) {
781+
// Scopes
794782
const reactScopeInstance = stateNode;
795-
const eventHandlerlisteners = getEventHandlerListeners(
783+
const eventHandlerListeners = getEventHandlerListeners(
796784
reactScopeInstance,
797785
);
798-
const lastCurrentTarget = ((lastHostComponent: any): Element);
799-
800-
if (eventHandlerlisteners !== null) {
801-
const eventHandlerlistenersArr = Array.from(eventHandlerlisteners);
802-
for (let i = 0; i < eventHandlerlistenersArr.length; i++) {
803-
const {
804-
callback,
805-
capture: isCapturePhaseListener,
806-
type,
807-
} = eventHandlerlistenersArr[i];
808-
if (type === targetType) {
809-
if (isCapturePhaseListener && inCapturePhase) {
810-
listeners.push(
811-
createDispatchListener(instance, callback, lastCurrentTarget),
812-
);
813-
} else if (!isCapturePhaseListener && !inCapturePhase) {
814-
listeners.push(
815-
createDispatchListener(instance, callback, lastCurrentTarget),
816-
);
817-
}
786+
if (eventHandlerListeners !== null) {
787+
eventHandlerListeners.forEach(entry => {
788+
if (entry.type === targetType && entry.capture === inCapturePhase) {
789+
listeners.push(
790+
createDispatchListener(
791+
instance,
792+
entry.callback,
793+
(lastHostComponent: any),
794+
),
795+
);
818796
}
819-
}
797+
});
820798
}
821799
}
822800
// If we are only accumulating events for the target, then we don't
@@ -844,8 +822,8 @@ export function accumulateTwoPhaseListeners(
844822
dispatchQueue: DispatchQueue,
845823
event: ReactSyntheticEvent,
846824
): void {
847-
const bubbled = event._reactName;
848-
const captured = bubbled !== null ? bubbled + 'Capture' : null;
825+
const bubbleName = event._reactName;
826+
const captureName = bubbleName !== null ? bubbleName + 'Capture' : null;
849827
const listeners: Array<DispatchListener> = [];
850828
let instance = targetFiber;
851829

@@ -856,16 +834,16 @@ export function accumulateTwoPhaseListeners(
856834
if (tag === HostComponent && stateNode !== null) {
857835
const currentTarget = stateNode;
858836
// Standard React on* listeners, i.e. onClick prop
859-
if (captured !== null) {
860-
const captureListener = getListener(instance, captured);
837+
if (captureName !== null) {
838+
const captureListener = getListener(instance, captureName);
861839
if (captureListener != null) {
862840
listeners.unshift(
863841
createDispatchListener(instance, captureListener, currentTarget),
864842
);
865843
}
866844
}
867-
if (bubbled !== null) {
868-
const bubbleListener = getListener(instance, bubbled);
845+
if (bubbleName !== null) {
846+
const bubbleListener = getListener(instance, bubbleName);
869847
if (bubbleListener != null) {
870848
listeners.push(
871849
createDispatchListener(instance, bubbleListener, currentTarget),
@@ -1026,20 +1004,14 @@ export function accumulateEventHandleNonManagedNodeListeners(
10261004

10271005
const eventListeners = getEventHandlerListeners(currentTarget);
10281006
if (eventListeners !== null) {
1029-
const listenersArr = Array.from(eventListeners);
10301007
const targetType = ((event.type: any): DOMEventName);
1031-
1032-
for (let i = 0; i < listenersArr.length; i++) {
1033-
const listener = listenersArr[i];
1034-
const {callback, capture: isCapturePhaseListener, type} = listener;
1035-
if (type === targetType) {
1036-
if (inCapturePhase && isCapturePhaseListener) {
1037-
listeners.push(createDispatchListener(null, callback, currentTarget));
1038-
} else if (!inCapturePhase && !isCapturePhaseListener) {
1039-
listeners.push(createDispatchListener(null, callback, currentTarget));
1040-
}
1008+
eventListeners.forEach(entry => {
1009+
if (entry.type === targetType && entry.capture === inCapturePhase) {
1010+
listeners.push(
1011+
createDispatchListener(null, entry.callback, currentTarget),
1012+
);
10411013
}
1042-
}
1014+
});
10431015
}
10441016
if (listeners.length !== 0) {
10451017
dispatchQueue.push(createDispatchEntry(event, listeners));

packages/react-interactions/events/src/dom/create-event-handle/useEvent.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,9 @@ export default function useEvent(
5050
clears.set(target, clear);
5151
},
5252
clear(): void {
53-
const clearsArr = Array.from(clears.values());
54-
for (let i = 0; i < clearsArr.length; i++) {
55-
clearsArr[i]();
56-
}
53+
clears.forEach(c => {
54+
c();
55+
});
5756
clears.clear();
5857
},
5958
};

0 commit comments

Comments
 (0)