To Wash It All Away: James Mickens
To Wash It All Away: James Mickens
JAMES MICKENS
This is my last column! Thanks for reading, and thanks for all of the support :-). Never forget that when you are alone, I am with you, and when you are with someone else, I am also with you, because I think that I am better than that other person and I have lengthy opinions about why this is true. mickens@microsoft.com
hen I was in graduate school in Ann Arbor, I had a friend who was deeply involved with the environmentalist movement. He purchased his food from local farmers markets, and he commuted by bike instead of by car to reduce his carbon footprint, and he maintained a horrid compost bin that will probably be the origin of the next flu pandemic. One day, he told me that he was going to visit a farm for a week. I asked him why, and he said that he wanted to get closer to the land, a phrase that you can only say with a straight face if youre narrating a documentary about ancient South American tribes. I told my friend that the land didnt want to get closer to him, and if he really looked at the land, hed see that it was not composed of delicious organic trail mix, but famine and vultures and backbreaking labor involving wheelbarrows and generally unacceptable quantities of insects. He responded with an extended lecture about eco-responsibility, a lecture that I immediately forgot because I realized that my nave friend was going to die on that farm. So, I told my friend that he shouldnt be afraid to end his trip early if he wasnt having a good time. He smiled at me, the way that people in slasher movies smile before they get chopped up, and he left for the farm. Precisely 37 hours later, he called me on the phone. I asked him how everything was going, and he made a haunting, elegiac noise, like a foghorn calling out for its mate. I asked him to describe his first day, and he said that his entire existence revolved around bleating things: bleating goats that wanted to be fed, and bleating crows that wanted to steal the food that he gave the bleating goats, and bleating farm machines that were composed of spinning metal blades and had no discernable purpose besides enrolling you in the Hook Hand of the Month club. I asked my friend when he was coming back home, and he said that he was calling me from the Ann Arbor train station; he had already returned. And then he let out that foghorn noise, that awful, lingering sound, and I thought, MAYBE THATS THE FIRST SYMPTOM OF COMPOST BIN FLU.
Computer scientists often look at Web pages in the same way that my friend looked at farms. People think that Web browsers are elegant computation platforms, and Web pages are light, fluffy things that you can edit in Notepad as you trade ironic comments with your friends in the coffee shop. Nothing could be further from the truth. A modern Web page is a catastrophe. Its like a scene from one of those apocalyptic medieval paintings that depicts what would happen if Galactus arrived: people are tumbling into fiery crevasses and lamenting various lamentable things and hanging from playground equipment that would not pass OSHA safety checks. This kind of stuff is exactly what youll see if you look at the HTML,
PAGE 2
ocean because nobody wants to look at a painting of a blue man who is composed of isosceles triangles and has a guitar emerging from his forehead for no reason at all. Given the unbearable proliferation of Web standards, and the comically ill-expressed semantics of those standards, browser vendors should just give up and tell society to stop asking for such ridiculous things. However, this opinion is unpopular, because nobody will watch your TED talk if your sense of optimism is grounded in reality. I frequently try to explain to my friends why they should abandon Web pages and exchange information using sunlight reflected from mirrors, or the enthusiastic waving of colored flags. My friends inevitably respond with a spiritually vacant affirmation like, People invented flying machines, so we can certainly make a good browser! Unfortunately, defining success for a flying machine is easy (IM ME BUT IM A BIRD), whereas defining success for a Web browser involves Cascading Style Sheets, a technology which intrinsically dooms any project to epic failure. For the uninitiated, Cascading Style Sheets are a cryptic language developed by the Freemasons to obscure the visual nature of reality and encourage people to depict things using ASCII art. Ostensibly, CSS files allow you to separate the definition of your content from the definition of how that content looksusing CSS, you can specify the layout for your HTML tags, as well as the fonts and the color schemes used by those tags. Sadly, the relationship between CSS and HTML is the same relationship that links the instructions for building your IKEA bed, and the unassembled, spiteful wooden planks that purportedly contain latent bed structures. CSS is not so much a description of what your final page will look like, but rather a loose, high-level overview of what could happen to your page, depending on the weather, the stock market, and how long its been since you last spoke to your mother. Like a nave Dungeon Master untouched by the sorrow of adulthood, you create imaginative CSS classes for your <div> tags and your <span> tags, assigning them strengths and weaknesses, and defining the roles that they will play in the larger, uplifting narrative of your HTML. Everything is assembled in its proper place; you load your page in a browser and prepare yourself for a glorious victory. However, you quickly discover that your elf tag is over weight. THE ELF CAN NEVER BE OVERWEIGHT. Even worse, your barbarian tag does not have an oversized hammer or axe. Without an oversized hammer or axe, YOUR BARBARIAN IS JUST AN ILLITERATE STEROID USER. And then you look at your wizard tag, and you see that hes not an old white man with a flowing beard, but a young black man from Brooklyn. FOR COMPLEX REASONS THAT ARE ROOTED IN EUROPEAN COLONIAL NARRATIVES, YOUR W IZARD MUST BE AN OLD WHITE MAN WITH A FLOWING BEARD, NOT A BLACK MAN WITH HIPSTER SHOES AND A FANTASTIC VINYL COLLECTION. Such are the disasters
PAGE 3
The rst log entry says that the browser executed a downloaded le as JavaScript, even though the MIME type of the le was text/html. Heres a life tip: when youre confused about what something is, DONT EXECUTE IT TO DISCOVER MORE CLUES. This is like observing that your next-door neighbor is a creepy, bedraggled man with weird eyes, and then you start falling asleep on his doorstep using a chloroform rag as a pillow, just to make sure that hes not going to tie you to a radiator and force you to paint tiny gurines. Heres how your life story ends: YOU ARE A PAINTER OF TINY FIGURINES. The second and third errors say that the pages JavaScript used a variable name that is deprecated in strict mode, but acceptable in quirks mode. How can I begin to explain this delicious confection of awfulness? Listen: when a man and a woman fall in love, they want to demonstrate their love to each other. So, they force browsers to support different types of runtime environments. Standards mode refers to the unreliable browser APIs that are described by recent HTML and CSS specications. Quirks mode refers to the unreliable browser APIs that were dened by browsers from the Eisenhower administration. Quirks mode was originally invented because many Web pages were made during the Eisenhower administration, and the computing industry wanted to preserve Web-based narratives about why the rock and roll is corrupting our youth. Quirks mode then persisted because Web developers learned about quirks mode and used it as an excuse to not learn new skills. But then some Web developers wanted to learn new skills, so standards mode was invented to allow these developers to make old mistakes in new ways. There is also a third browser mode called almost standards mode; this mode is similar to
Figure 1: One time, I tried to build a browser-agnostic debugging infrastructure. I had a client-side JavaScript library that could traverse the JavaScript heap and display fun things about the pages state. My art history friends told me that console output is for Neanderthals, so I made an HTML GUI to display the diagnostic information. The first version of the GUI used the browsers default layout policies. Much like Icarus, I dreamt of more, so I decided to make A Fancy Layout. I wrote CSS that specified whether my tags should have static positioning, or floating positioning, or relative zodiac-based positioning. Heres what I learned: Never specify whether your tags should be static or floating or zodiac-based. As soon as a single tag is released from the automatic layout process, the browser will immediately go insane and stack random HTML tags along the z-axis, an axis which apparently is an option even if your monitor can only display two dimensions. I eventually found a working CSS file inside a bottle that washed up on the beach, and I tweaked the file until it worked for my GUI. Then I went home and cried big man tears that were filled with ninja stars and that turned into lions when they hit the ground.
PAGE 4
Figure 2: They said that I could become anything, so I became the error log of a Web browser. Now I own fifteen cats and I wonder where the parties are.
standards mode, except that it renders images inside table cells using the quirks mode algorithm. For reasons that have been eaten by a wildebeest, almost standards mode is also called strict mode, even though it is less strict than standards mode. For reasons so horrendous that the wildebeest would not eat them, there is no completely reliable way to make all browsers load your page using the same compatibility mode. Thus, even if your page recites the recommended incantations, the browser may still do what it wants to do, how it wants to do it. And thats where babies come from.
The fourth and seventh errors represent uncaught JavaScript exceptions. In a rational universe, a single uncaught exception would terminate a program, and if a program continued to execute after throwing such an exception, we would know that Ragnarok is here and Odin is not happy. In the browser world, ignoring uncaught exceptions is called Wednesday, and all days not called Wednesday. The JavaScript event loop is quite impervious to conventional notions of software reliability, so if an event handler throws an exception, the event loop will literally pretend like nothing happened and keep running. This ludicrous momentum continues even if, in the case of the seventh error, the Web page tries to call init() on an object that has no init() method. You should feel uncomfortable that a Web page can disagree with itself about the existence of initialization routines, but the page is still allowed to do things
|MARCH 2014|WWW.USEN IX.OrG
with things. Such a dramatic mismatch of expectations would be unacceptable in any other context. You would be sad if you went to the hospital to have your appendix removed, and the surgeon opened you up, and she said, I DIDNT EXPECT YOUR LIVER TO HAVE GILLS, and then she proceeded with her original surgical plan, despite the fact that youre apparently a mer-person. Being a mer-person should have non-ignorable ramications in the material universe. Similarly, if a Web page thinks than an object should be initialized, but the object has no initialization method, the browser shouldnt laugh about it and then proceed under the assumption that the rest of the page is agnostic about whether its objects are composed of folly.
An interpretation of the remaining errors is left as an exercise to the reader. Note that understanding the eighth error requires a Ouija board, the eye of a newt, and the whispering of a secret to a long-lost friend. At this point, it should be intuitively obvious that different browsers may or may not produce the same error log for the same page. In general, if a Web page has more than three bits of entropy, different browsers will generate extravagantly unique mappings between the Web developers intentions and the schizophrenic beast palette that browsers use to paint the world. Thus, picking the best browser is like playing one of those horrid trust-building exercises where you decide
PAGE 5
\roaming\pots\pans\cache\4$$Dtub.partial, where \4$$ is an exotic escape sequence that resolves to the Latvian double umlaut. You do an Internet search for potential solutions, and youre confronted with a series of contradictory, ill-founded opinions: your browser has a virus; your virus has a virus; you should be using Emacs; you should be using vi, and this is why your marriage is loveless. Of course, the most popular advice for solving any browser problem is to clear your browser cache. It is definitely true that emptying the cache will sometimes help, in the same sense that if youre poor, kicking a tree will sometimes lead to a hilarious series of events that conclude with you finding a big bag of money on the ground with a note that says, Spend it all! XOXO, Life. Unfortunately, kicking a tree does not typically lead to riches, so your faith-based act of tree assault really just makes you a savage, tree-kicking monster who will be vilified by children and emotionally sensitive adults. Similarly, your arbitrary clearing of the browser cache, however well-intentioned, is just a topical anesthetic to briefly dull the pain of existence. Clearing the cache to fix a Web browser is like when your dad was driving you to kindergarten, and the car started to smoke, and he tried to fix the car by banging on the hood three times and then asking you if you could still smell the carbon monoxide, and you said, Yeah, its better, because you didnt want to expose your dad as a fraud, and then both of you rode to school in silence as you struggled to remain conscious. So, yes, it would be great if fixing your browser involved actions that were not semantically equivalent to voodoo. But, on the bright side, things could always be worse. For example, it would definitely be horrible if your browsers scripting language combined the prototype-based inheritance of Self, a quasi-functional aspect borrowed from LISP, a structured syntax adapted from C, and an aggressively asynchronous I/O model that requires elaborate callback chains that span multiple generations of hard-working Americans. OH NO IVE JUST DESCRIBED JAVASCRIPT. What an unpleasant turn of events! People were begging for a combination of Self, LISP, and C in the same way that the denizens of Middle Earth were begging Saruman to breed Orcs and men to make Uruk-hai. Orcs and men were doing a fine job of struggling in their separate communitiescreating a new race with the drawbacks of both is not a good way to win popularity contests. But despite its faults, JavaScript has become widespread. Discovering why this happened is similar to understanding the causes for World War Ieveryone agrees on the top five reasons, but everyone ranks those causes differently. The basic story is that, in the 90s, when JavaScript and Java were competing for client-side supremacy, Java applets were horrendously slow and lacked a story for interacting with HTML; in contrast, JavaScript was only semi-horrendously slow, and it had a bad (but extant)
PAGE 6
JavaScript is dynamically typed, and its aggressive type coercion rules were apparently designed by Monty Python. For example, 12 == 12 because the string is coerced into a number. This is a bit silly, but it kind of makes sense. Now consider the fact that null == undefined. That is completely janky; a reference that points to null is not undenedIT IS DEFINED AS POINTING TO THE NULL VALUE. And now that youre warmed up, look at this: \r\n\t == false. Heres why: the browser detects that the two operands have different types, so it converts false to 0 and retries the comparison. The operands still have different types (string and number), so the browser coerces \r\n\t into the number 0, because somehow, a non-zero number of characters is equal to 0. Voila0 equals 0! AWESOME. That explanation was like the plot to Inception, but the implanted idea was the correctness of your program has been coerced to false. Hello, kind strangerlet me keep you warm during this cold winter night! Did you know that JavaScript denes a special NaN (not a number) value? This value is what you get when you do foolish things like parseInt(BatmanIsNotAnInteger). In other words, NaN is a value that is not indicative of a number. However, typeof(NaN) returns number. A more obvious return value would be HAIL BEELZEBUB, LORD OF DARKNESS, but I digress. By the way, NaN != NaN, so Aristotle was wrong about that whole Law of Identity thing. Also, JavaScript denes two identity operators (=== and !== operators) which dont perform the type coercion that the standard equality operators do; however, NaN !== NaN. So, basically, dont use numbers in JavaScript, and if you absolutely have to use numbers, implement a software-level ALU. Its slow, but its the only way to be sure. Actually, you still cant be sure. Unlike C++, which uses statically declared class interfaces, JavaScript uses prototype-based inheritance. A prototype is a dynamically dened object which acts as an exemplar for instances of that object. For example, if I wanted to declare a Circle class in JavaScript, I could do something like this:
//This is the constructor, which defines a //radius property for new instances. function Circle(radius){ this.radius = radius; } //The constructor function has an object property //called prototype which defines additional //attributes for class instances. Circle.prototype.getDiameter = function(){ return 2*this.radius;
|MARCH 2014|WWW.USEN IX.OrG
The exemplar object for the Circle class is Circle.prototype, and that prototype object is a regular JavaScript object. Thus, by dynamically changing the properties of that object, I can dynamically change the properties of all instances of that class. YEAH I KNOW. For example, at some random point in my programs execution, I can do this
Circle.prototype.getDiameter = function(){ return -5; };
and all of my circles will think that they have a diameter of less than nothing. Thats a shame, but whats worse is that the predefined (or native) JavaScript objects can also have their prototypes reset. So, if I do something like this
Number.prototype.valueOf = function(){return 42;};
then any number primitive that is boxed into a Number object will think that its the answer to the ultimate question of life, the universe, and everything:
alert((0).valueOf()); //0 should be 0 for all values of 0, //but it is 42. alert((1).valueOf()); alert((NaN).valueOf()); //Zeus help me, 1 is 42 as well. //NaN is 42. DECAPITATE ME AND //BURN MY WRITHING BODY WITH FIRE.
I obviously get what I deserve if my JavaScript library redefines native prototypes in a way that breaks my own code. However, a single frame in a Web page contains multiple JavaScript libraries from multiple origins, so who knows what kinds of horrendous prototype manipulations those heathen libraries did before my library even got to run. This is just one of the reasons why the phrase JavaScript security causes Bibles to burst into flames.
Much like C, JavaScript uses semicolons to terminate many kinds of statements. However, in JavaScript, if you forget a semicolon, the JavaScript parser can automatically insert semicolons where it thinks that semicolons might ought to possibly maybe go. This sounds really helpful until you realize that semicolons have semantic meaning. You cant just scatter them around like youre the Johnny Appleseed of punctuation. Automatically inserting semicolons into source code is like mishearing someone over a poor cell-phone connection, and then assuming that each of the dropped words should be replaced with the phrase your mom. This is a great way to create excitement in your interpersonal relationships, but it is not a good way to parse code. Some JavaScript libraries intentionally begin with an initial semicolon, to ensure that if the library is appended to another one (e.g., to save HTTP roundtrips
PAGE 7
I could go on and on about the reasons why JavaScript is a cancer upon the world. I know that there are people who like JavaScript, and I hope that these people find the mental health services that they so desperately need. I dont know all of the answers in life, but I do know all of the things which arent the answers, and JavaScript falls into the same category as Scientology, homeopathic medicine, and making dogs wear tiny sweaters due to a misplaced belief that this is what dogs would do if they had access to looms and opposable thumbs. In summary, Web browsers are like quantum physics: they offer probabilistic guarantees at best, and anyone who claims to fully understand them is a liar. At this stage in human devel opment, there are big problems to solve: climate change, heart disease, the poor financial situation of Nigerian princes who want to contact you directly. With all of these problems unsolved, Web browsing is a terrible way to spend our time; the last thing that we should do is run unstable hobbyist operating systems that download strange JavaScript files from people we dont know. Instead, we should exchange information using fixed-length ASCII messages written in a statically verifiable
subset of Latin, with images represented as mathematical combinations of line segments, arcs, and other timeless shapes described by dead philosophers who believed that minotaurs were real but incapable of escaping mazes. That is the kind of clear thinking that will help us defeat the space Egyptians that emerge from the StarGates. Or whatever. Im an American and I dont really understand history, but I strongly believe that Greeks spoke Latin to defeat intergalactic Egyptians. #TeachTheControversy! Anyways, my point is that browsers are too complex to be trusted. Unfortunately, youth is always wasted on the young, and the current generation of software developers is convinced that browsers need more features, not fewer. So, we are encouraged to celebrate the fact that browsers turn our computers into little Star Wars cantinas where everyone is welcome and you can drink a blue drink if you want to drink a blue drink and if something bad happens, then maybe a Jedi will save you, and if not, HEY ITS A STAR WARS CANTINA YESSSSS. Space cantinas are fun, but theyre just a fantasy; theyre just a series of outlandish details stitched together to amuse and entertain. You have to open your eyes and see that in the real, non-hyperbolic world that you actually inhabit, your browser will frequently stop playing a video and then display flashing epilepsy pixels while making the sound that TVs make in Japanese horror movies before a pasty salamander child steps out of the screen and voids your warranty. Thats a thing which could actually happen, and we should wash it all away.