Welcome to MSDN Blogs Sign in | Join | Help

JScript Debugger in Internet Explorer 8 Beta 2

In Internet Explorer 8 Beta 2 JScript team has focused on improving developer productivity. You can read 'What’s new in JScript for IE8 Beta 2' and check out the JScript PM Channel 9 video to learn more. As part of our focus on developer productivity we have continued to invest in the IE8 Developer Tools in IE8 and added a JScript Profiler to the developer tools. You can read 'Introducing the IE8 Developer Tools JScript Profiler' for more details on the profiler. The JScript profiler along with the JScript debugger we introduced in Internet Explorer Beta 1 will help you get your site working correctly and optimally.

In this blog I will give more details about the following key improvements we have made in debugger for beta 2, you can check my JScript Debugger in Internet Explorer 8 Beta 1 blog for more details on the features we released in Beta 1:

  • Improved script viewer and script explorer
  • More powerful script console
  • New execution control features
  • Better keyboard navigation and overall usability

One of the goals for the script debugger has been to make sure that debugger has minimal impact on your regular browsing. We made that possible by moving JScript engine to debug mode only when you press start debugging. With this, you no longer need to keep debugging enabled in the Internet Options and thus don’t suffer the performance hit. We also wanted to provide you lot of power even when you are not debugging and ensure that you don’t need to transition to debug mode unless you have to debug. Now with Beta 2 we have added some powerful features to make that possible.

Improvements in Script Viewer

The script viewer in Beta 1 showed all the sources when you are debugging but it only showed source for main page when not debugging. Now with Beta 2 you will be able to browse all the sources even when you are not debugging. You can also set breakpoints even before starting debugging. The breakpoints will persist till you close IE window. To make code easier to read, we have updated the source viewer to show sources in syntax color. This is similar to what you might expect in code editors such as Visual Studio.

Source viewer with syntax colored code

We have also updated the script explorer dropdown to make it easy to browse and select files. Now the script explorer will show the domain to which the script file belongs to. We have also separated the eval code, other dynamic scripts and scripts executed from Console into ‘Others’ submenu of the script explorer. With this change it will be easy for you to find the script file you are looking for.

Source explorer dropdown

Updated Script Console

Console panel in the script tab makes it easy for you to try out new scripts. You can execute the scripts in the console irrespective of whether you are debugging or not. In Beta 2 we have improved the look and feel of the Console so that it is easy to read the output.

To make it easy for you to fix errors on your page, Console also logs all the script errors. These errors will be logged in the Console once Developer Tools has been opened for the tab. You can also navigate to the error location in script by clicking on the error hyperlink in the Console.

To help you log message to Console from your script source we have added support for ‘console’ object. Developer Tools provides multiple level of logging with console.log(), console.info(), console.warn(), console.error() and console.assert(). Instead of using window.alert for debugging, you can use these console commands to log messages to the Console. You can call these console commands with a list of arguments that will be concatenated to generate the output string. The input parameters can also be formatted by using substitution patterns in the style of printf().

Console with runtime error and console.log output

You can also control what messages you want to see in the Console pane by using the context menu. Context menu also provide you option to clear the console of all messages. If you only want to clear console.log messages, you can use console.clear().

Context menu for Console

The console.log is extensible and you can add your own console commands through custom scripts. For example you can add console.debug() command which takes string arguments by using following script –

console.debug = function(){

                            var args = "";

                            for(var x=0; x<arguments.length; x++)

                            {

                              args += arguments[x];

                            }

                            console.log("DEBUG: " + args);

                          }

This can be easily enhanced to take formatted strings.

More execution control features

The Developer Tools in Beta 1 offered execution control features like Break All, Step In, Step Out, Step Over. In Beta 2 we have added support for Conditional Breakpoints and Break on Error. In conditional breakpoint you can give any valid JScript expression to be evaluated and debugger will only halt if the expression evaluates to true. Break on Error provides a toggle switch to control whether debugger will break on JScript runtime error or continue while ignoring the error. Regardless of the toggle state the error will be logged to the console so that you can investigate them at your convenience.

We have also extended the just-in-time debugging experience of Internet Explorer. Although with IE8 you don’t need to keep debugging enabled from Internet Options, still if you have debugging enabled in the IE and you hit a script error, you now get an option to use Developer Tools debugger. You can still use Visual Studio and other stand alone debuggers by unselecting the check-box in the message and clicking on Yes.

Just in time debugging dialog

Improved Usability

In Beta 2 we have added extensive keyboard shortcuts. If you have been using Visual Studio for debugging script in IE, you already know the keyboard shortcuts! We have kept the keyboard shortcuts as close to Visual Studio as possible. List of all the keyboard shortcuts supported by JScript Debugger is available here.

We have added search functionality to Developer Tools. Searching in Script tab will show you the search term highlighted in the source viewer. When you browse to a new site or select another file from the source explorer dropdown the search term will continue to be highlighted.

We have also made other improvements like increased tool tips to improve the usability and looks of the debugger.

More Information

For more information on the Developer Tools and JScript Debugger check out these articles:

We look forward to your feedback about the debugger so please leave us a comment in this post. Thanks, and enjoy IE8 Beta 2!

Deepak Jain

Program Manager

JScript Team

Allen Wirfs-Brock and Pratap Lakshman on "Harmony", ECMAScript 3.1, IE 8, and more

The 4th episode of the Open Web Podcast featured Allen, Pratap , Dion, and John discussing the Open Web, ECMAScript, IE 8 and more. A recording of the discussion has been published. Enjoy!

 

