@samitouri / QOS-React / commits / 0a00804494

Remove Array.from() from hot path (#19908)

* Remove Array.from() from hot path * Fix build Don't declare block variables inside loops

Dan Abramov committed Sep 25, 2020 at 11:33 UTC 0a008044945a9dcdc9543575a8ba90b1aaacf56c
2 files changed +54 -83
packages/react-dom/src/events/DOMPluginEventSystem.js
+51 -79
@@ -726,8 +726,9 @@ export function accumulateSinglePhaseListeners(
726 inCapturePhase: boolean,
727 accumulateTargetOnly: boolean,
728 ): 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;
732 const listeners: Array<DispatchListener> = [];
733
734 let instance = targetFiber;
@@ -739,48 +740,34 @@ export function accumulateSinglePhaseListeners(
740 const {stateNode, tag} = instance;
741 // Handle listeners that are on HostComponents (i.e. <div>)
742 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;
744
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 + );
760 }
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 + });
762 }
763 }
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) {
769 listeners.push(
783 - createDispatchListener(instance, bubbleListener, currentTarget),
770 + createDispatchListener(instance, listener, lastHostComponent),
771 );
772 }
773 }
@@ -791,32 +778,23 @@ export function accumulateSinglePhaseListeners(
778 lastHostComponent !== null &&
779 stateNode !== null
780 ) {
781 + // Scopes
782 const reactScopeInstance = stateNode;
795 - const eventHandlerlisteners = getEventHandlerListeners(
783 + const eventHandlerListeners = getEventHandlerListeners(
784 reactScopeInstance,
785 );
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 + );
796 }
819 - }
797 + });
798 }
799 }
800 // If we are only accumulating events for the target, then we don't
@@ -844,8 +822,8 @@ export function accumulateTwoPhaseListeners(
822 dispatchQueue: DispatchQueue,
823 event: ReactSyntheticEvent,
824 ): 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;
827 const listeners: Array<DispatchListener> = [];
828 let instance = targetFiber;
829
@@ -856,16 +834,16 @@ export function accumulateTwoPhaseListeners(
834 if (tag === HostComponent && stateNode !== null) {
835 const currentTarget = stateNode;
836 // 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);
839 if (captureListener != null) {
840 listeners.unshift(
841 createDispatchListener(instance, captureListener, currentTarget),
842 );
843 }
844 }
867 - if (bubbled !== null) {
868 - const bubbleListener = getListener(instance, bubbled);
845 + if (bubbleName !== null) {
846 + const bubbleListener = getListener(instance, bubbleName);
847 if (bubbleListener != null) {
848 listeners.push(
849 createDispatchListener(instance, bubbleListener, currentTarget),
@@ -1026,20 +1004,14 @@ export function accumulateEventHandleNonManagedNodeListeners(
1004
1005 const eventListeners = getEventHandlerListeners(currentTarget);
1006 if (eventListeners !== null) {
1029 - const listenersArr = Array.from(eventListeners);
1007 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 + );
1013 }
1042 - }
1014 + });
1015 }
1016 if (listeners.length !== 0) {
1017 dispatchQueue.push(createDispatchEntry(event, listeners));
packages/react-interactions/events/src/dom/create-event-handle/useEvent.js
+3 -4
@@ -50,10 +50,9 @@ export default function useEvent(
50 clears.set(target, clear);
51 },
52 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 + });
56 clears.clear();
57 },
58 };