From e6360f656f37b915f43b06f431b397ae2c98f608 Mon Sep 17 00:00:00 2001 From: Apoorva Verma Date: Thu, 2 Jul 2026 08:40:44 +0530 Subject: [PATCH] fix(scale): clamp out-of-domain input before applying gamma pow(t, gamma) returns NaN for a negative t with a fractional gamma, so an out-of-domain value threw instead of clamping to the endpoint. --- src/generator/scale.js | 4 +++- test/scales.test.js | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/generator/scale.js b/src/generator/scale.js index d60b89da..1220a52e 100644 --- a/src/generator/scale.js +++ b/src/generator/scale.js @@ -117,7 +117,9 @@ export default function (colors) { } if (_gamma !== 1) { - t = pow(t, _gamma); + // clamp before pow: a fractional gamma over a negative base returns + // NaN, so out-of-domain values must be pinned to the endpoints first + t = pow(limit(t, 0, 1), _gamma); } t = _padding[0] + t * (1 - _padding[0] - _padding[1]); diff --git a/test/scales.test.js b/test/scales.test.js index 8213b96d..4b151a69 100644 --- a/test/scales.test.js +++ b/test/scales.test.js @@ -430,4 +430,18 @@ describe('Some tests for scale()', () => { expect(f(100).hex()).toBe('#000000'); }); }); + + describe('gamma scale with out-of-domain input', () => { + const f = scale('YlGn').domain([5, 15]).gamma(1.2); + + it('clamps below domain to left endpoint', () => { + expect(f(4).hex()).toBe('#ffffe5'); + expect(f(4).hex()).toBe(f(5).hex()); + }); + + it('clamps above domain to right endpoint', () => { + expect(f(16).hex()).toBe('#004529'); + expect(f(16).hex()).toBe(f(15).hex()); + }); + }); });