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

bug: Memory leak sharing store instance #573

Open
3 tasks done
nwhittaker opened this issue Feb 25, 2025 · 1 comment
Open
3 tasks done

bug: Memory leak sharing store instance #573

nwhittaker opened this issue Feb 25, 2025 · 1 comment
Labels
Bug: Validated This PR or Issue is verified to be a bug within Stencil Store Help Wanted

Comments

@nwhittaker
Copy link

Prerequisites

Stencil Store Version

2.0.16

Stencil Version

4.0.27

Current Behavior

Given a store instance that is shared between multiple components, any disconnected components can remain detached in memory until the store's dispose() function is called.

Expected Behavior

A component with a shared store is able to be garbage collected when it's disconnected.

Steps to Reproduce

  1. Checkout the repo and switch to the @stencil-store/disconnected-memleak branch, if needed.
  2. In the project, run npm install and npm start.
  3. In the browser (e.g. Chrome 133), open devtools.
  4. In the viewport, click the Create my-global-counter button and optionally click the button that appears.
  5. Click the Destroy my global-counter button.
  6. Optionally repeat steps 4 and 5 a few times.
  7. Optionally wait 2s to give the store's internal clean-up logic to run.
  8. In the devtools Memory tab, click the Collect garbage button and note that no "Garbage collected" messages are logged despite the existence of a FinalizationRegistry in index.html.
  9. Take a heap snapshot, search in the report for "counter", and note one or more MyGlobalCounter and Detached <my-global-counter> entries exist.

Code Reproduction URL

https://github.com/nwhittaker/stencil-component/tree/%40stencil-store/disconnected-memleak

Additional Information

The store's elmsToUpdate map looks to be what is retaining the component. Additionally, a couple issues appear to be at play preventing the map from being cleaned up in this scenario:

  1. Disconnecting a component doesn't trigger the store to run it's clean-up logic.
  2. When the store's clean-up logic does next run (e.g. on the next set), it doesn't identify the component as disconnected.

I don't know if using a WeakReference for the component is feasible. It's also not clear to me why the isConnected logic is checking for isConnected on the component instance instead of the component's element:

https://github.com/ionic-team/stencil-store/blob/74b752566e113f8e22b786a15b44fd01c2e79b4e/src/subscriptions/stencil.ts#L14

If I naively wrap maybeElement in the @stencil/core getElement() function, I'm able to resolve the 2nd issue that's preventing garbage collection.

@ionitron-bot ionitron-bot bot added the triage label Feb 25, 2025
@christian-bromann
Copy link
Member

@nwhittaker thanks for raising the issue. Any contributions that may resolve this problem are much appreciated.

@christian-bromann christian-bromann added Help Wanted Bug: Validated This PR or Issue is verified to be a bug within Stencil Store and removed triage labels Feb 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug: Validated This PR or Issue is verified to be a bug within Stencil Store Help Wanted
Projects
None yet
Development

No branches or pull requests

2 participants