Version
2.1.6 (also reproduces on 2.1.5)
Link to Minimal Reproduction
https://gist.github.com/chendaxin-tk/dfb94e188970055a1ddadc2332194c23
Self-contained HTML — save it and open in a browser, it loads vchart 2.1.6 from unpkg and prints the result on the page.
Steps to Reproduce
- Render a chart whose
spec.background is the mark form { fill: <gradient> }, with spec.theme.background = 'transparent' (the canvas base color has to be transparent, otherwise the gradient's alpha composites against it).
- Call
updateSpec() with a spec where background is a color string ('#4e83fd') and theme.background is back to an opaque color ('#ffffff').
- Look at the canvas.
A plain updateSpec(spec) is enough — no extra arguments needed.
Current Behavior
The canvas still paints the old gradient. Sampling the bottom-right pixel:
after render : pixel=255,159,67 stage.background=transparent
after update : pixel=255,159,67 stage.background=#4e83fd <-- still the gradient
Note stage.background is updated correctly to #4e83fd. The problem is that the background mark created from the previous { fill } spec is never rebuilt or removed, and it covers the whole viewBox — so the corrected canvas base color is invisible and nothing changes on screen.
Isolating it — same repro, only what changes in the update spec varies:
| # |
changed in updateSpec |
result |
| A |
background and theme |
❌ old gradient stays |
| B |
background only, theme untouched |
✅ blue |
| C |
background and theme, called as updateSpec(spec, false, { reuse: false, morph: false }, { change: true, reMake: true }) |
✅ blue |
Expected Behavior
Case A should behave like case B — the new background should be painted.
Probable Cause
In core/vchart.js, updateSpec only compares background when the theme is unchanged:
isEqual(lastSpec.theme, this._spec.theme)
? (isEqual(this._spec.background, lastSpec.background) || (result.reMake = !0, result.changeBackground = !0))
: result.changeTheme = !0;
When both change in the same call, the ternary takes the changeTheme branch, so reMake / changeBackground are never set and the background mark is not rebuilt. setBackground() still runs indirectly via _setCurrentTheme() → _updateCurrentTheme(), which is why stage.background looks right while the canvas does not change.
This looks like a remaining gap in the fix for #3054, which covered the case where only background changes.
Forcing reMake: true (case C above) is a workaround, but it rebuilds the whole chart.
Additional observation (could not minimize — treat as a lead, not a confirmed repro)
In a larger application the same gradient → solid transition throws instead of silently keeping the old background:
TypeError: Cannot read properties of undefined (reading 'group')
at GroupMark._compileProduct (...)
which aborts the entire updateSpec. In mark/base/base-mark.js, _compileProduct guards option on two lines but dereferences it bare on a third:
_compileProduct(option) {
this.commit(), this._context = null == option ? void 0 : option.context; // guarded
const product = this.getProduct();
if (this._visible) {
if (isValid(product)) option.group && product.parent !== option.group && option.group.appendChild(product); // NOT guarded
else {
if (!this.getCompiler().isInited) return;
this._initProduct(null == option ? void 0 : option.group); // guarded
}
I was not able to reproduce this one in isolation, so I am reporting it only as a pointer — the inconsistent guarding is visible statically and may or may not be related to the main issue above.
Environment
- @visactor/vchart 2.1.6 (UMD build from unpkg) and 2.1.5
- Chromium (Playwright), Linux
Version
2.1.6 (also reproduces on 2.1.5)
Link to Minimal Reproduction
https://gist.github.com/chendaxin-tk/dfb94e188970055a1ddadc2332194c23
Self-contained HTML — save it and open in a browser, it loads vchart 2.1.6 from unpkg and prints the result on the page.
Steps to Reproduce
spec.backgroundis the mark form{ fill: <gradient> }, withspec.theme.background = 'transparent'(the canvas base color has to be transparent, otherwise the gradient's alpha composites against it).updateSpec()with a spec wherebackgroundis a color string ('#4e83fd') andtheme.backgroundis back to an opaque color ('#ffffff').A plain
updateSpec(spec)is enough — no extra arguments needed.Current Behavior
The canvas still paints the old gradient. Sampling the bottom-right pixel:
Note
stage.backgroundis updated correctly to#4e83fd. The problem is that the background mark created from the previous{ fill }spec is never rebuilt or removed, and it covers the whole viewBox — so the corrected canvas base color is invisible and nothing changes on screen.Isolating it — same repro, only what changes in the update spec varies:
updateSpecbackgroundandthemebackgroundonly,themeuntouchedbackgroundandtheme, called asupdateSpec(spec, false, { reuse: false, morph: false }, { change: true, reMake: true })Expected Behavior
Case A should behave like case B — the new background should be painted.
Probable Cause
In
core/vchart.js,updateSpeconly comparesbackgroundwhen the theme is unchanged:When both change in the same call, the ternary takes the
changeThemebranch, soreMake/changeBackgroundare never set and the background mark is not rebuilt.setBackground()still runs indirectly via_setCurrentTheme()→_updateCurrentTheme(), which is whystage.backgroundlooks right while the canvas does not change.This looks like a remaining gap in the fix for #3054, which covered the case where only
backgroundchanges.Forcing
reMake: true(case C above) is a workaround, but it rebuilds the whole chart.Additional observation (could not minimize — treat as a lead, not a confirmed repro)
In a larger application the same gradient → solid transition throws instead of silently keeping the old background:
which aborts the entire
updateSpec. Inmark/base/base-mark.js,_compileProductguardsoptionon two lines but dereferences it bare on a third:I was not able to reproduce this one in isolation, so I am reporting it only as a pointer — the inconsistent guarding is visible statically and may or may not be related to the main issue above.
Environment