Mike Harder found this one that I didn't know about: all exceptions that you may get from the browser are not Error instances. DOMException is an exception that gets thrown when a DOM operation fails, but for some incomprehensible reason it doesn't derive from Error like SyntaxError or TypeError:
try{
document.createElement(' ');
}
catch (ex){
alert(ex instanceof Error);
}
This will alert false.
But wait, that's not all. There are other exceptions that derive from DOMException, so in order to handle that exception, you'd want to be able to know if an exception derives from it, something like that:
try{
document.createElement(' ');
}
catch (ex){
if (ex instanceof DOMException){
// Do stuff
}
}
Well, if you try that on Opera, you'll get a TypeError stating "DOMException does not implement [[HasInstance]]". Isn't that just awesome?
There's been some debate recently about good ways that we could enable web sites to share the browser cache in the future. The problem is that popular JavaScript frameworks currently end up being downloaded several times from different sites that use them and this is a great waste of resources. Of course, there are some ways to achieve re-use of scripts across sites today by hosting those frameworks in a central location, but that is an expensive thing to do for framework developers, most of which are open source projects (it basically amounts to asking the framework developers to pay for the hosting cost of everyone that uses them).
To summarize the debate, Doug Crockford has been mentioning a possible solution. He also wrote another piece on JavaScript that is disconnected from this debate.
Brendan answered on what really happened back in the Netscape days and mentioned in passing that he didn't like Doug's proposal and that he preferred another approach.
I have to admit I wasn't captivated by the whole debate about the qualities (or lack thereof) of JavaScript and regretted that the debate around such an important feature would be drowned in that. So let me summarize the interesting part...
Doug wants all elements that have a "src" or "href" attribute to also have an optional "hash" attribute that is computed from the contents of that file with a well-defined cryptographic hash algorithm. This way, when the browser encounters another tag that has the same hash value, and it already has a cache entry with that hash, it would just get the resource from the cache without looking at the remote file.
Brendan doesn't like this because crypto hashes are not that secure in that it is possible (but highly unlikely) to build a different (malicious) file that has the same hash, and also because a crypto hash in otherwise clean HTML would look weird and out of place.
He proposes an alternate approach where the tag has a readable "shared" attribute that would typically be a url. The mechanism is pretty much the same as the hash, except that it's readable.
I don't know if it's Brendan or me who is missing something here but his proposition looks a lot more insecure than Doug's. Here's how an attacker would compromise that system:
- EvlH4ckr666 sends spam with links to his new cute penguin image site.
- As everyone loves cute penguin images, a large number of people go to http://cutepenguinpictures.com (not a real site as I'm writing this), some of them with an empty cache.
- Our cute penguin site contains (in addition to cute penguin images) a script tag with src="evil.js" and shared=http://sharedscripthosting.com/pasteYourFavoriteFramework.js (also not a real site as I write this).
- A while later, some of those users will visit another web site that references a legitimate copy of pasteYourFavoriteFramework.js, but as it has the same shared value that evil.js maliciously used, the browser will use what it believes is a legitimate script, but that is in fact evil.js.
- Chaos ensues.
Really, am I missing something here?
Also, another variation of those ideas that would be a little chattier but would keep the html clean and could probably be more secure would be to have the shared attribute but have another attribute that points to a hashing web service. Here's how that could work:
- When the browser sees a tag with a shared attribute and it has a cache entry with that shared value, it would generate a public key, send it to the validation service url to challenge it to return a hash of the script using the provided public key.
- The browser receives the response to its challenge under the form of a hash. It performs the same hashing with the same public key on the cached version and compares it with what the validation service returned. If they are the same, use the cache entry, otherwise hit the src or href.
Of course, this is less simple than the other approaches, but I think it's more secure than both and still avoids sending redundant versions of the same potentially huge scripts. Instead, there is a small negotiation that should be fairly small in terms of network payload.
What are your thoughts on this? Worth the trouble?
Doug's post: http://blog.360.yahoo.com/blog-TBPekxc1dLNy5DOloPfzVvFIVOWMB0li?p=789
Brendan's answer to Doug: http://weblogs.mozillazine.org/roadmap/archives/2008/04/popularity.html
UPDATE: I had a mail exchange with Brendan and it seems like what he meant was that it's the shared attribute url that is hit when present. That sure removes reasonable possibilities of poisoning the cache but I don't see what values it brings: it just seems to replace src and to have exactly the same pros and cons. In particular, it still puts the burden of shared hosting on the script author, whereas Doug's proposal (and mine) distribute this burden across all user sites.
Also removed a word that he found abusive.
UPDATE 2: so apparently the only thing @shared brings when compared with the regular @src is that src can be used as a fallback if @shared is unavailable. The shared url is still queried every time the cache doesn't contain it, which means that it still requires some massive hosting capabilities. There is no distribution of the burden. Brendan even suggested that for performance reasons, both urls get queried whenever the cache is empty! But of course, anyone who gave thought to it had inferred all this from the following ;) :
"If the browser has already downloaded the shared URL, and it still is valid according to HTTP caching rules, then it can use the cached (and pre-compiled!) script instead of downloading the src URL. This avoids hash poisoning concerns. It requires only that the content author ensure that the src attribute name a file identical to the canonical ("popular") version of the library named by the shared attribute. [...] only the @shared value would be shared among script tags. The @src would be loaded only if there was no cache entry for @shared."
The OpenAjax Alliance has been working with some of the top Ajax developers on a wishlist that aims at gathering and prioritizing the development features that we need the most from next generation browsers. The process is completely open and Wiki-based, so feel free to contribute.
http://www.openajax.org/blogs/wp-trackback.php?p=53
I've been seeing more and more authors lately dismissing partial rendering (a.k.a. UpdatePanel) as a poor man's version of Ajax, something you should only choose if you're too lazy to implement "true" Ajax.
I think that view not only has a slightly pedantic ring (isn't laziness one of the most powerful driving forces in computer science? isn't it perfectly ok to choose the most productive approach in some contexts?) but also misses the point that there are cases where server-side rendering absolutely makes sense.
For example, search engines don't execute JavaScript today, which means that if you're doing all the rendering on the client, your contents won't be indexed. If you want search engines to index your site properly, the contents must be included in the GET response, preferably in nice HTML. That simply means that contents must be rendered on the server during the GET request in order to be picked up by search engines. If you also need to update that same contents later, doing it on the client from pure data means that you need to have the rendering logic reproduced in client code. The easiest way today to only write your rendering logic once and make it work both on the GET request and on subsequent out-of-band requests is partial rendering.
I've said some time ago that I personally would have preferred if IE8 was in standard mode by default, that it made more sense in the long run at the price of moderate suffering in the short term.
Well, it seems like announcing the "meta-tag" user agent switch well before the first public release of the new browser wasn't a random decision. The idea really was to stir up the debate well in advance and make it possible to revert their decision if the community reached a consensus that it was a bad one.
And they just did. A few months later, the community almost unanimously rejected the idea more or less strongly and the IE team decided to follow that consensus and make the browser use the potentially breaking standard mode the default. It could be argued that the community really is the most vocal part of the developer audience and that they may and do have different opinions and preoccupations from the silent, real-world developers out there.
Still, I think the IE team showed vision in announcing this enough in advance that they could act on the feedback, and great courage on potentially alienating some of their customers, just so they could do The Right Thing.
Kudos, I'm impressed and glad that you guys are in command of the fate of IE.
http://blogs.msdn.com/ie/archive/2008/03/03/microsoft-s-interoperability-principles-and-ie8.aspx
Apologies if you're not. Let me explain.
I'm publishing this post on my blog, which quite a few external sites chose to aggregate. I thank them for that, but I should still have the freedom to talk about any subject I want on my own blog no matter what the editorial line of those other sites is. That's why I've been very carefully tagging all my posts (except for this one which is deliberately not tagged). As a result, sites that want to aggregate my contents can choose which tags they're interested in and reject the others.
For example, let's imagine that you are interested in contents that are tagged with "ASP.NET" and "JavaScript". In that case, you can subscribe to:
http://weblogs.asp.net/bleroy/rss.aspx?Tags=ASP.NET/JavaScript&AndTags=1
Another example would be to get all posts that are tagged with "ASP.NET", "OpenAjax" or "Microsoft Ajax Library". You can then use:
http://weblogs.asp.net/bleroy/rss.aspx?Tags=ASP.NET/OpenAjax/Microsoft+AJAX+Library
Despite all that, I'm still getting irate comments asking me to stick to the point (which of course I have no idea what it is as I don't know on what feed they're reading me) and stop publishing contents that is "irrelevant to the feed".
As you can see, there are very flexible ways of selecting the contents of this blog while maintaining my freedom of speech, so if you're reading this as part of an aggregated RSS feed and it seems irrelevant to it, it means that its owner blindly subscribed to the full feed. Please point them to this post, or send me e-mail at bleroy at microsoft and I'll contact them myself so that I can explain them how to modify their subscription. Don't forget of course to specify the URL of the feed where you saw this post.
Thanks for your cooperation.
Ever since it came out, it seems like Wii Play has been somewhere on top of sales charts and even managed to be the #2 top-seller of 2007 in the US. Let's be clear about this: even if it looks like a good deal, being only $10 above the price of a standalone Wiimote, it really isn't. It would be a good deal *if* Wii Play itself was worth $10, which it isn't by a very large margin (i.e. at least $10). As a matter of facts, if you gave me $10 to play this thing (which I refuse to call a game), I would decline. And I want the fifteen minutes I spent trying to play it back.
The only person in the family who found this of any interest was my daughter but that's probably because she was 3 years old at the time. By buying this, you're sending the following message to Nintendo: "I'll buy anything from you, so please make more mini-pseudo-games that most sane persons would refuse to play if they were free internet Flash games".
Do yourself a favor: don't buy this thing and just go for a standalone Wiimote instead. And while you're there, pick up a copy of Super Mario Galaxy. Now that's a real game.
For some reason, there is no standard API to get the pixel coordinates of a DOM element relative to the upper-left corner of the document. APIs only exist to get coordinates relative to the offset parent. Problem is, it's very important to get those coordinates for applications such as drag and drop, or whenever you need to compare coordinates of elements that may be in completely different parts of the document.
In Microsoft Ajax, we implemented such a function (Sys.UI.DomElement.getLocation) but it proved to be one of the most difficult problems we had to solve. Not so surprisingly, every single browser has its own coordinate quirks that make it almost impossible to get the right results with just capability detection. This is one of the very rare cases where we reluctantly had to use browser sniffing and implement a completely different version of the function for each browser.
We also had to implement a pretty complex test suite to verify our algorithms for thousands of combinations of block or inline elements, offsets, scroll positions, frame containment, borders, etc., and run those on each browser that we support. The test suite in itself is quite interesting: it renders an element with the constraints to test, gets its coordinates from the API, creates a top-level semi-transparent element that is absolutely positioned and check that both overlap exactly to pixel precision. To do so, it takes a screen shot and analyses the image to find the rectangles and check their color.
The simplest runtime implementation is the IE one, thanks to a little-known API that does almost exactly what we want: getBoundingClientRect. Almost exactly as we quickly discovered it has a weird 2-pixel offset except on IE6 if the HTML element has a border (which is a "feature" that was removed in IE7 and which we chose not to support). It also doesn't include the document's scroll position. Finally, if the element is in a frame, the frame border should be subtracted. This actually was the cause for a bug that we unfortunately discovered after we shipped 1.0 but which is now fixed in ASP.NET 3.5 as the parent frame may not be in the same domain, in which case attempting to get its frame border will result in an access denied error. So you need to do this in a try-catch and just accept the bad offset in that fringe scenario.
In all other browsers, you currently need to recurse through the offset parents of the element and sum the offset coordinates.
In Safari 2, though, the body's offset gets counted twice for absolutely-positioned elements that are direct children of body. Something you don't just guess, you need the thousands of test cases I mentioned earlier to discover something like that...
In both Safari and Firefox, you must subtract to the coordinates the scroll positions of all parent nodes (and not the offset parents like before). Well, except if the element is absolutely positioned (this last restriction doesn't apply to Opera). Or if the parent is the body or html element. Confused yet? Wait, there's more.
In Firefox, non-absolutely positioned elements that are direct children of body get the body offset counted twice.
In both IE and Firefox (but you don't care for IE as it has getBoundingClientRect), the border of a table gets counted in both the border of the table and in the td's offset.
Finally, on Opera, there are scroll values on elements that are not scrolled so you need to explicitly check for the overflow mode before you subtract scroll positions. Opera also includes the scrolling into the offsets, except for positioned contents.
The worst part in all this is that we don't even know for sure that we nailed it, and we know that future browsers will require adjustments.
Speaking of which... Firefox 3 will implement getBoundingClientRect. I haven't tried their implementation yet and checked whether it has the IE quirks, but it should be a lot simpler than what we have to work around today to do the same thing and we'll definitely have to rely on less undocumented quirks. By the way, if you were thinking of using the undocumented getBoxObjectFor, forget it, it was designed for XUL elements and will probably get removed from non-XUL elements in future versions.
There is a bug open against WebKit to get that in Safari but it's currently without an owner. Here's to hoping this gets into the next version. Vote for it.
Opera apparently also implements that in 9.5, referencing a W3C draft which curiously doesn't contain any references to getBoundingClientRect.
More Posts
Next page »