Skip to content
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

in-element helper doesn't fire destroy hooks on children when destinationElement is removed from DOM #20710

Open
apellerano-pw opened this issue Jun 28, 2024 · 4 comments

Comments

@apellerano-pw
Copy link

🐞 Describe the Bug

If there are elements nested inside an in-element helper, they get rendered to a remote element defined by destinationElement. If this remote element is removed from the DOM, the elements nested inside the in-element helper are destroyed. However, their destroy hooks are not triggered.

This can cause leakage and stale reference exceptions to occur, because modifier and component destroy hooks did not get a chance to do cleanup.

🔬 Minimal Reproduction

Glimdown reproduction

😕 Actual Behavior

  • The destroy function for the modifier is not called.
  • The destroy hook for the component is not called.

🤔 Expected Behavior

  • The destroy function for the modifier is called.
  • The destroy hook for the component is called.

🌍 Environment

  • Ember: - I've reproduced this going back to Ember 3.28.12
  • Ember-CLI: - 3.28.6
  • Node.js/npm: - Node 18.20.0, npm 10.5.0
  • OS: - macOS 14.5 Sonoma
  • Browser: - Chrome 126.0.6478.127 (Official Build) (x86_64)
@apellerano-pw
Copy link
Author

I've found a similar lifecycle issue for modifiers when conditionally rendered, and have repro steps in the issue reported to ember-modifier: ember-modifier/ember-modifier#613

Unsure if it's related, but wanted to call it out in case they are

@KoKuToru
Copy link

KoKuToru commented Jul 8, 2024

#in-element just attaches its children dom-elements to the target dom element.
inside embers component-tree nothing changes, the children of #in-element are still in the "original" place like defined in the hbs.
you can see this if you use the ember-inspector addon.

the moment #in-element gets destroyed it of course cleans up its children..

@apellerano-pw
Copy link
Author

#in-element just attaches its children dom-elements to the target dom element. inside embers component-tree nothing changes, the children of #in-element are still in the "original" place like defined in the hbs. you can see this if you use the ember-inspector addon.

the moment #in-element gets destroyed it of course cleans up its children..

Regardless of what Ember's internal virtual DOM thinks, the actual DOM elements get removed when the destination element is removed from the DOM. This leads to crashes when referencing those elements.

Since the modifier API is specifically designed to give you references to DOM elements and not Ember's internal virtual DOM representations, it's easy to write these kinds of crashes when using Ember.

@kategengler
Copy link
Member

I updated the Glimdown reproduction to use entirely Glimmer Components

The problem still exists.

The workaround for now is to duplicate the if around the {{#in-element}} or at least the contents. I'm actually surprised this works at all because I recall {{#in-element crashing if the destination did not exist in early days, but this may have just been from the polyfill.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants