Skip to content

Commit

Permalink
Treat null as undefined. (#241)
Browse files Browse the repository at this point in the history
* treat null as undefined

* undefined isNaN

* treat null as undefined

* more tests
  • Loading branch information
mbostock committed Mar 29, 2021
1 parent c7efc99 commit 116ac06
Show file tree
Hide file tree
Showing 12 changed files with 30 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/continuous.js
Expand Up @@ -83,7 +83,7 @@ export function transformer() {
}

function scale(x) {
return isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x)));
return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x)));
}

scale.invert = function(y) {
Expand Down
2 changes: 1 addition & 1 deletion src/identity.js
Expand Up @@ -5,7 +5,7 @@ export default function identity(domain) {
var unknown;

function scale(x) {
return isNaN(x = +x) ? unknown : x;
return x == null || isNaN(x = +x) ? unknown : x;
}

scale.invert = scale;
Expand Down
2 changes: 1 addition & 1 deletion src/quantile.js
Expand Up @@ -15,7 +15,7 @@ export default function quantile() {
}

function scale(x) {
return isNaN(x = +x) ? unknown : range[bisect(thresholds, x)];
return x == null || isNaN(x = +x) ? unknown : range[bisect(thresholds, x)];
}

scale.invertExtent = function(y) {
Expand Down
2 changes: 1 addition & 1 deletion src/quantize.js
Expand Up @@ -11,7 +11,7 @@ export default function quantize() {
unknown;

function scale(x) {
return x <= x ? range[bisect(domain, x, 0, n)] : unknown;
return x != null && x <= x ? range[bisect(domain, x, 0, n)] : unknown;
}

function rescale() {
Expand Down
2 changes: 1 addition & 1 deletion src/sequential.js
Expand Up @@ -18,7 +18,7 @@ function transformer() {
unknown;

function scale(x) {
return isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t0) * k10, clamp ? Math.max(0, Math.min(1, x)) : x));
return x == null || isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t0) * k10, clamp ? Math.max(0, Math.min(1, x)) : x));
}

scale.domain = function(_) {
Expand Down
2 changes: 1 addition & 1 deletion src/sequentialQuantile.js
Expand Up @@ -7,7 +7,7 @@ export default function sequentialQuantile() {
interpolator = identity;

function scale(x) {
if (!isNaN(x = +x)) return interpolator((bisect(domain, x, 1) - 1) / (domain.length - 1));
if (x != null && !isNaN(x = +x)) return interpolator((bisect(domain, x, 1) - 1) / (domain.length - 1));
}

scale.domain = function(_) {
Expand Down
2 changes: 1 addition & 1 deletion src/threshold.js
Expand Up @@ -8,7 +8,7 @@ export default function threshold() {
n = 1;

function scale(x) {
return x <= x ? range[bisect(domain, x, 0, n)] : unknown;
return x != null && x <= x ? range[bisect(domain, x, 0, n)] : unknown;
}

scale.domain = function(_) {
Expand Down
10 changes: 10 additions & 0 deletions test/identity-test.js
Expand Up @@ -31,6 +31,16 @@ tape("identity(x) coerces input to a number", function(test) {
test.end();
});

tape("identity(undefined) returns unknown", function(test) {
var s = scale.scaleIdentity().unknown(-1);
test.equal(s(undefined), -1);
test.equal(s(null), -1);
test.equal(s(NaN), -1);
test.equal(s("N/A"), -1);
test.equal(s(0.4), 0.4);
test.end();
});

tape("identity.invert(y) is the identity function", function(test) {
var s = scale.scaleIdentity().domain([1, 2]);
test.equal(s.invert(0.5), 0.5);
Expand Down
7 changes: 2 additions & 5 deletions test/linear-test.js
Expand Up @@ -209,8 +209,9 @@ tape("linear.rangeRound(range) accepts an iterable", function(test) {
test.end();
});

tape("linear.unknown(value) sets the return value for undefined and NaN input", function(test) {
tape("linear.unknown(value) sets the return value for undefined, null, and NaN input", function(test) {
var s = scale.scaleLinear().unknown(-1);
test.equal(s(null), -1);
test.equal(s(undefined), -1);
test.equal(s(NaN), -1);
test.equal(s("N/A"), -1);
Expand Down Expand Up @@ -388,15 +389,12 @@ tape("linear.ticks(X) spans linear.nice(X).domain()", function(test) {
var ticks = s.ticks(count);
test.deepEqual([ticks[0], ticks[ticks.length - 1]], s.domain());
}

check([1, 9], 2);
check([1, 9], 3);
check([1, 9], 4);

check([8, 9], 2);
check([8, 9], 3);
check([8, 9], 4);

check([1, 21], 2);
check([2, 21], 2);
check([3, 21], 2);
Expand All @@ -408,7 +406,6 @@ tape("linear.ticks(X) spans linear.nice(X).domain()", function(test) {
check([9, 21], 2);
check([10, 21], 2);
check([11, 21], 2);

test.end();
})

Expand Down
3 changes: 2 additions & 1 deletion test/quantile-test.js
Expand Up @@ -129,9 +129,10 @@ tape("quantile.invertExtent() returns the first match if duplicate values exist
test.end();
});

tape("quantile.unknown(value) sets the return value for undefined and NaN input", function(test) {
tape("quantile.unknown(value) sets the return value for undefined, null, and NaN input", function(test) {
var s = scale.scaleQuantile().domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]).range([0, 1, 2, 3]).unknown(-1);
test.equal(s(undefined), -1);
test.equal(s(null), -1);
test.equal(s(NaN), -1);
test.equal(s("N/A"), -1);
test.equal(s(2), 0);
Expand Down
8 changes: 8 additions & 0 deletions test/quantize-test.js
Expand Up @@ -36,6 +36,14 @@ tape("quantize(value) clamps input values to the domain", function(test) {
test.end();
});

tape("quantize.unknown(value) sets the return value for undefined, null, and NaN input", function(test) {
var s = scale.scaleQuantize().range([0, 1, 2]).unknown(-1);
test.equal(s(undefined), -1);
test.equal(s(null), -1);
test.equal(s(NaN), -1);
test.end();
});

tape("quantize.domain() coerces domain values to numbers", function(test) {
var s = scale.scaleQuantize().domain(["-1.20", "2.40"]);
test.deepEqual(s.domain(), [-1.2, 2.4]);
Expand Down
2 changes: 1 addition & 1 deletion test/threshold-test.js
Expand Up @@ -26,7 +26,7 @@ tape("threshold(x) returns undefined if the specified value x is not orderable",
test.equal(x(), undefined);
test.equal(x(undefined), undefined);
test.equal(x(NaN), undefined);
test.equal(x(null), "a"); // null < 1/3
test.equal(x(null), undefined);
test.end();
});

Expand Down

0 comments on commit 116ac06

Please sign in to comment.