-
Notifications
You must be signed in to change notification settings - Fork 241
chore(overlay): optimize backdrop click detection and event handling #5967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
📚 Branch Preview Links🔍 First Generation Visual Regression Test ResultsWhen a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:
Deployed to Azure Blob Storage: If the changes are expected, update the |
| if (topOverlay?.type === 'modal') { | ||
| this.closeOverlay(topOverlay); | ||
| if (hasModalOrPageOverlay) { | ||
| const clickedBackdrop = composedPath.some( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const composedPath = event.composedPath() is still executed at the top of the handler, the optimisation is effectively lost. Can we move it inside hasModalOrPageOverlay to get a performance win?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
event.composedPath() is already executed in handlePointerdown (line 168) and cached in this.pointerdownPath. So here it's just a property read, not a function call. I did do the optimization about avoiding iterating through the path array for backdrop detection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice cleanup!
Non blocking: The HTMLDivElement check is fine for now but it would be great if you can add a short comment asserting that the backdrops are guaranteed to be <div>s and also if you can lock a test with this that would be great. Otherwise you can add a more semantic element + class check for future proofing this.
| if (hasModalOrPageOverlay) { | ||
| const clickedBackdrop = composedPath.some( | ||
| (el) => | ||
| el instanceof HTMLDivElement && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a little concern here: We are assuming that the backdrop will always be div and nothing else. This might not hold long term and will break the backdrop detection in future. Can you use a element + class check just to make sure we are detecting how its implemented rather than if its a backdrop or not?
const clickedBackdrop = composedPath.some(
(el) =>
el &&
(el as Element).nodeType === Node.ELEMENT_NODE &&
(el as Element).classList?.contains('modal-backdrop')
);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I nerded out a little bit on this, ran some performance benchmarks and and here are my results:
Testing with backdrop at index 5 in a path of 12 elements
Running 100,000 iterations per approach
instanceof Element + hasAttribute : 16.18ms
nodeType + hasAttribute : 19.15ms
Optional chaining : 10.02ms
instanceof Element + matches : 15.50ms
instanceof HTMLDivElement + classList : 9.41ms
tagName + hasAttribute : 15.39ms
--- Results (fastest to slowest) ---
1. instanceof HTMLDivElement + classList : 9.41ms (100.0% of fastest)
2. Optional chaining : 10.02ms (93.9% of fastest)
3. tagName + hasAttribute : 15.39ms (61.1% of fastest)
4. instanceof Element + matches : 15.50ms (60.7% of fastest)
5. instanceof Element + hasAttribute : 16.18ms (58.2% of fastest)
6. nodeType + hasAttribute : 19.15ms (49.1% of fastest)
--- Testing worst case (backdrop NOT in path) ---
1. instanceof HTMLDivElement + classList : 17.01ms (100.0% of fastest)
2. instanceof Element + hasAttribute : 23.15ms (73.5% of fastest)
3. Optional chaining : 26.70ms (63.7% of fastest)
4. instanceof Element + matches : 34.63ms (49.1% of fastest)
5. nodeType + hasAttribute : 38.58ms (44.1% of fastest)
6. tagName + hasAttribute : 42.94ms (39.6% of fastest)
So let's go for instanceof HTMLDivElement + classList! If the backdrop ever becomes other element other than a DIV, at least 6 tests fail, so we're covered on that front 😄
Co-authored-by: Rajdeep Chandra <rajrock38@gmail.com>
Rajdeepc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks for bringing this in.
Description
This PR optimizes event handling performance in the overlay system by optimizing backdrop click detection. I added an early return check to skip backdrop detection when no modal/page overlays are open, so we don't need to iterate through the event's
composedPathon everypointerupevent. I also changedinstanceof HTMLElementtoinstanceof HTMLDivElementfor faster filtering when checking for backdrop elements, since backdrops are always<div>elements.I took the opportunity and also eliminated redundant
stopPropagation()calls that were placed afterstopImmediatePropagation(), sincestopImmediatePropagation()already prevents all further event propagation.Motivation and context
Some code cleanup feels nice?
Author's checklist
Reviewer's checklist
patch,minor, ormajorfeatures