TL;DR
An arrow function (x, y) => { x[y.k] = y.v; return x; } is minified to (x, y) => x[y.k] = y.v, x inside a function call, so the use of the comma , without the curl braces { } messes up the function arguments.
Is this my mistake, or an erroneous over-enthusiastic minifier?
I am using ReactJS.NET's BabelBundle in MVC.
More in-depth investigation and resolution
In a small React component, which is bundled with a BabelBundle in ReactJS.NET, the following code was causing me errors:
const fields = this.props.children.reduce((obj, field) => {
obj[field.props.field_key] = field.props.field_value;
return obj;
}, {});
const fieldsString = JSON.stringify(fields, null, 2);
The idea is that given an array of key-value pairs [ { field_key: 'x', field_value: 'y' }, ... ], it should create a flat object from those pairs: { x: y, ... }.
When minified, the following code was generated:
const n = this.props.children.reduce(
(n, t) => n[t.props.field_key] = t.props.field_value,
n,
{}),
t = JSON.stringify(n, null, 2);
Which gave me the following error: ReferenceError: "can't access lexical declaration `n' before initialization".
Notice how this arrow function:
(obj, field) => {
obj[field.props.field_key] = field.props.field_value;
return obj;
}
was minified to, using the comma operator , to get rid of the return keyword:
(obj, field) => obj[field.props.field_key] = obj.props.field_value, obj
But it did this within a (reduce) function call, where the comma , has its own meaning (to separate function arguments). That made the call, which should have been reduce(lambda, initialValue), become reduce(lambda, uninitialisedVariable, initialValue).
The uninitialised variable ended up with the variable name n, which is the same as the one to which the result of the reduce is assigned. This caused the lexical error (otherwise with var it becomes an undefined error) when it was used as the initial value to the reduce function.
The fix for my code was simple: to replace the arrow function with an old-style function:
const fields = this.props.children.reduce(function (obj, field) {
obj[field.props.field_key] = field.props.field_value;
return obj;
}, {});
const fieldsString = JSON.stringify(fields, null, 2);
Because the old-style function cannot have its curly braces { ... } removed, then it is minified without clobbering the function call:
const n = this.props.children.reduce(
function (n, t) {
return n[t.props.field_key] = t.props.field_value, n
},
{}),
t = JSON.stringify(n, null, 2);
Now, the point of my question is this: is the minifier's behaviour caused by a mistake of my own, or is it an error in the minifier itself?
And if it is in fact an error in the minifier, where can I report it? I was not exactly sure which version of which tool my bundle is being minified with.