diff --git a/src/bin.js b/src/bin.js index 28d64aa..6f179ad 100644 --- a/src/bin.js +++ b/src/bin.js @@ -66,9 +66,11 @@ export default function bin() { } // Remove any thresholds outside the domain. - var m = tz.length; - while (tz[0] <= x0) tz.shift(), --m; - while (tz[m - 1] > x1) tz.pop(), --m; + // Be careful not to mutate an array owned by the user! + var m = tz.length, a = 0, b = m; + while (tz[a] <= x0) ++a; + while (tz[b - 1] > x1) --b; + if (a || (b < m)) tz = tz.slice(a, b), m = b - a; var bins = new Array(m + 1), bin; @@ -116,7 +118,7 @@ export default function bin() { }; histogram.thresholds = function(_) { - return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; + return arguments.length ? (threshold = typeof _ === "function" ? _ : constant(Array.isArray(_) ? slice.call(_) : _), histogram) : threshold; }; return histogram; diff --git a/test/bin-test.js b/test/bin-test.js index 389e505..e6453b2 100644 --- a/test/bin-test.js +++ b/test/bin-test.js @@ -241,6 +241,22 @@ it("bin(data) assigns integer values to the correct bins", () => { assert.deepStrictEqual(bin().domain([3, 8])(eights), [box([], 3, 4), box([], 4, 5), box([], 5, 6), box([], 6, 7), box(eights, 7, 8)]); }); +it("bin(data) does not mutate user-supplied thresholds as an array", () => { + const thresholds = [3, 4, 5, 6]; + const b = bin().domain([4, 5]).thresholds(thresholds); + assert.deepStrictEqual(b([5]), [box([], 4, 5), box([5], 5, 5)]); + assert.deepStrictEqual(thresholds, [3, 4, 5, 6]); + assert.deepStrictEqual(b.thresholds()(), [3, 4, 5, 6]); +}); + +it("bin(data) does not mutate user-supplied thresholds as a function", () => { + const thresholds = [3, 4, 5, 6]; + const b = bin().domain([4, 5]).thresholds(() => thresholds); + assert.deepStrictEqual(b([5]), [box([], 4, 5), box([5], 5, 5)]); + assert.deepStrictEqual(thresholds, [3, 4, 5, 6]); + assert.deepStrictEqual(b.thresholds()(), [3, 4, 5, 6]); +}); + function box(bin, x0, x1) { bin.x0 = x0; bin.x1 = x1;