Posted by don.raman | 2 Comments

ECMAScript 3 and beyond - the road to "Harmony"

The current ECMAScript specification was completed in 1999 and certainly needed to be updated to reflect today’s web environment and practices. Some participants in the standards process wanted to use what they thought of as a once-in-a-decade opportunity to make some significant changes that they felt would make the language better. Other participants, including Microsoft, were concerned about the ability of the web to “digest” such large changes and favoured a smaller set of revisions. There were passionate and well thought opinions on both sides of these issues and everybody seemed truly motivated by what they thought would be “best for the web”.  However, the net effect of the disagreement was to block any real chance of actually achieving an approved revision to the ECMAScript specification any time soon.

 

Most of these points of disagreement have now been resolved. Rather than re-telling this story, we’d like to point  to ECMA's press release and the accompanying white paper that  lay out the agreements that have been reached in the ECMAScript technical committee. We think that these agreements set the stage for real progress in advancing standards-based web scripting and Microsoft is committed to being an active participant in making these advances. We want to thank and congratulate our colleagues at Adobe, Apple, Google, IBM, Mozilla, Opera, Yahoo!, and  other organizations for working hard to get past these differences in order to find a common path forward for ECMAScript.

 

Pratap Lakshman

Allen Wirfs-Brock

 

Posted by don.raman | 9 Comments

GC Improvements in JScript for Internet Explorer 8 Beta 1

Hello Friends,

Today I am going to talk about some of the Garbage Collector improvement we have done. Actually the original fix was done in Script 5.7 (shipped with IE7/Vista and also available on down level platforms), which we further enhanced in JScript shipped with IE8 Beta1.

So if you have gone through the Eric’s post on JScript Garbage Collector, you must have noticed following lines…

Actually what we do is keep track of the number of strings, objects and array slots allocated.  We check the current tallies at the beginning of each statement, and when the numbers exceed certain thresholds we trigger a collection. “

“However, there are some down sides as well.  Performance is potentially not good on large-working-set applications”.

The three thresholds he talked about were fixed in previous versions of JScript. After each GC cycle, counters were reset to zero. Next time when they hit the thresholds, again GC was triggered and so on.

This was alright for small scripts as they never create lot of strings and objects and don’t take much time to execute. But in modern AJAX applications, lots of objects /strings/array entries are created and they live for long enough time. Since rate of object/string/array entry creation is too high in these applications, thresholds are hit quite often, GC is triggered but not able to collect anything because things are still alive and there is no garbage. Counters are reset, but within few statements they again hit the thresholds. GC is triggered again but very less is collected and so on.

So as you see, GC is not able to collect significantly, however it is triggered at fixed intervals (as thresholds are fixed). Each GC cycle proves to be costlier than previous one as more objects have been created since last GC cycle happened.

So to fix this problem, we made the three thresholds adaptive. After each GC cycle, we check if GC was profitable or not, meaning significant collection happened or not. If it was not, then we double the thresholds. If it was, then the thresholds are not changed. Obviously there is an upper bound on value of thresholds, beyond which they are not doubled even if GC cycle was not profitable. Also if GC cycle collected everything, thresholds are set to their initial values.

That’s it for now. Hope you enjoyed reading it.

-JP

Performance Optimization of Arrays - Part II

Hello Friends,

Hope you have read part I of this topic which I posted few days ago. If not then I would suggest going through that first as this post is just a continuation of that one.

So coming to the point, here is the second reason -

2. “JavaScript arrays are sparse arrays”– JavaScript allows arrays to be sparse therefore, when you write arrayObj = new Array(100); unlike C runtime, JScript doesn’t allocate any slot/memory for those 100 entries up front. It allocates slot for an index only when an index is to be populated with a value, for example…

arrayObj = new Array(100);
 
arrayObj[10] = 10;
 

In this example, the array size is 100, but in the actual physical memory there is only one slot allocated for this array. Remaining 99 slots don’t exist at all.

Wondering how this factor contributes to the bad performance? Not allocating memory for all the slots up front is good design. Isn’t it?

Well, JScript always assumed that all arrays are sparse. So even if you had a fully dense array in your code, JScript runtime would treat it like a sparse array only. So if you are going to do a pop() operation on a dense JScript array, JScript just won’t go and delete the last indexed entry and update the length attribute. It does something which is extremely performant for sparse arrays, but equally under-performant for dense arrays. Let‘s see what it is all about.

Internally, for each Array object, JScript runtime maintains a table (different from HashTable, let’s call it TrackerTable) which is nothing but a list of pointers to actual entries in the hash table. So if you just create an Array Object of size 100, and add 10 entries (indexed or named), the TrackerTable will have 10 pointers pointing to actual entries in the hash table. Let’s take one simple example…

arrayObj = new Array(100);
 
arrayObj[10] = 10;
 
arrayObj.length = 90;
 

In this example, I just create an Array of size 100, and populated index 10. Next I reduce length of array to 90. Since the length has been reduced, entries from 90 to 99 have to be deleted. The ideal thing to do would be to delete <key, value> pair from hash table for key = 90 to 99. That means 10 operations on Hash table. JScript is smart here and saves 9 out of 10 operations.

What JScript actually does is that it goes to the TrackerTable, iterates through it, for every entry it checks if it falls between deletion range (90-99 in this case), if yes then delete it. In above example, TrackerTable had only one entry. So instead of 10 operations on hash table, JScript does only one iteration and performs better.

However what if the array was a dense array and all the indexed entries from 0 to 100 were populated? Unfortunately in this case too, JScript would follow the same logic. Therefore it would do 100 iterations over TrackerTable and end up doing 90 more operations.

