Udostępnij za pośrednictwem


Enhanced Scripting in IE9: ECMAScript 5 Support and More

Up to this point we have mostly talked about improved JavaScript performance in Internet Explorer 9 but we haven’t said much about any new or changed language features in the “Chakra” engine. Now, with the third Platform Preview, we can tell you about JavaScript feature enhancements which you can try for yourself.

As context, the industry standard that defines the JavaScript language is ECMA-262: ECMAScript Language Specification developed and published by Ecma International. Prior to last year, it had been a decade since the introduction of the Third Edition of ECMA-262 in December 1999. In December 2009 Ecma approved the Fifth Edition of ECMA-262 as the successor to the Third Edition (a Fourth Edition was never published), and last year we debuted elements of ECMAscript 5 (ES5) support when we added native JSON support in IE8. Beyond JSON, though, ES5 standardizes many significant enhancements to the JavaScript language.

New ES5 Features in the IE9 Platform Preview

There are many important ES5 features implemented in IE9 Standards Document mode:

New Array Methods. There are nine new methods that operate upon arrays. Two of them, indexOf and lastIndexOf, support searching an array for a particular value. They are similar in concept to the functions with the same names that operate upon strings. The other seven new Array methods allow arrays to be manipulated using a functional programming style. For example, the following snippet uses the new filter method to collect the elements of an array that meet a specific condition:

//a function that tests whether menu item object is enabled or disabled
function enabled(menuItem) {return menuItem.status==="enabled"};

//Assume that individual menu items have a status property and
//that a menu object has a items property which is an array.
//Create an new array containing just the enabled menu items
var enabledItems=myMenu.items.filter(enabled);

These methods support various forms of array processing without having to explicitly code for loops. In addition, they are all generic, which means that they can be applied to any object with numerically indexed properties and not just objects created using the Array constructor. You can explore demos using these methods on the IE9 Test Drive site and they are summarized in the following table:

Array method

Description

indexOf

Search an array for the first occurrence of some value

lastIndexOf

Search an array for the last occurrence of some value

forEach

Apply a function to each element of an array

every

Determine if some condition is true for every element of an array

some

Determine if some condition is true for at least one element of an array

map

Apply a function to each element of an array and produce a new array containing the results

filter

Collect into a new array all the elements of an array for which some condition is true.

reduce

Accumulate a single value based upon all elements of an array.

reduceRight

Accumulate a single value based upon all elements of an array, processing them in reverse order.

Enhanced Object Model. The most important new feature in this area is accessor properties. These are also sometimes called “getter/setter” properties because they allow JavaScript programmers to control what happens when the program gets or sets the property value. ES5’s enhanced object model also allows programmers to control whether individual properties can have their value changed, are enumerated by for-in statements, and whether or not the property can be deleted or redefined. It also allows the programmer to control whether new properties can be added to an object. ES5 also enables JavaScript programmers to more easily create objects that inherit from specific prototype object and to inspect and manipulate the property definitions of object. All of these enhanced object model capabilities are accessible via new function properties of the Object constructor. However, note that the current release of the IE9 platform preview does not yet fully support use of these methods with DOM objects.

Object function

Description

Object.defineProperty

Create or modify a property definition. The property can be defined as either a data or an accessor property and its writable, enumerable, and configurable property attributes can be set.

Object.defineProperties

Create or modify multiple property definitions in a single operation.

Object.create

Create a new object with a specified prototype and optionally a set of specified properties.

Object.getPrototypeOf

Retrieve the prototype object of the argument object.

Object.getOwnPropertyDescriptor

Return a complete description of the attributes of a property of an object.

Object.getOwnPropertyDescriptor

Return an array containing the names of all of an object’s non-inherited properties.

Object.keys

Return an array containing the names of all of an object’s non-inherited properties that would be iterated by the for-in statement.

Object.seal

Disallow adding any additional properties to the argument object and disallow deletion or redefinition of any existing properties. Individual property values may still be modified if their writable attribute have the value true.

Object.freeze

Disallow adding any additional properties to the argument object and disallow deletion or redefinition of any existing properties. In addition the values of existing property may not be modified.

Object.isSealed

Test whether an object is has been sealed using Object.seal.

Object.isFrozen

Test whether an object is has been frozen using Object.freeze.

Object.preventExtensions

Disallow adding any additional properties to an object.

