Twitter crashes itself with commas
my.opera.com
my.opera.com
When you replace a thousand of them with commas, nothing has been gained!
When you start placing them only at the beginning of certain lines, subject to JS's parsing rules, you are thinking more, not less!
Anyway in this case I guess some automatic code reduction tool has decieded that four characters can be saved by changing it to commas. I doubt it was written that way to begin with.
I love Go's lack of semicolons but I don't extend that to some foolhardy attempt to write JavaScript without semicolons. In JavaScript, support for proper semicolon-less style is clearly lacking in practice if not in spec (if it weren't lacking this wouldn't be a oft-recurring story, but it is).
What does it gain you?
Update: Here's the thread I was thinking of https://github.com/twitter/bootstrap/issues/3057
The automatic semicolon insertion is a "feature" to give some leeway to new/sloppy developers, not a real feature that good developers should use.
</sarcasm>
The most recent intentional annoyance is less than two weeks old:
http://www.zdnet.com/google-annoys-opera-users-who-wont-swit...
"(...) it's a mark of pure arrogance from a company that isn't afraid to act like Microsoft (1998) when it needs to muscle out a competitor.
The Google roadblock for Opera is crude. If you change the User-Agent string for Opera so that it identifies itself as Google Chrome, the Blogger editing and management screens work perfectly."
It's not that I think Google is above using dirty tactics. It's that I think Google is above using dumb tactics.
I mean, are you seriously suggesting that Google assigned someone to comb through known Opera bugs, looking for one that they could exploit in their compiler while masquerading the exploit as a legitimate optimization? And then they assigned someone to implement that optimization? All in the hopes that someday a 4.5MB JS file would come along and break a popular website under Opera? And ignoring the facts that a) Opera might have fixed the bug by that time, b) said popular website might permanently switch to a different compiler when that happened, and c) it would take the Opera team a small fraction of the time Google had spent on this to put out a patch?
My point is, in the light of the all bullying tactics against Opera, the community should definitely have less tolerance to Google than it has. In five words: Monopolies bad, supporting Opera good.
But regardless of who is good and who is bad (and trust me, I have plenty of bad feelings toward Google myself), this was fundamentally Opera's mistake, not Google's. There is nothing in the ECMAScript standard that says that there is an upper limit on how long a statement can be, and that's the end of the matter.
They don't say it doesn't work, they just say they don't support it, so that people won't assume that being broken on Opera means it's broken on every browser. And don't claim that "if they code to standard it'll work" because this very story proves that's not always true.
I do think Opera deserves being supported, and Google shouldn't be pushing Chrome like that. But calling it a "roadblock for Opera" is misleading.
"And you cannot make those nagging messages go away. Any visit to a page in the Blogger content-editing interface results in this nag screen, and although you can dismiss the message, it will keep coming back."
On the other side, this is why many of the comments, including the top comment, seem overly invested in the notion of semicolon insertion, as opposed to looking at the specific usage of replacing sequences of ExpressionStatements (even if separated by semicolons) with a single ExpressionStatement holding a very long compound Expression (separated by commas).
The actual bug appears to be not a bug so much as a limitation in the Opera parser with regards to how many comma delineated calls it can handle at a single time. Somewhere around comma 1019 things get messy.
I think it's pretty sane to suggest that a single statement won't be 4MB in length.
The fact that you think otherwise is precisely the problem. If you don't want to write correct software (which, frankly, isn't any harder than writing broken parsers) you might want to reconsider your career choice.
Public shaming works to stamp out activities that the shamee knows to be bad/anti-social. I think the case here is well-intentioned.
Unfortunately, sometimes you have to put in some sane limits, because of constraints elsewhere.
To call software that has sane limits to cover 99.9% of usage patterns "broken" is pretty silly.
If you think as a software developer, you never have to make compromises, or make a tough call on what 99.9% of users will do, you're being naive.
For a very simpel reason -- you are not implementing a new language, but writing a parser/evaluator for an already existing one. And you shouldn't change the language (as much as all of us have a beef with Javascript).
In this case both the current title and the original title (if memory serves) give the impression that twitter is somehow at fault.
"Terrible code" is this sort've nebulous subjective thing. Clearly, to you and I, this is terrible code, though probably created by a minifier / compiler.
Lots of code can be terrible (We've all written some in our time). However, if terrible code is valid it's the interpreter's (in this case) problem to figure it out. The ECMAScript spec is nightmarish but we get the spec we deserve :). Twitter has ZERO fault here. They wrote terrible valid code and the parser / interpreter should be spec conformant no matter the pain.
Perhaps Twitter has chosen not to support Opera which is fine by me (even though I'm a user), but I think more than likely this was a slip-up in their QA process.
> I believe it's Google Closure compiler putting commas in there.
Someone else linked to an explanation of why
> http://blog.vjeux.com/2011/javascript/javascript-comma-trick...
</fact><opinion>
So from the looks of it, the problem is in Opera's javascript implementation.
I'm not sure how much Google uses Closure Compiler internally but I wouldn't have thought they would use code they knew to cause issues in some browsers. I guess that ether means the Opera implementation is wrong and the code should work fine, or Google didn't test this as fully as they should have done
We already knew that we had a limitation that other browsers don't have in the parser, and it was already considered important to fix. Breaking Twitter of course raises the profile of this bug.
Conclusion - Using the comma trick to do { }-less indentation is far from viable. However this may still be useful for debugging and overall it is fun to try new coding styles!
if(true){dothis();dothat();}
if(true)dothis(),dothat();Regardless, the actual bug is in Opera as the resulting javascript is legit, even if its absolutely crazy to have 4MB of script be only a single javascript statement.
Anyway variables in javascript have function scope, so two variables with the same name in the same function always refer to the same value, even if declared twice.
As a result I like to write all the variable statements at the top of each function, all in one var statement.
The problem then becomes that you write var a, b, c, d; and then later want to add variable e. If you aren't careful you might accidentally write var a, b, c, d; e; if you do that, the program may still work but e now has global scope. This results in nearly impossible to find bugs that may only happen if the function is recursive or it is called (perhaps indirectly) by some other function with a similarily named variable.
Considering that semicolons insertion mostly works, and the other can be a huge pain in the rear end, I can understand why people would want to skip the semicolons.
foo()
var bar = 1;
is actually run as var bar;
foo();
bar = 1; int* a, b
declares "a" as ( int* ) and b as ( int ). Instead, I just write int *a;
int *b; (function () {
'use strict';
var a = 1; b = 2;
}());
// ReferenceError: b is not defined var a,
b,
c,
d;
e;
Then your editor (which you've a integrated a linter... right?) will protested: yourJsFile.js |5 warning| 'e' was used before it was defined.
And if you have a global by the same name you'll see: yourJsFile.js |5 warning| Expected an assignment or function call and instead saw an expression.
Granted, if you assign it a default value then, yes you're going to have a bad time. But if you follow the white spacing rules of jsLint it will catch the obvious error. if (a) { b(); c() }
if (a) b(), c()Or you wouldn't, of course, if it weren't for some browsers being broken and unable to handle it.
As for "they aren't going to notice that 1% file size", you could keep saying that about small optimization after small optimization until your compiler's output is 10% bigger than the competition's, at which point you will start losing significant user base.
You're making a blanket statement about Twitter developing bad code because of a recent bug. It will be fixed.
But I don't think we need to think of it in terms of Twitter's scale at all. The point is that saving 1% for basically free, is saving 1% for basically free, and that's worthwhile no matter how big you are. On its own, it's a drop in the bucket, but the cumulative effect of many small low-opportunity-cost savings is a significant low-opportunity-cost saving.
IMO, the Javascript spec is kinda dumb for being so permissive, but it is covered in the spec, so it's legit to do it either way.
Whether that's a good thing or not.
this is literally the only objective reason i have ever seen for using/not using semicolons
nnoremap A :call EndOfLine()<CR>a
fu! EndOfLine()
normal $
if getline(".")[col(".")-1] == ';'
normal h
endif
endfunctionWhat on earth are the people at twitter doing that warrants that much code? Maybe their single page app -> dedicated page transition was more about disabling some things and rewiring urls with the plan of taking advantage of the dedicated setup later?
[{user: {name: 'jlarocco', userid: 1, /* 50 other attributes */}, message: 'my first tweet', id: 1, time: 123456},
{user: {name: 'jlarocco', userid: 1, /* 50 other attributes */}, message: 'my second tweet', id: 2, time: 123498},
/* similar thing 18 more times */]
If the rest of their stuff is like that, a 4MB Javascript file doesn't surprise me at all.You forget Twitter has been dealing with technical debt for years. The fact that Twitter still runs on Rails and serves as much traffic as it does is testament to what the engineers there have built.
I'd have to imagine that 355kb is the compressed size, but that character count (assuming one byte characters, not UTF8) works out to be 3.938 megabytes.
That's a lot of code. Even more when you consider it's been minified.
It's 1.34mb on disk uncompressed but still minified. The copy Twitter is hosting right now is 1409121 characters minified but uncompressed. I have to assume the 4mb mentioned is output from some middle step (closure compiler output?) I'm not arguing the merits of that filesize, just that it's definitely not 4mb.
Link to it on Twitter's servers (I uploaded to dropbox just in case the file expires or is changed): http://a0.twimg.com/c/phoenix/en/bundle/t1-more.5d72926b7850...
I don't feel like digging through minified javascript though, so I have no clue what the discrepency is.
At a quick glance you can definitely see some differences between the different scripts we were served. For instance, in the one you were served there are some unminified portions that include the license notice for some of the code (easyXDM). In the script served to me there are no unminified portions, with everything being served on a single line.
C, Pascal, and ALGOL (1958) use semicolons as a statement delimiter. Why was the semicolon chosen instead of, say, the period or newline? BCPL (like JS and Go) allows semicolons to be omitted if a statement ends unambiguously on one line.
Was the semicolon a QWERTY home row key before or after ALGOL?
It makes sense when you think of an entire resolution (program) as a single goal (output/result), which involves many separate steps/clauses (statements) that need to be executed.
A period is a terminator; it says 'This thought ends here', while a semicolon is a delimiter (ie, the clauses it separates are independent grammatically, but not contextually).
[1]http://web.utk.edu/~modelun/resolutions.htm (Model UN rules, but you get the idea).
Whereas John Q. Doe is an upstanding citizen who has contributed to the city, and
Whereas aforementioned Mr. Doe is an awesome dude, and
Whereas some people who happened to contribute to my campaign are fans of Mr. Doe,
Therefore, I, Mayor Wile E. Coyote do hereby declare Octember 31st, 2012 as John Q. Doe Day in the city of Acme, CO.
In this context, the UN resolution is actually similar to the comma-style used here by Twitter. We don't want the statement/sentence to end, so we use semicolons/commas to make it continue, and end up breaking browsers/non-lawyer readers.Pascal takes this literally: semicolons separate statements, and a full stop ends the unit contained in a file ("end.").
A period is indistinguishable from a decimal point.
So if you have a = 4. is that the end of the thought or the end of the integer? It's obvious in context to a human, but a bad idea for a computer.
Before, well before. Take a look at http://www.etsy.com/listing/10230221/immaculate-1930s-reming... for a picture of an old typewriter. The ; is exactly where it is today.
As for why semicolons are used, see http://programmers.stackexchange.com/questions/139482/why-ar... for a bunch of speculation on it. The one that seems most reasonable to me is dan04's answer (which was not voted up much because he put it lately.
Start with ASCII. Now take out the characters which did not reliably appear in character formats, take out characters that have meaning to us in mathematical expressions, have obvious utilities as delimiters in other context, or which convey mood. You're left with ; and :. Of the two, ; is more visible and easier to type. So ; it is.
Although, if I'm not mistaken, the exclusion of the semicolon is technically correct. So, both parties are at fault here.