共用方式為


How IE9 Platform Preview Feedback Changed the JavaScript Standard

When we first introduced our plans for Internet Explorer Platform Previews we said that “developers and people interested in standards and web development can try out new platform functionality and provide early feedback.” We are now getting such feedback on a daily basis and are using it to improve IE9. However, sometimes the impact of the feedback extends beyond just IE9. Here is the story of how some recent feedback regarding the third IE9 Platform Preview resulted in a correction to the new ECMAScript 5th Edition (ES5) standard for JavaScript.

The ES5 standard became official in December 2009 and the third IE9 Platform Preview is the first widely distributed implementation of some subtle details of the ES5 specification. ES5 was designed to be highly compatible with existing websites and the Ecma International TC39 technical committee worked to avoid any non-security related changes that might break existing JavaScript code. However, perfection generally does not exist in the world of software so with the third IE9 Platform Preview we were very interested to see if any ES5-related compatibility problems with existing sites would show up.

Soon after releasing this platform preview, we received reports that some web-apps that use the jQuery framework did not work correctly in the preview. We tracked the problem to a specific jQuery API method that in some cases passed a caller provided value to Object.prototype.toString without first checking if the value was null or undefined. Specifically, some calls to this jQuery method:

 isFunction: function( obj ) {
     return toString.call(obj) === "[object Function]";
},

failed with an exception: “TypeError: Object expected”. Further analysis showed that toString in the above code was the built-in method Object.prototpe.toString and that the failures occurred when isFunction was being called with undefined as its argument. Why does an exception occur in IE9 and not in previous versions of IE or other browsers? It is because the third IE9 Platform Preview in standards mode actually conforms to the ES5 specification for Object.prototype.toString.

According to the prior editions of the ECMAScript specification, calling any built-in method using null or undefined as the this value passes the “global object” (in browsers this is the DOM window object) to the method as its this value.  This opens a number of potential security holes for frameworks that aim to support mash-ups in a secure way.

The ES5 specification changed this so that null or undefined is not replaced with the window object and the definition for each built-in method was updated specifically to deal with receiving these values as their this value. The ECMAScript technical committee tried to do this in a way that preserves backwards compatibility for normal usage and throws an exception in cases where that is not possible. Object.prototype.toString was specified in ES5 to throw such an exception. This created the compatibility problem described above.

This problem can be easily corrected by modifying the jQuery code with the additions shown in red:

 isFunction: function( obj ) {
     return obj && toString.call(obj) === "[object Function]";
},

The jQuery team actually intends to make this change. However, such a change will not correct the thousands of locally hosted copies of jQuery that already exist on the Web. With the broad use of jQuery, it is clear that the ES5 specification contains a significant compatibility problem. It is fairly obvious how we can modify the IE9 ES5 implementation to eliminate the problem. We can just return the same string value ("[object Object]") that IE8 returns in this situation. Such a fix does not reintroduce any of the security problems that ES5 strives to eliminate. However, we do not want to unilaterally introduce such a variation into our implementation of a new standard. It does not help either compatibility or interoperability if IE fixes this problem one way, and other browsers either don’t fix it or fixed it a different way.

As soon as we understood the problem and the possible solution, I raised this on the TC39 es5-discuss mailing list as a backwards compatibility issue.  My first post on the issue went out at 5:51 PM on June 25, a Friday. By 10 PM there were responses from TC39 members representing Apple, Mozilla, and Google. We all agreed that this was a compatibility issue that needed to be fixed, and that in this case throwing the exception was unnecessary and undesirable. We also initially agreed that the idea of returning the same string value as ES3 for these cases sounded like a good idea. However, in further messages over the weekend we realized that browsers currently don’t all return "[object Object]" in this situation, some other values that were observed include "[object Window]" and "[object Global]". A proposal was made to return "[object null]" and "[object undefined]". This seemed to be a better solution as it not only fixes use cases such as jQuery’s but it also explicitly distinguishes null and undefined from actual objects. It is also better for browser interoperability because it requires that all browsers produce identical results rather than the ES3 situation that allowed different browsers to produce different results.

