Skip to content

Commit

Permalink
Remove Array.from() from hot path (#19908)
Browse files Browse the repository at this point in the history
* Remove Array.from() from hot path

* Fix build

Don't declare block variables inside loops
  • Loading branch information
gaearon authored Sep 25, 2020
1 parent 1890159 commit 0a00804
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 83 deletions.
130 changes: 51 additions & 79 deletions packages/react-dom/src/events/DOMPluginEventSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -726,8 +726,9 @@ export function accumulateSinglePhaseListeners(
inCapturePhase: boolean,
accumulateTargetOnly: boolean,
): void {
const bubbled = event._reactName;
const captured = bubbled !== null ? bubbled + 'Capture' : null;
const bubbleName = event._reactName;
const captureName = bubbleName !== null ? bubbleName + 'Capture' : null;
const reactEventName = inCapturePhase ? captureName : bubbleName;
const listeners: Array<DispatchListener> = [];

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

if (eventHandlerlisteners !== null) {
const eventHandlerlistenersArr = Array.from(eventHandlerlisteners);
for (let i = 0; i < eventHandlerlistenersArr.length; i++) {
const {
callback,
capture: isCapturePhaseListener,
type,
} = eventHandlerlistenersArr[i];
if (type === targetType) {
if (isCapturePhaseListener && inCapturePhase) {
listeners.push(
createDispatchListener(instance, callback, currentTarget),
);
} else if (!isCapturePhaseListener && !inCapturePhase) {
listeners.push(
createDispatchListener(instance, callback, currentTarget),
);
}
// createEventHandle listeners
if (enableCreateEventHandleAPI) {
const eventHandlerListeners = getEventHandlerListeners(
lastHostComponent,
);
if (eventHandlerListeners !== null) {
eventHandlerListeners.forEach(entry => {
if (entry.type === targetType && entry.capture === inCapturePhase) {
listeners.push(
createDispatchListener(
instance,
entry.callback,
(lastHostComponent: any),
),
);
}
}
}
}
// Standard React on* listeners, i.e. onClick prop
if (captured !== null && inCapturePhase) {
const captureListener = getListener(instance, captured);
if (captureListener != null) {
listeners.push(
createDispatchListener(instance, captureListener, currentTarget),
);
});
}
}
if (bubbled !== null && !inCapturePhase) {
const bubbleListener = getListener(instance, bubbled);
if (bubbleListener != null) {

// Standard React on* listeners, i.e. onClick or onClickCapture
if (reactEventName !== null) {
const listener = getListener(instance, reactEventName);
if (listener != null) {
listeners.push(
createDispatchListener(instance, bubbleListener, currentTarget),
createDispatchListener(instance, listener, lastHostComponent),
);
}
}
Expand All @@ -791,32 +778,23 @@ export function accumulateSinglePhaseListeners(
lastHostComponent !== null &&
stateNode !== null
) {
// Scopes
const reactScopeInstance = stateNode;
const eventHandlerlisteners = getEventHandlerListeners(
const eventHandlerListeners = getEventHandlerListeners(
reactScopeInstance,
);
const lastCurrentTarget = ((lastHostComponent: any): Element);

if (eventHandlerlisteners !== null) {
const eventHandlerlistenersArr = Array.from(eventHandlerlisteners);
for (let i = 0; i < eventHandlerlistenersArr.length; i++) {
const {
callback,
capture: isCapturePhaseListener,
type,
} = eventHandlerlistenersArr[i];
if (type === targetType) {
if (isCapturePhaseListener && inCapturePhase) {
listeners.push(
createDispatchListener(instance, callback, lastCurrentTarget),
);
} else if (!isCapturePhaseListener && !inCapturePhase) {
listeners.push(
createDispatchListener(instance, callback, lastCurrentTarget),
);
}
if (eventHandlerListeners !== null) {
eventHandlerListeners.forEach(entry => {
if (entry.type === targetType && entry.capture === inCapturePhase) {
listeners.push(
createDispatchListener(
instance,
entry.callback,
(lastHostComponent: any),
),
);
}
}
});
}
}
// If we are only accumulating events for the target, then we don't
Expand Down Expand Up @@ -844,8 +822,8 @@ export function accumulateTwoPhaseListeners(
dispatchQueue: DispatchQueue,
event: ReactSyntheticEvent,
): void {
const bubbled = event._reactName;
const captured = bubbled !== null ? bubbled + 'Capture' : null;
const bubbleName = event._reactName;
const captureName = bubbleName !== null ? bubbleName + 'Capture' : null;
const listeners: Array<DispatchListener> = [];
let instance = targetFiber;

Expand All @@ -856,16 +834,16 @@ export function accumulateTwoPhaseListeners(
if (tag === HostComponent && stateNode !== null) {
const currentTarget = stateNode;
// Standard React on* listeners, i.e. onClick prop
if (captured !== null) {
const captureListener = getListener(instance, captured);
if (captureName !== null) {
const captureListener = getListener(instance, captureName);
if (captureListener != null) {
listeners.unshift(
createDispatchListener(instance, captureListener, currentTarget),
);
}
}
if (bubbled !== null) {
const bubbleListener = getListener(instance, bubbled);
if (bubbleName !== null) {
const bubbleListener = getListener(instance, bubbleName);
if (bubbleListener != null) {
listeners.push(
createDispatchListener(instance, bubbleListener, currentTarget),
Expand Down Expand Up @@ -1026,20 +1004,14 @@ export function accumulateEventHandleNonManagedNodeListeners(

const eventListeners = getEventHandlerListeners(currentTarget);
if (eventListeners !== null) {
const listenersArr = Array.from(eventListeners);
const targetType = ((event.type: any): DOMEventName);

for (let i = 0; i < listenersArr.length; i++) {
const listener = listenersArr[i];
const {callback, capture: isCapturePhaseListener, type} = listener;
if (type === targetType) {
if (inCapturePhase && isCapturePhaseListener) {
listeners.push(createDispatchListener(null, callback, currentTarget));
} else if (!inCapturePhase && !isCapturePhaseListener) {
listeners.push(createDispatchListener(null, callback, currentTarget));
}
eventListeners.forEach(entry => {
if (entry.type === targetType && entry.capture === inCapturePhase) {
listeners.push(
createDispatchListener(null, entry.callback, currentTarget),
);
}
}
});
}
if (listeners.length !== 0) {
dispatchQueue.push(createDispatchEntry(event, listeners));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ export default function useEvent(
clears.set(target, clear);
},
clear(): void {
const clearsArr = Array.from(clears.values());
for (let i = 0; i < clearsArr.length; i++) {
clearsArr[i]();
}
clears.forEach(c => {
c();
});
clears.clear();
},
};
Expand Down

0 comments on commit 0a00804

Please sign in to comment.