<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Infrequently Noted &#187; alex</title>
	<atom:link href="http://infrequently.org/author/alex/feed/" rel="self" type="application/rss+xml" />
	<link>http://infrequently.org</link>
	<description></description>
	<lastBuildDate>Fri, 18 Nov 2011 16:25:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Vendor Prefixes Are A Rousing Success</title>
		<link>http://infrequently.org/2011/11/vendor-prefixes-are-a-rousing-success/</link>
		<comments>http://infrequently.org/2011/11/vendor-prefixes-are-a-rousing-success/#comments</comments>
		<pubDate>Fri, 18 Nov 2011 14:36:27 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[openweb]]></category>
		<category><![CDATA[politics]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1715</guid>
		<description><![CDATA[tl;dr version: Henri Sivonen&#8217;s arguments against vendor prefixing for CSS properties focus on harm without considering value, which in turn has caused him to come to a non-sensical set of conclusions and recommendations. Progress is a process, and vendor prefixes have been critical in accelerating that process for CSS. For a while now I&#8217;ve been [...]]]></description>
			<content:encoded><![CDATA[<p><em>tl;dr version: Henri Sivonen&#8217;s arguments against vendor prefixing for CSS properties focus on harm without considering value, which in turn has caused him to come to a non-sensical set of conclusions and recommendations. Progress is a process, and vendor prefixes have been critical in accelerating that process for CSS.</em></p>
<p>For a while now I&#8217;ve been hearing the meme resurface from CSS standards folks and a few implementers that &#8220;vendor prefixes have failed&#8221;. I&#8217;d assumed this was either a (bad) joke or that it was one of those things that web developers would scoff at loudly enough to turn the meme recessive. I was wrong.</p>
<p>Henri Sivonen, Mozilla hacker extrordinare, <a href="http://hsivonen.iki.fi/vendor-prefixes/">has made the case directly and at length</a>. Daniel Glazman, co-chair of the CSS WG posted a <a href="http://www.glazman.org/weblog/dotclear/index.php?post/2011/11/16/CSS-vendor-prefixes-an-answer-to-Henri-Sivonen">point-by-point response.</a> If you have the patience, you should read both.</p>
<p>Lost in the debate between &#8220;browser people&#8221; and &#8220;spec people&#8221; is the the essential nature of what has happened with prefixes: they <em>worked</em>. From the perspective of a web developer, any first approximation of the history of vendor prefixes are <em>pure win</em>, even if only a fraction of the value that has been delivered behind them is attributable to prefixes un-blocking vendors from taking risks and shipping early.</p>
<p>Daniel&#8217;s rebuttal to Henri gets a lot of things right, but he gives in on an essential point; by agreeing with Henri that vendor prefixes are &#8220;hurting web authors&#8221; he wites off the benefits that they&#8217;ve delivered &#8212; namely the ability of vendors to get things out to devs in a provisional way that has good fallback and future-proofing properties and the ability for devs to build with/for the future in an opt-in, degradable way.</p>
<p>Rounded corners, gradients, animations, flex box, etc. are all design and experience enablers that developers have been able to take advantage of while waiting for the standards dust to settle, and thanks to W3C process, it takes a LONG time to to settle. Yes, that has some costs associated with it. Henri is very worried that browsers that aren&#8217;t keeping up quickly will be &#8220;left behind&#8221; by webdevs who use only one vendor&#8217;s prefix. But surely that&#8217;s a lesser harm than not getting new features and not having the ability to iterate. And it provides incentive for following browsers to try to make a standard happen. What&#8217;s not to love? More to the point, I just don&#8217;t believe that this is a serious problem in practice. What front-ender in 2011 doesn&#8217;t test on <em>at least</em> two browsers? Yes, yes, i&#8217;m sure such a retrograde creature exists, but they were going to be making non-portable content <em>regardless of prefixes</em>. Assuming you&#8217;re testing fallback <em>at all</em> (e.g., by testing on more than one browser), prefixes not appearing on some browser are just the fallback case. CSS FTW! Webdevs who don&#8217;t test on more than one browser&#8230;well, they&#8217;re the ones hanging the noose around the neck of their own apps. Vendor prefixes no more enable this stupidity than the existence of the <code>User-Agent</code> header. Compatibility is a joint responsibility and the best each side (browser, webdev) can hope of the other is some respect and some competence. Cherry picking egregious examples and claiming &#8220;it&#8217;s hurting the web&#8221; seems, at a minimum, premature.</p>
<p>And how did we think we&#8217;d get a good standard, anyway? By sitting in a room in a conference center more often and thinking about it harder? Waiting on a handfull of early adopters to try something out in a tech demo and never stress it in practice? That&#8217;s not a market test (see: XHTML2), it doesn&#8217;t expose developers to the opportunities and tradeoffs that come with a new feature, and doesn&#8217;t do anything to address the inevitable need to integrate feedback at <em>some</em> point.</p>
<p>Yes, we could go with Henri&#8217;s suggestion that the first person to ship wins by default, never iterate on any designs, and avoid any/all first-mover disadvantage situations, but who among the browser vendors is perfect? And what would the predictable consequences be? I can only assume that Henri thinks that we&#8217;ll end up in a situation where vendors coordinate with the CSS WG early to add new stuff, will design things more-or-less in the open, and will only ship features to stable (no flag) when they&#8217;re sure of their design. That could happen at the limit, but I doubt it. Instead, the already fraught process of adding new features to the platform will be attempted by even fewer engineers. Who wants the responsibility for having to be perfect lest you screw the web over entirely? Fuck that noise, I&#8217;m gonna go work on a new database back-end or tune something to go faster. Browsers are made by smart people who have a choice of things to be working on, and any time you see a new platform feature, it probably came about as the result of an engineer taking a risk. Many times the engineers in a position to take those risks don&#8217;t have a great sense for what good, idiomatic web platform features might be designed, so they&#8217;ll need to tweak/iterate based on feedback. And feedback is painfully hard to extract from webdevs unless you&#8217;ve made something available in a tangible way such that they can use it and discover the limitations.  Shipping things only to dev is perhaps a good idea for other aspects of the platform where we can&#8217;t count on CSS&#8217;s forgiving parsing behavior (the basis for prefixes). Syntax changes for JS and CSS seem like good examples. But for features that are primarily new CSS properties? Oy. Making the stakes even higher, reducing the ability to get feedback and iterate isn&#8217;t going to lead to a harmonious world of good, fast standards creation. It&#8217;s going to predictably reduce the amount of new awesome that shows up in the platform.</p>
<p>Prefixes are an enabler in allowing the <em>necessary</em> process of use, iteration, and consensus building to take place. Want fewer messes? There&#8217;s an easy way to achieve that: try less stuff, add fewer features, and make each one more risky to add. That&#8217;s Henri&#8217;s prescription, wether or not he knows it, and the predictable result is a lower rate of progress &#8212; advocating this sort of thing is <em>much</em> worse for the web and for developers than any of the harm that either Henri or Daniel perceive.</p>
<p>Which brings me to Henri&#8217;s undifferentiated view of harm. His post doesn&#8217;t acknowledge the good being done by prefixed implementations &#8212; I get the sense he doesn&#8217;t build apps with this stuff or it&#8217;d be obvious how valuable prefixed implementations are for work-a-day web app building &#8212; instead focusing on how various aspects of the process of prefixed competition can be negative. So what? Everything worth having costs <em>something</em>. Saying that things &#8220;hurt the web&#8221; or &#8220;hurt web developers&#8221; without talking in terms of <em>relative harm</em> is just throwing up a rhetorical smoke screen to hide behind. If you focus only on the costs but write the benefits out of the story of <em>course</em> the conclusion will be negative. In many cases, the costs that Henri points out are <em>correctly aligned</em> with getting to a better world: having to type things out many times sucks, creating demand among webdevs for there to be a single, standardized winner. Having multiple implementations in your engine sucks, creating demand from vendors to settle the question and get the standards-based solution out to users quickly. Those are good incentives, driven by prices that are low but add up over time in ways that encourage a good outcome:  a single standard implemented widely.</p>
<p>And as Sylvain Galineau pointed out, what looks like pure cost to one party might be huge value to another. I think there&#8217;s a lot of that going on here, and we shouldn&#8217;t let it go un-contextualized. The things that Henri sees as down-sides are the predictable, relatively minor, costs inherent in a process that allows us to make progress faster and distribute the benefits quickly, all while <em>minimizing</em> the harm. That he&#8217;s not paying the price for not having features available to build with doesn&#8217;t mean those opportunity costs aren&#8217;t real and aren&#8217;t being borne by webdevs every day. Being able to kill table and image based hacks for rounded corners is providing HUGE value, well ahead of the spec. Same for gradients, transitions, and all the rest. Calling prefixed implementations in the wild a bad thing needs to argue that the harm is greater than all of that value. I don&#8217;t think Henri could make that case, nor has he tried.</p>
<p>I think the thing that most shocks me about Henri&#8217;s point of view is that he&#8217;s arguing against a process when in fact the motivating examples (transforms, gradients) have been sub-optimal in <em>exactly</em> the better-than-before ways we might have hoped for! Gradients, for example, saw a lot of changes and browsers had different ideas about what the syntax should be. Yes, it&#8217;s harder to get a consistent result when you&#8217;re trying to triangulate multiple competing syntaxes, but we got to <em>use</em> this stuff, get our hands dirty, and get most of the benefits of the feature while the dust settled. Huzzah! This is <em>exactly</em>> the way a functioning market figures out what&#8217;s good! Prefixes help developers understand that stuff can and will change, and they clear the way for competition of ideas without burdening the eventual feature&#8217;s users with legacy bagage tied to a single identifier.</p>
<p>So what about the argument that there might be content that doesn&#8217;t (quickly?) adopt the non-prefixed version, or that vendors can&#8217;t remove their prefixed implementations because content depends on it?</p>
<p>To the first, I say: show me a world where 90+% of users have browsers support the standard feature and I&#8217;ll show you a world in which nobody (functionally) continues to include prefixes. That process is gated in part by the WG&#8217;s ability to agree to a spec, and here I think there&#8217;s real opportunity for the CSS WG to go faster. The glacial pace of CSS WG in getting things to a final, ratified spec is in part due to amazingly drawn-out W3C process, and in part a cultural decision on the part of the WG members to go slow. My view is that they should be questioning both of these and working to change them, not blaming prefixes for whatever messes are created in the interim.</p>
<p>As for removing prefixes, this is about vendors just doing it, and quickly. But the definition of &#8220;quickly&#8221; matters here. My view is that vendors should be given <em>at least</em> as long as it took to get a standard finalized from the introduction of their prefixed version for the removal process to be complete. So if Opera adds an amazing feature behind a <code>-o-</code> prefix in early 2012 and the standard is finalized in 2014, the deprecation and eventual removal should be expected to take 2 years (2016). This has the nice symmetry of incentives that punish the WG for going slow (want to kill prefix impls? get the standard done) while allowing the vendors who took the biggest risks to provide the softest landings for their users. And it doesn&#8217;t require that we simply go all-in on the first person&#8217;s design to ship. Yes, there will be mounting pressure to get <em>something</em> done, but that&#8217;s good too!</p>
<p>The standards process needs to lag implementations, which means that we need spaces for implementations to lead in. CSS vendor prefixes are one of the few shining examples of this working in practice. It&#8217;s short-term thinking in the extreme to either flag the costs associated with them as either justifying their removal or even suggesting that the costs are too high.</p>
<p>And webdevs, always be skeptical when someone working on an implementation or a spec tells you that something is &#8220;hurting the web&#8221; when your experience tells you otherwise. The process of progress needs more ways to effectively gauge webdev interest, collect feedback, and test ideas. Not fewer or narrower channels.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/11/vendor-prefixes-are-a-rousing-success/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Function-ality</title>
		<link>http://infrequently.org/2011/10/function-ality/</link>
		<comments>http://infrequently.org/2011/10/function-ality/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 09:51:45 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1708</guid>
		<description><![CDATA[I&#8217;m sitting here in Derek Featherstone&#8217;s amazing a11y talk at Fronteers and I feel like I need to follow up the last post with a quick primer on the zen of function for (both of) the spec authors who read this blog. The reason it&#8217;s offensive to the JS hacker for WebIDL to disallow new [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m sitting here in Derek Featherstone&#8217;s <a href="http://fronteers.nl/congres/2011/sessions">amazing a11y talk at Fronteers</a> and I feel like I need to follow up the last post with a quick primer on the zen of <code>function</code> for (both of) the spec authors who read this blog.</p>
<p>The reason it&#8217;s offensive to the JS hacker for WebIDL to disallow <code>new</code> against DOM types &#8212; <em>any</em> of them &#8212; is that it means that it&#8217;s no longer specifying how you&#8217;d describe these types in the primitive we use over here in JS for this sort of thing: functions. This might sound nuts to folks who come from C++ or who spend their time in spec-ese, but there&#8217;s <em>no difference</em> between a plain-old function, a &#8220;constructor&#8221;, and a &#8220;partial&#8221; or &#8220;mixin&#8221; in JS semantics. We use functions for all of them. You can say <code>new function(){ ... }</code> and create an instance of an anonymous &#8220;class&#8221; in JS. You can take the same function and invoke it as a &#8220;regular function&#8221; &#8212; <code>(function(){ ... })();</code> &#8212; and you can use that sort of function as a mixin or <code>partial</code> interface too: <code>new function(){ (function(){ ... }).call(this); ... }</code>. The <em>exact same</em> function object can even act in all of these capacities (although it&#8217;s rare). People use them as they need to, but they all boil down to functions.</p>
<p>What, then, does it mean for something to disallow <code>new</code> against some type for which you can in some otherwise get an instance in JS? The same thing when you can&#8217;t <code>.call()</code> it: <em>it&#8217;s alien</em>. It&#8217;s not a class as we know it, which means that it&#8217;s not a function, and if it&#8217;s not a function&#8230;well, it doesn&#8217;t belong. Fundamentally, it&#8217;s smuggling static semantics into a language that has perfectly good dynamic semantics for the same thing. This strikes at the very heart of what WebIDL is supposed to be for: describing JS types for things implemented somewhere else. By not allowing <code>new</code> and <code>.call()</code> WebIDL is giving JS semantics the bird, asserting that the fact that these things aren&#8217;t JS types makes them <em>better</em> in some way&#8230;and <em>that</em> is a bug, either in the perspective of the spec authors or of the specs themselves.</p>
<p>Luckily, the fix is easy: all WebIDL types should de-sugar to functions. All of them. All the time. No questions asked. That you will be able to use <code>new</code> and <code>.call()</code> and all the rest isn&#8217;t a bug, and it&#8217;s not something to guard against. It&#8217;s just how JavaScript rolls&#8230;and how JavaScript&#8217;s largest, most important library should roll too.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/10/function-ality/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Real Constructors &amp; WebIDL Last Call</title>
		<link>http://infrequently.org/2011/10/real-constructors-webidl-last-call/</link>
		<comments>http://infrequently.org/2011/10/real-constructors-webidl-last-call/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 14:10:03 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1693</guid>
		<description><![CDATA[For those who haven&#8217;t been following the progress of WebIDL &#8212; and really, how could you not? An IDL? For the web? I&#8217;d like to subscribe to your newsletter&#8230; &#8212; the standard is now in last call, which is W3C for &#8220;alllllllllllmost done&#8221;. Which it is not. Before I get to why, let me first [...]]]></description>
			<content:encoded><![CDATA[<p>For those who haven&#8217;t been following the progress of WebIDL &#8212; and really, how could you not? An IDL? For the web? I&#8217;d like to subscribe to your newsletter&#8230; &#8212; the standard is now in <a href="http://www.w3.org/TR/2011/WD-WebIDL-20110927/">last call</a>, which is W3C for &#8220;<em>alllllllllllmost</em> done&#8221;.</p>
<p>Which it is not.</p>
<p>Before I get to why, let me first say some nice, well-earned things about WebIDL: first, it has helped us out of the ad-hoc IDL sludge that used to be how APIs for JavaScript have been exposed in the past. It has shaved off many sharp edges and is giving spec authors a single dialect in which to write their API descriptions. From a browser perspective, this is a <em>Very</em> Good Thing (TM). Next, the draft in question contains some wonderful changes from the status quo, particularly the <a href="http://www.w3.org/TR/2011/WD-WebIDL-20110927/#interface-prototype-object">addition of a sane prototype to all WebIDL-specified objects</a>.</p>
<p>That all sounds good, so what&#8217;s missing?</p>
<p>In a word, constructors.</p>
<p>Well, a lot more than that, but I&#8217;d settle for constructors. Functionally speaking, it boils down to the fact that WebIDL makes spec authors do extra work to make something like this sane:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">new</span> HTMLDivElement<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Why doesn&#8217;t this work today? Funny story&#8230;see, HTML defines <a href="http://www.w3.org/TR/html5/grouping-content.html#htmldivelement">HTMLDivElement</a> as a regular WebIDL interface. WebIDL doesn&#8217;t really have the notion of concrete classes, just interfaces with and without constructors. Since the HTML spec is just doing what most specs will do &#8212; adding the smallest IDL you can get away with &#8212; the JS usability of this API is left in limbo; neither clearly HTML5&#8242;s responsibility nor WebIDL&#8217;s.</p>
<p>So what should a contentious version of HTML5 do? One answer is to specify a constructor, turning the IDL from this:</p>

<div class="wp_syntax"><div class="code"><pre class="idl" style="font-family:monospace;"><span style="color: #990078; font-weight: bold">interface</span> HTMLDivElement <span style="color: #66cc66;">:</span> HTMLElement <span style="color: #808080;">&#123;</span><span style="color: #808080;">&#125;</span><span style="color: #66cc66;">;</span></pre></div></div>

<p>to this:</p>

<div class="wp_syntax"><div class="code"><pre class="idl" style="font-family:monospace;"><span style="color: #808080;">&#91;</span>Constructor<span style="color: #808080;">&#93;</span>
<span style="color: #990078; font-weight: bold">interface</span> HTMLDivElement <span style="color: #66cc66;">:</span> HTMLElement <span style="color: #808080;">&#123;</span><span style="color: #808080;">&#125;</span><span style="color: #66cc66;">;</span></pre></div></div>

<p>Repeat ad-infinitum for each and every interface that <em>should</em> be constructable in every single spec that browser vendors ever implement. Don&#8217;t miss any! And please make sure that all your spec editors are on-board with good JS APIs as a goal! As it stands today, WebIDL doesn&#8217;t even force most spec authors to consider the question &#8220;do I need a constructor here?&#8221; &#8212; spoiler: <em>yes</em> &#8212; let alone the obvious follow-ups like &#8220;what arguments should one take?&#8221;.</p>
<p>The obvious better answer here is to flip the default on interfaces, causing them to generate constructors by default unless turned off with <code>[NoConstructor]</code> attributes or specified as <code>partial</code> interfaces (i.e., mixins or traits).</p>
<p>Cameron McCormack who is heading up the WebIDL effort <a href="http://twitter.com/#!/heycam/status/118784862164484096">tweeted in response to my exasperation</a> that:</p>
<blockquote><p>I think a &#8220;W3C Web API design guidelines&#8221; document would be a perfect place for such a recommendation.</p></blockquote>
<p>For serious? Such a document might be useful (and I&#8217;m working on something that might pass as a first draft), but what&#8217;s the argument against flipping the default here? This isn&#8217;t a dissent on the facts of the situation: most WebIDL &#8220;interfaces&#8221; that are exposed to JS are things that could be easily <code>new</code>&#8216;d up to useful ends. Most specs flub this in spectacular style. Most spec authors seem entirely ignorant of the problem and the design language of WebIDL continues to lead down a primrose copy-and-paste path that has little overlap with sanity. So why punt the decision? And why did it take and act of coordination with TC39 to get the prototype thing fixed?</p>
<h3>And Why Are We Having This Discussion Anyway?</h3>
<p>WebIDL, for all of its virtues, is deeply confused.</p>
<p>If you&#8217;re reading any of the stuff in the HTML5 spec that&#8217;s describing its API this way, it&#8217;s hard to see how it would have any sane relationship to JavaScript. Sure, you could argue that there might be other languages that matter, other languages for which you&#8217;d need to be able to generate some API, but none of them rise to anything like the importance of JavaScript. It <em>is</em> the programming language of the web, so if WebIDL has any animating force at all, it&#8217;s JS. Then there&#8217;s the &#8220;accident of history&#8221; aspect. Early DOM was specified as a form of IDL in part because there was some expectation that other languages would need to consume it and IDL was how C++ hackers (who still make up the entire set of people working on browser engines) are/were comfortable in describing their FFIs thanks to the legacy of COM/CORBA. <a href="http://www.w3.org/TR/2011/WD-WebIDL-20110927/#java-binding">Hilarious examples of multi-language-ism still persist in the WebIDL spec</a> for no apparent reason whatsoever, warping the entire design around the altar of an ideal that is either quixotic or vestigial depending on which argument you give more weight. </p>
<p><a href="http://lists.w3.org/Archives/Public/public-script-coord/2011JulSep/thread.html#msg114">Since the debate was re-kindled thanks to a debate at a TC39 meeting in July</a>, I&#8217;ve been on the receiving end of more than one webdev&#8217;s rant about DOM&#8217;s JS incoherence, generally taking the form:</p>
<blockquote><p>Why the *#!*?^@$ isn&#8217;t DOM just #@!*@ing specified in JavaScript?</p></blockquote>
<p>To be honest, I have no answer aside from pointing to the IDL history, the fact that browser hackers don&#8217;t tend to write JS so don&#8217;t feel the pain, and noting that WebIDL <em>is</em> better in some important ways. Certainly these interfaces <em>could</em> be specified in a subset of JS with annotations for where native behavior is required. But their larger lament has merit too: seamlessness with JS is the bar WebIDL should be judged by. I.e. does it help spec authors do the right thing by JS devs? Or does it lead them down paths that make their generated APIs stick out like sore thumbs, full of anti-social/alien behavior such that you can&#8217;t think of them as &#8220;regular&#8221; JS?</p>
<p>Yes, constructors are only one minor step toward reaching this aspiration, but the fact that WebIDL has gotten to last-call without a reasonable solution to them speak volumes. If WebIDL <em>isn&#8217;t</em> animated by the need of JS developers, it would be good if that could be loudly called out somewhere so that the community can have the spirited debate that this point demands. If it is, can we please get on discussing how best to ensure that most &#8220;interfaces&#8221; generate constructors and stop punting?</p>
<p>Either way, WebIDL isn&#8217;t done yet.</p>
<p><b>Update:</b> It occurred to me, as part of the discussion in the comments, that the provision against <code>new</code> with a class or type of any type is completely non-sensical in JS, as is the lack of <code>call()</code> and <code>apply()</code> methods on them. Idiomatic subclassing requires that the mixin-style be available, which uses <code>ClassName.call(this)</code>. This is what you&#8217;d do with things that are &#8220;virtual&#8221; or &#8220;partial&#8221; interfaces if you&#8217;re describing them in actual JS. And there&#8217;s no real problem with folks <code>new</code>-ing them up. Doesn&#8217;t happen, doesn&#8217;t matter. Strong restrictions against it are, to quote Andrew DuPont, anti-social. Long story short: <b><em>there is absolutely no reason whatsoever to disable construction on any WebIDL interface. It&#8217;s deeply non-sensical from the JavaScript perspective.</em></b></p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/10/real-constructors-webidl-last-call/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Standards Are Insurance</title>
		<link>http://infrequently.org/2011/09/standards-are-insurance/</link>
		<comments>http://infrequently.org/2011/09/standards-are-insurance/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 19:47:00 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1685</guid>
		<description><![CDATA[I keep getting distracted from writing this long thing by responding to the discussion created by the last short-ish thing, but I wanted to explicitly call out one aspect, namely that standards are a form of insurance. More correctly &#8212; and apologies if this sounds like a Planet Money episode &#8212; vendors sell derivatives contracts [...]]]></description>
			<content:encoded><![CDATA[<p>I keep getting distracted from writing this long thing by responding to the discussion created by the last short-ish thing, but I wanted to explicitly call out one aspect, namely that <em>standards are a form of insurance</em>. </p>
<p>More correctly &#8212; and apologies if this sounds like a <a href="http://www.npr.org/blogs/money/">Planet Money</a> episode &#8212; vendors sell derivatives contracts (insurance) against the proprietary nature of technologies. I.e., as a hedge against winner-take-all dynamics of network effects and the potential for monopoly rent extraction. Adopters of that technology often refuse to buy it at all without the availability of a derivative to cover their risk of lock-in.</p>
<p>The nice bit about these contracts is that the results (price) are free to the public &#8212; ITU and other old-skool orgs are exceptions &#8212; meaning anyone who wants to implement can assess what it&#8217;ll cost, and if they can provide a solution at a lower to-end-user price, they can compete under the same terms. The public nature of the derivative contract can have the effect of lowering the price of the good itself in markets that clear and have many participants.</p>
<p>Standards organizations are correctly understood as middle-men or market-makers for these contracts.</p>
<p><b>Update:</b> It may seem strange to some that derivatives contracts (insurance) can drive prices down, but it happens in many industries. E.g., satellite insurance has done wonders for the commercial launch vehicle industry. And who would fund the construction of new cargo ships if you couldn&#8217;t convince enough people to ship their precious goods? Insurance matters.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/standards-are-insurance/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>What A Breakup Would Look Like</title>
		<link>http://infrequently.org/2011/09/what-a-breakup-would-look-like/</link>
		<comments>http://infrequently.org/2011/09/what-a-breakup-would-look-like/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 18:12:05 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1680</guid>
		<description><![CDATA[Karl Dubost asked what a plan would look like for a W3C split along the lines I proposed in my last post. It&#8217;s a fair question, so let me very quickly sketch out straw-men while noting that I would support many alternative plans as well. The shape of the details might matter, but not as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.la-grange.net/karl/">Karl Dubost</a> asked what a plan would look like for a W3C split along the lines I proposed in my <a href="http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/">last post</a>. It&#8217;s a fair question, so let me <em>very</em> quickly sketch out straw-men while noting that I would support many alternative plans as well. The shape of the details might matter, but not as much as movement in the right direction, and I have faith that the W3C members and staff would do a good job of executing on any such plan. Here are some general forms it could take, both of which seem workable to me:</p>
<h3>Spin-Off With Cross-licensing</h3>
<p>Taking many of the W3C&#8217;s activities to a different organization might be traumatic for some members due to IPR concerns. If the members agree that this is the most important consideration, a pure split could be effected, leaving smaller, parallel organizations with identical legal arrangements and identical IPR policies in place. Member organizations would, in a transition period, decide to move their membership to the spin-off, stay with the W3C, or join both (perhaps at a discount?). A contract between the new organizations would allow perpetual cross-licensing of applicable patent rights.</p>
<p>The risk to this plan is that it may not be clear that <em>one</em> new organization would be appropriate &#8212; remember, we&#8217;re talking about many strange bedfellows under the current W3C umbrella &#8212; so perhaps this may only work for whatever center of gravity exists in the spun-off concerns. Smaller efforts (Java-centric APIs, etc.) may want to find other homes.</p>
<h3>Merger</h3>
<p>One or more of the sub-efforts on the block may wish to find a new home in an existing standards organization. For these efforts there is likely to be larger mismatch between processes, IPR policies, etc. than a spin-off would entail, but the benefits to both receivers and members are clear: a viable home for the long term is hard to build, but coming home to &#8220;your people&#8221; isn&#8217;t nearly as difficult. XML standards, for instance, have a long history at OASIS and it&#8217;s unlikely that many members who care primarily about XML at the W3C aren&#8217;t also active there. Transfer of IPR in this case is likely to be more fraught, so contracts which stipulate license from the W3C to these new organizations would also need to include clauses which cause the receiving orgs to exercise similar processes to the ones currently in place for the standards which they receive ownership of. The contract would also need to stipulate that RF never be endangered for new versions of divested specs. I haven&#8217;t thought hard about transfer of membership under this scenario, but pro-rated and discounted membership terms at all merging organizations &#8212; but only for divested activities &#8212; might work.</p>
<p>Whatever path a breakup takes, the W3C should listen to each of the non-web communities it&#8217;s spinning off and work to ensure that their needs are met in the process. There are lots of details I don&#8217;t have time to think through right now, but none of the ones I can identify seem like deal-breakers. The biggest missing piece is the political will to make <em>something</em> happen in the first place.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/what-a-breakup-would-look-like/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Things the W3C Should Stop Doing</title>
		<link>http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/</link>
		<comments>http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 18:36:55 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1661</guid>
		<description><![CDATA[The time has come for the W3C to grab the mantle of the web, shake off its self-doubt, and move to a place where doing good isn't measured by numbers of specs and activities, but by impact for web developers.]]></description>
			<content:encoded><![CDATA[<p><em>This is a quick thought as I&#8217;m working on something much longer (and hopefully more interesting) to be published in the next week or so. Also, I just want to re-iterate that what&#8217;s said here are my own thoughts and not those of Google unless expressly stated otherwise.</em></p>
<p>I&#8217;ve been arguing &#8212; mostly over beers &#8212; for the last year or so that the W3C needs to find a ways to re-focus on the needs of the constituencies that give it credibility; namely web developers and browser vendors. This tends to fall on frustrated W3C staffer ears as individuals might agree but the organization feels the effects of its failures not as a question about how to re-focus around a credible mission but as a short-run funding shortfall. I&#8217;m excited that the new <a href="http://www.w3.org/community/">Community Groups</a> have the potential to help fix some of this by allowing a freer flow of ideas and a more representative expressions of demand, but there&#8217;s the lingering pay-for-play issue that I think is liable to drag the organization back to the status-quo as soon as the excitement and newness of Community Groups wear off.</p>
<p>Now, let me say clearly up front that I don&#8217;t think that standards bodies are charities, nor should they be. People join (in the case of the W3C, &#8220;people&#8221; == &#8220;companies&#8221;, an equivalence that works as US legal fiction but never in the real world) because they&#8217;re expressing their economic interests in agreement on thorny, market-focused issues. The W3C, as an organ, has grown out of an IETF alternative into a critical mediator in the flow of ideas and technology in the web ecosystem. When it fails, we&#8217;re starved of progress because nothing else can easily grow in its place. Bless Hixie and the WHATWG for trying, but the W3C sits on fertile spec and patent rich land. It&#8217;s tough growing in the rocky craigs, particularly without a patent policy.</p>
<p>So, in the spirit of reform, not revolution, I have a proposal, complete with Swiftian modesty:</p>
<h3>At <a href="http://www.w3.org/2011/11/TPAC/">this year&#8217;s TPAC</a>, it should be agreed that the W3C will divest itself of any and all Semantic Web, RDF, XML, Web Services, and Java related activities. SVG can be saved, but only if it re-charters to drop all XML dependencies in the next version.</h3>
<p>Where should these specs and member organizations go to get their itches scratched? I&#8217;m not sure it matters, although it seems likely that OASIS wouldn&#8217;t mind being the go-to place for XML. And there&#8217;s always ECMA, or IETF, or ISO, or&#8230;you get the idea.</p>
<p>Why do such a drastic thing?</p>
<p>Well, it&#8217;s not that drastic, really. The SemWeb folks use the term &#8220;web&#8221; in a hopeful, forward looking way that nobody else does. Their technology is showing promise inside firewalls but their work has near zero relationship to the actual, messy web we swim in every day. The result is that their narrow  constituency isn&#8217;t the one that animates whatever legitimacy the W3C might enjoy, and therefore their influence in the W3C is out of all proportion to their organizational and web-wide value. Sir Tim&#8217;s belief in their goal is noble, but to use the suffix &#8220;web&#8221; on it today is simply wishful thinking. And things that don&#8217;t have anything to do with the web probably don&#8217;t belong at the W3C. Besides, the W3C imprimatur doesn&#8217;t help these specs and groups as much as their advocates might think &#8212; standards bodies aren&#8217;t venues for creating the future after all, only for cleaning it up in response to the messy, explosive process of market-driven evolution. Anyway, being endlessly frustrated that the entire web hasn&#8217;t changed to accomodate some new model even though it has the phrase &#8220;web&#8221; in the name can&#8217;t be fun. Technologies need to find their success where they <em>really do fit</em> and distributed extensibility and semantics might be valuable&#8230;but it hasn&#8217;t been to the web yet. It needs to go.</p>
<p>As for XML, well, it won the enterprise and lost the web. That&#8217;s still success, but it&#8217;s not the web.</p>
<p>Rinse, repeat for RDF, Web Services, and Java.</p>
<p>What would that leave us with? CSS, DOM &#038; JS APIs, HTML, a11y, i18n, and all the other stuff that has legs out on the public web. More to the point, it would have the beneficial effect of re-focusing the organization around getting HTML5 done, getting DOM APIs done that don&#8217;t suck for JavaScript on the altar of IDL &#8220;language neutrality&#8221;, etc.</p>
<p>Organizationally, it would leave the W3C in a much leaner, more focused place. It&#8217;s much easier to build a focused constituency and membership, and the lower cost structure would only help the organization weather hard times. I have high hopes that it can be brutally effective again&#8230;but to get there, it needs to focus, and focus is the process of ignoring things. The time has come for the W3C to grab the mantle of the web, shake off its self-doubt, and move to a place where doing good isn&#8217;t measured by numbers of specs and activities, but by impact for web developers.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/things-the-w3c-should-stop-doing/feed/</wfw:commentRss>
		<slash:comments>46</slash:comments>
		</item>
		<item>
		<title>Why &#8220;class&#8221; Doesn&#8217;t Mean What You Think It Means</title>
		<link>http://infrequently.org/2011/09/why-class-doesnt-mean-what-you-think-it-means/</link>
		<comments>http://infrequently.org/2011/09/why-class-doesnt-mean-what-you-think-it-means/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 14:33:30 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1662</guid>
		<description><![CDATA[There&#8217;s a lot of &#8220;don&#8217;t turn it into Java!&#8221; in the comments on my last post, and I feel it needs a response &#8212; and not because I think there&#8217;s anything to like about Java&#8217;s class or type systems (perhaps that they exist at all? I&#8217;m torn on even that). Lets look at some possible [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a lot of <em>&#8220;don&#8217;t turn it into Java!&#8221;</em> in the comments on my last post, and I feel it needs a response &#8212; and not because I think there&#8217;s anything to like about Java&#8217;s class or type systems (perhaps that they exist at all? I&#8217;m torn on even that).</p>
<p>Lets look at some possible ES.next code and walk through how it relates to today&#8217;s equivalent JS:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">module widgets <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">export</span> <span style="color: #003366; font-weight: bold;">class</span> DropDownButton <span style="color: #003366; font-weight: bold;">extends</span> Widget <span style="color: #009900;">&#123;</span>
    constructor<span style="color: #009900;">&#40;</span>attributes<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #003366; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>attributes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">buildUI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    buildUI<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">domNode</span>.<span style="color: #660066;">onclick</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-&gt;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// ...</span>
      <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Ignoring the semantic improvements of Harmony modules over the module patterns we&#8217;re using today, we can see a pretty straight-up de-sugaring of that to today&#8217;s JS with an emphasis on the many and varied uses of the word <code>function</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> widgets <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>global<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
  <span style="color: #003366; font-weight: bold;">function</span> DropDownButton<span style="color: #009900;">&#40;</span>attributes<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    Widget.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> attributes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">buildUI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  DropDownButton.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> Object.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>Widget.<span style="color: #660066;">prototype</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
    constructor<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> value<span style="color: #339933;">:</span> DropDownButton <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    buildUI<span style="color: #339933;">:</span>     <span style="color: #009900;">&#123;</span>
      value<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">domNode</span>.<span style="color: #660066;">onclick</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #006600; font-style: italic;">// ...</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>What you should take away from this isn&#8217;t that we&#8217;re turning JS into Java, it&#8217;s that we&#8217;re making it easier to read, <em>AND THAT&#8217;S ALL</em>. Once more for effect: what <em>class</em> means in ES6 is <em>function</em>. Or at least one of the things you currently do with <code>function</code>.</p>
<p>Better yet, we&#8217;re blessing a single pattern which you can use with old-style classes just as easily as you do today. I&#8217;ll leave it as an exercise for you to name all the different class patterns and systems that do nearly the same thing in slightly incompatible ways today. It&#8217;s a very long list.</p>
<p>If you like JS, and you like functions + prototypes (I do!), you have nothing to fear from the sugar we&#8217;re adding in ES6.</p>
<p><b>Update:</b> A lunchtime conversation here at DojoConf today reminded me of perhaps the largest thing that this new system <em>doesn&#8217;t</em> do; ES.next aren&#8217;t tied to a Java-like type system. Many of the conjoined fears of Java come from the very real pain created by a strict, nominal type system, and nobody in the committee is proposing a mistake like that &#8212; least of all me.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/why-class-doesnt-mean-what-you-think-it-means/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Google &amp; the Future of JavaScript</title>
		<link>http://infrequently.org/2011/09/google-the-future-of-javascript/</link>
		<comments>http://infrequently.org/2011/09/google-the-future-of-javascript/#comments</comments>
		<pubDate>Tue, 13 Sep 2011 00:36:54 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[openweb]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1657</guid>
		<description><![CDATA[Simply stated, Google is absolutely committed to making JavaScript better, and we're pushing hard to make it happen.]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s very little public information yet about Dart (nee, Dash), and as I&#8217;m not on Lars&#8217; team I can&#8217;t comment about it. More details will be forthcoming at the <a href="http://gotocon.com/aarhus-2011/presentation/Opening%20Keynote:%20Dart,%20a%20new%20programming%20language%20for%20structured%20web%20programming">GOTO session next month</a>. I&#8217;ll also be at GOTO, <a href="http://gotocon.com/aarhus-2011/presentation/Send%20Less,%20Do%20More,%20Go%20Faster:%20The%20Future%20of%20Front%20End%20Development">speaking on JavaScript and the state of the web platform</a>.</p>
<p>Making the rounds is an accidentally leaked early draft of notes from a meeting last year that discusses both Dart and JavaScript. I work on many web platform-related things at Google, including serving as a representative to TC39, the body that standardizes the JavaScript language. I wasn&#8217;t at the meetings having previously committed to <a href="http://2010.full-frontal.org/">presenting at FFJS</a>, but my views were represented by others and my name is on the document. As I said, though, it was a draft and doesn&#8217;t reflect either the reality of what has happened in the meantime or even the decisions that were taken as a result. And it certainly doesn’t reflect my personal views.</p>
<p>So what&#8217;s the deal with Google and JavaScript?</p>
<p>Simply stated, Google is absolutely committed to making JavaScript better, and we&#8217;re pushing hard to make it happen.</p>
<p>Erik Arvidsson, Mark Miller, Waldemar Horwat, Andreas Rossberg, Nebojša Ćirić, Mark Davis, Jungshik Shin and I attend TC39 meetings, work on implementations, and try to push JS forward in good faith. And boy, does it need a push.</p>
<p>Erik and I have specifically been working to focus the TC39 agenda away from syntax-free, semantics-only APIs (Object.defineProperty, anyone?) which might be good for tools, compilers, and frameworks but which are hard for day-to-day use.</p>
<p>Through <a href="http://code.google.com/p/traceur-compiler/">Traceur</a> and other efforts we&#8217;ve been socializing the idea that the one thing the committee can exclusively do &#8212; and should do more of &#8212; is to carve out syntax for commonly exercised semantics. Seemingly small things like the <a href="http://wiki.ecmascript.org/doku.php?id=harmony:classes"><code>class</code> keyword as sugar</a> for the constructor function pattern, or a <a href="http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax&#038;s=short+function">shorter syntax for functions</a> are big improvements, if only because it&#8217;s TC39 that&#8217;s making them. Syntax can end battles over common patterns and help you say what you mean, and JS is overdue for some of this. Larger but more subtle things, like agreement to use pragmas as a way to enable the process of progress in a compatible web, are even more exciting to me. Even proposals that haven&#8217;t made it through like <a href="http://wiki.ecmascript.org/doku.php?id=strawman:scoped_object_extensions">Scoped Object Extensions</a> and <a href="http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions">deferred functions</a> have been fought for by us because we desperately want JavaScript to get better. We&#8217;re big fans of much of the work coming out of Mozilla for the same reason &#8212; in particular Dave Hermann&#8217;s excellent <a href="http://wiki.ecmascript.org/doku.php?id=harmony:modules">modules proposal</a>. Together, these are going to do much to help give modern JS some &#8220;backbone&#8221; in the near term. I’m proud of what we’ve accomplished in TC39 over the last year, and while I hoped for more, the result is an ES.next that looks like it’ll embody many of the things I feel are currently missing. The day-to-day practice of writing JS is going to change dramatically for the better when ES.next arrives.</p>
<p>But it&#8217;s not the end &#8212; not by a long shot. Classes will give us a humane, interoperable inheritance syntax, but it leaves composition unaddressed by syntax. I&#8217;m hopeful that we bless traits in future versions, removing the use of inheritance in most cases. Similarly, I think we can find a way to repair &#8220;this&#8221; binding foot-guns with softly-bound &#8220;this&#8221;. Repairing the shared-prototypes issue, either through DOM or through something like Scoped Object Extensions, can and should be done. And once we have all of this, the stage will be set for a flexible, advanced type system that does not need to be all-or nothing and does not need to be hobbled by the ghost of C++/Java&#8217;s inflexible nominal-only types. That&#8217;s the dream, and we&#8217;re not shying away from it.</p>
<p>It&#8217;s hard to square this sort of wild enthusiasm for &#8220;raw&#8221; JavaScript with what&#8217;s in the leaked memo, and I can only beg for some amount of understanding. As committed and enthusiastic as I am about the prospects for JavaScript, others are just as enthused about Dart. Google is big, can do many things at once, and often isn&#8217;t of one mind. What we do agree on is that we&#8217;re trying to make things better the best we know how. Anyone who watches Google long enough should anticipate that we often have different ideas about what that means. For my part, then, consider me and my team to be committed JS partisans for as long as we think we can make a difference.</p>
<h3>Reality Check</h3>
<p>There are risks, of course. TC39 is long on seasoned language design skill and short on webdev experience, meaning that many things that Erik and I may take for granted as pressing problems need to be explained, sometimes to an incredulous audience. The flip side risk is that naïve solutions may have better alternatives that seasoned language hands can quickly spot and that simple answers have non-obvious risks or preclude movement in other important areas later. It&#8217;s good, then, that the committee is working well and is taking appeals to developer productivity seriously.</p>
<p>Whatever you might think about programming languages for the browser, let me assure you of one thing: your problem isn&#8217;t the language. Not really, anyway. We&#8217;ve made good progress in the last year repairing some of the seams between JS and DOM, and Cameron McCormack has helped us drive a new version of WebIDL that correctly explains DOM as a reasonable prototype chain. But it&#8217;s only the beginning. The DOM is in terrible shape, and not due to implementation differences. The malign neglect of IDL-addled designs, the ghosts of dead-end XML experiments, and endless cruft will plague any language that sidles up to it. Until we get a real <a href="http://wiki.whatwg.org/wiki/Component_Model">Component Model</a>, a better CSS OM, and some sort of a pragma for DOM that allows us to fix DOM&#8217;s abhorrent JS bindings, we&#8217;ll continue to be hostage to C++ APIs inartfully wired up to an incredibly dynamic language. And that’s to say nothing of the pressing need for <a href="http://code.google.com/p/experimental-css/">better CSS</a>, animations, and <a href="http://code.google.com/p/mdv/">a built-in data-binding/templating system</a>. When the platform doesn’t provide it, today, we get it from JavaScript. But that’s not where the solutions always belong.</p>
<p>Let me put it another way: when you find yourself thinking &#8220;man, JavaScript sucks,&#8221; remember that it&#8217;s only painful in large quantities. And why do you need so much of it? &#8216;Cause the DOM, CSS, and HTML standards are letting you down. Any language wired up to the browser today is subject to the same fate, and the insane reality that these things are specified under different roofs in processes that aren&#8217;t subject to the popular will of web developers. Python doesn’t have it’s DOM APIs decided by the W3C, they borrow the idiomatic <a href="http://docs.python.org/library/xml.etree.elementtree.html">ElementTree API</a> from within their own community. WebIDL is an artifact of a different time that has a tenuous relationship to idiomatic JavaScript, the CSS-OM barely exists, and DOM apologists are doing more harm than any of JavaScript&#8217;s warts ever have. We can fix these things, of course, and here at Google we&#8217;re trying – in good faith – to work in standards to make them better. But the bottom line is that the language isn’t the problem. I repeat: the language isn’t the problem, the platform is.</p>
<p>The only thing that&#8217;s going to replace the web as universal platform is the next version of the web. Those of us working on Chrome believe that to the core and feel a deep urge to make things better faster. We might not always agree on the &#8220;how,” but we all believe that we can’t do it alone.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/09/google-the-future-of-javascript/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Non-Admin Chrome Frame, Now Stable!</title>
		<link>http://infrequently.org/2011/08/non-admin-chrome-frame-now-stable/</link>
		<comments>http://infrequently.org/2011/08/non-admin-chrome-frame-now-stable/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 04:17:28 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[chrome]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[openweb]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1638</guid>
		<description><![CDATA[The title says it all: you can now put a link like this in your app and users will get the stable version of either admin or non-admin Chrome Frame, depending on what rights they have on their system: &#60;!--[if lt IE 9 ]&#62; &#60;p&#62;Your browser is &#60;em&#62;ancient!&#60;/em&#62; &#60;a href=&#34;http://microsoft.com/ie&#34;&#62;Upgrade&#60;/a&#62; or &#60;a href=&#34;http://www.google.com/chromeframe/?redirect=true&#34;&#62; install Google [...]]]></description>
			<content:encoded><![CDATA[<p>The title <a href="http://blog.chromium.org/2011/08/non-admin-chrome-frame-reaches-stable.html">says it all</a>: you can now put a link like this in your app and users will get the stable version of either admin or non-admin Chrome Frame, depending on what rights they have on their system:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;!--[if lt IE 9 ]&gt;
&lt;p&gt;Your browser is &lt;em&gt;ancient!&lt;/em&gt;
&lt;a href=&quot;http://microsoft.com/ie&quot;&gt;Upgrade&lt;/a&gt; or
&lt;a href=&quot;http://www.google.com/chromeframe/?redirect=true&quot;&gt;
   install Google Chrome Frame&lt;/a&gt; to experience this app.
&lt;/p&gt;
&lt; ![endif]--&gt;</pre></div></div>

<p>The <code>redirect=true</code> ensures that once the the install completes, users are automatically redirected back to your site (slick, huh?) and the conditional comments keep the prompt from being shown to folks with modern browsers.</p>
<p>At the top of your document you&#8217;ll still need to add the <a href="http://www.chromium.org/developers/how-tos/chrome-frame-getting-started#TOC-Making-Your-Pages-Work-With-Google-">header or meta tag to your apps/pages</a> to opt-in to Chrome Frame rendering:</p>
<pre>
    <b>&lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"&gt;</b>
</pre>
<p>Couldn&#8217;t be easier, and if you&#8217;re using a starter kit like the excellent <a href="http://html5boilerplate.com/">HTML5 Boilerplate</a>, it&#8217;s already in there!</p>
<h3>Nearly forgot&#8230;</h3>
<p>So, why, you might ask, did it take this long from <a href="http://www.youtube.com/watch?v=3YkEUpJQP3o">showing user-mode at I/O</a> to get this to the the world?</p>
<p>Good, if convoluted question. The answer is long, complicated, and involves a harrowing-yet-seamless transition of hundreds of millions of Chrome installs to a new installer infrastructure, but I&#8217;ll skip to the punch line: <em>millions of users won&#8217;t even have to download Chrome Frame</em> to install it. Chrome Frame&#8217;s quick-enable mode is available on every system that has Chrome installed &#8212; even if Chrome isn&#8217;t being used as the default browser &#8212; which means that for many of your users installing Chrome Frame can be nearly instant. No download, no traditional install process. Just &#8220;activate&#8221;, &#8220;accept&#8221; and those users are on their way back to your site to experience the HTML5 goodness you&#8217;ve built.</p>
<p>If you&#8217;re contemplating adding a prompt to your site or app, know that you&#8217;re not alone either. As promised, GMail is asking all IE 6 and 7 users to upgrade or install Chrome Frame. A growing list of sites like <a href="http://chrome.angrybirds.com">Angry Birds</a> couldn&#8217;t have been built without assuming Chrome Frame as a solution to &#8220;the IE problem&#8221;.</p>
<p>Chrome Frame is all about turning HTML5 from a &#8220;someday&#8230;&#8221; prospect to a reality for your very next project, even if you&#8217;re deploying to users and organizations that can&#8217;t join us here in the future by adopting modern browsers. Only the trailing edge has been standing still, and now that we&#8217;re all free of it I can&#8217;t wait to see we build.</p>
<p>The web is about to get better a whole lot faster.</p>
<p><b>Update:</b> Erik Wright informs me that we don&#8217;t even need the <code>prefersystemlevel</code> now! Post updated to reflect this.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/08/non-admin-chrome-frame-now-stable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Browser Wars (plural)</title>
		<link>http://infrequently.org/2011/03/browser-wars-plural/</link>
		<comments>http://infrequently.org/2011/03/browser-wars-plural/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 16:24:01 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1624</guid>
		<description><![CDATA[In a half hour, I&#8217;m going to be on the Web 2.0 Expo Browser Wars panel with a cast of incredible folks. A couple of weeks back, I had the privilege of doing something similar on a browser panel expertly moderated by Arun Ranganathan. As a part of that panel, Brendan, Lars, Arun, John, and [...]]]></description>
			<content:encoded><![CDATA[<p>In a half hour, I&#8217;m going to be on the <a href="http://www.web2expo.com/webexsf2011/public/schedule/detail/17798">Web 2.0 Expo Browser Wars panel</a> with a cast of incredible folks. A couple of weeks back, I had the privilege of doing something similar on a browser panel expertly moderated by <a href="http://arunranga.com/blog/">Arun Ranganathan</a>.</p>
<p>As a part of that <a href="http://schedule.sxsw.com/events/event_IAP7286">panel, Brendan, Lars, Arun, John, and I</a> all agreed to post a list of links to demos and such that showed off what our latest browsers are doing. Belatedly, here goes:</p>
<hr />
<p>The <a href="http://schedule.sxsw.com/events/event_IAP7286">browser wars panel</a> is designed to be a discussion, so we didn&#8217;t use any kind of presentation media.  So here&#8217;s a list of demos and resources so that you can learn more about stuff we talk about.  Pictures speak volumes about what gets us excited about the web, anyway.</p>
<h3>HTML5, CSS, and JavaScript Demos</h3>
<ul>
<li>
<p><a href="https://demos.mozilla.org/en-US/">The Web O&#8217; Wonder</a> Website works in browsers that support the latest web standards.</p>
</li>
<li>
<p><a href="http://www.beautyoftheweb.com/#/experience/category/coolhtml5">The Beauty of the Web</a> site showcases a bunch of different things with a bit of an <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home">IE9</a> slant.</p>
</li>
<li>
<p><a href="http://studio.html5rocks.com/">HTML5 Rocks</a> showcases a lot of great demos, which work best in <a href="http://www.mozilla.com/en-US/firefox/RC/">Firefox 4</a> and the latest <a href="http://www.google.com/chrome">Chrome</a> (but the site uses feature detection, so much of it will work in <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home">IE9</a> and <a href="http://www.apple.com/safari/">Safari</a>.).</p>
</li>
<li>
<p><a href="http://www.foursquareplayground.com/">FourSquare Playground</a> has a strong <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home">IE9</a> bias, but showcases HTML5.</p>
</li>
<li>
<p><a href="http://www.ietestdrive.com/">IE Test Drive</a>.  Need I say more about bias?  Showcases HTML5, with the promise of some demos that may work cross-browser.</p>
</li>
<li>
<p>Here&#8217;s <a href="http://arunranga.com/presentations/India2010Presentations/Feb2010/BangaloreDevDay.html">a presentation I gave</a>, which may actually have a Firefox bias, given that I showcased technologies that were &#8220;Moz&#8221; prefixed (e.g. <a href="https://developer.mozilla.org/en/DOM/MozOrientation">MozOrientation</a>).  Still, shows off some great demos in a variety of arena (<a href="https://developer.mozilla.org/en/Using_geolocation">Geolocation</a>, etc.).</p>
</li>
</ul>
<h3>WebGL Demos</h3>
<p>To get maximum mileage out of these, you&#8217;ll want a fast PC with the latest Chrome or Firefox.</p>
<ul>
<li>
<p><a href="http://www.ambiera.com/copperlicht/demos.html">The CopperLicht Stuff from Ambiera</a> blows my mind every time.</p>
</li>
<li>
<p><a href="http://videos.mozilla.org/serv/mozhacks/flight-of-the-navigator/">Flight of the Navigator</a> is a really compelling mix of different elements. </p>
</li>
<li>
<p><a href="https://mozillademos.org/demos/remixingreality/demo.html">Remixing Reality</a> is really compelling demo of the use of models.</p>
</li>
<li>
<p><a href="http://www.khronos.org/webgl/wiki/Demo_Repository">The WebGL Demo Repository</a> at Khronos contains demos that are classic GL ones (that 3D programmers are all well familiar with).</p>
</li>
</ul>
<h3>Resources</h3>
<ul>
<li>
<p><a href="http://caniuse.com/">Can I Use</a> provides incredibly useful feature matrices to determine which browser supports what in the HTML5 and CSS arena.</p>
</li>
<li>
<p><a href="http://www.quirksmode.org/">Quirksmode</a> is the go-to place for compatibility tables.</p>
</li>
<li>
<p><a href="http://hacks.mozilla.org/">Hacks</a> is Mozilla&#8217;s showcase for articles, demos, and API updates.</p>
</li>
<li>
<p><a href="http://www.html5rocks.com/">HTML5 Rocks</a> features great stuff about HTML5, and includes code snippets and documentation for developers.</p>
</li>
<li>
<p><a href="http://www.amazon.com/HTML5-Now-Step-Step-Tutorial/dp/0321719913">HTML5 Now</a> is <a href="http://www.tantek.com/">Tantek Celik&#8217;s</a> book on the subject.</p>
</li>
<li>
<p><a href="http://books.alistapart.com/products/html5-for-web-designers">HTML5 for Web Designers</a> is <a href="http://www.adactio.com/">Jeremy Keith&#8217;s</a> book on the subject.</p>
</li>
<li>
<p><a href="http://www.brucelawson.co.uk/2010/introducing-html5-lands/">Bruce Lawson and Remy Sharp&#8217;s HTML5 Lands</a></p>
</li>
<li>
<p><a href="http://learningwebgl.com/blog/">Learning WebGL</a> and the <a href="http://learningwebgl.com/cookbook/index.php/Main_Page">WebGL Cookbook</a> are great sites to learn WebGL</p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/03/browser-wars-plural/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Half Lives</title>
		<link>http://infrequently.org/2011/03/half-lives/</link>
		<comments>http://infrequently.org/2011/03/half-lives/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 16:04:02 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[openweb]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1616</guid>
		<description><![CDATA[I&#8217;m headed to Austin soon for spring break SxSWi, and this year I&#8217;m lucky and grateful to be representing Chrome on the always-packed browser panel (more usable Lanyrd talk page here). The context for this year&#8217;s panel is interesting to me &#8212; a couple of years into a renewed era of browser competition, users have [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m headed to Austin soon for <del>spring break</del> SxSWi, and this year I&#8217;m lucky and grateful to be <a href="http://schedule.sxsw.com/events/event_IAP7286">representing Chrome on the always-packed browser panel</a> (more usable <a href="http://lanyrd.com/">Lanyrd</a> talk page <a href="http://lanyrd.com/2011/sxsw/scrxm/">here</a>). The context for this year&#8217;s panel is interesting to me &#8212; a couple of years into a renewed era of browser competition, users have more choice but developers are still struggling with the same landscape, even as HTML5 starts to materialize as the platform of choice for <em>most</em> apps &#8212; even the ones wrapped up in native wrappers to jump the various app-store-form distribution hurdles.</p>
<p>It&#8217;s good to see <a href="http://ie6countdown.com/">MSFT belatedly trying to put IE6 out to pasture</a>, but what about IE 7? Or 8? Lets take stock of where we really are and where we&#8217;re likely to be in the next couple of years. First, remember that there&#8217;s no IE 9 for Windows XP &#8212; an OS that&#8217;s currently the most popular in the world &#8212; and no matter what happens with IE 6, IE 8 is the end of the upgrade road for XP. Unless you think half of the world&#8217;s computers will be replaced/upgraded in the next couple of years, it seems likely that IE 8 will be with us for the foreseeable future.</p>
<p>And what about the folks who <em>do</em> get IE 9? Well, so far, there&#8217;s nothing to make me believe that the uptake rate will be anything better than the IE 8 transition; a process which has taken 2 years to give ~30% of the market the latest version. If anything, we should expect that rate to be retarded somewhat by the XP hurdle.</p>
<p>MSFT&#8217;s browser replacement rates bear understanding because they&#8217;re the most popular and suffer from the longest half-lives. That is to say, the time it takes for an old version of IE to decay in the wild is much, much higher than for other browsers. Some part of this is surely due to sheer market share, but not all of it. The XP hurdle, for instance, is a form of structural drag on uptake rates &#8212; a flaw that browsers that aren&#8217;t tightly tied to OSes don&#8217;t suffer from. For web developers, I dare say that half-life of popular browsers matters much, much more than the current or trending market share since it&#8217;s predictive of our potential for browser improvement in the near future. It&#8217;s one thing to get the new shiny, but how long will it take you to install it? If the shiny is old and dingy by the time it&#8217;s in place, what good is that? It&#8217;s this lens that makes browser market share stats interesting to me; i.e., what percentage of the web&#8217;s users will get the new features soonest? &#8216;Cause those are the folks we can start building super compelling content for.</p>
<p>The average half-life of the majority of browsers in the wild also gates the rate of progress in standards. When the process is working well, bugs in browsers or pre-standards implementations of features aren&#8217;t a permanent features of the landscape. Instead, they&#8217;re the understandable and inevitable result of a process that prioritizes implementation experience and iteration over raw compliance with an academic spec that may or may not actually get it right on the first go &#8217;round. But that iterative, feedback-rich process only works when browsers iterate quickly and web developers can target the future without thinking so hard about the past, else progress simply turns into something to resent and distrust. That&#8217;s good for no one, and a shorter half-life is the key to making progress more than just a spec-tease.</p>
<p>I&#8217;m personally hopeful that when IE 9 is finally RTM&#8217;d, that it includes some provisions for shortening its life expectancy in the ways that Chrome and Firefox have through aggressive auto-updating. Getting IE 9 out to the world will be a good thing, but only if it happens quickly and if IE 10 can follow it even faster.</p>
<p>There&#8217;s obviously a lot more to talk about at the browser panel &#8212; <a href="http://chrome.blogspot.com/2011/03/speedier-simpler-and-safer-chromes.html">Chrome 10 just launched with Crankshaft</a>, for instance &#8212; but the fact that nearly every Chrome user will have those improvements <em>this week</em> and that if you&#8217;re building a Chrome Web Store app, you&#8217;ll get to target those improvements nearly instantly seems like the biggest, most interesting change from where we were just a couple of years ago.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/03/half-lives/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Performance Innumeracy &amp; False Positives</title>
		<link>http://infrequently.org/2011/02/on-performance-innumeracy-false-positives/</link>
		<comments>http://infrequently.org/2011/02/on-performance-innumeracy-false-positives/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 18:49:41 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1575</guid>
		<description><![CDATA[tl;dr version: the web is waaaay too slow, and every time you write something off as &#8220;just taking a couple of milliseconds&#8221;, you&#8217;re part of the problem. Good engineering is about tradeoffs, and all engineering requires environmental assumptions &#8212; even feature testing. In any case, there are good, reliable ways to use UA detection to [...]]]></description>
			<content:encoded><![CDATA[<p><em>tl;dr version: the web is waaaay too slow, and every time you write something off as &#8220;just taking a couple of milliseconds&#8221;, you&#8217;re part of the problem. Good engineering is about tradeoffs, and all engineering requires environmental assumptions &#8212; even feature testing. In any case, there are good, reliable ways to use UA detection to speed up feature tests in the common case, which I&#8217;ll show, and to which the generic arguments about UA <b>vs.</b> feature testing simply don&#8217;t apply. We can and should go faster. <b>Update:</b> <a href="http://www.nczonline.net/blog/2011/02/08/on-ua-sniffing-browser-detection-and-alexs-post/">Nicholas Zackas explains it all, clearly, in measured form. Huzzah!</a></em></p>
<h2>Performance Innumeracy</h2>
<p>I want to dive into concrete strategies for low-to-no false positive UA matching for use in caching feature detection results, but first I feel I need to walk back to some basics since I&#8217;ve clearly lost some people along the way. Here are some numbers every developer (of any type) should know, borrowed from <a href="http://norvig.com/21-days.html">Peter Norvig&#8217;s indispensable &#8220;Teach Yourself To Program In Ten Years&#8221;</a>:</p>
<blockquote><p>
Approximate timing for various operations on a typical PC:<br />
<table class="callout">
<tr>
<td>execute typical instruction</td>
<td align=right> 1/1,000,000,000 sec = 1 nanosec
</td>
</tr>
<tr>
<td>fetch from L1 cache memory</td>
<td align=right> 0.5 nanosec
</td>
</tr>
<tr>
<td>branch misprediction</td>
<td align=right> 5 nanosec
</td>
</tr>
<tr>
<td>fetch from L2 cache memory</td>
<td align=right> 7 nanosec
</td>
</tr>
<tr>
<td>Mutex lock/unlock</td>
<td align=right> 25 nanosec
</td>
</tr>
<tr>
<td>fetch from main memory</td>
<td align=right> 100 nanosec
</td>
</tr>
<tr>
<td>send 2K bytes over 1Gbps network</td>
<td align=right> 20,000 nanosec
</td>
</tr>
<tr>
<td>read 1MB sequentially from memory</td>
<td align=right> 250,000 nanosec
</td>
</tr>
<tr>
<td>fetch from new disk location (seek)</td>
<td align=right> 8,000,000 nanosec
</td>
</tr>
<tr>
<td>read 1MB sequentially from disk</td>
<td align=right> 20,000,000 nanosec
</td>
</tr>
<tr>
<td>send packet US to Europe and back</td>
<td align=right> 150 milliseconds = 150,000,000 nanosec
</td>
</tr>
</table>
<p>
</p>
</blockquote>
<p>That data&#8217;s a bit old &#8212; 8ms is optimistic for a HD seek these days, and SSD changes things &#8212; but the orders of magnitude are relevant. For mobile, we also need to know:</p>
<table class="callout">
<tr>
<td>fetch from flash storage</td>
<td align=right>1,300,000 nanosec</td>
</tr>
<tr>
<td>60hz time slice</td>
<td align=right>16,000,000 nanosec</td>
</tr>
<tr>
<td>send packet outside of a (US) mobile carrier network and back</td>
<td align=right>80-800 milliseconds = 80,000,000 &#8211; 800,000,000 nanosec</td>
</tr>
</table>
<p>The 60hz number is particularly important. To build UI that feels not just fast, but instantly responsive, we need to be yielding control back to our primary event loop in <em>less than 16ms</em>, all the time, every time. Otherwise the UI will drop frames and the act of clicking, tapping, and otherwise interacting with the app will seem &#8220;laggy&#8221; or &#8220;janky&#8221;. Framing this another way, anything your webapp blocks on for more than 16ms is the enemy of solid, responsive UI.</p>
<p>Why am I blithering on and on about this? Because some folks continue to mis-prioritize the impact of latency and performance on user satisfaction. Google (my employer, who does not endorse this blog or my private statements in any way) has <a href="http://code.google.com/speed/files/delayexp.pdf">shown that seemingly minor increases in latency directly impact user engagement</a> and that <a href="http://glinden.blogspot.com/2006/11/marissa-mayer-at-web-20.html">major increases in latency (> 500ms) can reduce traffic and revenue <em>significantly</em></a>. Latency then, along with responsiveness (do you drop below 60hz?), is a key metric for measuring the quality of an web experience. It&#8217;s no accident that Google employs <a href="http://stevesouders.com/">Steve Souders</a> to help evangelize the cause of improving performance on the web, and has gone so far as to build products like Chrome &amp; V8 who have as a core goal to the web faster. A faster web is a better web. Full stop.</p>
<p>That&#8217;s why I get so deeply frustrated when we get <a href="http://farukat.es/journal/2011/02/499-lest-we-forget-or-how-i-learned-whats-so-bad-about-browser-sniffing">straw-man based, data-challenged advocacy</a> from the maintainers of <a href="http://www.modernizr.com/">important bits of infrastructure</a>:</p>
<blockquote><p>
This stuff is far from easy to understand; even just the basics of feature detection versus browser detection are quite confusing to some people. That’s why we make libraries for this stuff (and, use browser inference instead of UA sniffing). These are the kind of efforts that we need, to help move the web forward as a platform; what we don’t need is more encouragement for UA sniffing as a general technique, only to save a couple of milliseconds. Because I can assure you that the Web never quite suffered, technologically, from taking a fraction of a second longer to load.
</p></blockquote>
<p>What bollocks. Not only did I not encourage UA sniffing &#8220;as a general technique&#8221;, latency does in fact hurt sites and users &#8212; all the time, every day. And we&#8217;re potentially not talking about &#8220;a couple of milliseconds&#8221; here. Remember, in the context of mobile devices, the CPUs we&#8217;re on are single-core and clocked in the 500mhz-1ghz range, which directly impacts the performance of single-threaded tasks like layout and JavaScript execution &#8212; which by the way happen <em>in the same thread</em>. In my last post I said:</p>
<blockquote><p>
&#8230;if you’re a library author or maintainer, please please please consider the costs of feature tests, particularly the sort that mangle DOM and or read-back computed layout values
</p></blockquote>
<p>Why? Because many of these tests inadvertently force layout and style re-calculation. See for instance <a href="https://github.com/phiggins42/has.js/blob/master/detect/events.js#L14">this snippet from <code>has.js</code></a>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>has.<span style="color: #660066;">isHostType</span><span style="color: #009900;">&#40;</span>input<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  input.<span style="color: #660066;">type</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;checkbox&quot;</span><span style="color: #339933;">;</span>
  input.<span style="color: #660066;">style</span>.<span style="color: #660066;">display</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;none&quot;</span><span style="color: #339933;">;</span>
  input.<span style="color: #660066;">onclick</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// ...</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">try</span><span style="color: #009900;">&#123;</span>
    de.<span style="color: #660066;">insertBefore</span><span style="color: #009900;">&#40;</span>input<span style="color: #339933;">,</span> de.<span style="color: #660066;">firstChild</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    input.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    de.<span style="color: #660066;">removeChild</span><span style="color: #009900;">&#40;</span>input<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">catch</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span>
  <span style="color: #006600; font-style: italic;">// ...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Everything looks good. The element is <code>display: none;</code> so it shouldn&#8217;t be generating render boxes when inserted into the DOM. Should be cheap, right? Well, lets see what happens in WebKit. Debugging into a simple test page with equivalent code shows that part of the call stack looks like:</p>
<pre>
#0	0x0266267f in WebCore::Document::recalcStyle at Document.cpp:1575
#1	0x02662643 in WebCore::Document::updateStyleIfNeeded at Document.cpp:1652
#2	0x026a89fd in WebCore::MouseRelatedEvent::receivedTarget at MouseRelatedEvent.cpp:152
#3	0x0269df03 in WebCore::Event::setTarget at Event.cpp:282
#4	0x026af889 in WebCore::Node::dispatchEvent at Node.cpp:2604
#5	0x026adbcb in WebCore::Node::dispatchMouseEvent at Node.cpp:2885
#6	0x026ae231 in WebCore::Node::dispatchSimulatedMouseEvent at Node.cpp:2816
#7	0x026ae3f1 in WebCore::Node::dispatchSimulatedClick at Node.cpp:2837
#8	0x02055bb5 in WebCore::HTMLElement::click at HTMLElement.cpp:767
#9	0x022587e6 in WebCore::HTMLInputElementInternal::clickCallback at V8HTMLInputElement.cpp:707
...
</pre>
<p><code>Document::recalcStyle()</code> can be <em>very</em> expensive, and unlike painting, it blocks input and other execution. And the cost is at page loading is likely to be much higher than other times as there will be significantly more new styles streamed in from the network to satisfy for each element in the document when this is called. This isn&#8217;t a full layout, but it&#8217;s most of the price of one. Now, you can argue that this is a WebKit bug and I&#8217;ll agree &#8212; synthetic clicks should probably skip this &#8212; but I&#8217;m just using this as an illustration to show that what browsers are doing on your behalf isn&#8217;t always obvious. Once this bug is fixed, this test may indeed be nearly free, but it&#8217;s not today. Not by a long shot.</p>
<p>Many layouts in very deep and &#8220;dirty&#8221; DOMs can take ten milliseconds or more, and if you&#8217;re doing it from script, you&#8217;re causing the system to do lots of work which it&#8217;s probably going to need to throw away later when the rest of your markup and styles show up.  Your average, dinky test harness page likely under-counts the cost of these tests, so when someone tells me &#8220;oh, it&#8217;s only 30ms&#8221;, not only do my eyes bug out at the double-your-execution-budget-for-anything number, but also the knowledge that in the real world, it&#8217;s probably a LOT worse. Just imagine this happening in a deep DOM on a low-end ARM-powered device where memory pressure and a single core are conspiring against you.</p>
<h2>False Positives</h2>
<p>My last post concerned how you can build a cache to eliminate many of these problems <b>if and only if you build UA tests that don&#8217;t have false positives</b>.  Some commenters can&#8217;t seem to grasp the subtlety that I&#8217;m <em>not</em> advocating for the same sort of lazy substring matching that has deservedly gotten such a bad rap.</p>
<p>So how would we build less naive UA tests that can have feature tests behind them as fallbacks? Lets look at some representative UA strings and see if we can&#8217;t construct some tests for them that give us sub-version flexibility but won&#8217;t pass on things that aren&#8217;t <em>actually</em> the browsers in question:</p>
<p>IE 6.0, Windows:</p>
<pre>
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
</pre>
<p>FF 3.6, Windows:</p>
<pre>
Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.13) Firefox/3.6.13
</pre>
<p>Chrome 8.0, Linux:</p>
<pre>
Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Ubuntu/10.10 Chromium/8.0.552.237 Chrome/8.0.552.237 Safari/534.10
</pre>
<p>Safari 5.0, Windows:</p>
<pre>
Mozilla/5.0 (Windows; U; Windows NT 6.1; sv-SE) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4
</pre>
<p>Some features start to jump out at us. The &#8220;platform&#8221; clauses &#8212; that bit in the parens after the first chunk &#8212; contains a lot of important data and a lot of junk. But the important stuff always comes first. We&#8217;ll need to allow but ignore the junk. Next, stuff after platform clauses is good, has defined order, and can be used to tightly form a match for browsers like Safari and Chrome. With this in mind, we can create some regexes that don&#8217;t allow much in the way of variance but do allow sub-minor version to match so we don&#8217;t have to update these every month or two:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">IE60 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/4\.0 \(compatible; MSIE 6\.0; Windows NT \d\.\d(.*)\)$/</span><span style="color: #339933;">;</span>
FF36 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(Windows; U;(.*)rv\:1\.9\.2.(\d{1,2})\)( Gecko\/(\d{8}))? Firefox\/3\.6(\.\d{1,2})?( \(.+\))?$/</span><span style="color: #339933;">;</span>
CR80 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \((Windows|Macintosh|X11); U;.+\) AppleWebKit\/534\.10 \(KHTML\, like Gecko\) (.+)Chrome\/8\.0\.(\d{3})\.(\d{1,3}) Safari\/534\.10$/</span><span style="color: #339933;">;</span></pre></div></div>

<p>These look pretty wordy, and they are, because they&#8217;re designed NOT to let through things that we don&#8217;t really understand. This isn&#8217;t just substring matching on the word &#8220;WebKit&#8221; or &#8220;Chrome&#8221;, this is a tight fit against the structure of the entire string. If it doesn&#8217;t fit, we don&#8217;t match, and our cache doesn&#8217;t get pre-populated. Instead, we do feature detection. Remember, false positives here are the enemy, so we&#8217;re using &#8220;^&#8221; and &#8220;$&#8221; matches to ensure that the string has the right structure all the way through, not just at some random point in the middle, which UA&#8217;s that parade around as other browsers tend to do.</p>
<p> Here&#8217;s some sample code that incorporates the approach:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>global<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// The map of available tests</span>
    <span style="color: #003366; font-weight: bold;">var</span> featureTests <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> audio <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">return</span> audio <span style="color: #339933;">&amp;&amp;</span> audio.<span style="color: #660066;">canPlayType</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009966; font-style: italic;">/*...*/</span> <span style="color: #009900;">&#125;</span>
        <span style="color: #006600; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// A read-through cache for test results.</span>
    <span style="color: #003366; font-weight: bold;">var</span> testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// An (exported) function to run/cache tests</span>
    global.<span style="color: #660066;">ft</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> testCache<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> testCache<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">&quot;undefined&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span>
                                    featureTests<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span>
                                    testCache<span style="color: #009900;">&#91;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Tests for 90+% of current browser usage</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> ua <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>global.<span style="color: #660066;">navigator</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> global.<span style="color: #660066;">navigator</span>.<span style="color: #660066;">userAgent</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// IE 6.0/WinXP:</span>
    <span style="color: #003366; font-weight: bold;">var</span> IE60 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/4\.0 \(compatible; MSIE 6\.0; Windows NT \d\.\d(.*)\)$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>IE60<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// IE 7.0</span>
    <span style="color: #006600; font-style: italic;">// ...</span>
    <span style="color: #006600; font-style: italic;">// IE 8.0</span>
    <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// IE 9.0 (updated with fix from John-David Dalton)</span>
    <span style="color: #003366; font-weight: bold;">var</span> IE90 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(compatible; MSIE 9\.0; Windows NT \d\.\d(.*)\)$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>IE90<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Firefox 3.6/Windows</span>
    <span style="color: #003366; font-weight: bold;">var</span> FF36 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(Windows; U;(.*)rv\:1\.9\.2.(\d{1,2})\)( Gecko\/(\d{8}))? Firefox\/3\.6(\.\d{1,2})?( \(.+\))?$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>FF36<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Chrome 8.0</span>
    <span style="color: #003366; font-weight: bold;">var</span> CR80 <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \((Windows|Macintosh|X11); U;.+\) AppleWebKit\/534\.10 \(KHTML\, like Gecko\) (.+)Chrome\/8\.0\.(\d{3})\.(\d{1,3}) Safari\/534\.10$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>FF36<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Safari 5.0 (mobile)</span>
    <span style="color: #003366; font-weight: bold;">var</span> S5MO <span style="color: #339933;">=</span> <span style="color: #009966; font-style: italic;">/^Mozilla\/5\.0 \(iPhone; U; CPU iPhone OS \w+ like Mac OS X; .+\) AppleWebKit\/(\d{3,})\.(\d+)\.(\d+) \(KHTML\, like Gecko\) Version\/5\.0(\.\d{1,})? Mobile\/(\w+) Safari\/(\d{3,})\.(\d+)\.(\d+)$/</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ua.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span>FF36<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        testCache <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;audio&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;audio-ogg&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span> <span style="color: #009966; font-style: italic;">/* ... */</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// ...</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>New versions of browsers won&#8217;t match these tests, so we won&#8217;t break libraries in the face of new UAs &#8212; assuming the feature tests also don&#8217;t break, which is a big if in many cases &#8212; and we can go faster for the majority of users. Win.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/02/on-performance-innumeracy-false-positives/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>Cutting The Interrogation Short</title>
		<link>http://infrequently.org/2011/01/cutting-the-interrogation-short/</link>
		<comments>http://infrequently.org/2011/01/cutting-the-interrogation-short/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 22:21:04 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1560</guid>
		<description><![CDATA[I&#8217;ve been having a several-day mail, IRC, and twitter discussion with various folks about performance and the feature detection religion technique, particularly on mobile where CPU ain&#8217;t free. So what&#8217;s the debate? I say you shouldn&#8217;t be running tests in UA&#8217;s where you can dependably know the answer a-priori. Wait, what? Why does Alex Russell [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been having a several-day mail, IRC, and twitter discussion with various folks about performance and the feature detection <strike>religion</strike> technique, particularly on mobile where CPU ain&#8217;t free. So what&#8217;s the debate? I say you shouldn&#8217;t be running tests in UA&#8217;s where you can dependably know the answer a-priori.</p>
<p>Wait, what? Why does Alex Russell hate feature testing, kittens, and cute fuzzy ducklings?</p>
<p>I don&#8217;t. <a href="http://paulirish.com/">Paul</a> warned me that my approach isn&#8217;t going to be popular at first glance, but hear me out. My assumptions are as follows:</p>
<ul>
<li>Working is better than busted</li>
<li>Fast is better than slow</li>
<li>No browser vendor changes the web-facing features in a given version. Evar. Does not happen</li>
</ul>
<p>If you buy those, then I think we can all get some satisfaction by retracing our steps and asking, seriously, what <em>is</em> the point of feature testing?</p>
<p>Ok, I&#8217;ll go first: feature testing is motivated by a desire not to be busted, particularly in the face of new versions of UA&#8217;s which will (hopefully) improve standards support and reduce the need for hacks in the first place. Sensible enough. Why should users wait for a new version of your library just &#8217;cause a new browser was released or because you didn&#8217;t test on some version of something.</p>
<p>Extra bonus: if you don&#8217;t mind running them every time, you can write just the feature test and your work is done now and in the future! Awesome! Except some of us do mind. Yes, things are now resilient in the face of new UA&#8217;s and new versions of old ones, but only on the back of testing for everything you need ever time you load a library on a page. Slowly. Veeerrrrry slooowly.</p>
<p>Paul suggested that some library could use something like Local Storage to cache the results of these tests locally, but this hardly seems like an answer. First, what if the user upgrades their browser? Guess you have to cache and check against the UA string anyway. And what about the cost of going to storage? Paul reported that these tests can be <em>wicked</em> expensive to run at all, on the order of 30ms for the full suite (which you hopefully won&#8217;t hit&#8230;but sheesh). Reported worst-case for <a href="https://github.com/phiggins42/has.js/">has.js</a> is even worse. But apparently going to Local Storage is <em>also</em> expensive. And we&#8217;re still running all these tests in the fast path the first time anyway. If we think that they&#8217;re so expensive that we want to cache the results, why don&#8217;t we think they&#8217;re so expensive that we don&#8217;t want to run them in the common case?</p>
<p>Now for a modest proposal: <b>feature tests should only ever be run <em>when you don&#8217;t know what UA you&#8217;re running in</em></b>.</p>
<p>Feature testing libraries should contain pre-built caches &#8212; the kind that come with the library, not the kind that get built on the client &#8212; but they should only be consulted for UA versions that you <em>know</em> you know. If we assume that behavior for UA/version combination never changes, we&#8217;ve got ourselves a get-out-of-jail free card. Libraries can have <code>O(1)</code> behavior in the common case and in the situations where feature testing would keep you from being busted, you&#8217;re still not busted.</p>
<p>So what&#8217;s the cost to this? Frankly, given the size of some of the feature tests I&#8217;ve seen, it&#8217;s going to be pretty minimal vs. the bloat the feature tests add. All performance work is always a tradeoff, but if your library thinks it&#8217;s important not to break <em>and</em> to be fast, then I don&#8217;t see many alternatives. New versions of libraries can continue to update the caches and tests as necessary, keeping the majority of users fast, while at the same time keeping things working in hostile or unknown environments.</p>
<p>Anyhow, if you&#8217;re a library author or maintainer, please please <em>please</em> consider the costs of feature tests, particularly the sort that mangle DOM and or read-back computed layout values. Going slow hurts users, hurts the web, and hurts the culture of performance that&#8217;s so critical to keeping the platform a viable contender for the next generation of apps. We owe it to users to go faster.</p>
<p><b>A quick aside</b>: I hesitated writing this for the same reasons that Paul cautioned me about how unpopular this was going to be: there&#8217;s a whole lot of know-nothing advocacy that&#8217;s still happening in the JS/webdev/design world these days, and it annoys me to no end. I&#8217;m not sure how our community got so religious and fact-disoriented, but it has got to stop. If you read this and your takeaway was &#8220;Alex Russell is against feature testing&#8221;, then you&#8217;re part of the problem. Think of it like a feature test for bogosity. Did you pass? If so, congrats, and thanks for being part of the bits of the JavaScript universe that I like.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/01/cutting-the-interrogation-short/feed/</wfw:commentRss>
		<slash:comments>51</slash:comments>
		</item>
		<item>
		<title>On The Care And Feeding of Spinning Disks</title>
		<link>http://infrequently.org/2011/01/on-the-care-and-feeding-of-spinning-disks/</link>
		<comments>http://infrequently.org/2011/01/on-the-care-and-feeding-of-spinning-disks/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 00:58:24 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1531</guid>
		<description><![CDATA[or: Why I spent last summer rebooting Windows or: How to compress several months of research into 50 lines of code and unblock a product launch, for fun and profit. Home parlor entertainment edition. Fun for all ages. Warranty void if seal broken. Offer not available in some states. Now that others have found the [...]]]></description>
			<content:encoded><![CDATA[<p>or:<br />
<h2>Why I spent last summer rebooting Windows</h2>
<p>or:<br />
<h3>How to compress several months of research into 50 lines of code and unblock a product launch, for fun and profit. Home parlor entertainment edition. Fun for all ages. Warranty void if seal broken. Offer not available in some states.</h3>
<p>Now that <a href="http://twitter.com/#!/shaver/status/28970313320505345">others have found</a> the <a href="http://twitter.com/#!/paulrouget/status/28978459631943680">same technique</a> that I <a href="http://code.google.com/p/chromium/issues/detail?id=45510">used to drop Chrome and Chrome Frame cold start times by more than 2/3</a> last summer, I feel compelled to explain what&#8217;s going on. Particularly as there seems to be <a href="http://news.ycombinator.com/item?id=2131524">some confusion over in the Hacker News thread</a>.</p>
<p>First, a couple of notes and caveats. SSDs are coming (see: ChromeOS, iOS, etc.), and in an SSD world, none of what follows will matter. Some of it could even hurt you. Other concerns &#8212; drive-internal parallelism, bus bandwidth/latency, and the amounts of crapware (that&#8217;s you, Sophos/Bit9/etc.) between your driver and your <code>LoadLibrary</code> call &#8212; are going to dominate. Also note that what I&#8217;m about to say is app specific. If you want your app to start faster, collect data on real-world systems and go from there. Cargo-cult hacks at your own peril.</p>
<p>Right then, spinning disks.</p>
<p>Good programs start fast, and that includes when you start them just after the OS has started. In this state, many of the caches the OS populates on your behalf are unlikely to be full of goodies that&#8217;ll help you start faster, so you pay full freight for all of your dependencies. This is called a &#8220;cold start&#8221;. When you start cold you have to go get everything you need from disk. Usually spinning disk. With > 10ms average latencies for random reads. Ouch.</p>
<p>For a sense of scale, consider that warm starts of Chrome (on Windows) take just ~200ms. That&#8217;s ~200ms for both the browser and renderer processes. 20 random reads from disk <em>double</em> that. Last summer, depending on OS version, disk speed, and amount of Prefetch/SuperFetch training cold starts ranged from 2000-3700ms. Fortunately, browsers are the sorts of things that users tend to keep open, and if they close, re-open later in the same session. Cold start hurts, but it&#8217;s not most user&#8217;s primary experience of a browser.</p>
<p>But that doesn&#8217;t hold for a plugin, particularly one that isn&#8217;t already ubiquitous. Yes, Flash loads quickly, but for most sites it starts fast because some other site had previously loaded it. Cold start matters even more for Chrome Frame. You&#8217;ve already started your browser, so why is this page taking so long to come in? It&#8217;s not enough that the network response is being buffered and the page will feel instant when the renderer finally starts&#8230;we need pixels on screen <em>stat</em>. Hence began my summer of rebooting. We couldn&#8217;t ship Chrome Frame to Stable until cold start was sub-second.</p>
<p>Using custom logging via <a href="http://blogs.microsoft.co.il/blogs/sasha/archive/2008/03/15/xperf-windows-performance-toolkit.aspx">ETW</a> as a starting point, I quickly found that most of the time spent in Chrome startup wasn&#8217;t going to subprocess or thread creation, cache loading, profile reading, or any of the other obvious big-ticket items. Tremendous discipline has been enforced in the Chromium codebase, ensuring that things which might otherwise block startup tend to happen asynchronously, keeping your experience responsive.</p>
<p>What&#8217;s left? ETW, <a href="http://code.google.com/p/sawbuck/">Sawbuck</a> and <a href="http://msdn.microsoft.com/en-us/performance">XPerf</a> eventually showed that we were thrashing disk for lots of little 16-64K reads into <code>chrome.dll</code>. Why not 4K, the size of single page? The Windows memory manager uses a read-ahead optimization when a hard fault occurs. That is to say, when your program tries to execute some bit of code from a library that isn&#8217;t yet in memory, the memory manager will go get the bits that correspond to the code in question, plus a little. Compilers optimize for code locality so you&#8217;re probably going to need the other pages too. Read-ahead (probably) saves you another expensive seek. If you don&#8217;t use those pages, no biggie. Windows is smart enough to prioritize caches. Lots of little 16-64K reads (aka: random I/O!) matched up with the hard page fault data&#8230;bingo. Even with <a href="https://www.microsoft.com/india/windows/windows-vista/features/superfetch.aspx">SuperFetch doing its thing on modern Windows versions</a>, we were seeing lots of slow (>10ms on 5400rpm disk) reads thanks to hard page faults.</p>
<p>Why were we getting these faults? To be entirely honest, we never quite figured this out. SuperFetch/PreFetch do their thing before your program ever hits it&#8217;s CRT main (the very first program-supplied entry point), meaning frequently used pages should already be available. Part of the reason they weren&#8217;t might be the different patterns of access between the Chrome Browser and Renderer processes. The same binary (<code>chrome.exe</code>) and main library (<code>chrome.dll</code>) are used for both, but the bits that each use are pretty radically different. There&#8217;s no access to WebKit code from the Browser process, e.g., but that&#8217;s most of what the Renderer uses. Other theories included some cap on the number of pages that SuperFetch will remember and log. Whatever the reason, fault location graphs showed a pretty violent thrashing toward the top end of <code>chrome.dll</code>.</p>
<p>Idea time: how can we pull all of the pages into the standby list &#8212; the bit of the Virtual Memory cache with the lowest priority &#8212; with a single seek, i.e. one big sequential read? What can we do to slurp the entire DLL into memory so that when the program needs some bit of the library, it gets it from <em>memory</em>, not from spinning (read &#8220;slow&#8221;) disk?</p>
<p>We tried loading the library and walking the pages sequentially. No joy&#8230;well, not much. Certainly not enough. More on that in a second. What about pulling the DLL into the disk cache? Hrmmm. A quick test showed that this worked <em>great</em> on Windows Vista. Just <code>fread</code> the sucker in and <em>boom</em>. ~750ms cold starts!</p>
<p>Except on XP. Balls.</p>
<p>Seemingly the memory manager bypasses the disk cache for faults on XP. Back to the bat-DLL-memory-walk approach, Batman! Yes, this works on XP, albiet with some caveats &#8212; namely that it&#8217;s slower than the other method. We still get stalls and slow seeks, but things improve to the 1300ms range. Average cold starts cut in half. We&#8217;ll take it. The final patch isn&#8217;t pretty, but it does something like what we want. See <a href="http://src.chromium.org/viewvc/chrome/trunk/src/base/file_util_win.cc?view=markup">this file</a>, look for <code>PreReadImage</code> which gets used in Chromium&#8217;s <code>WinMain</code> which does custom DLL loading <a href="http://src.chromium.org/svn/trunk/src/chrome/app/client_util.cc">here</a>, and only on the first (parent, aka, browser) process that&#8217;s created. Voila! Really, really fast starts nearly everywhere.</p>
<p>So, is doing this a good idea?</p>
<p>It&#8217;s not a slam dunk. For users with SSDs, this is more data than they strictly need, possibly slowing starts marginally for them. We&#8217;ll probably have to revisit this at some point. Also, the Vista+ approach potentially pollutes the disk caches. Not great, but at least the pages in questions won&#8217;t cause unnecessary thrashing unless the system is <em>already</em> under memory pressure in which case, the impending startup operations (allocating enough heap for V8, renderer process startup, etc.) are going to hurt no matter what. Also, we&#8217;re not exactly sipping data here. As the size of <code>chrome.dll</code> grows, so will the time required to pull it across the bus, even if the reads are serial. On my most recent dev channel rev, that&#8217;s a 23MB DLL, so if we get 75-100MB/s across the bus (optimistic for these old drives), we&#8217;re looking at a couple of hundred milliseconds just spent reading. Beats a tons of random seeks, but it&#8217;s still not great. Ideally we&#8217;d be able to use PGO/WPO to scope down the amount we <em>really</em> need to read by clumping early-use stuff towards the front of the binary, but so far this hasn&#8217;t panned out thanks to the aforementioned multi-process/single-dll thing. Turns out binary re-writing on Windows isn&#8217;t trivial. Perhaps the biggest down-side is that the XP experience isn&#8217;t ideal yet, and users on XP are most likely to have neither SSDs nor particularly speedy spinning disks. They need the help most. We were able to do something for them thanks to some dark magic in the Windows XP Prefetch system, but that&#8217;s a tale for another day. Suffice to say I now have tremendous respect for the folks who built these systems. Some parts of Windows truly are beautiful.</p>
<p>All in all, this hack has panned out in the real world in a pretty compelling way. Our start time histograms show the improvement in the real world (thanks to all of you who turned on reporting!), and Chrome Frame was able to ship to Stable last fall after we were relatively certain that we weren&#8217;t degrading overall system performance for users.</p>
<p>If you&#8217;ve read all of this, I hope that for your sake it&#8217;s with a sense of historical bemusement. What? They didn&#8217;t all have SSDs/quantum-rent-an-exabytes? Pssh. How did they get by? Well, now you know. One slow reboot of Windows at a time.</p>
<p><b>Bootnote</b>: I should mention that it wasn&#8217;t as straight line to suss out what actually happens in a cold start, pin down causality, understand the differences between XP and Vista+, and convince ourselves with real-world data that this was really our best option. It took a long time. Also, at some point, I stopped borrowing Amit&#8217;s copies of <a href="http://www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174">Windows Internals 4</a> and <a href="http://www.amazon.com/Windows%C2%AE-Internals-Including-Windows-PRO-Developer/dp/0735625301">Windows Internals 5</a> and bought my own. You&#8217;ll need both if you still work with XP. Recommended.</p>
<p><b>Footnote to the Bootnote</b>: Obvious Windows Hacker question: why not just do something like read in the DLL from the GCF BHO when you start up? Y&#8217;all get your BHO component loaded at IE launch, after all. </p>
<p>Good thought, Obvious Windows Hacker! Sadly, this is evil&#8230;or at least not very sporting. Even with low-priority I/O on Vista+, it&#8217;s sort of punitive to go do tons of I/O near when the user is probably starting to browse sites that might not make use of our BHO-based goodness, don&#8217;t you think? Besides, if we can get an honest startup win, why cheat? Honest wins pay off for both Chrome and Chrome Frame, which is doubly awesome.</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2011/01/on-the-care-and-feeding-of-spinning-disks/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>In which I eat crow.</title>
		<link>http://infrequently.org/2010/12/in-which-i-eat-crow/</link>
		<comments>http://infrequently.org/2010/12/in-which-i-eat-crow/#comments</comments>
		<pubDate>Tue, 21 Dec 2010 21:23:48 +0000</pubDate>
		<dc:creator>alex</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crow]]></category>
		<category><![CDATA[meaculpa]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://infrequently.org/?p=1525</guid>
		<description><![CDATA[Ok, ok. I&#8217;ve done my bitching and moaning, for years in person and more recently in blog form. I&#8217;ve listened to the interminable discussions at conferences about how everyone knows exactly what&#8217;s wrong with Twitter and how terribly hard it is to be so popular, and to this day I&#8217;ve escaped such a fate &#8212; [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, ok. I&#8217;ve done my bitching and moaning, for years in person and more recently in <a href="http://infrequently.org/2010/09/twitter-by-the-back-of-a-napkin/">blog form</a>. I&#8217;ve listened to the interminable discussions at conferences about how everyone knows exactly what&#8217;s wrong with Twitter and how terribly hard it is to be so popular, and to this day I&#8217;ve escaped such a fate &#8212; to the extent that Pete even made a <a href="http://twitter.com/#!/fakealexrussell">fake me</a> who, true to form, is nearly as infrequent a poster as I am here. But no longer. Behold! An empty, lame <a href="http://twitter.com/#!/slightlylate">n00b account</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://infrequently.org/2010/12/in-which-i-eat-crow/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