How it was fixed– As I said in the last post, in IE8 JScript we have the mechanism in place to decide whether an array is a sparse or dense. So we have changed the implementation to take sparse path only when the array is actually sparse. That means for operations on dense arrays, we don’t use TrackerTable anymore. We directly go to the right storage and get the things done in fast manner.

So this is all I had to tell about array improvements. Hope you got an idea of what was/is happening under the hood? If not, do leave a note and I would try to address that. And yes, I have lot many interesting things to share with you all, so keep checking this blog.

-JP

Reading XML File With JScript

I am Titus working as a SDET in JScript team. Sometime back I came across a situation where the requirement was to pass a XML file and get a Tree Listing back. The Tree Listing should have all nodes in the file along with proper parent/child relationship as well as a good way to differentiate between nodes with/without values. Let’s call nodes with value as properties. I achieved this by using JScript. In this blog you will learn how to read/parse XML file using Microsoft’s XML DOM and use this to create the Tree Listing. 

Let’s take a sample XML file, say test.xml (can be a URL or a file on your system) to get a clear picture of the kind of Tree Listing required and later we will look at the actual code.

 

The XML file can be looked as

Root Node, name is BookList, has 2 child nodes

childnode0, name is Book and has two properties,

Prop0: Author has a value Paul

Prop1: Price has a value 10.3

childnode1, name is Book and has three properties

Prop0: Author has a value Joe

Prop1: Price has a value 20.95

Prop2: Title has a value Web 2.0

The Required Tree Listing after parsing test.xml is

nName

NodeName

nValue

NodeValue

cNodes

List of Child Nodes

cProps

List of Child Properties

 

The ReadXMLFile function in the code listing below returns the Tree Listing as required.

Many a times you know the XML file contents and are interested in the list of only a specific node. Making a call to ReadXMLFile with second argument as the node name gives just such a list.

Referring test.xml, a call to ReadXMLFile(“test.xml”, “Author”) gives a list like

Whereas a call to ReadXMLFile(“test.xml”, “Book”), returns the list like the below one

If you have carefully noticed the Tree listing, cNodes as well as cProps is an Array. so by using the proper index value, one can reach the desired node.

Here goes the actual code:

var NODE_ELEMENT = 1;
 
var NODE_ATTRIBUTE = 2;
 
var NODE_TEXT = 3;
 
/**** INTERNALLY USED FUNCTIONS ****/
 
/*
* Builds up xmlNode list on parentXMLNode
* by iterating over each node in childNodesLst
*/
 
function getXMLNodeList_1(childNodesLst,
 
parentXMLNode)
 
{
 
    var i;
 
    var curNode;
 
    var arrLen
 
    //traverse nodelist to get nodevalues and all child nodes
 
    for (i = 0; i < childNodesLst.length; i++) {
 
        //we will ignore all other node types like
 
        //NODE_ATTRIBUTE, NODE_CDATA_SECTION, …
 
        if (childNodesLst[i].nodeType == NODE_ELEMENT
 
        || childNodesLst[i].nodeType == NODE_TEXT) {
 
            if (childNodesLst[i].nodeType == NODE_TEXT) {
 
                //we got the value of the parent node, populate
 
                //parent node and return back
 
                parentXMLNode.nValue = childNodesLst[i].nodeValue;
 
                return;
 
            }
 
            //we have a new NODE_ELEMENT node
 
            curNode = new XMLNode(childNodesLst[i].nodeName, childNodesLst[i].nodeValue);
 
            if (childNodesLst[i].hasChildNodes) {
 
                getXMLNodeList_1(childNodesLst[i].childNodes, curNode);
 
                if (curNode.nValue != null) {
 
                    //we need to add this as a property to the parent node
 
                    if (parentXMLNode.cProps == null) {
 
                        parentXMLNode.cProps = new Array();
 
                        parentXMLNode.hasCProps = true;
 
                    }
 
                    arrLen = parentXMLNode.cProps.length;
 
                    parentXMLNode.cProps[arrLen] = curNode;
 
                } else {
 
                    //we need to add this as child node to the parent node
 
                    if (parentXMLNode.cNodes == null) {
 
                        parentXMLNode.cNodes = new Array();
 
                        parentXMLNode.hasCNodes = true;
 
                    }
 
                    arrLen = parentXMLNode.cNodes.length;
 
                    parentXMLNode.cNodes[arrLen] = curNode;
 
                }
 
            } else {
 
                //no use of such a node
 
                //mark currNode as null for GC collection
 
                curNode = null;
 
            }
 
        }
 
    }
 
    return;
 
}
 
/*
* Generates appropriate XMLNodeList from nodes
* in childNodes
*/
 
function getXMLNodeList(childNodes)
 
{
 
    var xmlNode = new XMLNode(null, null);
 
    getXMLNodeList_1(childNodes, xmlNode);
 
    var xmlNodeList = null;
 
    if (xmlNode.hasCNodes) {
 
        xmlNodeList = xmlNode.cNodes;
 
    } else if (xmlNode.hasCProps) {
 
        xmlNodeList = xmlNode.cProps;
 
    }
 
    return xmlNodeList;
 
}
 
/**** INTERNALLY USED FUNCTIONS ****/
 
/* XMLNde DataStruct */
 
functionXMLNode(ndName, ndVal)
 
