I am transpiling this package wirh ClojureScript, and faced a peculiar behaviour when using the SI prefix formatter (s
type). The prefix always rendered as undefined
, e.g. 1undefined
, 100undefined
, 42undefined
, etc. This was caused by the fact that prefixExponent
on line 84 was invariably undefined
. The issue appears to be that formatPrefixAuto.js
on line 10 expects prefixExponent
to be in (global) scope. The transpilier however copies the value in an attempt to alias the name, here's the transpiled code:
goog.provide("module$usr$src$node_modules$d3_format$src$formatPrefixAuto");
goog.require("module$usr$src$node_modules$d3_format$src$formatDecimal");
var prefixExponent$$module$usr$src$node_modules$d3_format$src$formatPrefixAuto;
var $jscompDefaultExport$$module$usr$src$node_modules$d3_format$src$formatPrefixAuto = function(x, p) {
/*snip*/
var i = exponent - (prefixExponent$$module$usr$src$node_modules$d3_format$src$formatPrefixAuto = /*snip*/)
/*snip*/
};
module$usr$src$node_modules$d3_format$src$formatPrefixAuto.prefixExponent = prefixExponent$$module$usr$src$node_modules$d3_format$src$formatPrefixAuto;
module$usr$src$node_modules$d3_format$src$formatPrefixAuto.default = $jscompDefaultExport$$module$usr$src$node_modules$d3_format$src$formatPrefixAuto;
...and prefixExponent$$module$usr$src$node_modules$d3_format$src$formatPrefixAuto
is never referenced again. I don't know if this is still an issue with Closure advanced optimisations (maybe it is, maybe it isn't).
I think that it's fair to say that formatPrefixAuto.js
is trying to expose its internals and it hasn't ended well in my case.
I can think of a couple of alternatives to fix the problem, both feel like hacks to me:
Box prefixExponent
Instead of exposing prefixExponent
as a primitive that is passed by value, wrap it in an object:
export var internals;
export default function(x, p) {
/*snip*/
var i = exponent - (internals.prefixExponent = /*snip*/) + 1
/*snip*/
}
Perhaps the intention was to attach it to the exported function? I.e.
export default function formatPrefixAuto(x, p) {
/*snip*/
var i = exponent - (formatPrefixAuto.prefixExponent = /*snip*/) + 1
/*snip*/
}
Add to API
Instead of using some sneaky backdoor, go through a window at the front:
export default function(x, p, window) {
window = window || {};
/*snip*/
var i = exponent - (window.prefixExponent = /*snip*/) + 1
/*snip*/
}
(Okay, so the naming is a little cheeky, but you get the idea!)
Or accept an optional callback:
export default function(x, p, cb) {
var prefixExponent;
/*snip*/
var i = exponent - (prefixExponent = /*snip*/) + 1
/*snip*/
cb && cb(prefixExponent);
/*snip*/
}
Then locale.js
would need to do something like this:
var window = {};
value = formatType(Math.abs(value), precision, window);
valueSuffix = (type === "s" ? prefixes[8 + window.prefixExponent / 3] : "") + /*snip*/ "";
or
var prefixExponent;
value = formatType(Math.abs(value), precision, x => prefixExponent = x);
valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + /*snip*/ "";