Object.isExtensible

Test whether new properties may be added to an object.

Other Computational Methods and Functions. In addition to the new Array and Object methods, ES5 adds or enhances several additional methods that perform useful computational operations.

Method or Function

Description

String trim

Removes “white space” from the beginning and end of a string.

Date toISOString

Convert a Date to a string format that all ES5 implementations must support.

Date.parse

Existing function enhance to recognize the format create by toISOString.

Date.now

Return a numeric timestamp

Array.isArray

Reliably test whether an object is an Array

Function bind

Preset some of the arguments of a function to fixed values.

ES5 also includes a number of other minor changes and technical corrections to the language. Many have no impact on most JavaScript programmers because they simply standardize minor features that have always been supported by browsers. An example of such a feature is line continuations within string literals. One minor change is of more interest. Reserved names such as if, super, and public can now be used as property names within object literals and for property access following a dot. With this change, programmers no longer need to worry about a long and arbitrary list of words that they can’t easily use as property names.

“Same Script, Same Markup”

Updating IE9’s JavaScript implementation isn’t just about supporting new ES5 features. It’s also about ensuring that web developers can use the same markup and script within IE9 that they use in other browsers. Earlier this year we released documents that describe in detail how JavaScript as implemented in IE8 differs from the ECMAScript, Third Edition Specification. In IE9 standards mode, we looked closely at these differences and made changes to ensure that IE9 can execute the same script as other browsers.

 

Corrected Issue

Example

Function expressions were processed as if they were function declarations.

function f() {alert("declaration")}; obj.callback=function f() {alert("expression")}; f(); // IE8 incorrectly alerts "expression"

Function names in function expressions were not locally defined within the function body.

var fact="the web is big"; Math.factorial=function fact(n)     {return n<=1?1:fact(n-1)}; alert(Math.factorial(9)); // IE8 throws an exception

Catch clause parameters were visible in enclosing scope.

var e = "outer"; try {throw "inner"} catch(e) {}; alert(e); // IE8 incorrectly alerts "inner"

In many cases the runtime exception thrown was different from what is specified in the standard

var obj; //obj has value undefined try {alert(obj.prop)} catch (e) {     if (e instanceof ReferenceError) alert("correct")     else if (e instanceof TypeError) alert("IE8 wrong")     }

Trailing commas in array literals added to the array’s length

var len = [1,2,3,].length; alert(len); //should be 3, IE8 says 4

Empty elements in array literals didn’t result in a sparse array

var a=[0,,2,,4]; alert(a.hasOwnProperty(1));//IE8 incorrectly says true

The dontenum attribute was inherited by own properties

var obj={valueOf:0, toString:1,foo:2}; var n=0; for (var p in obj) n++; alert(n); // IE8 displays 1, should be 3

\v was not recognized as an escape sequence for the vertical tab control characters

alert("\v"==="v");//IE8 said true, should be false alert("\v"==="\u000b");     //IE8 said false, should be true

The global object didn’t inherit from Object.prototype

alert(hasOwnProperty===undefined);     // IE8 incorrectly alerts true, should be false

Unsatisfied capturing parentheses in regular expressions produce the empty string instead of undefined.

var x=/((a)|(ab))((c)|(bc))/.exec("abc"); // x should be: //    ["abc","a","a",undefined, "bc",undefined, "bc"] // IE8 produces: ["abc","a","a","","bc","","bc"]

toFixed incorrectly rounds for certain ranges of values

alert((0.09).toFixed(1)); // Should display 0.1 // IE8 displays 0.0

“Running the same script” isn’t just about what Internet Explorer can run. It’s also about making sure that the scripts you develop and test using IE will also run in any other standards conforming browser your users might be running. One type of issue that can interfere with this goal is unnecessary features that exist only on IE and no other browser. If a feature doesn’t provide any essential browser-specific functionality or unique value, is only implemented by a single browser, and is unlikely to ever become part of a Web standard then the existence of that feature becomes an interoperability hazard. If you inadvertently use such a feature in your script your users won’t be able to run it on any other browser.

Internet Explorer’s JavaScript implementation has historically had several features that fall into this category and we have eliminated them within IE9 Standards Mode. Generally, these are features that were conceived as usability enhancements in the earliest days of IE development. However, they were not adopted by other browsers and it is now clear that they will never be incorporated into the ECMAScript standard.

