Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #7311 (closed enhancement: duplicate)

Opened 1 year ago

Last modified 3 months ago

Requesting syntactical cleanup

Reported by: TimTripcony Assigned to: mislav
Priority: normal Milestone:
Component: Prototype Version:
Severity: major Keywords: lint pack
Cc:

Description

I use Prototype heavily in non-Rails projects, and typically use Dean Edwards' Packer to minimize the file size for all Javascript. This requires syntax to be precise (no missing semicolons, no missing curly braces) because it removes all line breaks. Each time Prototype is updated, I spend a significant amount of time updating abbreviated code blocks (missing curly braces on if's, for's, while's, etc.) before I can compress the new version. I'm requesting that the formal syntax be utilized going forward so that I can avoid having to repeat this step every time a new version is released.

Change History

(follow-up: ↓ 4 ) 02/06/07 16:41:17 changed by mislav

  • summary changed from Requesting syntactical cleanup for prototype.js to Requesting syntactical cleanup.

Use Dojo ShrinkSafe. It knows JavaScript so you can obfuscate scripts even without semicolons at all.

Minified version of Prototype 1.5 is available, although not supported officially.

This has been requested multiple times (#4191, #4729, #7301 ...) and ultimately rejected because:

  • our code is valid JavaScript and we don't feel like changing style;
  • change packers, not every library in the world;
  • minification is overrated - good gzip settings do better.

02/07/07 00:53:06 changed by mislav

Adding #7201 (patch to make Prototype lint-safe) to the above list ... This is getting out of hand. We will have an internal discussion about this. I'm not closing these tickets anymore until the matter is resolved properly.

02/27/07 12:51:05 changed by mislav

  • cc set to mislav.
  • keywords set to lint pack.
  • type changed from defect to enhancement.
  • severity changed from minor to major.

Read the guide from Andrew Dupont.

... also adding #7201 to the above list ...

(in reply to: ↑ 1 ) 02/27/07 13:31:01 changed by danielgalan

Use Dojo ShrinkSafe. It knows JavaScript so you can obfuscate scripts even without semicolons at all.

Yeah, but it relies on Mozilla Rhino, and that's GPL.

Minified version of Prototype 1.5 is available, although not supported officially.

Why not, so why don't write clean JS, instead you break support and possiblities to minify/obfuscate/whatever.

- our code is valid JavaScript and we don't feel like changing style;

We don't need an obfuscator with your Codeguidelines ;D

minification is overrated - good gzip settings do better.

That depends on the environment. If you have CPU cycles left, gzip might be better, otherwise you preprocess the JS once, and have ratios about 75%, that can save some GByte on high traffic websites, each day. Of course, with gzip and minifed even more..

Anyway, it's a pity.

Best regards Daniel

04/02/07 21:32:18 changed by orangechicken

  • priority changed from low to normal.

Just voting for this ticket.

Using anything similar to packer with prototype/scriptaculous leads to buggy compressed files because of missing semi-colons, etc. Would be nice (and not difficult) to add the few semi-colons and curly braces to make prototype compression-friendly (and lint-compatible).

Combining packer-style compression techniques with good gzip settings results in a 80-90% reduction in transferred size and that's important enough to validate the minimal work necessary to make the changes to prototype.

I don't know how this qualifies as 'major' in severity but it's definite not low priority.

(follow-up: ↓ 8 ) 04/02/07 22:03:48 changed by mislav

  • cc deleted.
  • owner changed from sam to mislav.

We may move our little finger to add a semicolon here and there. We will not make it lint-compatible since it requires changing code, and we love our code as it is.

Can you explain how adding semicolons helps reduce size, please?

04/02/07 22:13:26 changed by orangechicken

Adding the semi-colons where appropriate will allow prototype/scriptaculous users to run the libraries through compression tools such as Packer and have them come out the other end without the errors caused by the "missing" semi-colons.

I partially agree that the packer-style tools should handle syntactically-correct Javascript. But that syntactical-correctness evaporates once the line-breaks are removed (and thus relies on the semi-colons).

Making it lint compatible would be nice, but yeah would probably be more work than it's worth. Adding the semi-colons, however, isn't a lot of work - about 20 minutes to go through the files and add the semi-colons (even less with a couple good Regexes to find them) - and it's good-neighborly.

(in reply to: ↑ 6 ) 04/02/07 22:16:47 changed by mislav

Replying to mislav:

Can you explain how adding semicolons helps reduce size, please?

I'm sorry, I mistyped. I meant curly braces, not semicolons

04/02/07 23:25:28 changed by orangechicken

In the same way: It would let compression tools perform their magic. Then, combined with good gzip settings, leads to nice, small libraries.

04/03/07 10:32:54 changed by mislav

Imagine the following:

if(some_condition)
some.really.long.line().foo;

Now, the only possible way to reduce the size of this example is to remove the line break (1 byte)

if(some_condition)some.really.long.line().foo;

Packers (most of them) can't do this automatically, they need curly braces - but putting curly braces in actually makes it 1 byte longer

if(some_condition){some.really.long.line().foo;}

This is why I don't understand the cries about curly braces

04/03/07 16:06:33 changed by TimTripcony

I think you're overlooking the RegEx-based packers, like the one by Dean Edwards: instead of simply stripping out whitespace, these actually reconstruct the script such that each variable / operator etc. is only listed once and then re-inserted on load where appropriate. So in some cases, you can add new code to an existing library and find that the compressed version is smaller than it was when the uncompressed source was smaller. I know that sounds strange, but it's true.

Of course, the underlying issue is that the reason this process breaks when semi's or curlies are missing is because it's using a stricter standard than a typical browser. This is all very similar to the distinction between XML and HTML: all HTML is XML, but most browsers do not yet require it to be valid XML... but I suspect they will at some point. Similarly, JavaScript that does not include semicolons where the specification indicates they are required is still JavaScript, but it is not valid JavaScript, in the sense that it will only behave as intended in a context where strict syntactical compliance is not required. In other words, it's brittle. Why ignore the language specification just because a browser temporarily allows us to? The second it stops doing so, our code breaks. Why not just do it the right way to begin with and avoid having to fix it later?

04/03/07 16:24:00 changed by mislav

I know perfectly well of code-compressing tools. But you are wrong when you compare HTML vs. XML with JavaScript vs. linted JavaScript. (X)HTML has flavors, while there are no levels of syntactical compliance in JavaScript - there is the ECMAScript specification, which defines only one languages with one set of rules. I will not accept a stricter set of rules that is being dictated by some 3rd-party JavaScript tools because they are not in position to do so.

And no - browsers don't allow us to "temporarily ignore" the specs. Refer to part 7.9 of ECMA-262 - you'll see that they're in fact pretty strict about it.

06/18/07 22:21:29 changed by dgrijalva

There are places where leaving off semi-colons is allowed by the language, but they are still valuable as they're clues to JavaScript compressors. There is no penalty for including these and the benefits are pretty great for a lot of developers looking to use some compressors that have issues with implied semi-colons.

Also, JS Lint is a valuable tool for finding code errors that actually will cause parsing errors, such as dangling commas in Hash declarations. By not complying to JSLint, prototype produces a lot of noise in JSLint output that makes it more difficult to find issues.

I've attached a complete patch for bringing the head up to speed on ticket 8680. The work is already done.

06/26/07 14:01:20 changed by Tobie

  • status changed from new to closed.
  • resolution set to duplicate.

Duplicate of #7301

02/14/08 20:41:26 changed by DNewfield

  • status changed from closed to reopened.
  • resolution deleted.

A valid javascript interpreter can add semicolons wherever there is a newline.

So:

if(some_condition)
some.really.long.line().foo;

Can be interpreted by a valid javascript interpreter as

if(some_condition);
some.really.long.line().foo;

Which will execute the second line regardless of the condition. How can you rationally argue that the semicolons are not needed if a newline exists between those two lines?

02/14/08 20:47:45 changed by DNewfield

Whoops. I meant "...that curly braces are not needed..."

02/18/08 13:12:33 changed by mislav

  • status changed from reopened to closed.
  • resolution set to duplicate.

DNewfield: on which part of the spec are you basing this argument? How about this:

"foo" +
  "bar" +
  "baz"

If some interpreter "adds" semicolons whenever there is a newline, I don't think how it can be valid. Anyway, I'm closing this again until you find a web browser in which this alert is shown:

if (false)
  alert("I should not be here!!");

02/18/08 18:55:08 changed by DNewfield

  • status changed from closed to reopened.
  • resolution deleted.

This argument is based on section 7.9 of the ECMAScript specification: "Automatic Semicolon Insertion"

Here's a relevant example from the spec:

The source
return
a + b
is transformed by automatic semicolon insertion into the following:
return;
a + b;

02/19/08 00:41:13 changed by mislav

  • status changed from reopened to closed.
  • resolution set to duplicate.

Section 7.9 is well-known to us; especially me who, of the whole team, doesn't write semicolons personally.

You didn't read the section carefully. The NOTE in 7.9.1 says that ReturnStatement is among the few "restricted productions in the grammar". The example that you cited above is true; a line terminator cannot appear between the return keyword and its value. But, it is not true that curly braces are needed here:

if (false)
  alert("I should not be here!!");

By section 7.9, a semicolon won't be inserted after if (false) since no invalid stream of tokens is encountered (and also because it would produce an empty statements).

If you want to convince us and browser vendors that we have read the section wrong and that my example can be misinterpreted, please do that on the prototype-core mailing list. Until you find a real (and valid) argument while we should insert curly braces, I'll keep this closed.

04/25/08 20:21:54 changed by noelito

  • status changed from closed to reopened.
  • resolution deleted.

All the time spent on trying to prove that good syntax is or is not the way to go could have been spent on adding ";" and "{}" in the files to allow for minification.

I just went through and added them to the source files and it did not take me more then like one hour. I only have two more files to go, the two biggest of course :0). I believe that prototype is a very grate product but I have shyed away from it for a while do to the fact that it is not available in a minified format and most other libs are. If it where a matter of some small site-specific code, it would not be that important. But since this is a lib that hundreds, if not thousands of site are using it is important. I am sure that if a poll was take, more then 80% of your loyal prototype users would want them ";" and "{}" added.