{
 
    this.nName = ndName; //XMLNode name
 
    this.nValue = ndVal; //the value(if any) associated with XMLNode
 
    //As of now only property nodes have associated values
 
    this.hasCNodes = false; //Bool to mark presense of Child Nodes
 
    this.cNodes = null; //List of child nodes (of type XMLNode)
 
    this.hasCProps = false; //Bool to mark presense of Property Nodes
 
    this.cProps = null; //List of property nodes (of type XMLNode)
 
}
 
/* Exposed Functions */
 
function ReadXMLFile(fileName, tagName)
 
{
 
    if (arguments.length < 1 || arguments.length > 2)
 
    return null;
 
    var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
 
    //load the file sync'ly
 
    xmlDoc.async = false
 
    try {
 
        xmlDoc.load(fileName);
 
    } catch(e) {
 
        //failed to load xml file
 
        return null;
 
    }
 
    //lets get the child nodes
 
    var childNodes = null;
 
    if (arguments.length == 2) {
 
        try {
 
            childNodes = xmlDoc.getElementsByTagName(tagName);
 
        } catch(e) {
 
            return null;
 
        }
 
    } else {
 
        childNodes = xmlDoc.childNodes;
 
    }
 
    return (getXMLNodeList(childNodes));
 
}
 
var xmlNodes;
 
xmlNodes = ReadXMLFile("http://www.noweb.com/test.xml");
 
//For a file on you system
 
//xmlNodes = ReadXMLFile ("C:\\My Documents\\test.xml");
 
//root node name is
 
var RootNodeName = xmlNodes[0].nName;
 
xmlNodes = ReadXMLFile("http://www.noweb.com/test.xml", "Book");
 
var cntBooks = xmlNodes.length;
 
xmlNodes = ReadXMLFile("http://www.noweb.com/test.xml", "Author");
 
var authorName = xmlNodes[0].nValue;

Hope you enjoyed the blog!

Thanks,

Titus

Posted by JSBlog | 10 Comments
Filed under: , ,

Performance Optimization of Arrays - Part I

Hello Friends,

Have you observed better performance of Array operations in IE8 than IE7? If not, try the following code in both IE7 & IE8 and I can bet you would not leave this page without reading till the last word.

var arrObj = new Array();
var count = 10000;
var before, after;
for(var i = 0; i < count; i ++)
{
   arrObj.push(i);
}
before = new Date();
for(var i = 0; i < count; i ++)
{
    arrObj.pop();
}
after = new Date();
alert(after- before);

On my machine, IE7 took 7640 ms while IE8 took just 18 ms. As you see the above example is doing nothing but populating an array with 10000 entries and then popping them one by one, and just the pop operation is taking so much time in IE7.

This was just one example. Pick any array operation, and you would notice a huge difference between IE7 and IE8 performance.

So, won’t it be interesting to know why array operations in IE7 were taking so much time? Won’t you like to know how we dealt with all those issues? I am sure the answer is ‘yes’ and in the next few paragraphs that is what I have tried to explain. So keep reading.

Why Array operations were slow?

There were two main reasons which made Array operations so less performant. I will be explaining one of them in this post and leave other one for the next post, otherwise it would be so long to read that I would surely lose the bet.

1. JScript didn’t treat Arrays as Arrays – What does this mean? Arrays, in general sense, are considered a contiguous memory storage which enables fast random access to indexes. In JScript world, Arrays can be sparse, that means an Array can be of length 1 million but it may not have storage committed for all those 1 million indexes. But in real world scenarios, Arrays are hardly used as sparse arrays. They are mostly dense

Unfortunately JScript runtime was not handling arrays for real word usage. It always handled them as sparse arrays. Therefore it never committed any contiguous space for them, resulting into slower access to indexes.

Instead it used to insert indexed entries into a property bag which is nothing but a classic hash table whose keys are strings.

So if you are doing something like the following in your code…

var arrObj = new Array();
for (i = 0; i < 100; i ++)
arrObj[i] = i;
 

… and expecting that JScript runtime internally would allocate a C-Style contiguous array, then sorry to say, it doesn’t meet your expectation at all. Instead what it does internally is…

a) Allocates a generic object, which is nothing but the HashTable.

b) Since the generic object (HashTable) has to be treated like an array object, associate a special attribute “length” with it and set its value to 0.

c) In the for loop, for each value of i

a. Convert ‘i’ to string (e.g. for i = 10, it would be “10”)

b. Add <key value> pair of <string equivalent of i, i> (e.g. <”10” , 10>) to the hash table.

c. Set the “length“attribute’s value properly.

So every time you access an indexed entry of an array, it first converts the index to string, computes hash value for the string and then looks up the hash table.

How we fixed it

No rewards if you already guessed it.

Now JScript runtime treats an Array Object as an special object, different from other JScript objects. Basically it maintains two storage areas for arrays. One is the old HashTable, which is used for storing named entries. The other one is special one which is used exclusively for indexed entries and resembles a C-Style Array.

So if you have some code like following…

arrObj = new Array(20);
for(var i = 0; i < 20; i ++ )
    arrObj[i] = i;
    arrObj.Name = “IE8 Array”;
 

… then for loop is adding entries to a different storage and “Name” is added to the different storage.

Ok. So looks like all indexed entries always go to new storage. No. That is not the case. There is a condition which should be met before we put an indexed entry to the new storage. The condition is that new entry must not make the array sparse and to decide that whether a particular indexed entry would make the array sparse or not, we have certain heuristics, for example…

arrObj = new Array();
arrObj[10] = 20;
arrObj[50000] = 500000;

In above snippet, indexed entry 10 satisfies our heuristics and is added to new storage. But the indexed entry 50000 will not meet them and will be added to old HashTable as a normal named entry.

Cool. looks fine if you always populate the array such that it meets the heuristics, e.g. in an incrementing for loop starting from 0. But what if you want to populate it in a decrementing for loop starting from max length…

arrObj = new Array();
for(var i = 2000; i >=0 ; i -- )
  arrObj[i] = i;
 

or you want to populate the array from both ends …

arrObj = new Array();
var length = 2000;
for(var i = 0; i < length/2 ; i ++ )
{
  arrObj[i] = i;
  arrObj[length – i - 1] = length – i;
}

In such scenarios, not all of your indexed entries will go to new storage and performance of further operations on this array would not be as great as it can be.

For such scenarios, to get working in most performant way, what you have to do is to pass the actual array size to constructor when you create the object. If you pass the size, JScript runtime assumes that you are sure that your array would be dense and don’t want our heuristics to ensure that. We will not exercise those heuristics for any indexed entry added within that size range, in whatsoever order they are added. So if you write something like following…

arrObj = new Array(50000);
arrObj[10] = 20;
arrObj[50000] = 500000;

… both will go to the new storage even though the last indexed entry doesn’t satisfy heuristics. But do remember that anything beyond 50000, will have to meet the heuristics, else it would go to HashTable.

Time out. Hope you enjoyed reading it and would like to read second part as well. See you soon.

-JP

Posted by JSBlog | 12 Comments

Insight into String Concatenation in JScript

Hello Friends,

Have you read my post on the String Concatenation issue? If yes, then I can sense your curiosity to know a little bit more about what went on behind the scenes.  For example, what is the new algorithm used to get to the performance results projected in the blog, what were the issues faced, how tough/easy it was to implement etc. etc. Well, I didn’t talk much about all these last time as we were still testing the fix and things were not stable at that point of time. But now since IE8 Beta is out and you are already running it on your box (if not, install from here) and loving it J, why not talk a little bit more and try to get few of the queries answered.

In the new implementation, which is running on your box if you are reading this in IE8, we don’t produce actual regular string for each append operation anymore. Instead, we keep the information about all strings which took part in the append operation. The production of actual regular string is deferred for later point of time.

 Let’s apply it on the same example I used in the previous blog post…

resultStr = “Jscript” + “String” + “Append” + “problem”

In the previous implementation, we used to produce the actual string and store it in the resultStr. In the current implementation, resultStr points to a structure (let’s call it pseudo-string), which keeps the details like what all strings are needed to produce actual string and in which order.

The logic looks simple. However there were few issues we faced while implementing it, which I think are worth sharing here…

When to Convert pseudo-string back to actual String – As Eric mentioned in his blog, their ‘Fancy-String’ implementation was heavy as they had to convert ‘Fancy–Strings’ back to regular string every time one is passed by variable reference. We also had this big question facing us – ‘When to convert pseudo-strings back to regular strings’? Should it be done as soon as ‘pseudo-string’ has grown to certain size or should it be done soon after append operation is done? Or should it be done when it is passed by variable reference? We evaluated all these approaches but none of them seemed to be giving the kind of gains we wanted. Later we thought why not defer the conversion to the point when pseudo-string can’t serve the purpose and we have to have the regular string. In other words, do the conversion only when actual regular string is needed. For example do the conversion when a ‘subStr’ or ‘trim’ operation is performed on the ‘pseudo – string’ or when the pseudo string needs to be passed somewhere out of the engine, like IE or VBScript, that doesn’t understand pseudo-strings. We tried it and yes, with this, we hit bulls-eyeJ.

Multiple References to single Pseudo-String

If there are multiple references to a single ‘pseudo-string’, then we want to do the conversion only once. For example…

                        X = “Hi” + “Microsoft”;

                        Y = X;

                        Z= X;

In this example X, Y and Z are pointing to the same pseudo-string. Now if x.toString() is called, one approach is, allocate a buffer of size 11 and copy the strings “HI” and “Microsoft” one by one to the buffer. Later when Y.toString() and Z.toString() are called, we again allocate new buffers for each of them and copy the strings.

Hmmm. with such multiple allocations and copy operations, are we not back to the problem we were trying to solve? Yes, we are.

So how did we address this? Well, we decided not to have X, Y and Z point to actual pseudo-String. Instead they point to a proxy object, which keeps actual reference to pseudo-string. When X.toString() is called, conversion from pseudo-string to regular string happens (a new buffer of enough size is allocated and strings are copied one by one) and the proxy object is made point to regular string. Later when Y.toString() and z.toString() are called, we need not do the conversion again as they point to the proxy-object which already points to the regular string.

So X, Y and Z always point to the proxy-object. Proxy object may either contain a pseudo-string or a regular string, depending upon the time of conversion.

What if Pseudo-string is partially converted to regular string?

        X = “Jscript” + “Team”;

Z = X  + “Microsoft”;

X.toString();

In above snippet, X is a pseudo string and is used in formation of another pseudo string Z. Now toString() is called on X, so X has to be converted to regular string. Fine. I can do it. But wait a moment. X is used by another pseudo string Z. I can’t convert it just like that?

Well, as I said, all references to a pseudo-string are through the proxy-object. Hence Z also refers to the proxy object for X, not to the actual pseudo-string. So even after X is converted to the regular string, references to proxy object remain alive and things work perfectly.

And yes we had to test it J

‘Maintaining compatibility is priority no. 1’ – this is the mantra we all in the team swear by. At any cost we had to ensure that we don’t break real world when fix is out. Our test team has done an awesome job in ensuring it. They found couple of cool crashes, which were not directly in the new implementation, but because new implementation broke few assumptions made in the engine. Interesting part is that they were reported on the last day of our internal milestones; therefore we had to sit whole night gazing at our screens, fixing and testing them.

This is all about string append problem and I hope it was an interesting read. One more interesting performance improvement I have worked on in this release and would like to share with you all is ‘Arrays’, but we’ll leave that for another post so stay tuned.

-   JP

IE8 Script Debugger - Under the Hood

IE8 Beta1 (download available here) now includes a Script debugger that is part of IE8 Developer Tools. This Script debugger was built by the JScript team and I hope you have been using it to fix all script errors when building your web applications.

In this post I will be discuss the design of the script debugger.

The debugger is designed with Active Debugging Framework (more information here). Here is the block diagram of how debugger looks.

Debugger Design

A brief description about the different components in the above block diagram:

IE – the host controls the JScript engine by providing the script code and other objects that are needed to execute that code.

The JScript engine is responsible for parsing and executing script code and handling other debugger related operations like stack enumeration, expression evaluation, variable inspection, and both parsing-time and runtime error notifications. The JScript engine interacts with the IE to resolve the external references to named objects (eg. window or document), it also notifies host about execution errors and script state changes.

The Process Debug Manager (PDM) manages various process related information (where is the process running, thread information, parent-child relationship among threads-processes etc.) and also co-ordinates the interaction between all components like engine, debugger, host etc.

Debugger is the component that implements the UI and other functionality that normally comes to our mind with word script debugger.

When we started work on the design for a script debugger for IE8 Developer Tools, the first decision was whether the debugger would be residing in the same process or in a different process. Since the primary reason for building a debugger that is available with IE8 Developer Tools was to provide an integrated debugging experience, we decided to go down the path of building an in-process debugger. Also, having the script debugger in the same process would result in better integration with the host since the debugger will have direct access to host events like say page load and there would be fewer COM calls required to interact with the host or engine.

As soon as we went down this path of having the script debugger in the same process, we hit a fundamental issue, which was that the JScript engine is loaded by the IE UI (rendering engine) thread. What this meant was that when a breakpoint is hit, the UI thread would halt and the script debugger wouldn’t even be displayed. To address this issue, we designed the debugger so that the UI of the debugger would be on a different thread than the script engine.

But with this choice we now had to address the issue of interaction of the debugger with PDM, since this component expects the debugger to be on the same thread. So we split the debugger into two components. The first one, the UI component, renders the debugger application and runs as a separate thread. And the second one, the core or worker component interacts with PDM and host to provide data to the UI component for rendering, and runs on IE’s UI thread.

I hope this blog post explains some of the design decisions of the script debugger of the IE8 Developer Tools and the impact on the functionality of the script debugger.

So how have you been using the script debugger to improve your productivity? We would love to hear from you on your experiences using the script debugger and would also like to know what features you find the most useful.

Sheetal Kamat, SDE, JScript.

JScript Debugger in Internet Explorer 8

As Shreesh mentioned in his blog, Internet Explorer 8 has a built-in JScript debugger. With Internet Explorer Developer Tools you get a light weight JScript debugger that is well integrated in the browser and available out of the box. This is an in-proc debugger making sure that you don’t have to launch a separate app. It has familiar Visual Studio feel and features like call stacks, watches, locals and immediate window.

To get to the debugger just press SHIFT+F12, or click the developer tools icon in the command bar. After launching the Developer Tools, switch to the script tab.

Toolbar - SHIFT+F12

Before starting debugging you can browse the source code of the websites’ main page and also use immediate window to try out JScript code. You can start the debugger session by clicking on the ‘Start Debugging’ button. The debugger lets you debug even when debugging is disabled in Internet Options Control Panel. This will allow you to enable debugging only for the IE instance you are debugging. All other IE instances will still be in non-debug mode making sure that you don’t get script error dialogs. This will also make sure that debugging won’t have any performance hit on IE instances other than the one being debugged. Debugger will refresh the web page with your consent, in case debugging was previously disabled. If you want to avoid page refresh, you can enable debugging from Internet Options.

Debugging Not Enabled

After starting debugging, the script debugger provides you execution control. Similar to Visual Studio you can set breakpoints by clicking in the source viewer next to the line number. You can also use context menu or keyboard shortcut (F9) to set breakpoints on the script statement at the cursor location in source viewer. If you have multiple script statements in a line of code, you can set multiple breakpoints on that line and they will be hit based on script statement. In case you want to break execution at first script statement, debugger provides a Break All button in the toolbar.

Pause

You can also browse the included files and eval() code using the source explorer drop down list.

Browse Scripts

While debugging, debugger will also break on script runtime error locations. Debugger will only highlight the script statement that will be executed. On a breakpoint debugger provides you Visual Studio like options to control the execution. You can use following commands to control the execution:

- Step Into: Executes the next statement of script and pauses, even if the next statement is inside a new method. You can either use toolbar button or keyboard shortcut F11.

- Step Over: Executes the next statement of script, continues until the next line of script in the current method, and then pauses. You can either use toolbar button or keyboard shortcut F8.

- Step Out: Continues executing script until the next statement in the method that called the current method. You can either use toolbar button or keyboard shortcut SHIFT+F11.

- Continue: Continue running script without pausing until hitting another breakpoint (if any are set). You can either use toolbar button or keyboard shortcut F5.

Execution Control

At breakpoints you can navigate call stack and inspect local variables. All this functionality is provided in the right hand side tabs of the debugger. Let’s just take a look at each of these tabs –

