Skip to content

fix(tooltip): clear pending timers on dispose - #21733

Open
SEPURI-SAI-KRISHNA wants to merge 1 commit into
apache:masterfrom
SEPURI-SAI-KRISHNA:fix/tooltip-clear-pending-timers-on-dispose
Open

fix(tooltip): clear pending timers on dispose#21733
SEPURI-SAI-KRISHNA wants to merge 1 commit into
apache:masterfrom
SEPURI-SAI-KRISHNA:fix/tooltip-clear-pending-timers-on-dispose

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown

Brief Information

This pull request is in the type of:

  • bug fixing
  • new feature
  • others

What does this PR do?

Clears the tooltip's pending setTimeout handles when the tooltip view is disposed, so a delayed callback can no longer run against a torn-down view and throw.

Fixed issues

Details

Before: What was the problem?

When tooltip.showDelay is greater than 0, showing a tooltip schedules a timer in TooltipView#_showOrMove:

const delay = tooltipModel.get('showDelay');
cb = bind(cb, this);
clearTimeout(this._showTimout);
delay > 0
    ? (this._showTimout = setTimeout(cb, delay) as any)
    : cb();

TooltipView#dispose never cleared that handle, but it did reset the members the callback depends on:

this._tooltipContent = null;
this._tooltipModel = null;

So if the chart is disposed while a showDelay timer is still pending — which is the normal case when a user hovers a chart and then the view is unmounted (React/Vue route change, tab switch, echarts.dispose() before re-init) — the callback fires afterwards and dereferences the nulled content:

TypeError: Cannot read properties of null (reading 'setEnterable')
    at TooltipView._showTooltipContent
    at TooltipView.<anonymous>

The error surfaces up to showDelay milliseconds after the chart is gone, so it is reported as a random uncaught exception rather than being traced back to dispose. It reproduces with both renderMode: 'html' and renderMode: 'richText', and with both trigger: 'item' and trigger: 'axis'.

Two smaller teardown leaks are in the same area:

  • _refreshUpdateTimeout is also left pending. Its callback is guarded by !api.isDisposed() so it does not throw, but the timer keeps the disposed view reachable until it fires.
  • TooltipRichContent#dispose does not clear its hideDelay timer, while TooltipHTMLContent#dispose already does clear both of its timers.

After: How does it behave after the fixing?

TooltipView#dispose now clears _showTimout and _refreshUpdateTimeout, and TooltipRichContent#dispose clears _hideTimeout to match TooltipHTMLContent#dispose.

The timers are cleared at the very top of dispose, before the env.node || !api.getDom() early return and before the members are nulled, so the cleanup cannot be skipped.

Disposing a chart with a pending tooltip timer no longer throws, and no tooltip timer outlives the chart.

Document Info

One of the following should be checked.

  • This PR doesn't relate to document changes
  • The document should be updated later
  • The document changes have been made in apache/echarts-doc#xxx

Misc

Security Checking

  • This PR uses security-sensitive Web APIs.

ZRender Changes

  • This PR depends on ZRender changes (ecomfe/zrender#xxx).

Related test cases or examples to use the new APIs

Added test/ut/spec/component/tooltip/dispose.test.ts, covering showDelay for
html/richText render modes and item/axis triggers, plus the richText
hideDelay timer. Each case asserts that no tooltip timer is left pending after
dispose and that running pending timers does not throw.

Verified that the four showDelay cases fail on master with
TypeError: Cannot read properties of null (reading 'setEnterable') and pass with this change.

npm run test (27 suites / 199 tests), npx tsc --noEmit, and eslint on the
changed files all pass.

Merging options

  • Please squash the commits into a single one when merging.

Other information

While auditing this area I also noticed that _showTimout is not cleared in
manuallyHideTip, which is the separate problem reported in #16859 (closed as
stale) and attempted in the unmerged #17499. That is a behavioural change rather
than a teardown fix, so it is intentionally left out of this PR.

@echarts-bot

echarts-bot Bot commented Aug 15, 2026

Copy link
Copy Markdown

Thanks for your contribution!
The community will review it ASAP. In the meanwhile, please checkout the coding standard and Wiki about How to make a pull request.

Please DO NOT commit the files in dist, i18n, and ssr/client/dist folders in a non-release pull request. These folders are for release use only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant