Prevent dom-repeat's forwardHostProp from retaining HTMLElement this
#5599
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
TL;DR: The function
__ensureTemplatized
in elements/dom-repeat.jscaused the
templatizeInstanceClass
to retain a reference to theHTMLElement (i.e. the DomRepeat object) that triggered creation of the
templatizeInstanceClass (see templatize.js:566).
The function __ensureTemplatized in elements/dom-repeat.js contained
an arrow function definition for the
MutationObserver
and thefunction for
forwardHostProp
in it; the arrow function definitionforces context allocation of
this
so it can accesses it later. Thisintroduces false sharing with
forwardHostProp
: that function refersto the same context, and transitively also to the
this
of__ensureTemplatized
, although it neither references nor accesses it.Note that
forwardHostProp
will get it's ownthis
variable on eachinvocation). This results in the HTMLElement that originally created
the __ctor to be retained (i.e. not cleaned up by the GC). The
retainment path can be seen in the following heap snapshot:
https://imgur.com/a/javUpRx
In the screenshot, the tab on the top shows the detached HTML element
(the
HTMLElement
that created the __ctor, which I suspect is reallya
DomRepeat
object inheriting fromHTMLElement
) and the bottom showsthe retainment chain. The retainment chain is to be read as follows:
Line 1:
this
is a property of a context. Line 2: that context isthe context of the function
forwardHostProp
. Line 3: That functionis stored in a property called
forwardHostProp
of an Object. Line 4:that Object is stored in a property
__templatizeOptions
in an objectwith constructor
TemplateLegacy
. Line 5: ThatTemplateLegacy
objectis the
__proto__
of an object constructed with constructorklass
.Line 6: That object, in turn, is the
__proto__
of an objectconstructed with
klass$jscomp$1
. Line 7: that object is a propertycalled
__templatizeInstance
on am HTMLElement object. Line 8: thatHTMLElement is an internal property of a ShadowRoot object, and so on.
This CL fixes this problem by moving the arrow function into its own
method
__waitForTemplate
. This causes the context of__waitForTemplate
to get a context-allocatedthis
, but preventsthe context of
__ensureTemplatized
from having a context-allocatedthis
. Unfortunately, it is hard to verify this fix, becauseinspecting the function object for
forwardHostProp
shows all thesecontext collapsed into 'Local'. Basically, the only way to verify a
fix for an issue like this atm. is to get a reproducible way to
produce a heap snapshot that exhibits the problem, and then verifying
that the problem is not present anymore after applying the fix.
In my repro (navigating between to pages of Gerrit code review tool)
this got rid of about 37 detached HTMLElements.
Reference Issue