The first feature in this category is the elimination of the option to place a semi-colon after any code block. For example, IE has traditionally allowed an if statement to be coded like this:

if (conditionMet) {performTrueAlternative()};
else {performFalseAlternative()};

Note the semi-colon at the end of the first line. The ECMAScript standard has never allowed a semi-colon to occur at that position. If you try to load a script containing these lines on any browser other than IE, a syntax error will be detected and the entire script will fail to load. The original motivation for this feature was to be liberal in what IE accepts for execution – to handle some syntax errors transparently. Unfortunately, being liberal in these situations causes interoperability issues when the script runs on other browsers. In situations like this, it is better to report the error so it can be corrected by the script developer.

IE has included several extensions to function declaration syntax. One extension allows function declarations to directly define method properties of objects. For example:

 

function String.prototype.firstChar() {return this.substring(0,1)};

means the same thing as

String.prototype.firstChar = function (){return this.substring(0,1)};

Another extension allowed a function declaration to define multiple names for a function. Such as:

function declaration,dcl() {return processDeclaration)()};

which defines both a short name and a long name for the same function. Neither of these extensions adds any functionality that can’t already be expressed using standard features of the language, they are not part of the standard, and no other browser implements them so we are eliminating them in IE9 standards mode.

Note that this doesn’t mean we are removing all functionality that is unique to IE’s JavaScript implementation. Some features are essential for situations where a developer really does need to access some unique capability of Internet Explorer or Microsoft Windows. For example, the JavaScript features that support access to ActiveX objects fall into this category.

Testing Our Progress

A primary goal for IE9 is that the same markup can be used across browsers, which of course includes JavaScript code. So how do we know how we are progressing towards that goal? In another IEBlog post we discussed Microsoft’s position regarding standardizing JavaScript test suites. We believe the organizations responsible for web standards should also publish a definitive test suite that ensures the same script and markup works in all browsers.  There is not yet a standard test suite for JavaScript. However, the ECMAScript standards committee has agreed to develop such a suite and we are working together with the other browser vendors who are Ecma members.  That test suite is not yet complete or publically available.  In the interim, more than 1300 ES5 related tests that we use and will contribute to Ecma are available on the Internet Explorer Testing Center. As a result of the support we added for ES5, IE9 now passes all sixteen of the Acid3 tests in bucket 6 (JavaScript).

Take It Out for a Test Drive

We want your feedback. Let us know when you find JavaScript bugs. We are especially interested in interoperability issues. If you are using a standard JavaScript feature and it works differently on this Platform Preview in IE9 Standards Mode than in other browsers, you may have found a bug – report it on Connect. Because these changes only apply to IE9 Standards Mode documents, web sites running in IE9’s compatibility modes do not have these changes and continue to operate as they always have.

Finally, look very carefully at any existing code you have that does browser detection based upon known IE JavaScript differences or bugs, as these are likely to no longer work as expected in IE9 Standards Mode. This isn’t just the same old IE JavaScript.

Thanks

Allen Wirfs-Brock
Microsoft JavaScript Language Architect

