From 7f8f114c29292797d0175dce1ec442ab9b302f24 Mon Sep 17 00:00:00 2001 From: tommyhgunz14 Date: Sat, 2 May 2026 15:53:53 +0000 Subject: [PATCH] fix: handle splice with single argument (no deleteCount) When Array.prototype.splice is called with only a start index and no deleteCount argument, JavaScript removes all elements from the start index to the end of the array. The _onDataSplice handler did not account for the omitted deleteCount, causing: 1. No elements being removed from metadata (count was undefined/falsy) 2. newCount becoming -1 (arguments.length - 2), leading to 'RangeError: Invalid array length' Fix by inferring the delete count from the metadata length when deleteCount is omitted, and clamping newCount to a minimum of 0. Closes #12191 --- src/core/core.datasetController.js | 6 ++- test/specs/core.datasetController.tests.js | 44 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 9b7126a93fd..8cb069d9efb 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -1062,10 +1062,14 @@ export default class DatasetController { } _onDataSplice(start, count) { + if (arguments.length <= 1) { + // splice(start) with no deleteCount removes everything from start onwards + count = this._cachedMeta.data.length - start; + } if (count) { this._sync(['_removeElements', start, count]); } - const newCount = arguments.length - 2; + const newCount = Math.max(arguments.length - 2, 0); if (newCount) { this._sync(['_insertElements', start, newCount]); } diff --git a/test/specs/core.datasetController.tests.js b/test/specs/core.datasetController.tests.js index 18011efcb95..b11a6d06e35 100644 --- a/test/specs/core.datasetController.tests.js +++ b/test/specs/core.datasetController.tests.js @@ -538,6 +538,50 @@ describe('Chart.DatasetController', function() { expect(controller.getParsed(2)).toBe(data[2]); }); + it('should correctly handle splice with a single argument (no deleteCount)', function() { + var data = [0, 1, 2, 3, 4, 5]; + var chart = acquireChart({ + type: 'line', + data: { + datasets: [{ + data: data + }] + } + }); + + var meta = chart.getDatasetMeta(0); + expect(meta.data.length).toBe(6); + + // splice(0) with no deleteCount should remove all elements (per spec) + data.splice(0); + chart.update(); + + expect(data.length).toBe(0); + expect(meta.data.length).toBe(0); + }); + + it('should correctly handle splice with a single argument from a mid-index', function() { + var data = [0, 1, 2, 3, 4, 5]; + var chart = acquireChart({ + type: 'line', + data: { + datasets: [{ + data: data + }] + } + }); + + var meta = chart.getDatasetMeta(0); + expect(meta.data.length).toBe(6); + + // splice(2) should remove elements from index 2 onwards + data.splice(2); + chart.update(); + + expect(data.length).toBe(2); + expect(meta.data.length).toBe(2); + }); + it('should re-synchronize metadata when the data object reference changes', function() { var data0 = [0, 1, 2, 3, 4, 5]; var data1 = [6, 7, 8];