SEPURI-SAI-KRISHNA opened a new pull request, #21733:
URL: https://github.com/apache/echarts/pull/21733
<!-- Please fill in the following information to help us review your PR more
efficiently. -->
## Brief Information
This pull request is in the type of:
- [x] 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
<!-- No existing issue; found while auditing component teardown paths. -->
## Details
### Before: What was the problem?
When `tooltip.showDelay` is greater than `0`, showing a tooltip schedules a
timer in `TooltipView#_showOrMove`:
```js
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:
```js
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.
- [x] 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
- [x] 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.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]