By Tuesday, the consensus on the mailing list was to follow this final proposal. As soon as that agreement was reached, I passed the revised Object.prototype.toString specification on to our IE9 JavaScript development team so they could make the fix in time to widely test it with the next IE9 platform preview build.  Mozilla has also indicated that they will be incorporating this fix into a future Firefox beta. I also updated the official TC39 Erratum for ES5  so this specification change is recorded there (section 15.2.4.2).

Web standards are complex software artifacts and like all software, they contain bugs. Sometimes the best way to find and fix compatibility bugs is to implement and deploy the standard on widely used browsers. This generally takes place in the context of early releases such as the IE9 platform preview builds. So, when you as a web developer are providing feedback on such releases you aren’t just providing feedback on a specific browser you are also providing feedback on the new and emerging standards that it implements. Of course, for this feedback to be worthwhile, browser implementers and standards authors need to be able and willing to quickly respond to feedback that identifies significant problems. The rapid response to the ES5 jQuery toString problem and other issues on es5-discuss show how browser implementers and other TC39 members can and do work closely together to create a more compatible and interoperable Web. But it all starts with your feedback, so please keep it coming.

Allen Wirfs-Brock
Microsoft JavaScript Language Architect

Comments

  • Anonymous
    July 16, 2010
    Nice explaination. Though I'm unsure why you are going to return [Object undefined] while the type of the 'undefined' value is 'Undefined', as stated in the ES5 spec. Same goes for 'null' whose type is 'Null'. To be consistant, you should return "[Object Undefined]" and "[Object Null]", or is there any reason why you should not ?

  • Anonymous
    July 16, 2010
    That was a very refreshing look at the standards process. Good post.

  • Anonymous
    July 16, 2010
    If this was released on XP, maybe it would have been found earlier.

  • Anonymous
    July 16, 2010
    @h - IE9 Platform Preview 3, the first to have this EcmaScript5-defined behavior, was released on Wednesday, June 23. The problem was discovered and analysed and a potential solution submitted to the es5 mailing list by Friday, June 25. Just how much earlier do you think it would have been found if the previews were released on XP? A few minutes? Maybe an hour?

  • Anonymous
    July 16, 2010
    Object.prototpe.toString is like, totally a typo.

  • Anonymous
    July 16, 2010
    Good to see you working with other browser vendors to come to a consensus.  I'm ok with any outcome that is agreed to by all. So, is IE9 going to return something more useful in JavaScript errors that appear in the browser (bottom left corner)? Object does not support property or method..... Or whatever it says without giving any indication what object or what property is really annoying.  The dialog also needs a clear button. Next and previous buttons are also useless Esp. If the dialog is fixed to show a real, scrollable list.

  • Anonymous
    July 16, 2010
    @Mitchum (and maybe Allen can help broker this...) the little yellow error sign can be trapped and managed in IE and Firefox using the window.onerror handler (eg using a script like http://jserrlog.appspot.com/ ) but... sadly Webkit (Chrome and Safari) and Opera don't support this (as noted in the comments on that link) because they would prefer to argue that the de facto spec isn't good enough so rather than support it (and maybe offer up a better suggestion) they'll just break scripts... jQuery have since given up trying to help developers trap unexpected errors and degrade gracefully because of this. Would love to see Webkit follow IE and Firefox on this as I can see with more javascript coding rather than less coming hand in hand with the HTML5 improvements a way to manage this gracefully is going to become more important, not less.

  • Anonymous
    July 16, 2010
    A very interesting post and maybe a reflection of how powerful jQuery has become that the ECMAScript specification is changed so as not to the break jQuery code. The widespread adoption of various JavaScript libraries should mean less sites break on the release of new browsers. A good solution from all concerned.

  • Anonymous
    July 17, 2010
    The comment has been removed

  • Anonymous
    July 17, 2010
    @jabcreations: If you're running with script debugging, you can simply view the "Call Stacks" tab on the Script Debugging tab on the F12 developer tools.

  • Anonymous
    July 18, 2010
    some browsers allow user to stop futher javascript alert, which help to stop some websites' annoying alert, would IE consider to add this function?

  • Anonymous
    July 18, 2010
    typeof null === 'object' There you go!

  • Anonymous
    July 18, 2010
    @EricLaw [MSFT] Awesome, thank you!

  • Anonymous
    July 20, 2010
    apologies for the drive-by offtopic question, but seen as how this blog is active and the RSS teams' isn't... are there any changes to the way RSS feeds work planned? specifically, at the moment, all data about feeds is kept in the local part of the user profile.  This means you lose your RSS subscriptions if you change PC.  A workaround is to use outlook, which monitors the RSS store for feeds, and copies them into its own RSS system.  But I prefer to read my feeds in IE, since in most cases I'm going to end up clicking through to the website anyway.  From my point of view, changing at least the feed URL & preferences, and enough data to be able to work out what counts as an unread article, to be part of the roaming profile, would be fantastic. Again, apologies for the OT comment on something that's only half related to the blog ;)

  • Anonymous
    July 20, 2010
    @frymaster : Nice idea. I would suggest you to use the contact form of the blog, though, as your proposal don't seem to find its right place here.

  • Anonymous
    July 20, 2010
    Up to IE8, the JavaScript engine that comes with IE is also used in the Windows Script Host (WSH) environment. Could you confirm that installing IE9 will bring those ES5 features to WSH? Is it already the case when installing the IE9 preview? Does your javaScript test suite test the engine in WSH too?

  • Anonymous
    July 20, 2010
    @Olivier: Installing the IE9PPB wil not change the script engine used by WSH. I don't think the JavaScript team has yet announced any plans for use of the new engine by non-Web Browser hosts.

  • Anonymous
    July 22, 2010
    does console.log(msg); work in IE9 yet?

  • Anonymous
    July 22, 2010
    @console: The statement console.log(msg) has been supported since IE8. It's important to note, however, that the console object is only non-null while the Developer Tools are in Script Debugging mode.

  • Anonymous
    July 22, 2010
    The comment has been removed

  • Anonymous
    July 22, 2010
    @David: You should probably try the Platform Preview build. The Network Monitor tab shows AJAX POST data. To log "the innards" of an object, you can simply stringify the object using the JSON object.

  • Anonymous
    July 22, 2010
    @EricLaw : The problem with stringification is that it takes a lot of place in the console. The why Firebug handle it is way better because we can click on the log and navigate through the object's properties in a popup window, if we need it. In other cases, we just get the result of the "toString" stringification, which is usually short.

  • Anonymous
    July 22, 2010
    Loved this post!  As a web developer, it's very rewarding to see all the browser vendors tackling these kinds of problems together. Cheers to the good folks at Microsoft for taking the initiative, and cheers to the esteemed individuals involved in this case. :)

  • Anonymous
    July 25, 2010
    The comment has been removed

  • Anonymous
    July 27, 2010
    The comment has been removed

  • Anonymous
    July 27, 2010
    @hAl: the HTML5 version of keygen seems rather complete to me... It's actually almost as big as ssh-keygen's man page. Only the default settings are weak (RSA+MD5), but that can be expected due to its Netscape history (for compatibility reasons), and it supports more. There is also information on MSDN about Netscape's KEYGEN support, so I'll venture a guess that 'keygen' might be supported by IE 9 later on. Moreover, if keygen had little to do inside HTML 4 and its definition as a static markup language, HTML5 fits the bill a bit more: it's supposed to be more dynamic.

  • Anonymous
    July 27, 2010
    Mitch: It's quite a leap to guess that IE will support KEYGEN only because legacy documentation on MSDN mentions this Netscape-era feature. Considering the complexity, privacy, and security impact, I would be very surprised to see support for this feature in IE, and would not be at all surprised to see it pulled from HTML5 when they decide that it might be nice to finish the spec before 2020.

  • Anonymous
    July 28, 2010
    Question is it Google's progarming that is causing IE9 no to function with Google wave?

  • Anonymous
    July 28, 2010
    The comment has been removed

  • Anonymous
    July 28, 2010
    continued rant 13.) why do all my images, in the HTML source, have a complete="complete" attribute? WT_?!?! 14.) HTML source claims "Empty text node" if source contains " " or UTF variants 15.) Locking/Unlocking my (XP) PC causes the toolbox icons on the pinned toolbar to shift from far right to floating left beside the Document Mode status

  • Anonymous
    July 29, 2010
    Sorry for the OT, but is there any chance you can make IE9 store the temporary files in a cache file (like Firefox and Chrome), instead of "normal" clear multiple files and folders? The current IE's behaviour makes it so easy to recover files after deleting its browser history. Even if the files are actually fully/partially overwritten on the hard disk, you can always read their names using undelete/recovery applications (like Recuva for example). This change would enhance IE's privacy features. Thank you.

  • Anonymous
    July 29, 2010
    The comment has been removed

  • Anonymous
    July 29, 2010
    @EricLaw [MSFT]: Thank you for your reply. It was more a "computer shared with a friend"-style scenario actually. But the "laptop loss"-style scenario could work as well. Just out of curiosity, besides its intrinsic simplicity, is there any particular advantage to the IE's individual cache files over the single cache file?

  • Anonymous
    July 29, 2010
    @Paul: There are a bunch of tradeoffs between using a single-db-file and multiple individual files, related to performance, reliability, interoperability, etc. I don't think that one design is inherently better than other in all ways. The reason that IE has individual files is largely architectural-- in the IE model, plugins/addons and traditional applications all expect to be able to operate on individual cache files directly within the cache. Hence, they expect a file to be there, and if it's not, they won't work properly. Now, clearly you could build a API model around allowing such code to be smart enough to read from the single-db-file, but then the plugins/addons/applications would all need to use the browser API to retreive data from the cache database rather than simply opening a file on disk. Not an insurmountable obstacle, but something that would make shifting from one type of cache to another non-trivial.

  • Anonymous
    July 29, 2010
    @EricLaw [MSFT]: I see, thank you for the explanation. :) Anyway, what about the index.dat files? Those are not even deleted by the various "delete browser history" commands available in IE, and they have to be deleted by third parties' scripts/applications such as CCleaner. It would be nice if IE could delete those files through an option the same way it deletes temporary files and cookies.

  • Anonymous
    July 29, 2010
    Paul: Index.dat files aren't deleted but what's not obvious is that the Delete Browser History command fully overwrites the contents. That prevents undeletion of the file, since the file is still present, but has been completely wiped.

  • Anonymous
    July 29, 2010
    The comment has been removed

  • Anonymous
    July 29, 2010
    @EricLaw [MSFT]: Actually, as you can see running Index.dat Analyzer (www.systenance.com/indexdat.php), the index.dat files in the following directories are not wiped when deleting browser history (IE8 on Windows 7 32-bit): C:UsersMyUserNameAppDataLocalMicrosoftFeeds Cacheindex.dat C:UsersMyUserNameAppDataLocalMicrosoftWindowsHistoryHistory.IE5MSHist_some_numberindex.dat C:UsersMyUserNameAppDataLocalLowMicrosoftInternet ExplorerDOMStoreindex.dat The index.dat files in the main history/temporary files directories are wiped though, as you explained. :)

  • Anonymous
    July 29, 2010
    You shouldn't expect deleting your browser history to clear your RSS feeds. For the DOMStore and History Containers, do you find anything interesting in those files after clearing your cache?

  • Anonymous
    July 29, 2010
    @EricLaw [MSFT]: I have no feeds actually. The ones reported in those index.dat files are old ones I deleted several weeks ago in IE. As for the DOMStore and History Containers, I do find the URL of various websites (such as something regarding Facebook Connect and the MeeboBar some sites/forums uses) I visited before clearing my cache, which are something I would expect to be wiped when deleting my browser history.

  • Anonymous
    July 29, 2010
    Question is it Google's progarming that is causing IE9 not to function with Google wave? Based on this article, IE9 has better support for Javascript, but the page refuses to load.

  • Anonymous
    July 29, 2010
    I really like these blog posts but you haven't posted anything for some time now. /cry btw, I hope you have fixed the subsequent <a> elements getting hidden while an <a> element is highlighted. [started from PP3; test it here: www.bakabt.com/description.php ]

  • Anonymous
    July 29, 2010
    The comment has been removed