diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index cccfa46d4bf..f7a0d02c590 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -195,10 +195,20 @@ export default class LinearScaleBase extends Scale { } if (min === max) { - setMax(max + 1); + let offset = 1; + if (max >= Number.MAX_SAFE_INTEGER || min <= Number.MIN_SAFE_INTEGER) { + // In this case, the magnitude of the number is so large that + // max === max + 1 due to how IEEE754 doubles work. We need to increase + // the range by a larger number. Let's be safe and make this 5% of the number + // + // TODO - V4, make this the new default behaviour and eliminate +1 in other cases + offset = Math.abs(max * 0.05); + } + + setMax(max + offset); if (!beginAtZero) { - setMin(min - 1); + setMin(min - offset); } } me.min = min; diff --git a/test/specs/scale.linear.tests.js b/test/specs/scale.linear.tests.js index 8591ceba69d..e2ad37e41a2 100644 --- a/test/specs/scale.linear.tests.js +++ b/test/specs/scale.linear.tests.js @@ -482,6 +482,56 @@ describe('Linear Scale', function() { expect(chart.scales.y.max).toBe(1); }); + it('Should ensure that the scale has a max and min that are not equal - large positive numbers', function() { + // https://github.com/chartjs/Chart.js/issues/9377 + var chart = window.acquireChart({ + type: 'line', + data: { + datasets: [{ + // Value larger than Number.MAX_SAFE_INTEGER + data: [10000000000000000] + }], + labels: ['a'] + }, + options: { + scales: { + y: { + type: 'linear' + } + } + } + }); + + expect(chart.scales.y).not.toEqual(undefined); // must construct + expect(chart.scales.y.min).toBe(10000000000000000 * 0.95); + expect(chart.scales.y.max).toBe(10000000000000000 * 1.05); + }); + + it('Should ensure that the scale has a max and min that are not equal - large negative numbers', function() { + // https://github.com/chartjs/Chart.js/issues/9377 + var chart = window.acquireChart({ + type: 'line', + data: { + datasets: [{ + // Value larger than Number.MAX_SAFE_INTEGER + data: [-10000000000000000] + }], + labels: ['a'] + }, + options: { + scales: { + y: { + type: 'linear' + } + } + } + }); + + expect(chart.scales.y).not.toEqual(undefined); // must construct + expect(chart.scales.y.max).toBe(-10000000000000000 * 0.95); + expect(chart.scales.y.min).toBe(-10000000000000000 * 1.05); + }); + it('Should ensure that the scale has a max and min that are not equal when beginAtZero is set', function() { var chart = window.acquireChart({ type: 'bar',