Locals – This tab displays the name, value, and type of all variables available in the current execution scope. Just like Visual Studio, you can drill down in objects hierarchies and change the value of variables. When you step in or step out the variables which have been modified will be indicated with value in red color.

Watch – Watches are user defined variables or expressions to be watched at each halt of script execution. Like locals you can drill down object hierarchies, change values and observe values changed during stepping through code. Watches can be added either by typing a variable name or expression into the watch window or through context menu available in source view.

Watch Window

Call Stack – Whenever the execution is paused at a breakpoint call stack tab will let you transverse the stack and inspect the variables at that execution context. Double clicking on the stack entry will take you to the location in source code.

Call Stack

Immediate Window – Immediate window can be used to run scripts at the runtime. While on a breakpoint the script will be run in the current execution context. You can also use immediate window for running script while not on breakpoint or even when not debugging. In these scenarios, scripts entered in the immediate window will run in the global scope. Immediate window also gives you option to provide multiline script block by expanding the input window. This can be done using the ‘Multiline’ button. You can go back to the single line input by clicking on the ‘Single Line mode’ button.

Immediate Window

Breakpoint – This tab displays all the breakpoints currently set. You can enable/disable breakpoints by using the check box or the context menu. You can also remove breakpoints using the context menu. Double clicking on the breakpoint will take you to the source code. Breakpoints are maintained until IE8 Developers Tools is closed.

Breakpoint Window

This debugger has inbuilt support to debug eval() code and event handlers. You don’t need to enable any options to debug them.

Debugging eval Code

Debugging Event Handlers

More details on the debugger are available in the Developer Tools Whitepaper. We will also have some debugger videos up very soon. Keep checking this blog. John from IE team has a blog entry  describing the Developer tool and also some overview videos. The release notes are available here.

We would love to hear back from you about this debugger. Let us know how this debugger has helped you and also any issue you might have encountered.

Thanks and happy debugging!

Deepak Jain

Program Manager

JScript Team

JScript in Internet Explorer 8 Beta 1 for Developers

Making developers more productive through the design, development, and debug phases of web application development is one of the key goals for Internet Explorer 8. I’d like to take this opportunity to walk you through the features that the JScript team contributed to IE8 Beta 1 for Developers.

Let me start with the JScript language and the scripting engine optimization. Performance of the JScript engine has been our number one goal for the Beta1 release. With today’s rich AJAX web-applications, some of the most common JScript operations include String and Array operations. We received feedback from developers on the slow performance of the inbuilt string concatenation functions of JScript. This is not a new problem and quite a lot has been written about the issue (discussed in this Jscript blog post). With IE8, we fixed this problem in the JScript engine. String concatenation is now many times faster when compared to the previous JScript engine.

Prior to this optimization of string concatenation, most developers used Array join operations to achieve the same result. We were aware of this tradeoff and made sure that the Array operations are also optimized. In either scenario, developers will experience significant performance gains.

One of the challenges for the team was to understand the language compatibility and issues that existed in our JScript implementation of the ECMAScript Language Specification 3rd Edition. We have identified the JScript Deviations from ES3 (discussed in detail in this blog post).  This document will act as a starting point for the developers targeting cross browser web applications and helps in understanding the deviations in detail. In the near future, we intend to make JScript more compatible with ES3 specifications.

Another challenge for the JScript developers is the circular memory leak problem. We took a hard look at this problem and realized that this has to be fixed at the COM infrastructure. We implemented a design that bridges the gap between COM ref-counting and automatic garbage collection models. We extended the IDispatchEx interface to enable COM clients to simultaneously live in both the ref-counted and garbage collected worlds. The good news is that since this is impacting the underlying core infrastructure, many built-in COM components including IE8 DOM and custom COM components can take advantage of this.

If you are a web developer, you would have certainly used Firebug or Visual Studio for debugging web applications. Web developers can get started with Visual Web Developer Express for basic debugging or can leverage the power of Visual Studio Team System which is meant for complex testing and debugging scenarios. While we cover the whole spectrum through the Visual Studio family, one of the experiences lacking in Internet Explorer is a built-in JScript debugger.  The IE8 Developer Tools now offer an integrated JScript debugger that provides the basic set of debugging features. We believe this compliments Visual Studio debugging experience and is an important step towards making JavaScript developers more productive.  

We look forward to hearing about your experiences with JScript and IE8 Beta 1 for Developers.

Shreesh Dubey, Product Unit Manager, JScript

Thank you - Smartsheet !

We are constantly looking to engage with our customers on this blog and understand their pain-points, and in that spirit, it was really heartening to see the blog post by Mark Mader from Smartsheet. The JScript team is very appreciative of this kind of customer engagement and hope more customers frequent this blog and provide feedback to us. This helps us understand problems real-world customers face and provide solutions that benefit other customers.

Thank you, Mark !

Don Raman

JScript errors as warnings in Visual Studio 2008 RTM

Now Visual Studio 2008 code named Orcas is out of door with incredible features. The most highly anticipated feature of this release is JScript Authoring Services which includes JavaScript Intellisense and JavaScript Syntax Checking.

In the final version of Visual Studio 2008, with default profile settings VS shows all JScript/JavaScript syntax errors as warnings and warnings as messages because of which customer will end up unnoticed JScript Syntax Checking feature.   

To view JScript Errors as Errors in Error List window enable below option from Options dialog of Visual Studio

-       Launch Options dialog by clicking on Tool à Options menu

-       Expand Text Editor à HTML à Validation

