Summary
RolloverMarkerSvgAnnotation.create contains an assignment typo — this.currentColor === color; (a no-op comparison) where this.currentColor = color; was clearly intended. As a result currentColor is never assigned, the "color changed" check at the top of create() is always true, and the rollover marker SVG node is destroyed and re-created on every single update — i.e. on every mousemove over the chart, for every rollover-enabled series.
Affected versions
Verified present in the published npm packages:
- 4.0.944
- 5.2.35 (latest stable at the time of writing)
- 6.0.0-alpha.120
The bug
Charting/Visuals/Annotations/RolloverMarkerSvgAnnotation.js (line numbers from 5.2.35):
RolloverMarkerSvgAnnotation.prototype.create = function (xCalc, yCalc, xCoordSvgTrans, yCoordSvgTrans) {
var _a = this.tooltipProps, tooltipColor = _a.tooltipColor, markerColor = _a.markerColor;
var color = markerColor !== null && markerColor !== void 0 ? markerColor : tooltipColor;
if (this.svg && this.currentColor !== color) { // ← always true: currentColor is never set
this.clear();
}
if (!this.svg) {
this.currentColor === color; // ← line 54: comparison, no effect (typo for `=`)
var svgString = tooltipSvgTemplate(color);
var clippedSvgString = this.applyClipping(svgString, this.clipping);
var svgNode = annotationHelpers_1.annotationHelpers.createSvg(clippedSvgString, this.svgRoot, this.nextSibling);
this.setSvg(svgNode);
}
};
Since this.currentColor stays undefined forever:
- First update:
svg is undefined → marker SVG created (but currentColor not recorded).
- Every subsequent update while the mouse is in the series area:
this.svg && this.currentColor !== color → clear() removes the SVG node → re-created via createContextualFragment + DOM insertion.
So each mousemove pays one fragment parse + node removal + node insertion per rollover marker, forever. The marker is tiny, but the DOM/GC churn is measurable on busy pages and it defeats the entire purpose of the currentColor caching check.
Measured impact
Instrumented Range.prototype.createContextualFragment in a real application (one rollover-enabled series): exactly 1 marker SVG re-creation per mousemove. After patching the assignment (workaround below): 1 creation per session, marker repositioned via attributes as intended.
Suggested fix
this.currentColor = color;
Workaround we currently use
import { RolloverMarkerSvgAnnotation } from 'scichart';
const proto = RolloverMarkerSvgAnnotation.prototype as any;
const origCreate = proto.create;
proto.create = function (...args: unknown[]) {
origCreate.apply(this, args);
this.currentColor = this.tooltipProps.markerColor ?? this.tooltipProps.tooltipColor;
};
Related
While verifying this against 5.2.35 we also confirmed that the label cache texture poisoning reported in #289 is fixed in 5.2.35 (the deleteSafe call on entry replacement in LabelCache.setLabel is commented out there) — that one only affects the 4.x line.
Summary
RolloverMarkerSvgAnnotation.createcontains an assignment typo —this.currentColor === color;(a no-op comparison) wherethis.currentColor = color;was clearly intended. As a resultcurrentColoris never assigned, the "color changed" check at the top ofcreate()is always true, and the rollover marker SVG node is destroyed and re-created on every single update — i.e. on every mousemove over the chart, for every rollover-enabled series.Affected versions
Verified present in the published npm packages:
The bug
Charting/Visuals/Annotations/RolloverMarkerSvgAnnotation.js(line numbers from 5.2.35):Since
this.currentColorstaysundefinedforever:svgis undefined → marker SVG created (butcurrentColornot recorded).this.svg && this.currentColor !== color→clear()removes the SVG node → re-created viacreateContextualFragment+ DOM insertion.So each mousemove pays one fragment parse + node removal + node insertion per rollover marker, forever. The marker is tiny, but the DOM/GC churn is measurable on busy pages and it defeats the entire purpose of the
currentColorcaching check.Measured impact
Instrumented
Range.prototype.createContextualFragmentin a real application (one rollover-enabled series): exactly 1 marker SVG re-creation per mousemove. After patching the assignment (workaround below): 1 creation per session, marker repositioned via attributes as intended.Suggested fix
Workaround we currently use
Related
While verifying this against 5.2.35 we also confirmed that the label cache texture poisoning reported in #289 is fixed in 5.2.35 (the
deleteSafecall on entry replacement inLabelCache.setLabelis commented out there) — that one only affects the 4.x line.