Repository navigation
fix: compare Taro chart specs safely - #4723
dajiaohuang wants to merge 2 commits into
Conversation
|
|
||
| const leftIsArray = Array.isArray(left); | ||
| if (leftIsArray !== Array.isArray(right)) return false; | ||
| if (!leftIsArray && (!isPlainObject(left) || !isPlainObject(right))) return false; |
There was a problem hiding this comment.
[P2] Avoid treating recreated class-valued data rows as changed specs
With freshly constructed data rows having the same enumerable fields (e.g. new Row('A', 3) on each render), this line returns false at the first row. VChart's datum shape accepts arbitrary fields, and both wrappers interpret false as a reason to call updateSpec(..., true). A Node 22 reproduction using this comparator returned unequal on 100/100 equivalent rerenders, whereas the former JSON guard returned equal. Large datasets or dashboards consequently merge/render unchanged charts repeatedly. Compare enumerable fields of supported row objects, or handle this case at the wrapper boundary. This reproduces the comparator/guard, not a full Taro integration test.
| const leftObject = left as object; | ||
| const rightObject = right as object; | ||
| const activeRight = active.get(leftObject); | ||
| if (activeRight) return activeRight === rightObject; |
There was a problem hiding this comment.
[P2] Distinguish cyclic data graphs that share a right-hand node
active only tracks left-to-right pairs, so two different active left nodes may map to the same right node. For data values containing a two-node cycle versus a one-node self-cycle with identical scalar fields, isSpecEqual(oldSpec, newSpec) returns true while the reverse comparison returns false (reproduced using the actual comparator under Node 22). Since the wrappers call updateSpec only when this returns false, replacing such cyclic data is silently ignored. Track the reverse active mapping too, so changed cycle topology cannot compare equal. Full chart integration was not runnable without workspace dependencies.
🤔 This is a ...
🔗 Related issue link
Fixes #4656
💡 Background and solution
Both Taro wrappers used
JSON.stringifyas the spec-change guard. The shared comparator now compares functions by reference, handles cyclic arrays/plain objects, and compares Date values by timestamp. It retains structural comparison, so a newly allocated but equivalent spec still skipsupdateSpecinstead of switching to a reference-only guard.A synthetic cost check on Node v24.14.1 compared two equal specs containing 10,000 data rows (3 samples × 100 comparisons after warmup): JSON serialization took 89.3–92.3 ms per 100 comparisons; the cycle-safe comparator took 114.1–120.0 ms per 100 (~0.23–0.31 ms additional per comparison). This measures the comparison only, not full chart rendering.
📝 Changelog
☑️ Self-Check before Merge
Validation:
npm testinpackages/taro-vchartpassed (callback identity, structurally equal specs, Dates, and equal/different cycles). The helper passed strict TypeScript 4.9.5 checking. Full package build was not run because workspace dependencies are not installed in this task checkout.