1

I'm minifying Javascript in production with jsMin.php https://github.com/rgrove/jsmin-php/

Here is the unminified JS code:

  function arc(r, p, a) {
    return "A" + r + "," + r + " 0 " + +(a > Math.PI) + ",1 " + p;
  }

and the minified code:

function arc(r,p,a){return"A"+r+","+r+" 0 "++(a>Math.PI)+",1 "+p;}

When minified, the code throws an 'unexpected identifier' error. If I take the + sign before (a > Math.PI) away, it works okay.

I guess my question has two parts - why is this an error when it's all on one line, and am I changing the way it works by removing the second + sign? It seems to work okay without it, but I didn't write the code so I'm not entirely sure what it's doing.

Grim...
  • 16,518
  • 7
  • 45
  • 61
  • Sorry but, which is the sense of using two "+" operators together? Can't you just use one of them? – Niccolò Campolungo May 10 '13 at 14:28
  • 1
    The minified version parses just fine in both Firefox and Chrome. – Pointy May 10 '13 at 14:28
  • 1
    He's using the "+" to coerce the boolean to 0 or 1. – Pointy May 10 '13 at 14:29
  • Oups, indeed... I remove my wrong remark. – Laurent S. May 10 '13 at 14:43
  • just change "+(a > Math.PI)" to "Number(a > Math.PI)" ... – dandavis May 10 '13 at 16:15
  • from js-min.php git: "jsmin-php This project is unmaintained. I stopped using it years ago. You shouldn't use it. You shouldn't use any version of JSMin. There are much better tools available now." is better to use Uglify or Google Closure Compiler. I have tried with closure compiler and it works with or without "+" That's all folks! – aorlando May 10 '13 at 14:40
  • Minified code work in my chrome console: /*def */ function arc(r,p,a){return"A"+r+","+r+" 0 "+ +(a>Math.PI)+",1 "+p;} /*call*/ arc(3,2,0) /*result*/ "A3,3 0 0,1 2" /*definition 2*/ function arc(r,p,a){return"A"+r+","+r+" 0 "+ (a>Math.PI)+",1 "+p;} /*call */ arc(3,2,0) /* result */ "A3,3 0 false,1 2" Whats's the problem?!?! – aorlando May 10 '13 at 14:52
  • Yeah, I saw that as I was looking for the URL to put in my question. Dagnamit! – Grim... May 10 '13 at 15:37
  • Irritatingly, though, I ideally need a PHP minifier as it compresses the JS on the go (then versions it and saves it to a location that can be picked up by our CDN). I might just fix this one =/ – Grim... May 10 '13 at 15:46
  • @dandavis: Yup, or even `(+(a > Math.PI))`. – T.J. Crowder May 10 '13 at 16:27

2 Answers2

7

You shouldn't be getting an "unexpected identifier" error from the minified code you've presented. If you are, it's a bug in the JavaScript engine you're using it with. That was true of the code you posted originally, which was:

function arc(r,p,a){return"A"+r+","+r+" 0 "+ +(a>Math.PI)+",1 "+p;}
// You used to have a space here -----------^

But with the updated code you've posted:

function arc(r,p,a){return"A"+r+","+r+" 0 "++(a>Math.PI)+",1 "+p;}
// No space here anymore -------------------^

...it's a problem, because the ++ is an increment operator (either the prefix [++a] or postfix [a++]). And that would need an identifier (the thing to increment). The ++ just isn't valid in that position (the exact error you get is likely to vary by JavaScript engine).

You can defend the code against the minifier doing this by changing it slightly:

function arc(r, p, a) {
  return "A" + r + "," + r + " 0 " + (+(a > Math.PI)) + ",1 " + p;
}

The parens prevent the + and the other + from getting combined into ++. They also make the intent a bit clearer, IMHO.


Re the second part of your question, no, you can't remove that +, it will change how the function works. In particular, a > Math.PI will be true or false, and the + is there to make it a number (1 for true, 0 for false) before it's concatenated to the string. If you remove it, you'll see true or false in the string instead of 1 or 0.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • How about if the minified code was `function arc(r,p,a){return"A"+r+","+r+" 0 "++(a>Math.PI)+",1 "+p;}` (no space between the `+` signs)? – Grim... May 10 '13 at 15:39
  • @Grim...: Now *that* would be a problem, see the updated answer. – T.J. Crowder May 10 '13 at 16:21
  • @Grim...: Re your comment on a now-deleted comment-posted-as-a-answer that you need a PHP minifier, you can call out to the OS fairly easily in PHP, making it possible to use any minifier that works on your platform. I'm surprised (and horrified) to find that Crockford's own `jsmin` makes the `++` error (so it wasn't a bug in the PHP port), but (for instance) Google's [closure compiler](https://developers.google.com/closure/compiler/) runs on nearly any platform (it's Java based) and in simple mode it's effective without side effects. (Advanced mode requires changes to your code.) – T.J. Crowder May 10 '13 at 16:25
1

I guess the problem isn't really there, but just before, even if it looks like it's here because the invalid token is function. Try to add ; :

;function arc(r,p,a){return"A"+r+","+r+" 0 "+ +(a>Math.PI)+",1 "+p;};

I'm a little surprised that the minifier did let the ; before the }, though. It's useless.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758