-       Clear Show errors “as warnings (JScript)” check box

 Options

This has been added after VS 2008 Beta2 after considering customer feedback. In Visual Studio 2005 and Visual Web Developer Express 2005 all markup and CSS validation related issues such as unsupported tags and attributes are shown as errors in Error List. Few like it since validation errors encourage standard compliance while few didn't want validation errors to show up in Error list as these errors are browser errors. The same applies for JScript errors in VS 2008. This has been addressed by adding above option in the final version of Visual Studio 2008.

   JScript_errors_As_warning

JScript Performance Update for IE6 users

Sometime back Don blogged about Windows Script 5.7 release. We got lots of feedback on this, people asked for making this as an automatic update and support for 64 bit platform. The good news is that we have heard you. The biggest fix in JScript was the improvements done in Garbage Collection which improved the performance of AJAX/script heavy web site drastically. This fix is now available to all the IE6 users from the Microsoft Download Centre.  After monitoring user feedback on this update for a few weeks, we plan to release this as an automatic update to all IE6 users. However for IE6 users who want to try this now, one can go to the above provided link and download it.

 

- Suresh, Scripting Team

 

ECMAScript, Mashups, and Security

A mashup composes a web application by combining programs and data services from multiple originators, and delivers it for presentation on a single web page. Usually, these programs and services interact with each other - housing maps being the canonical example.

 

The same origin policy (SOP) governs access control in today’s browsers. It prevents documents or scripts loaded from one origin from getting or setting properties of documents from a different origin - it provides total isolation. While this is useful to protect one origin from another, it shackles mashups. A common technique mashup authors have used to break free is by clever use of the script tag. The SOP is not applicable to the src attribute on the <script> tag; a document may contain <script> elements from different origins (or domains). Such third party scripts are treated as originating from the document’s origin and can access all of the document’s resources - they have total trust.

 

Faced with this all-or-nothing security model, the mashup developer can use the <iframe> structure to confine components such that they cannot interfere with each other, but the SOP isolates them so completely that they are also unable to cooperate, or, use the <script> tag and ECMAScript to enable cross domain data exchange and compose rich client-side mashups.

 

ECMAScript, thus, finds itself being used as a composition language - composing separately written programs into a single web page. Such composition presents several challenges, one of them being the ability to compose securely. When separately written programs are composed so that they may cooperate, how do you prevent them from interfering in unanticipated ways? Does ECMAScript, as a language, support secure software composition? Several features in the language would suggest otherwise. Here are a few:

 

Global scope: All script code executing within the same web page (or <iframe>) implicitly share access to the same global scope. Therefore, globally reachable objects cannot be isolated from each other.

 

Freely mutable state: Certain objects, like Array.prototype, are implicitly reachable even without naming any global variable names. Even if the global scope problem is addressed, the mutability of these objects prevent isolation.

 

Freely mutable properties: While some built-in properties are constrained to be Internal, ReadOnly, DontEnum, or DontDelete, there is no way to express these constraints in the language. Any object defined in user script code is freely mutated by any other code which can access it.

 

Lack of encapsulation: Objects need to be able to encapsulate their private state. The best one can do is to use an idiomatic functional style to simulate private members as well as private static members. But it is idiomatic; neither widely taught nor uniformly followed.

 

for..in loop: The for..in loop enumerates the names of all of an object's properties, whether inherited or not, unless the property has the DontEnum attribute (which the programmer has no way to express). When composing using mixins, programmers must carefully skip over some of these names. Re-inventions of idiomatic mechanisms to achieve this abound.

 

"this" binding: The rules for binding “this" depend on whether a function is invoked by construction, by method call, by function call, or by reflection. If a function written to be called in one way is instead called in another way, its “this" might be re-bound to a different object or even to the global scope.

 

eval: There is no simple way to constrain the script or to inspect it before it executes. It runs with the same authority as scripts from the page.

 

with: with augments the scope chain causing some confusion to the reader about the specific object to which a particular property access gets bound. A bigger problem is probably the with-like semantics implemented by Internet Explorer and Firefox for the exception object within a catch clause of an exception handler. This semantics allows malicious code to inject names into the dynamic scope of a theoretically secure handler. This construct, along with eval, calls for studied usage.

 

Mashups are not new. The early and simple mashups merely loaded an image from a different site, while the contemporary and more profitable ones pop up relevant advertisements as you browse. Rich media ads are mashups. Most rich ads are served from third-party sites into the context of the existing experience. The ad script has access to all of the information on the page, including cookies and the connection to the originating server. Whenever you include any script on your page, you are implicitly trusting that script will neither interfere, maliciously or otherwise, nor destabilize your page. After all, a poorly coded ad can easily bring down the entire application. Security, then, is critical to the growth and success of mashups.

 

Within the Web community there are various initiatives that attempt to address this challenge. Facebook with FBML and FBJS attempts to constrain the language and DOM semantics to protect their users. Adsafe and Caja propose a subset of the language and corresponding semantics that can be validated. Many gadget approaches attempt to use IFrames to provide isolation.

 

Such initiatives are valuable because they are exploring the solution space of the mashup security problem. However, currently they only provide local and limited solutions to the problem. In the long run the best solution is to provide common ubiquitous support for secure mashups within all browsers. This is the realm of web standards, and mashup security should be a high priority item for future revisions.

 

In the meantime, I am interested in knowing what kind of composition challenges you have faced with JScript and mashups, and how you have addressed each of them.

 

Pratap Lakshman, JScript
Posted by don.raman | 14 Comments
Filed under:
More Posts Next page »
 
Page view tracker