Detecting (and cleaning) trailing commas in array literals?

Jul 5, 2013 at 9:52 PM
I've noticed that ajaxmin seems to cleanup trailing commas in Object literals.

For example, when this object literal (which has a trailing comma after baz: 4):
var foo = {
  bar: 3,
  baz: 4,
is crunched, the trailing comma has been removed:
var foo={bar:1,baz:4}
But if I have a trailing comma in an array literal, it is left behind.
If I crunch this:
var foo = {
  bar: 3,
  baz: 4,
var bat = [
I get this
var foo={bar:1,baz:4},bat=["One","Two",]
Is this the intended behavior? If so is there a way to override it to either warn on the trailing comma, or have it cleaned?
The trailing comma causes no end of headaches in IE8.
Jul 6, 2013 at 5:11 AM
The short answer is: yes, this is intended behavior.

The longer answer has two parts. First off, a trailing comma in an object literal adds absolutely nothing to the object literal. It adds nothing, and some older browsers will actually throw a syntax error if a trailing comma is present. Because of this (error in older browsers, absolutely no value in newer browsers), a trailing comma is automatically eliminated in the AjaxMin output.

Array literals are a completely different beast. Not only are trailing commas allowed in all browsers, they are significant. So no: I absolutely cannot eliminate trailing commas in array literals; they actually means something and I'd be changing the semantic meaning of the code.

The most I'd be willing to do is throw a severity-2 warning about cross-browser issues (which won't show up by default; you'd have to raise the warning level via the -warn:N switch to see it) when trailing commas are parsed in the code. This is because although they are significant, different browsers treat them differently. Syntactically in modern browsers, a comma after a comma means that there is an item there in the literal, its value is undefined, and the length is adjusted accordingly. Officially, a single trailing comma is ignored because it's not a comma-after-a-comma; but not all browsers implement the language that way. Take this code for instance; put it on a webpage and open it in a bunch of different browsers:
        function out(txt)
            var arr = eval(txt);
            document.write("<h1>array: " + txt + "; length=" + arr.length + "</h1>");

Most browsers (IE9+, Safari, Chrome, Firefox) will correctly output the lengths 0, 3, 3, 4, 5, and 6, as per the ECMA specs. Opera 12.12 is weird and outputs 0,3,4,4,5,6 (go figure; I'm currently downloading 12.16 to see if they've fixed that bug, but it seems to be stalled). IE8 and below add elements after every comma. so they don't ignore the last one and output 0,3,4,5,6,7.

So yeah: I feel your pain about IE8 and below. Lots of things don't behave according to the specs in those browsers. I'll see about adding a sev-2 cross-browser warning for you, but I can't automatically clean it up because I don't know the intention of the developer. They might only be targeting a particular browser and don't care about cross-browser behavior, or they might be using the differences as a behavioral browser-sniff.
Jul 6, 2013 at 5:19 AM
(note: nope -- Opera 12.16, the latest version at this time, still has the funky bug that creates a behavior different than any other browser when it comes to trailing commas in array literals.)
Jul 8, 2013 at 6:43 PM
Thanks for the detailed answer. :)
Yeah I wrote my own trailing comma detector (did you know, with a little effort, you can include powershell directly in your msbuild project?), and found that we have code that depends on that behavior, I'll be talking to some people later today ;).

Still it's caused quite a few hard to diagnose bugs, so I'm leaving it in, with exclusions, and if we could get a warning from AjaxMin that would be great.
Jul 8, 2013 at 6:47 PM
4.96 swill throw a sev-2 cross-browser warning if it finds trailing commas in array literals.
Jul 12, 2013 at 5:48 PM
Okay, I just release 4.96. It should throw a sev-2 (cross-browser) warning when trailing commas are detected in array literals. Remember that the default severity threshold is 0, so you will have to adjust the allowed warning level to at least 2 using the -warn:N switch (if you haven't already).
Jul 13, 2013 at 4:22 AM
Great, thanx for the quick turnaround.