I always take the small amount of time needed to make sure that my site-specific javascript code is well formatted, so as to be minified and then gziped with out errors. I think that if much bigger (and not as good) javascript libs can take the time to add a couple of extra ";" and "{}" for the sake of correctness everybody should.

If it is a matter of not wanting to click the ";" and "{}" keys then I would be more then happy to send you the diff for the corrections I have made. I will also continue to add them as new versions arrive and as time permits me to do so if you will use them.

Well, I hope that in the future I can use your 75% smaller lib :0).

One last note, if you haven't seen it yet, here is a link to some grate articles/videos on javascript : http://www.crockford.com/javascript/
This is where I learned the importants of a few well placed ";" and "{}".

04/25/08 23:03:23 changed by mislav

  • status changed from reopened to closed.
  • resolution set to duplicate.

Noelito~

At the risk of sounding rude, I have to convince you that you had no right to reopen this ticket. You didn't say anything new in your comment and I don't think you have read this entire discussion.

We are aware of the work of Douglas Crockford. We are also aware that it isn't hard to add this to Prototype library in under a few hours. We just don't want to because we prefer gzipping over minification. People who only want the latter (or both) can choose to use software that will pack prototype.js without us or them having to add semicolons or curly braces.

Actually, someone has done all the work for you. Check out Protopacked. Turns out you can enjoy a Prototype distribution that's only 17% (!) of the original size. We will not give you support for using it, but it's there and it's everyone's for the taking.

For "the sake of correctness" we will not add extra semicolons or curly braces. Our code is correct and beautiful JavaScript and we will not be convinced otherwise without strong argument. And so far, none of the people provided enough to keep this ticket open.

We hear you, our users, but now it's time for you to hear us. Trust us in what we say. After all, we're heavily using Prototype library ourselves and are very concerned by speed (as any web professional).

04/26/08 05:33:00 changed by matthuhiggins

Noelito: If you are in a position where javascript load time performance is so crucial that you must minify prototype, I recommend not using prototype.js in the first place.

Also, welcome to the world of Ruby purism.