-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Fix CanvasKit SVG clipPath leak #26227
Fix CanvasKit SVG clipPath leak #26227
Conversation
final html.Element clipDefs = | ||
_svgPathDefs!.querySelector('#sk_path_defs')!; | ||
for (String id in _svgClipDefs[viewId]!) { | ||
clipDefs.querySelector('#$id')?.remove(); |
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.
Should we keep a reference to the actual DOM Node of each clipDef (newClipPath
?), so we don't have to do any DOM lookups here?
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.
That's how I tried to do it at first (keeping a Map<int, List<html.Node>>
... but for whatever reason, when I remove the html.Node
created by html.DocumentFragment.svg
, it doesn't remove the <clipPath>
element from the DOM...
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 added a comment explaining why we can't just store the node directly.
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.
querySelector
used to be extremely expensive. I think the issue is that DocumentFragment is a transient concept. When attaching it to the DOM it simply iterates over its children and attaches them one by one. The fragment itself is not attached. Would it be possible to wrap all clip elements under a common parent and then attach the parent? This way we can keep the reference to the parent.
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.
The common parent exists, it seems to be the clipDef
tag. Maybe we can just inject it into the page just in case it's needed (right now, it's being probed every time there's a mutator of type clip, it seems)
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.
'The first collection was requested here:\n' | ||
'${firstCollection.stackTrace}\n\n' | ||
'The second collection was requested here:\n' | ||
'${collection.stackTrace}'); |
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 think dartfmt might do a better job if there was a trailing comma after the message.
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.
Done.
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! Small comment about not doing "many" querySelector calls (which is probably a micro-optimization and not worth the effort of the change)
Keeps LGTM! |
Landing even though tests are "In Progress". According to LUCI, they finished successfully. |
Removes old SVG clip path definitions when a platform view is recomposited. This is to avoid a leak caused by infinitely adding SVG clip definitions to the DOM.
Fixes flutter/flutter#82768
Pre-launch Checklist
writing and running engine tests.
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.