Comments

  • Anonymous
    June 25, 2010
    Seems my comment didn't go though. Not the first time its happened to me on this blog. Object.getPrototypeOf is undefined in IE. I would like to see that implemented. Particularly so that to investigate host objects. Garrett

  • Anonymous
    June 25, 2010
    Seems my comment didn't go though. Not the first time its happened to me on this blog. Object.getPrototypeOf is undefined in IE. I would like to see that implemented. Particularly so that to investigate host objects. Garrett

  • Anonymous
    June 25, 2010
    Good - that comment made it. Good work on bringing IE up, now if I can only get that testrunner to work...

  • Anonymous
    June 25, 2010
    That sounds great!

  • Anonymous
    June 25, 2010
    Great work. Would love you guys to propose adding EMCA-335 to the browser stack post IE9.

  • Anonymous
    June 25, 2010
    It's a great step on ECMAv5. And I think providing an extension syntax -- Lambda Expression will be a great help for JSers. Like that in C#.

  • Anonymous
    June 25, 2010
    The comment has been removed

  • Anonymous
    June 25, 2010
    Well, I still have a question about your ES5 implementation. When calling Object.defineProperty(obj, "prop", {get: function() { return 'value'; }}) and then obj.prop="set?", we face no error. It seems that everything goes as if we add an empty set defined for the property (which seems to be the case, see getOwnPropertyDescriptor (the empty function seems to be native)) Now, the spec. It says if no "set" has been defined, "UA should use the default value". The problem is that I found no place in the spec that say what's the default value. For me, it should be null, or a function that throw a "Property was readonly error". So, my question is what exactly requires the spec ? why did you implement it that way (no error throw) ? Please also have a look at this bug : connect.microsoft.com/.../defineproperty-works-even-if-the-object-is-frozen Fremy

  • Anonymous
    June 25, 2010
    The expected behavior is what Safari implemented, at least. When setting a get-only property, it throw this exception: "TypeError: setting a property that has only a getter"

  • Anonymous
    June 26, 2010
    The comment has been removed

  • Anonymous
    June 26, 2010
    The comment has been removed

  • Anonymous
    June 26, 2010
    @vkelman I can't speak to these as I'm not a DOM expert but I will pass them along to people who are. You should also report them via connect.microsoft.com/ie  As a general rule if you think an IE9 preview has a  bug or an interoperability issue you should report it via connect.  Even if you think it is long standing and a well known issue reporting it via connect againt ie9 will ensure that we are tracking it specifically for IE9.

  • Anonymous
    June 26, 2010
    RegExp split bugs in IE9: xregexp.com/.../split.html

  • Anonymous
    June 26, 2010
    Get back XBM format support please!

  • Anonymous
    June 26, 2010
    Please consider 3rd party html5 tests like this: http://www.html5test.com/ You perform very good on your own tests, but there are a lot of technologies you have not implemented according to that test and other browsers score about twice as much points for html5.

  • Anonymous
    June 26, 2010
    Hmm, I don't dislike the extensions to function declaration syntax. I wonder if we would have seen less global namespace pollution had the first extension been part of EcmaScript 3 and adopted by other browser vendors in the past. Talking about non-standard extensions, Mozilla (the ones with the JavaScript creator Brendan Eich on board) have also created loads of non-standard extensions, some mentioned at: developer.mozilla.org/.../new_in_javascript_1.8 developer.mozilla.org/.../New_in_JavaScript_1.8.1 Also, what about the ES 5 test created by Google and others? http://sputnik.googlelabs.com/ kangax.github.com/es5-testsuite And what about cases that are correct in ES3 but wrong in ES5? Will we see JavaScript libraries specifically only for pre-ES5?

  • Anonymous
    June 26, 2010
    The new methods are great help for meta-programming and OO. But it uses ugly. I'd like some extension syntax in IE9 beta, like

  • extension methods

  • lambda expressions Like that in C#. The extension methods looks like that:    T.extension = function(self, a){      "use extension method"    }    var obj = new T()    obj.extension(1) // === T.extension(obj, a) the "use extension method" defines an extension method for constructor T. It looks like prototype overwriting, but much safer. And lambda expressions are my largest expection:    arr.sort((x,y) => x.a - y.a) It looks much simpler than:    arr.sort(function(x,y){return x.a-y.a}) I'd like to see that in IE9 beta. Thanks.

  • Anonymous
    June 26, 2010
    Will IE9 support JScript or is Microsoft officially going with Javascript?

  • Anonymous
    June 26, 2010
    Split bug in IE: bolknote.ru/.../~2261

  • Anonymous
    June 27, 2010
    It is encouraging to see that this article doesn't say "JScript" even once.

  • Anonymous
    June 27, 2010
    (Sorry if this post is a dupplicate, I made it short because my previous comment did'nt appear after a few minutes, so I suppose something went wrong). Seems ok for the "no-exception thrown on set" problem. If I would have seen it before, I would have requested a change to throw an exception even in non-strict mode (which is the default mode). For the other bug, the code is in the reproduction steps. I don't know if it matters, but this code is executed inside an eval statement because I use my own JScript console to debug JScript implementation in the different browsers, so I use eval to run my code.

  • Anonymous
    June 27, 2010
    ES5 support is incredibly good news and terrific work.  Obviously, there are quite a lot of very hard working, extremely talented and conscientious people working on IE 9.  Another excellent development is Canvas support. Unfortunately, even with all of these incredible new features, IE 9 still lags behind other browsers in terms of standards support.  I am talking about WebGL for 3D graphics.  I cannot help be believe that this omission is a deliberate decision by executives in order to try to keep their other competing technologies breathing.   Because of the monopoly position Microsoft has, the decision not to support WebGL keeps you in an antagonistic attitude towards the web development community, and means that my 3D applications for the web will need to have a disclaimer requiring users to upgrade to standards supporting browsers such as Firefox, Chrome, Safari or Opera.

  • Anonymous
    June 27, 2010
    The comment has been removed

  • Anonymous
    June 27, 2010
    @AMWJ Those are just names. Call it JScript or call it IE's JavaScript implementation or call it IE’s ECMAScript implementation, it’s all the same thing and the MIME type you use in the script tag is "text/javascript".  What’s important is the behavior and features that are implemented. IE9 in IE7 Compatibility mode supports the same JavaScript (JScript) behavior as did IE7; in IE8 Compatibility mode the same behavior as did IE8 in IE8 Standards mode, and in IE9 Standards mode it supports ES5 behavior and features. @Wurst Note that most Mozilla extensions require opt in versioning so they don’t create implicit interoperability issues.   Our position on tests were expressed in blogs.msdn.com/.../javascript-same-code-and-a-standardized-test-suite.aspx  While we are working towards a standard test suite, that doesn’t mean we ignore other test suites.  For example, see results posted in @Saitir comment to test suite post. There are a relatively small number of feature changes from ES3 to ES5 that would cause ES3 specific tests to fail.  For example, using reserved identifiers as unquote property names in object literals.  As long as there are still a large number of ES3 level browsers, library and application authors will generally write code that is compatible with both ES3 and ES5 and should use feature detection to determine if ES5 features can be used. @Infinte We work with the ECMAScript standards committee on evolving the standard features of the language.  You can see the sort of the things that are being discussed at wiki.ecmascript.org/doku.php .  However nothing there is final and won’t be for quite a long while. In IE9 we are focusing on implementing the ES5 versions of the standard not what comes after it. @Fremy Ok thanks, that repros.  defineProperty for an accessor property seems to be ignoring the [[Extensible]] property of the object.  It seems to work correctly for data properties. @Bored already Yes Use @awbjs to follow my JavaScript related twitter posts

  • Anonymous
    June 27, 2010
    Shiny new UI please, IE7-8 seemed to enjoy excess bloat, and Google chrome, and firefox seem to be moving torwards less toolbar and more webpage, My suggestion, Use the dual purpose icon approach of chrome, and combine a lot of the big features from IE8, into a smaller form. Most of the new button toolbars that came with IE7 could probably be condensed into a multipurpose button, Remove the menu bar permanantly, or maybe combine it together like the Office 2007-10 giant Windows button, Maybe even go for a ribbon approach, and take the navigation and bookmarks as the main ribbon, and put a lot of the safety features and stuff in different ones.

  • Anonymous
    June 27, 2010
    @atomic1fire: This mockup is done by me: phenacenn.deviantart.com/.../IE9-User-Interface-Redesigned-160232929 corodidea.net/.../185 (CHS and English) corodidea.net/.../192 (Simplified Chinese) I'm making a new mockup, in Microsoft style. IE9 should be integrated with .NET, silverlight and live. That's almost the only way.

  • Anonymous
    June 27, 2010
    Infinite: Hopefully IETeam will not adopt your/Google idea. IMHO combining title with controls is not good at all. (It's minimalistic enough already)

  • Anonymous
    June 28, 2010
    The comment has been removed

  • Anonymous
    June 28, 2010
    @atomic1fire: Visit here: corodidea.net/.../279 Advices by me ;-)

  • Anonymous
    July 02, 2010
    @Allen W-B [MSFT], Thank you for a suggestion to use connect.microsoft.com/ie for submitting bugs.

  1. Incorrect behavior of window.onblur event. I found this as already submitted to MS Connect. Unfortunately it was already marked as "Won't fix" http://goo.gl/6HlF, but at least I submitted my workaround http://goo.gl/VKTc.
  2. IE automatically creates matching global JavaScript objects for all DOM elements on the page based on their id http://goo.gl/a4Cy. I submitted this bug (non-standard behavior, at least) to MS Connect http://goo.gl/Eugd. (BTW, even this page is apparently using some non-standard HTML/JavaScript, because I cannot post these comments using Chrome browser.)