<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>HD DVD / Randomness... : iHD</title><link>http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx</link><description>Tags: iHD</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>What Now?</title><link>http://blogs.msdn.com/ptorr/archive/2008/02/20/what-now.aspx</link><pubDate>Wed, 20 Feb 2008 22:18:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7822373</guid><dc:creator>ptorr</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/7822373.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=7822373</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=7822373</wfw:comment><description>&lt;p&gt;I have had some readers ask what is to become of this blog. Well, it started out discussing &lt;a href="http://blogs.msdn.com/ptorr/archive/2003/09/09/56181.aspx"&gt;Office Development&lt;/a&gt;, then it covered &lt;a href="http://blogs.msdn.com/ptorr/archive/2005/02/22/GuerillaThreatModelling.aspx"&gt;Threat Modelling&lt;/a&gt;, and most recently it has been about &lt;a href="http://blogs.msdn.com/ptorr/archive/2007/05/16/a-game-of-chance-that-pirates-like-to-play.aspx"&gt;HDi&lt;/a&gt;. There have been several posts about the &lt;a href="http://blogs.msdn.com/ptorr/archive/2006/04/11/573572.aspx"&gt;Pet Shop Boys&lt;/a&gt; and then there was &lt;a href="http://blogs.msdn.com/ptorr/archive/2004/12/20/327511.aspx"&gt;this little post&lt;/a&gt;, too. That's the cool thing about Microsoft; you work on one thing for a while, and if it doesn't work out (or if you decide you want to try something new) then you just go do it.
&lt;/p&gt;&lt;p&gt;One thing's for sure – I'm not about to start posting about BD-J authoring :-)
&lt;/p&gt;&lt;p&gt;I still have a few &lt;a href="http://blogs.msdn.com/ptorr/archive/2008/01/29/fun-friends-for-functions.aspx"&gt;script-based posts&lt;/a&gt; to finish, but after that I don't know how often I will update the blog because most likely I will be working on the Next Big Thing, and most likely that won't be public (and thus not blog-able). Anyway, thanks for reading and if you choose to stick around then maybe I'll post something cool again in a few months...
&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.hddvdforever.com/"&gt;http://www.hddvdforever.com/&lt;/a&gt;
	&lt;/p&gt;&lt;p&gt;Peter.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7822373" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Randomness/default.aspx">Randomness</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HD+DVD/default.aspx">HD DVD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HDi/default.aspx">HDi</category></item><item><title>Fun Friends for Functions, Part 2: Handling Exceptions</title><link>http://blogs.msdn.com/ptorr/archive/2008/02/01/fun-friends-for-functions-part-2-handling-exceptions.aspx</link><pubDate>Sat, 02 Feb 2008 04:24:40 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7380450</guid><dc:creator>ptorr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/7380450.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=7380450</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=7380450</wfw:comment><description>&lt;p&gt;Previously we looked at how you can &lt;a href="http://blogs.msdn.com/ptorr/archive/2008/01/29/fun-friends-for-functions.aspx"&gt;bind a function to a set of arguments&lt;/a&gt; and then call the resultant function at some time in the future. This technique is very powerful, but as-is it is a ticking bomb. As Amy points out in her &lt;a href="http://blogs.msdn.com/amyd/archive/2007/12/07/exception-handling.aspx"&gt;blog post on exception handling&lt;/a&gt;, you always need to be prepared to handle an exception in your code. Failure to catch an exception usually leads to playback stopping and an error diagnostic from your player.
&lt;/p&gt;&lt;p&gt;The trouble is that when you start using bound functions, you don't always have an easy way to deal with exceptions. Typically, a bound function is used as part of an asynchronous callback, and in those cases you don't have any functions further up the stack to save you from unhandled errors. Simple, you might think, I'll just wrap the contents of my function in a try-catch and be done with it.
&lt;/p&gt;&lt;p&gt;Not so fast.
&lt;/p&gt;&lt;p&gt;Let's look at the example function we were using in the previous blog post:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to set a backgroundImage&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; SetBackgroundImage(markupId, url)&lt;br/&gt;{&lt;br/&gt;  document[markupId].style.backgroundImage = url;&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;This could throw for several reasons – for example, an element with the &lt;strong&gt;markupId&lt;/strong&gt; doesn't exist, or &lt;strong&gt;url&lt;/strong&gt; isn't a correctly-formatted property value. Simply wrapping this up in a try-catch would result in something like this:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to set a backgroundImage&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; SetBackgroundImage(markupId, url)&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:blue"&gt;try&lt;br/&gt;&lt;/span&gt;  {&lt;br/&gt;    document[markupId].style.backgroundImage = url;&lt;br/&gt;  }&lt;br/&gt;  &lt;span style="color:blue"&gt;catch&lt;/span&gt;(ex)&lt;br/&gt;  {&lt;br/&gt;    &lt;span style="color:green"&gt;// What do we do here?!?&lt;br/&gt;&lt;/span&gt;  }&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;But there's a problem – what do we do when we catch the exception? I don't know. And that's a key thing about exception handling:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;strong&gt;Functions should only handle exceptions if they are &lt;em&gt;actually prepared to deal with them&lt;/em&gt;. If a function doesn't know what to do in an error condition, it should let its caller figure it out. The exception [groan] to this rule is that your top-level code should &lt;em&gt;always&lt;/em&gt; swallow exceptions (unless of course things are so out of whack that you think the player should stop immediately).
&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;In this case, the &lt;strong&gt;SetBackgroundImage&lt;/strong&gt; function has no idea what a failure means. It might be perfectly OK if the background image can't be set correctly, or it could be totally disastrous. It all depends on the context, so the &lt;strong&gt;SetBackgroundImage&lt;/strong&gt; function should remain silent on the topic of exceptions and let the calling function figure out what (if anything) to do with them.
&lt;/p&gt;&lt;p&gt;In our particular case, let's say that the exception is benign; we are simply updating some eye-candy graphics and it doesn't matter if they fail to appear. So then: maybe we should write a wrapper function, &lt;strong&gt;SafeSetBackgroundImage&lt;/strong&gt;, that does this for us?
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to set a backgroundImage, ignoring exceptions&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; SafeSetBackgroundImage(markupId, url)&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:blue"&gt;try&lt;br/&gt;&lt;/span&gt;  {&lt;br/&gt;    SetBackgroundImage(markupId, url);&lt;br/&gt;  }&lt;br/&gt;  &lt;span style="color:blue"&gt;catch&lt;/span&gt;(ex) { }&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;I actually like to use this approach if I am going to be calling the 'Safe' version in a lot of different places, but if it is only in one or two places that seems like too much overhead to someone lazy like me. Anytime you update the parameter list of the wrapped function, you have to update the wrappers, too. It can also hide the intent of your code by sprinkling endless wrapper functions all over the place, and this also has the productivity-reducing effect of polluting IntelliSense with unnecessary function names. Instead, we can use the same kind of nested-function trick we used in the argument-binding case to get a "safe" version of any function:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// return a version of a function that is wrapped in try-catch&lt;br/&gt;// you can optionally provide an errorFunc, which will be&lt;br/&gt;// called with the 'tag' parameter in case of an exception&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; Function_WrapInTryCatch(errorFunc, tag)&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:green"&gt;// stash the target function&lt;br/&gt;&lt;/span&gt;  &lt;span style="color:blue"&gt;var&lt;/span&gt; func = &lt;span style="color:blue"&gt;this&lt;/span&gt;;
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;  &lt;span style="color:green"&gt;// return the nested function&lt;br/&gt;&lt;/span&gt;  &lt;span style="color:blue"&gt;return&lt;/span&gt; wrappedFunction;
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;  &lt;span style="color:blue"&gt;function&lt;/span&gt; wrappedFunction()&lt;br/&gt;  {&lt;br/&gt;    &lt;span style="color:green"&gt;// wrap the original function in a try-catch&lt;br/&gt;&lt;/span&gt;    &lt;span style="color:blue"&gt;try&lt;br/&gt;&lt;/span&gt;    {&lt;br/&gt;      func();&lt;br/&gt;    }&lt;br/&gt;    &lt;span style="color:blue"&gt;catch&lt;/span&gt; (ex)&lt;br/&gt;    {&lt;br/&gt;      &lt;span style="color:green"&gt;// call the errorFunc if it was provided&lt;br/&gt;&lt;/span&gt;      &lt;span style="color:green"&gt;// note this MUST be resilient to errors; if it throws&lt;br/&gt;&lt;/span&gt;      &lt;span style="color:green"&gt;// then it is game over.&lt;br/&gt;&lt;/span&gt;      &lt;span style="color:blue"&gt;if&lt;/span&gt; (&lt;span style="color:blue"&gt;typeof&lt;/span&gt; errorFunc == &lt;span style="color:#a31515"&gt;"function"&lt;/span&gt;)&lt;br/&gt;      {&lt;br/&gt;        errorFunc(ex, tag);&lt;br/&gt;      }&lt;br/&gt;    }&lt;br/&gt;  }&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;Function.prototype.WrapInTryCatch = Function_WrapInTryCatch;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;In this example, we also allow the caller of the &lt;strong&gt;WrapInTryCatch&lt;/strong&gt; function to provide an optional error-handling function that will be called if an error occurs. This allows you to do things like channel all your async exceptions to the same error handling function, which can figure out what to do based on the value of the &lt;strong&gt;tag&lt;/strong&gt; parameter. Now we can re-write the last couple of lines of the example as:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// Call the download function, passing in the set-image function as the callback handler&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;var&lt;/span&gt; setBackgroundHandler = SetBackgroundImage.BindToArguments(&lt;span style="color:#a31515"&gt;"button1"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"file:///filecache/bar.png"&lt;/span&gt;);&lt;br/&gt;&lt;span style="color:blue"&gt;var&lt;/span&gt; wrappedHandler = setBackgroundHandler.WrapInTryCatch();&lt;br/&gt;DownloadFile(&lt;span style="color:#a31515"&gt;"http://foo/bar.png"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"file:///filecache/bar.png"&lt;/span&gt;, wrappedHandler);
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;This helper has the same limitations as the &lt;strong&gt;BindToArguments&lt;/strong&gt; function (specifically: you can't pass any arguments to the returned function, and any tracing information is lost if 'errorFunc' is called) but this is also a solvable problem.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7380450" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HDi/default.aspx">HDi</category></item><item><title>Fun Friends For Functions</title><link>http://blogs.msdn.com/ptorr/archive/2008/01/29/fun-friends-for-functions.aspx</link><pubDate>Wed, 30 Jan 2008 03:45:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7315751</guid><dc:creator>ptorr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/7315751.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=7315751</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=7315751</wfw:comment><description>&lt;p&gt;And now for a more techy post. In ECMAScript, functions are considered first-class objects. "What," you might ask, "differentiates a 'first-class' object from a merely 'economy-class' object?" Well, the main thing is that functions in ECMAScript are treated just like any other type of data (strings, numbers, arrays, etc.) in that they can be assigned to variables, they can be passed as function arguments, and they can have properties and methods of their own. They also have a prototype object, just like all other ECMAScript objects. The upshot of this is that you can do fun things with functions in ECMAScript that you can't do in other languages such as C or Java.
&lt;/p&gt;&lt;p&gt;In this entry I will introduce four types of "helper" functions that are ideally suited to HDi development. They are:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Binding a function to a set of arguments and / or a 'this' object
&lt;/li&gt;&lt;li&gt;Wrapping an existing function in an exception handler
&lt;/li&gt;&lt;li&gt;Chaining function calls together one after the other
&lt;/li&gt;&lt;li&gt;Calling a function after a specified period of time
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In all cases, you write the actual function (the one that does the interesting work) just as you normally would, but when it comes time to call that function you do something funky with it to make some magic happen. Exactly why you might want to do this will become clearer soon, but it mostly comes down to how you write event handlers and callbacks.
&lt;/p&gt;&lt;p&gt;A common theme in this post will be that you want to &lt;a href="http://blogs.msdn.com/ptorr/archive/2007/08/29/using-timers-effectively-in-hdi.aspx"&gt;avoid closures&lt;/a&gt; as much as possible, and using these helpers should get you a long way to doing that (even though these helper functions rely on closures, they do so in a "safe" manner). And although there are various ad-hoc ways to accomplish the same tasks, generally these require writing specialised wrapper functions or following ugly coding practices (which I might blog about in the future) when what I would prefer to focus on is writing highly readable, highly re-usable code and utilising some clever, general-purpose helper functions to take care of all the tricky dirty work.
&lt;/p&gt;&lt;h3&gt;Binding to arguments
&lt;/h3&gt;&lt;p&gt;Many operations in HDi use a callback function to notify you when a specific task is completed (such as a File I/O operation or an event handler). Oftentimes you will want to associate more information with your callback than the HDi API actually allows for, and there are a couple of ways to accomplish this. But first, an example: 
&lt;/p&gt;&lt;p&gt;Say you have an application where you want to dynamically download some images from the network and display them inside a markup page. The basic code you want to write is probably like this (the code is simplified for clarity; obviously there is some additional code to convert the &lt;strong&gt;onStateChange&lt;/strong&gt; callback into a single "the download is complete" call, etc.):
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to download an image&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; DownloadImage(src, dest)&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:blue"&gt;var&lt;/span&gt; httpClient = Network.createHttpClient(src, dest);&lt;br/&gt;  httpClient.onStateChange = SetBackgroundImage;&lt;br/&gt;  httpClient.send();&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to set a backgroundImage&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; SetBackgroundImage(markupId, url)&lt;br/&gt;{&lt;br/&gt;  document[markupId].style.backgroundImage = url;&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// call the download function... but what next?&lt;br/&gt;&lt;/span&gt;DownloadImage(&lt;span style="color:#a31515"&gt;"http://foo/bar.png"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"file:///filecache/bar.png"&lt;/span&gt;);
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Note that both functions have been written to be "highly readable, highly re-usable" and do one thing in a very straight-forward manner. The problem, of course, is that this code won't work because there is no way for the callback to &lt;strong&gt;SetBackgroundImage&lt;/strong&gt; to communicate what &lt;strong&gt;markupId&lt;/strong&gt; or the final download &lt;strong&gt;url&lt;/strong&gt; is supposed to be. 
&lt;/p&gt;&lt;p&gt;One common way of solving this problem is to use a nested function, like this:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to download an image and set it as the background URL&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; DownloadBackgroundImage(src, dest, markupId)&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:blue"&gt;var&lt;/span&gt; httpClient = Network.createHttpClient(src, dest);&lt;br/&gt;  httpClient.onStateChange = SetBackgroundImage;&lt;br/&gt;  httpClient.send();
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;  &lt;span style="color:green"&gt;// nested function to set a backgroundImage&lt;br/&gt;&lt;/span&gt;  &lt;span style="color:blue"&gt;function&lt;/span&gt; SetBackgroundImage()&lt;br/&gt;  {&lt;br/&gt;    document[markupId].style.backgroundImage = dest;
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;    &lt;span style="color:green"&gt;// Clean up the memory&lt;br/&gt;&lt;/span&gt;    httpClient = &lt;span style="color:blue"&gt;null&lt;/span&gt;;&lt;br/&gt;  }&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// call the download function and update the element 'button1'&lt;br/&gt;&lt;/span&gt;DownloadBackgroundImage(&lt;span style="color:#a31515"&gt;"http://foo/bar.png"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"file:///filecache/bar.png"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"button1"&lt;/span&gt;);
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Note that even though we've done work to ensure the closure won't memory leak memory, there is still at big problem in that neither the download function nor the background setting function are generic any more. If you want to (eg) download an XML file, or if you want to set the backgroundImage to a file on persistent storage, you will need to either add some more hacks to this function (making it less readable and less maintainable) or you will need to duplicate the code into a similar-but-not-entirely-the-same function.
&lt;/p&gt;&lt;p&gt;The solution I prefer is to use the fact that functions are first-class objects and solve this problem using "argument binding." In this case, the code would be re-written as follows:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to download a file and then call 'handler' when it is done&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; DownloadFile(src, dest, handler)&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:blue"&gt;var&lt;/span&gt; httpClient = Network.createHttpClient(src, dest);&lt;br/&gt;  httpClient.onStateChange = handler;&lt;br/&gt;  httpClient.send();&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// function to set a backgroundImage&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; SetBackgroundImage(markupId, url)&lt;br/&gt;{&lt;br/&gt;  document[markupId].style.backgroundImage = url;&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// Call the download function, passing in the set-image function as the callback handler&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;var&lt;/span&gt; setBackgroundHandler = SetBackgroundImage.BindToArguments(&lt;span style="color:#a31515"&gt;"button1"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"file:///filecache/bar.png"&lt;/span&gt;);&lt;br/&gt;DownloadFile(&lt;span style="color:#a31515"&gt;"http://foo/bar.png"&lt;/span&gt;, &lt;span style="color:#a31515"&gt;"file:///filecache/bar.png"&lt;/span&gt;, setBackgroundHandler);
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;Now both the download function and the set-image function are still written in a clear, simple, re-usable fashion, but we can easily chain them together to get the desired result. Even the call that makes this possible (the &lt;strong&gt;BindToArguments&lt;/strong&gt; call) is straight-forward and understandable. All that is missing is the magic &lt;strong&gt;BindToArguments&lt;/strong&gt; helper function... which looks like this:
&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;
 &lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// helper function to return a copy of the target function, but&lt;br/&gt;// bound to the original arguments&lt;br/&gt;&lt;/span&gt;&lt;span style="color:blue"&gt;function&lt;/span&gt; Function_BindToArguments()&lt;br/&gt;{&lt;br/&gt;  &lt;span style="color:green"&gt;// store a reference to the target function and its arguments&lt;br/&gt;&lt;/span&gt;  &lt;span style="color:blue"&gt;var&lt;/span&gt; storedFunction = &lt;span style="color:blue"&gt;this&lt;/span&gt;;&lt;br/&gt;  &lt;span style="color:blue"&gt;var&lt;/span&gt; storedArguments = arguments;
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;  &lt;span style="color:green"&gt;// return the nested function&lt;br/&gt;&lt;/span&gt;  &lt;span style="color:blue"&gt;return&lt;/span&gt; boundFunction;
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;  &lt;span style="color:green"&gt;// nested function simply invokes the stashed values&lt;br/&gt;&lt;/span&gt;  &lt;span style="color:blue"&gt;function&lt;/span&gt; boundFunction()&lt;br/&gt;  {&lt;br/&gt;    storedFunction.apply(&lt;span style="color:blue"&gt;null&lt;/span&gt;, storedArguments);&lt;br/&gt;  }&lt;br/&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:green"&gt;// make the helper available to all functions&lt;br/&gt;&lt;/span&gt;Function.prototype.BindToArguments = Function_BindToArguments;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;As noted in the comments, this helper function simply stores a reference to the "target" function and the arguments that are passed to the &lt;strong&gt;BindToArguments&lt;/strong&gt; call. Then it returns a nested function, which when called will invoke the stored function (&lt;strong&gt;SetBackgroundImage&lt;/strong&gt;) with the stored arguments (&lt;strong&gt;"button1"&lt;/strong&gt; and &lt;strong&gt;"file:///filecache/bar.png"&lt;/strong&gt;). Note that the &lt;strong&gt;apply&lt;/strong&gt; function is a built-in function of ECMAScript Function objects that invokes a given function with the specified 'this' object and arguments array.
&lt;/p&gt;&lt;p&gt;This is the most basic form of a "binding" helper, and the resultant function is one that has no 'this' object and that cannot take any arguments of its own. It also can't participate in a typical &lt;a href="http://blogs.msdn.com/ptorr/archive/2007/06/27/helpful-tracing-routines.aspx"&gt;logging infrastructure&lt;/a&gt; because much of the required metadata (original function name, number of expected arguments, etc.) is missing. The good news is that all this can be added with the help of more code, and hopefully that's something I'll be posting soon. 
&lt;/p&gt;&lt;p&gt;As usual, this is longer (and took longer) to write, so I'll have to save the other "friends" for later. The depressing thing is that actually writing the code is the easy part (and it's all done already); it's wrapping it all up in a post and explaining how things work that take forever!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7315751" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HDi/default.aspx">HDi</category></item><item><title>HD DVD Emulator for Xbox 360!</title><link>http://blogs.msdn.com/ptorr/archive/2007/12/13/hd-dvd-emulator-for-xbox-360.aspx</link><pubDate>Fri, 14 Dec 2007 04:22:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6766599</guid><dc:creator>ptorr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/6766599.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=6766599</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=6766599</wfw:comment><description>&lt;p&gt;It's finally here! &lt;a href="http://www.thisishddvd.com/emulator/details.aspx"&gt;The Xbox 360 HD DVD Emulator&lt;/a&gt; went live today, enabling content authors to test their HD DVD content in a real-world consumer player before committing it to a shiny disc. This can save a &lt;strong&gt;lot&lt;/strong&gt; of time and a &lt;strong&gt;lot&lt;/strong&gt; of money for those folks building advanced HD DVD titles. It might help you save your hair, too :-)
&lt;/p&gt;&lt;p&gt;"But," you might be saying, "doesn't Microsoft already ship an &lt;a href="http://blogs.msdn.com/amyd/archive/2007/04/11/getting-started-with-hd-dvd.aspx"&gt;HD DVD Simulator&lt;/a&gt; for free? Why would I want this emulator?"
&lt;/p&gt;&lt;p&gt;Good question. Here are just a few reasons why:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The simulator only plays Windows Media files, and poorly at that. The emulator plays real multiplexed EVOB files (with VC-1 and AVC and TrueHD etc.) that you will ship on the real disc.
&lt;/li&gt;&lt;li&gt;The simulator doesn't support subtitles or multiple audio tracks. The emulator does, enabling you to actually test them.
&lt;/li&gt;&lt;li&gt;The simulator shows you how your code performs on your desktop PC. The emulator shows you how it performs on real shipping hardware.
&lt;/li&gt;&lt;li&gt;The simulator has some primitive logging functionality, but you need to &lt;a href="http://blogs.msdn.com/ptorr/archive/2007/06/27/helpful-tracing-routines.aspx"&gt;do some work yourself&lt;/a&gt;. The emulator has very robust logging for all aspects of HDi playback (including markup timing!).
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;There are obviously more reasons to use the emulator, but that's a quick rundown of some of the key reasons why you might want to do it. Of course the simulator is still great for doing early title development – where access to real video and multiple audio tracks might not matter – because using the PC enables a great edit-run-debug workflow. But the emulator is absolutely critical for putting everything together, fine-tuning your code, verifying performance and compatibility, and running a through a thorough test pass prior to check-disc replication.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6766599" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/HD+DVD/default.aspx">HD DVD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HDi/default.aspx">HDi</category></item><item><title>Simple ACA dumper</title><link>http://blogs.msdn.com/ptorr/archive/2007/07/05/simple-aca-dumper.aspx</link><pubDate>Fri, 06 Jul 2007 00:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3713342</guid><dc:creator>ptorr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/3713342.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=3713342</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=3713342</wfw:comment><description>&lt;P&gt;Quick one today – if you have an ACA with some files in it, you can use the &lt;STRONG&gt;createaca&lt;/STRONG&gt; tool (provided as part of the &lt;A href="http://blogs.msdn.com/amyd/archive/2007/04/11/getting-started-with-hd-dvd.aspx" mce_href="http://blogs.msdn.com/amyd/archive/2007/04/11/getting-started-with-hd-dvd.aspx"&gt;Jumpstart Kit&lt;/A&gt;) to list the files inside it. Trouble is that the output is not very helpful; it contains too much information. &lt;/P&gt;
&lt;P&gt;So here is a simple JScript file you can run on the output of &lt;STRONG&gt;createaca -r&lt;/STRONG&gt; to just dump the filenames (and it checks for duplicates, too!). Just copy to &lt;STRONG&gt;dumpaca.js&lt;/STRONG&gt; (or the file of your choice) and run it from a command prompt. It expects a file named &lt;STRONG&gt;filelist.txt&lt;/STRONG&gt; to exist in the same folder. Modifications to do whatever you want to do should be trivial... &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Open file named "filelist.txt"&lt;BR&gt;‎&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; fso = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; ActiveXObject(&lt;SPAN style="COLOR: #a31515"&gt;"Scripting.FileSystemObject"&lt;/SPAN&gt;);&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; stream = fso.OpenTextFile(&lt;SPAN style="COLOR: #a31515"&gt;"filelist.txt"&lt;/SPAN&gt;);&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; contents = stream.ReadAll(); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Regular expression to search for DATA_FNAME followed by a name&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; re =/DATA_FNAME : ((?:\w|\.)+)/g; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Lists of result data&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; names = {};&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; nameList = [];&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; result;&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; dupes = []; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Search for every instance of the regular expression&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;while&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt; != (result = re.exec(contents)))&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; name = result[1]; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// Record dupes&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (names[name] != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dupes.push(name);&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// else record new values&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;else&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;names[name] = nameList.length;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nameList.push(name);&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Print results&lt;BR&gt;&lt;/SPAN&gt;print(&lt;SPAN style="COLOR: #a31515"&gt;"---------- Complete file list ----------"&lt;/SPAN&gt;); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; i &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; nameList)&lt;BR&gt;&amp;nbsp;&amp;nbsp;print(nameList[i]); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Print dupes&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (dupes.length &amp;gt; 0)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;print(&lt;SPAN style="COLOR: #a31515"&gt;"---------- Duplicate file names ----------"&lt;/SPAN&gt;); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; j &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; dupes)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(dupes[j]);&lt;BR&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Helper&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; print(s) { WScript.Echo(String(s)); }&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3713342" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HDi/default.aspx">HDi</category></item><item><title>Helpful Tracing Routines</title><link>http://blogs.msdn.com/ptorr/archive/2007/06/27/helpful-tracing-routines.aspx</link><pubDate>Wed, 27 Jun 2007 11:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3561879</guid><dc:creator>ptorr</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/3561879.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=3561879</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=3561879</wfw:comment><description>&lt;P&gt;Last time we looked at &lt;A class="" title="Open blog post on conditional compilation" href="http://blogs.msdn.com/ptorr/archive/2007/06/01/using-conditional-compilation-in-hdi.aspx" mce_href="http://blogs.msdn.com/ptorr/archive/2007/06/01/using-conditional-compilation-in-hdi.aspx"&gt;conditional compilation&lt;/A&gt;, and how using it with HDiSim could aid with interactive debugging of runtime exceptions. But as useful as interactive debugging is, there are three major cases where it is impractical or impossible: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;When the bug is timing related, and using a debugger masks the bug; or &lt;/LI&gt;
&lt;LI&gt;Reproducing the bug requires running a large amount of code it's impractical or laborious to step through by hand; or &lt;/LI&gt;
&lt;LI&gt;You're trying to track down an issue on a real player (which you can't debug on). &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;In these cases, it is very useful to have some robust tracing primitives built in to your code to give you a trace (or log) of everything that the player is doing up until the time the bug occurs. I already posted a while back on &lt;A class="" title="Open blog on red-box debugging" href="http://blogs.msdn.com/ptorr/archive/2007/02/01/red-box-debugging.aspx" mce_href="http://blogs.msdn.com/ptorr/archive/2007/02/01/red-box-debugging.aspx"&gt;red box debugging&lt;/A&gt;, and how that relates to &lt;STRONG&gt;printf&lt;/STRONG&gt; debugging; now we're going to add some more &lt;STRONG&gt;printf&lt;/STRONG&gt;-like tracing to our HDi toolkit to help diagnose issues on retail players or to trace errors through the system in critical timing sections. &lt;/P&gt;
&lt;P&gt;The general approach is to pepper our code with calls to a &lt;STRONG&gt;trace()&lt;/STRONG&gt; function that will either write the trace info to a log file, or display it on the screen, or both. Usually the trace function will be called when execution enters a new function, when an exception is handled, and at any other point in time where it is useful to know the result of a test or the value of a particular variable or property. Now, the key to any good trace log is the ability to identify the &lt;EM&gt;function&lt;/EM&gt; that was active at the time a given log entry was made. Whilst it is possible to hard-code the name of the function into the trace call (for example, &lt;STRONG&gt;trace("Inside function 'foo'")&lt;/STRONG&gt;), this is problematic because any time you re-name a function (or copy-and-paste it to a new function) you need to update the function name in the script. It would be much better if you could somehow automatically get the function name... &lt;/P&gt;
&lt;P&gt;Enter the &lt;STRONG&gt;GetFunctionName&lt;/STRONG&gt; function, defined like this: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Returns the name of a function &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; GetFunctionName(func)&lt;BR&gt;{&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; try&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp; {&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;/SPAN&gt; re = /&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt;\s+(\w+)/;&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;/SPAN&gt; s = re.exec(func.toString())[1]; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Based on naming convention of 'object_FunctionName'&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/SPAN&gt; (s.indexOf(&lt;SPAN style="COLOR: maroon"&gt;"_"&lt;/SPAN&gt;) &amp;gt;= 0)&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt; s.substring(s.indexOf(&lt;SPAN style="COLOR: maroon"&gt;"_"&lt;/SPAN&gt;)); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt; s;&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; catch&lt;/SPAN&gt;(ex) { ; } &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; return&lt;/SPAN&gt; &lt;SPAN style="COLOR: maroon"&gt;"AnonymousOrUnknownFunction"&lt;/SPAN&gt;;&lt;BR&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Given a &lt;STRONG&gt;Function&lt;/STRONG&gt; object as its only argument, this function will return the name of the function (or the string &lt;STRONG&gt;"AnonymousOrUnknownFunction"&lt;/STRONG&gt; if the function name is not available – for example, you pass in a function expression or a native method). It does this by creating a Regular Expression &lt;STRONG&gt;re&lt;/STRONG&gt; that looks for the word &lt;STRONG&gt;"function"&lt;/STRONG&gt; followed by some whitespace &lt;STRONG&gt;\s+&lt;/STRONG&gt; and then a word &lt;STRONG&gt;(\w+)&lt;/STRONG&gt;. If the word is found, it is "captured" (because it is in parentheses) and returned by the expression &lt;STRONG&gt;re.exec(...)[1]&lt;/STRONG&gt;. The &lt;STRONG&gt;toString&lt;/STRONG&gt; call inside of &lt;STRONG&gt;exec&lt;/STRONG&gt; simply converts the &lt;STRONG&gt;Function&lt;/STRONG&gt; object into an implementation-defined representation of the function body, but ECMA 262 defines that at a minimum this contains the function name (ie, it is a &lt;EM&gt;FunctionDeclaration&lt;/EM&gt;). &lt;/P&gt;
&lt;P&gt;OK, that's kind of useful, but how do you get the right &lt;STRONG&gt;Function&lt;/STRONG&gt; object to pass to the &lt;STRONG&gt;GetFunctionName&lt;/STRONG&gt; function? Good question. The answer is that you use the &lt;STRONG&gt;arguments&lt;/STRONG&gt; object, and in particular the &lt;STRONG&gt;callee&lt;/STRONG&gt; property; it holds a reference to the function being called. Neato, eh? &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;I want to take a quick detour here to say that I &lt;EM&gt;personally&lt;/EM&gt; think that &lt;SPAN style="TEXT-DECORATION: underline"&gt;relying on the &lt;STRONG&gt;arguments&lt;/STRONG&gt; object as a way of passing parameters to a function is a bad programming practice&lt;/SPAN&gt; and should be avoided for normal development; I won't bore you with all the details, but basically it makes your code harder to read (and thus harder to understand) if all the expected parameters aren't immediately obvious from the function's declaration. Nevertheless, the &lt;STRONG&gt;arguments&lt;/STRONG&gt; object is great for &lt;EM&gt;tracing&lt;/EM&gt;, and so we shall use it for this. &lt;/P&gt;
&lt;P&gt;So while we're on the subject of the &lt;STRONG&gt;arguments&lt;/STRONG&gt; object, it's also worth noting that it's a great way to trace the arguments passed to a function in a generic way (again, avoiding the copy-and-paste problem, or having to keep up with added or removed parameters). To do this, we'll write another function (and a little helper) that can be used to generate a string holding the value of all the arguments passed to a function. It looks like this: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;// Returns a string representing the arguments list of a function&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; GetArgumentsString(args) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; var&lt;/SPAN&gt; s = &lt;SPAN style="COLOR: maroon"&gt;"("&lt;/SPAN&gt;;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; var&lt;/SPAN&gt; first = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; i = 0; i &amp;lt; args.length; i++)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/SPAN&gt; (first != &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s += &lt;SPAN style="COLOR: maroon"&gt;", "&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; first = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;/SPAN&gt; arg = args[i];&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s += ObjectToString(arg);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; } &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; s += &lt;SPAN style="COLOR: maroon"&gt;")"&lt;/SPAN&gt;;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; return&lt;/SPAN&gt; s;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Returns a string representation of an object;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; ObjectToString(obj)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; try&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(obj) == &lt;SPAN style="COLOR: maroon"&gt;"function"&lt;/SPAN&gt;)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt; &lt;SPAN style="COLOR: maroon"&gt;"function "&lt;/SPAN&gt; + GetFunctionName(obj); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(obj) == &lt;SPAN style="COLOR: maroon"&gt;"string"&lt;/SPAN&gt;)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt; &lt;SPAN style="COLOR: maroon"&gt;"\""&lt;/SPAN&gt; + obj + &lt;SPAN style="COLOR: maroon"&gt;"\""&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt; String(obj);&amp;nbsp;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; }&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; catch&lt;/SPAN&gt;(ex)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt; &lt;SPAN style="COLOR: maroon"&gt;"[native Object]"&lt;/SPAN&gt;;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; }&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Together these two functions will take an &lt;STRONG&gt;arguments&lt;/STRONG&gt; object and return a string that contains all their values, including special handling for functions and native (host) objects. Now we can build a simple function that is used to trace function entry like this: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Global to define whether to do tracing or not; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Tracing can be expensive so you might not want to do it on a released title &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; _DO_TRACE = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Trace function name and argument list &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; TraceFunctionEntry(args)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;{&lt;BR&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;// Bail immediately if tracing is not desired&lt;/SPAN&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; if&lt;/SPAN&gt; (_DO_TRACE != &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; var&lt;/SPAN&gt; name = GetFunctionName(args.callee);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; var&lt;/SPAN&gt; argString = GetArgumentsString(args);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; TraceString(name + argString);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And we can use the &lt;STRONG&gt;TraceFunctionEntry&lt;/STRONG&gt; function like this: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; MyFunction(a, b, c)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; TraceFunctionEntry(arguments); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp; // Do some actual work...&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Now we just need to define the &lt;STRONG&gt;TraceString&lt;/STRONG&gt; function; but that's the easy part ;-) &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Global startup code to open the diagnostics file, if necessary.&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (_DO_TRACE)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; try&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Diagnostics.listeners.add(&lt;SPAN style="COLOR: maroon"&gt;"file"&lt;/SPAN&gt;);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Diagnostics.trace.autoFlush = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; } &lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt; (ex) { }&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Lucida Console"&gt;// Function to trace a message to the diagnostics log and, if available,&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;// an on-screen input.&lt;/SPAN&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; TraceString(msg)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;{&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; if&lt;/SPAN&gt; (_DO_TRACE != &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp; // Write out the message to the diagnostics log&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; try&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Diagnostics.trace.writeLine(msg, &lt;SPAN style="COLOR: maroon"&gt;"Trace"&lt;/SPAN&gt;, 1);&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; } &lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt; (ex) { } &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp; // Try to add the message to an &amp;lt;input&amp;gt; named 'trace', if one exists&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp; try&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp; {&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;/SPAN&gt; node = document.trace;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/SPAN&gt; (node != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt; &amp;amp;&amp;amp; node.nodeName == &lt;SPAN style="COLOR: maroon"&gt;"input"&lt;/SPAN&gt;)&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; node.state.value = node.state.value + &lt;SPAN style="COLOR: maroon"&gt;" | "&lt;/SPAN&gt; + msg; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;&amp;nbsp;&amp;nbsp;} &lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt; (ex) { }&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Lucida Console"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And there you have it! I have &lt;A class="" title="Download tracing sample" href="http://blogs.msdn.com/ptorr/attachment/3561879.ashx" mce_href="http://blogs.msdn.com/ptorr/attachment/3561879.ashx"&gt;attached a sample project&lt;/A&gt; that includes a couple of other helpful tracing aids (one for errors, one for informational tracing). As usual, you need to copy a file named &lt;STRONG&gt;font.ttf&lt;/STRONG&gt; into the &lt;STRONG&gt;ADV_OBJ&lt;/STRONG&gt; folder in order for it to work (I use the "Kooteny" sample font from the HDiSim download). &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3561879" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/ptorr/attachment/3561879.ashx" length="4237" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HD+DVD/default.aspx">HD DVD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>Using Conditional Compilation in HDi </title><link>http://blogs.msdn.com/ptorr/archive/2007/06/01/using-conditional-compilation-in-hdi.aspx</link><pubDate>Sat, 02 Jun 2007 05:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3034398</guid><dc:creator>ptorr</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/3034398.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=3034398</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=3034398</wfw:comment><description>&lt;P&gt;One of the cardinal rules for developing HD DVD applications is, &lt;EM&gt;"let no exception go unhandled." &lt;/EM&gt;The reason for this is simple – if you fail to handle an exception, the player will kill your application and stop the disc. This leads many developers to wrap entire functions in &lt;STRONG&gt;try / catch&lt;/STRONG&gt; blocks, which solves the problem but introduces some of its own. &lt;/P&gt;
&lt;P&gt;To me, one of the biggest problems with using &lt;STRONG&gt;try / catch&lt;/STRONG&gt; during development is that it makes debugging script with Visual Studio virtually impossible. For a start, you can't rely on "just-in-time" (JIT) debugging to work because you never have any unhandled exceptions. Additionally, even if you manually attach the debugger and step through your code line by line, as soon as there is an exception it will dump you out at the &lt;STRONG&gt;catch&lt;/STRONG&gt; handler, losing all the context information you might need to fix the bug (stack trace, local variables, even the location in the source file). &lt;/P&gt;
&lt;P&gt;As an example, try this script (run it under WSH with the command-line &lt;STRONG&gt;cscript //x test.js&lt;/STRONG&gt;) and step through each line by hitting F11. Step over the &lt;STRONG&gt;PretendThisIsAPlatformAPI&lt;/STRONG&gt; function by hitting F10 instead. &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;// Hit F11 to step INTO each line &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: Courier New"&gt;try &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{ &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; foo(1) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt;(ex) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;WScript.Echo(ex) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; foo(x) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Imagine lots of complex code here...&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; y = x - 1 &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; bar(y) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; bar(x) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// More complex code here...&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; y = x / 2&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: green"&gt;// Hit F10 to step OVER this function&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;PretendThisIsAPlatformAPI(y) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; PretendThisIsAPlatformAPI(x) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (x &amp;lt;= 0)&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;throw&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"bad parameter value"&lt;/SPAN&gt;) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Note that everything is fine until you call that fake platform API. Then you are dumped back into the &lt;STRONG&gt;catch&lt;/STRONG&gt; block of the global code with a message saying "bad parameter value." But what &lt;EM&gt;was&lt;/EM&gt; the parameter value I passed to the function? I can't find out, because all the context (the stack frames for &lt;STRONG&gt;bar&lt;/STRONG&gt; and &lt;STRONG&gt;foo&lt;/STRONG&gt;) has been removed. &lt;/P&gt;
&lt;P&gt;Is the solution to remove the &lt;STRONG&gt;try / catch&lt;/STRONG&gt; block during development, then add it back at the last minute before shipping? &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;NO! &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;That is a recipe for disaster for at least two reasons: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;You might forget to put it back in &lt;/LI&gt;
&lt;LI&gt;You will never have tested your exception-handling code &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;There's a better approach, and it relies on a feature of Microsoft's JScript implementation that lets you "hide" parts of the script from JScript whilst making it clearly visible to normal ECMAScript engines. This allows you to toggle exception handling on or off during development (with HDiSim), whilst never risking having it turned off when you ship. &lt;/P&gt;
&lt;P&gt;This feature is called &lt;A href="http://msdn2.microsoft.com/en-us/library/ahx1z4fs(VS.80).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ahx1z4fs(VS.80).aspx"&gt;conditional compilation&lt;/A&gt;, and here's how we use it: &lt;/P&gt;
&lt;P&gt;The first thing to do is to activate conditional compilation. We do that like this – note how it is in an ECMAScript comment, so that other script engines will ignore the command: &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;//@cc_on &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Next, we define a conditional-compilation variable that will determine whether or not we want exception handling (note: you can name the variable anything you want; this isn't some magic value): &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;//@set @enable_exceptions = true &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Perhaps obviously, we set this to &lt;STRONG&gt;true&lt;/STRONG&gt; if we want to handle exceptions with &lt;STRONG&gt;try / catch&lt;/STRONG&gt;, and &lt;STRONG&gt;false&lt;/STRONG&gt; if we do not. &lt;/P&gt;
&lt;P&gt;Finally, we wrap our &lt;STRONG&gt;try&lt;/STRONG&gt; and &lt;STRONG&gt;catch&lt;/STRONG&gt; blocks with a conditional statement: &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;&lt;A&gt;//@if(@enable_exceptions&lt;/A&gt;) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: Courier New"&gt;try &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{ &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;&lt;A&gt;//@end&lt;/A&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;foo(1) &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;&lt;A&gt;//@if(@enable_exceptions&lt;/A&gt;) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt;(ex) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;WScript.Echo(ex) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: Courier New"&gt;//@end &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now, depending on the value of &lt;STRONG&gt;@enable_exceptions&lt;/STRONG&gt;, JScript either sees this source code (when &lt;STRONG&gt;true&lt;/STRONG&gt;): &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: Courier New"&gt;try &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;foo(1) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;catch&lt;/SPAN&gt;(ex) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;{&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;WScript.Echo(ex) &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;} &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Or this source code (when &lt;STRONG&gt;false&lt;/STRONG&gt;): &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; &lt;/SPAN&gt;foo(1) &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Non-JScript engines will &lt;EM&gt;always&lt;/EM&gt; see the former source code, because they simply treat the &lt;STRONG&gt;@if&lt;/STRONG&gt; statements as comments. That means they will always have &lt;STRONG&gt;try / catch&lt;/STRONG&gt; turned on, and is why I say it is impossible to "forget" to turn exception handling back on when you ship. &lt;/P&gt;
&lt;P&gt;During normal testing and development, you should leave &lt;STRONG&gt;@enable_exceptions&lt;/STRONG&gt; set to &lt;STRONG&gt;true&lt;/STRONG&gt;, because you &lt;EM&gt;need&lt;/EM&gt; to test your exception-handling code. But when you are trying to debug a problem caused by a thrown exception, you can set it to &lt;STRONG&gt;false&lt;/STRONG&gt; and use the JIT feature of Visual Studio to jump right to the line that is throwing the exception. &lt;EM&gt;You should then turn it back to &lt;STRONG&gt;true&lt;/STRONG&gt; again after you've finished debugging&lt;/EM&gt;, because it is possible that some players on Windows might use the JScript engine. Even then, this approach is better than manually adding and removing the exception-handling code from your applications since there's only one place in your code to do it, rather than every single location where you use &lt;STRONG&gt;try / catch&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;You can try this out now, by running the sample script again with exception handling turned on and off. In this case, instead of stepping through the file with F11, just hit F5 to run the program. When exception handling is turned on, you don't get any help from the VS debugger. When it's turned off, VS will break at the offending line so you can investigate the problem and determine the right fix. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Marvellous! &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Typically I have a single file, &lt;STRONG&gt;cc.js&lt;/STRONG&gt;, that I always include as the first &lt;STRONG&gt;&amp;lt;Script&amp;gt;&lt;/STRONG&gt; element in my manifest. It contains the &lt;STRONG&gt;@cc_on&lt;/STRONG&gt; statement and the &lt;STRONG&gt;@enable_exceptions&lt;/STRONG&gt; variable, along with any others I might decide to use. As part of your shipping process, you could decide to always remove this file (or replace it with one that forces &lt;STRONG&gt;@enable_exceptions &lt;/STRONG&gt;to &lt;STRONG&gt;true&lt;/STRONG&gt;) "just in case"...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3034398" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>link</title><link>http://blogs.msdn.com/ptorr/archive/2007/06/01/link.aspx</link><pubDate>Sat, 02 Jun 2007 04:07:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3033104</guid><dc:creator>ptorr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/3033104.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=3033104</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=3033104</wfw:comment><description>&lt;p&gt;No, not the &lt;strong&gt;application.link&lt;/strong&gt; API. A web link. Or two.
&lt;/p&gt;&lt;p&gt;Some of you may have noticed a new name on the &lt;a href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=527&amp;amp;SiteID=1"&gt;HD DVD Forums&lt;/a&gt; of late: &lt;strong&gt;Amy Dullard&lt;/strong&gt;. She also has a great blog that focuses on getting people up-and-running with HDi. Check it out at &lt;a href="http://blogs.msdn.com/amyd"&gt;http://blogs.msdn.com/amyd&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;Another person you might recognise from the Forums, &lt;strong&gt;Andy Pennell&lt;/strong&gt;, also has a blog at &lt;a href="http://blogs.msdn.com/andypennell/"&gt;http://blogs.msdn.com/andypennell/&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;And finally, the Microsoft "industry" site for HD DVD is &lt;a href="http://www.thisishddvd.com"&gt;http://www.thisishddvd.com&lt;/a&gt;. There's not much there now, but it should get better.
&lt;/p&gt;&lt;p&gt;OK, so three links. Four if you count the forums. But who didn't know that already?
&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3033104" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/HD+DVD/default.aspx">HD DVD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>A Game of Chance that Pirates like to Play</title><link>http://blogs.msdn.com/ptorr/archive/2007/05/16/a-game-of-chance-that-pirates-like-to-play.aspx</link><pubDate>Thu, 17 May 2007 01:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2682093</guid><dc:creator>ptorr</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/2682093.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=2682093</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=2682093</wfw:comment><description>&lt;P&gt;Ahoy there me laddies! Yarrrr you better be readin' this blog then matey, or you'll be feelin' the lick o' the cat come nightfall! &lt;/P&gt;
&lt;P&gt;No, it's not &lt;A href="http://en.wikipedia.org/wiki/International_Talk_Like_a_Pirate_Day" mce_href="http://en.wikipedia.org/wiki/International_Talk_Like_a_Pirate_Day"&gt;&lt;EM&gt;Talk Like a Pirate Day&lt;/EM&gt;&lt;/A&gt;; it's &lt;EM&gt;Let's Post Another HDi Game Day&lt;/EM&gt;. The other week I &lt;A href="http://blogs.msdn.com/ptorr/archive/2007/04/02/coloured-blocks-advancing-on-a-moving-block.aspx" mce_href="http://blogs.msdn.com/ptorr/archive/2007/04/02/coloured-blocks-advancing-on-a-moving-block.aspx"&gt;posted an HDi sample&lt;/A&gt; based of the old arcade game &lt;A href="http://en.wikipedia.org/wiki/Space_Invaders" mce_href="http://en.wikipedia.org/wiki/Space_Invaders"&gt;&lt;EM&gt;Space Invaders&lt;/EM&gt;&lt;/A&gt;. Today it's a (somewhat prettier) example that implements the old game &lt;A href="http://en.wikipedia.org/wiki/Liar's_Dice" mce_href="http://en.wikipedia.org/wiki/Liar's_Dice"&gt;Liar's Dice&lt;/A&gt;. Some of you may wonder how I chose these two games to demo as HDi applications; the rest of you already know this is to show just how easy it is to get great interactivity on a next-generation high-definition optical disc &lt;EM&gt;without&lt;/EM&gt; expensive replication, &lt;EM&gt;without&lt;/EM&gt; expensive programmers, and &lt;EM&gt;without&lt;/EM&gt; an expensive games console to play it on. This was all written by little old me in a couple of hours, is about 130k in size (most of which are PNGs), and will play on any &lt;A href="http://www.amazon.com/dp/B000IJV4BC/" mce_href="http://www.amazon.com/dp/B000IJV4BC/"&gt;sub-$300 HD DVD player&lt;/A&gt; without first running through a &lt;A href="http://www.blueboard.com/bluray/movie_review_chickenlittle.htm" mce_href="http://www.blueboard.com/bluray/movie_review_chickenlittle.htm"&gt;performance test application&lt;/A&gt;. &lt;EM&gt;[Ed: I am currently travelling without access to a real player so have been unable to test it properly; it works on HDiSim and if there are any issues with up-to-date players I will resolve them next week]&lt;/EM&gt; &lt;/P&gt;
&lt;P&gt;Here's a screenshot of the game: &lt;/P&gt;
&lt;P&gt;&lt;IMG alt="Screenshot of the Liar's Dice game" src="http://blogs.msdn.com/photos/ptorr/images/2681862/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;As with the last game, this was thrown together very quickly and doesn't necessarily represent "best practices" (I know, I know, I should be demonstrating those too). Nevertheless the concepts should be pretty easy to understand. If not, post a comment! :-) &lt;/P&gt;
&lt;P&gt;The download is &lt;A class="" title="Download the ADV_OBJ ZIP" href="http://blogs.msdn.com/ptorr/attachment/2682093.ashx" mce_href="http://blogs.msdn.com/ptorr/attachment/2682093.ashx"&gt;here&lt;/A&gt;. Enjoy. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2682093" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/ptorr/attachment/2682093.ashx" length="202482" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>Coloured Blocks Advancing on a Moving Block</title><link>http://blogs.msdn.com/ptorr/archive/2007/04/02/coloured-blocks-advancing-on-a-moving-block.aspx</link><pubDate>Tue, 03 Apr 2007 00:14:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2014399</guid><dc:creator>ptorr</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/2014399.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=2014399</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=2014399</wfw:comment><description>&lt;p&gt;This blog would be titled &lt;em&gt;Space Invaders&lt;/em&gt;, but I don't own that trademark so I had to choose something a bit more generic. This is a preliminary post to show a very hacked up version of the popular game in HDi. Note that I hope to follow up with a more complete version at some stage, but people have been asking for this so I am going to post it anyway.
&lt;/p&gt;&lt;p&gt;&lt;span style="color:red"&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I hacked this together in a couple of hours after someone asked me if it could be done. It is not very good code, it uses magic numbers, it hasn't been well tested, etc. and is not functionally complete. Nevertheless, you can have some fun with it and maybe use it to build something cooler.
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I also won't provide much commentary here, since I hope to do that with a better-written version soon(ish). Having said that, a &lt;em&gt;very&lt;/em&gt; quick summary is:
&lt;/p&gt;&lt;p&gt;You (the blue box at the bottom) move by hitting &lt;strong&gt;left&lt;/strong&gt; or &lt;strong&gt;right&lt;/strong&gt; on the keyboard / remote. Once moving, you can't stop until you hit the edge or turn around. You fire by hitting &lt;strong&gt;enter&lt;/strong&gt; (or &lt;strong&gt;OK&lt;/strong&gt; on the remote), and you can only have one bullet in the air at any given time (so don't miss :-) ). 
&lt;/p&gt;&lt;p&gt;You get 100 points for hitting an enemy. Hit them all, and you win (the "you've won!" sequence is so mind-blowingly cool that you have to see it for yourself). If an enemy hits you with a bullet, or if the bottom row of enemies advances into your "home base", you lose. Again, the cinematic for losing is simply breathtaking. 
&lt;/p&gt;&lt;p&gt;Things you might want to work on:
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Add animated graphics for you and the enemies. Simple &lt;strong&gt;backgroundFrame&lt;/strong&gt; animation can do this
&lt;/li&gt;&lt;li&gt;Improve the hit-testing logic (right now, bullets are assumed to be 1-pixel wide)
&lt;/li&gt;&lt;li&gt;Add the "shields" to the game; I planned for it but haven't done it yet
&lt;/li&gt;&lt;li&gt;Make enemies score different points when you hit them (based on rank and how far down they are)
&lt;/li&gt;&lt;li&gt;Have different "skill levels" if you complete one screen
&lt;/li&gt;&lt;li&gt;Improve the code to be more modular, not query the markup page so much, and not rely on hard-coded numbers (like "485" on line 109!)
&lt;/li&gt;&lt;li&gt;Improve perf by not doing any per-tick operations if you know nothing needs to be done
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Etc.
&lt;/p&gt;&lt;p&gt;Anywho, that's it. I'll try to do more later...
&lt;/p&gt;&lt;p&gt;[&lt;a href="https://blogs.msdn.com/ptorr/attachment/2014390.ashx"&gt;Download the ADV_OBJ as a ZIP file&lt;/a&gt;]&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2014399" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>The Difference Between “Selected” and “Current” tracks</title><link>http://blogs.msdn.com/ptorr/archive/2007/02/20/the-difference-between-selected-and-current-tracks.aspx</link><pubDate>Tue, 20 Feb 2007 21:24:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1728382</guid><dc:creator>ptorr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/1728382.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=1728382</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=1728382</wfw:comment><description>&lt;p&gt;In HD DVD, there are two ways to figure out which subtitle or audio track the user has chosen. The &lt;strong&gt;selectedAudioTrackNumber&lt;/strong&gt; (and &lt;strong&gt;selectedAudioLanguageCode&lt;/strong&gt; / &lt;strong&gt;selectedAudioLanguageCodeExtension&lt;/strong&gt;) properties refer to the track (language) that the user has selected, but they may or may not represent the currently-playing track / language. The &lt;strong&gt;currentAudioTrackNumber&lt;/strong&gt; (etc.) refer to the track that is actually playing right now. The same goes for subtitle tracks. 
&lt;/p&gt;&lt;p&gt;The different sets of properties are basically used to ensure the user gets the language they prefer if it is available, but if not then the script code can always check what the fallback value was to display the appropriate UI. For example, assume you have a main feature with the following audio tracks:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;English
&lt;/li&gt;&lt;li&gt;Spanish
&lt;/li&gt;&lt;li&gt;German
&lt;/li&gt;&lt;li&gt;Japanese
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;And also assume you have a documentary with the following audio tracks:
&lt;/p&gt;&lt;ol&gt;&lt;li&gt;English
&lt;/li&gt;&lt;li&gt;Japanese
&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;If the user is listening in &lt;strong&gt;English&lt;/strong&gt;, it is easy. The selected and current tracks are always &lt;strong&gt;1&lt;/strong&gt;, and the language code is &lt;strong&gt;EN&lt;/strong&gt; (I won't go into extensions here). Now if the user is listening to the feature in &lt;strong&gt;Japanese&lt;/strong&gt;, both the selected and current tracks are &lt;strong&gt;4&lt;/strong&gt;, and the language code is &lt;strong&gt;JA&lt;/strong&gt;. Now the user jumps to the documentary, but track &lt;strong&gt;4&lt;/strong&gt; no longer exists. Using the selection algorithm (section &lt;strong&gt;4.3.19.4.2&lt;/strong&gt; of the spec) the system searches for another &lt;strong&gt;Japanese&lt;/strong&gt; track and finds it in track number &lt;strong&gt;2&lt;/strong&gt;. So the &lt;em&gt;selected&lt;/em&gt; track is still &lt;strong&gt;4&lt;/strong&gt; (so that when jumping back to the main feature, the right track is selected) but the &lt;em&gt;current&lt;/em&gt; track is &lt;strong&gt;2&lt;/strong&gt;. Both selected and current language is still &lt;strong&gt;JA&lt;/strong&gt;.
&lt;/p&gt;&lt;p&gt;Now if the user is listening to the feature in &lt;strong&gt;German&lt;/strong&gt; (track &lt;strong&gt;3&lt;/strong&gt;), we have a bit of a problem. Switching to the documentary, there is neither a track number &lt;strong&gt;3&lt;/strong&gt; nor a &lt;strong&gt;DE&lt;/strong&gt;-language track, so we select the lowest available instead (&lt;strong&gt;English&lt;/strong&gt;). Now the &lt;em&gt;selected&lt;/em&gt; track / language is &lt;strong&gt;3&lt;/strong&gt; / &lt;strong&gt;DE&lt;/strong&gt;, but the &lt;em&gt;current&lt;/em&gt; track / language is &lt;strong&gt;1&lt;/strong&gt; / &lt;strong&gt;EN&lt;/strong&gt;. But when they switch back to the feature, they get their native &lt;strong&gt;German&lt;/strong&gt; back again.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1728382" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>A tip for writing script for HD DVD</title><link>http://blogs.msdn.com/ptorr/archive/2007/02/16/a-tip-for-writing-script-for-hd-dvd.aspx</link><pubDate>Fri, 16 Feb 2007 22:46:23 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1690881</guid><dc:creator>ptorr</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/1690881.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=1690881</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=1690881</wfw:comment><description>&lt;p&gt;A very quick tip today, although this one trips me up &lt;strong&gt;a lot&lt;/strong&gt;.
&lt;/p&gt;&lt;p&gt;&lt;em&gt;When you write script files for your HDi applications, always include a blank line at the start of the file and at the end of the file.
&lt;/em&gt;&lt;/p&gt;&lt;p&gt;This is because the player will concatenate all the individual files together and execute them as a single large virtual file. So, for example, if you have two files like this:
&lt;/p&gt;&lt;p&gt;&lt;strong&gt;first.js
&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="color:#0070c0"&gt;var&lt;/span&gt; x = &lt;span style="color:#7030a0"&gt;42&lt;/span&gt;;&lt;br/&gt;&lt;span style="color:#00b050"&gt;// end of first.js
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;second.js
&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="color:#0070c0"&gt;var&lt;/span&gt; y = &lt;span style="color:#7030a0"&gt;42&lt;/span&gt;;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Then the player will see this:
&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;lt;virtual_file&amp;gt;
&lt;/strong&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="color:#0070c0"&gt;var&lt;/span&gt; x = &lt;span style="color:#7030a0"&gt;42&lt;/span&gt;;&lt;br/&gt;&lt;span style="color:#00b050"&gt;// end of first.jsvar y = 42;&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;And then later on when you try to reference the &lt;strong&gt;y&lt;/strong&gt; variable, it doesn't exist because it was considered part of the comment. Doh!
&lt;/p&gt;&lt;p&gt;At least, that's what the players do, but &lt;a href="http://blogs.msdn.com/ptorr/archive/2006/11/08/script-execution-order-in-hd-dvd.aspx"&gt;HDiSim doesn't&lt;/a&gt;. Which is why you can get away without the padding when running on the simulator, and then you get weird errors when running on the emulator / player.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1690881" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>Red Box Debugging</title><link>http://blogs.msdn.com/ptorr/archive/2007/02/01/red-box-debugging.aspx</link><pubDate>Thu, 01 Feb 2007 23:07:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1575033</guid><dc:creator>ptorr</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/1575033.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=1575033</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=1575033</wfw:comment><description>&lt;p&gt;Today I have a simple debugging tip.
&lt;/p&gt;&lt;p&gt;Sometimes when you have an obscure bug, you need to answer the question &lt;em&gt;"is my code even getting executed?"&lt;/em&gt; Often you can find that really obscure bugs are caused simply by a bad conditional, a typo, an unexpected exception, or some other flow-control issue that bypasses your code altogether.
&lt;/p&gt;&lt;p&gt;Whilst you can use an interactive debugger such as Microsoft Visual Studio for tracking down some of these things, debuggers aren't always available (eg, if you are on a hardware emulator), and if the bug is timing-related then they hamper your ability to reproduce the problem. Worse still, if your bug is in a declarative timing section (rather than in a script file) there's currently no way to debug that at all.
&lt;/p&gt;&lt;p&gt;So you need something a bit less impactful.
&lt;/p&gt;&lt;p&gt;In the good old days of C programming, people used to use "printf debugging" to display a message on the console indicating that a particular line of code had executed, and possibly to show the value of a variable. In the web world, this was changed to "alert debugging" where a popup window was used to the same effect.
&lt;/p&gt;&lt;p&gt;For HD DVD, I like to use "red box debugging". Basically I create a big red &lt;strong&gt;div&lt;/strong&gt; in my markup file and set &lt;strong&gt;style:display="none"&lt;/strong&gt;. Then at the point in my script where I want to "prove" that it gets executed or not, I simply say &lt;strong&gt;document.whateverTheIdIs.style.display = "auto"&lt;/strong&gt; and see if the red box appears. And if your bug is timing related, you simply has a cue that does a &lt;strong&gt;&amp;lt;set style:display="auto" /&amp;gt;&lt;/strong&gt; and similarly proves (or disproves...) that your program is working as planned.
&lt;/p&gt;&lt;p&gt;That's all &lt;span style="font-family:Wingdings"&gt;J&lt;/span&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1575033" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>Simple Pre-Processor for HDi</title><link>http://blogs.msdn.com/ptorr/archive/2007/01/10/simple-pre-processor-for-hdi.aspx</link><pubDate>Wed, 10 Jan 2007 11:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1443007</guid><dc:creator>ptorr</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/1443007.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=1443007</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=1443007</wfw:comment><description>&lt;P&gt;Hope you all had a good break. I haven't blogged for a while due to travel (both business and pleasure) and laziness… but I thought I'd start off today with simple pre-processor for HDi. &lt;/P&gt;
&lt;P&gt;One of the things that is missing from HD DVD is a good pre-processor; anyone familiar with C will know of all the good (and evil) things you can do with a few &lt;STRONG&gt;#define&lt;/STRONG&gt; macros. Anyone not familiar with C, well, you don't know what you're missing out on :-) &lt;/P&gt;
&lt;P&gt;Anyway, what I am basically talking about is the ability to define &lt;STRONG&gt;macros&lt;/STRONG&gt; (symbolic constants; shortcuts; expansions; whatever) that you can use in your markup files and script files to simplify development. &lt;/P&gt;
&lt;P&gt;Here's a common problem scenario (at least for me): &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Lay out some simple markup &lt;/LI&gt;
&lt;LI&gt;Create a button &lt;STRONG&gt;foo&lt;/STRONG&gt; with (eg) an &lt;STRONG&gt;x&lt;/STRONG&gt; position of &lt;STRONG&gt;100px&lt;/STRONG&gt; &lt;/LI&gt;
&lt;LI&gt;Write some animation that moves &lt;STRONG&gt;foo&lt;/STRONG&gt; from &lt;STRONG&gt;100px&lt;/STRONG&gt; to &lt;STRONG&gt;200px&lt;/STRONG&gt; (this could be in script or markup) &lt;/LI&gt;
&lt;LI&gt;Realise you need to shift &lt;STRONG&gt;foo&lt;/STRONG&gt; to &lt;STRONG&gt;110px&lt;/STRONG&gt; to accommodate a stylistic change &lt;/LI&gt;
&lt;LI&gt;Now figure out all the places where you need to change &lt;STRONG&gt;100px&lt;/STRONG&gt; to &lt;STRONG&gt;110px&lt;/STRONG&gt;, noting that you can't do a global search-and-replace because &lt;STRONG&gt;100px&lt;/STRONG&gt; could refer to other things as well &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Traditionally this kind of problem (known as a "magic number") is solved by using a symbolic constant – we define a placeholder value named (eg) &lt;STRONG&gt;FOO_X&lt;/STRONG&gt; and we define it to be &lt;STRONG&gt;100px&lt;/STRONG&gt;. Then everywhere we want to refer to the &lt;STRONG&gt;x&lt;/STRONG&gt; location of &lt;STRONG&gt;foo&lt;/STRONG&gt;, we use &lt;STRONG&gt;FOO_X&lt;/STRONG&gt; rather than &lt;STRONG&gt;100px&lt;/STRONG&gt;. Then if we want to update &lt;STRONG&gt;foo&lt;/STRONG&gt; to be at &lt;STRONG&gt;110px&lt;/STRONG&gt; later on, we simply change the definition of &lt;STRONG&gt;FOO_X&lt;/STRONG&gt; to be &lt;STRONG&gt;110px&lt;/STRONG&gt; and our work is done. &lt;/P&gt;
&lt;P&gt;This is easily done in script (where you have variables) but not so easily done in markup. So, I have written a very simple pre-processor that will take a bunch of macro definitions and replace them in your markup files AND give you a nice script file containing matching declarations to go along with it. &lt;/P&gt;
&lt;P&gt;In addition to simple text expansion (&lt;STRONG&gt;FOO_X = 100px&lt;/STRONG&gt;) you can also do arithmetic (&lt;STRONG&gt;FOO_X = BAR_X + 100&lt;/STRONG&gt;) and indeed perform any kind of processing in your macros because they are all &lt;STRONG&gt;eval&lt;/STRONG&gt;-ed at "compile" time. This has made my life a lot easier, especially when I am just testing things out and I need to re-lay-out stuff over and over again. &lt;/P&gt;
&lt;P&gt;&lt;A class="" title="Download the sample" href="http://blogs.msdn.com/ptorr/attachment/1443007.ashx" mce_href="http://blogs.msdn.com/ptorr/attachment/1443007.ashx"&gt;Attached is a simple project&lt;/A&gt;, along with &lt;STRONG&gt;preprocess.js&lt;/STRONG&gt;. You run &lt;STRONG&gt;preprocess.js&lt;/STRONG&gt; like this: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;cscript.exe preprocess.js &amp;lt;defs&amp;gt; &amp;lt;infile&amp;gt; &amp;lt;outfile&amp;gt; [-d] &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;where: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&amp;lt;defs&amp;gt; is the name of the definitions file, eg "my_definitions.ini" &lt;/LI&gt;
&lt;LI&gt;&amp;lt;infile&amp;gt; is the name of the input file, eg "markup_with_symbolic_names.xmu" &lt;/LI&gt;
&lt;LI&gt;&amp;lt;outfile&amp;gt; is the name of the output file to create, eg "markup.xmu" &lt;/LI&gt;
&lt;LI&gt;The optional –d switch produces a .JS file with the same base name as &amp;lt;defs&amp;gt; containing JScript declarations for all the macros &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The definitions file is a simple text file that contains four types of lines: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Empty lines or lines beginning with a semi-colon are ignored (eg, use for comments) &lt;/LI&gt;
&lt;LI&gt;Lines of the format &lt;EM&gt;NAME &amp;lt;space&amp;gt; TEXT&lt;/EM&gt; define &lt;EM&gt;NAME&lt;/EM&gt; to be exactly &lt;EM&gt;TEXT&lt;/EM&gt; &lt;/LI&gt;
&lt;LI&gt;Lines of the format &lt;EM&gt;NAME &amp;lt;space&amp;gt; '=' CODE&lt;/EM&gt; define &lt;EM&gt;NAME&lt;/EM&gt; to be the evaluation of &lt;EM&gt;CODE&lt;/EM&gt;, which can contain references to functions or other &lt;EM&gt;NAME&lt;/EM&gt;s &lt;/LI&gt;
&lt;LI&gt;Lines of the format '#' &lt;EM&gt;CODE&lt;/EM&gt; run &lt;EM&gt;CODE&lt;/EM&gt; directly without creating any new names (it is assumed the function being called adds names implicitly) &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;If a macro definition looks like a number, the system will automatically create an additional macro with the same name with "_PX" on the end that has the same value with "px" on the end. An example of a simple file: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; Here is a simple file &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; These lines are ignored &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; This creates two macros &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; The first is called "BUTTON_X" and has the value 100 &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; The second is called "BUTTON_X_PX" and has the value "100px" &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;BUTTON_X&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;100 &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; This also creates two macros by doing simple arithmetic &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; Given the definition of BUTTON_X above, this will produce &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; both "BUTTON_Y" with a value of 200 &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; and "BUTTON_Y_PX" with a value of "200px" &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;BUTTON_Y&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;= BUTTON_X + 100 &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; This runs the theoretical function DoSomethingCool, which you &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;; could add to preprocess.js &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;STRONG&gt;#DoSomethingCool() &lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Note that &lt;STRONG&gt;preprocess.js&lt;/STRONG&gt; is not necessarily the best code in the world, nor is it a secure application (it will &lt;STRONG&gt;eval&lt;/STRONG&gt; arbitrary input code, so DO NOT USE IT on untrusted definition files!). It was something I threw together and have been iterating on in the normal hacker fashion. It was an itch that needed scratching, not a well-designed and thought-out application. &lt;/P&gt;
&lt;P&gt;Also note that whilst using the –d switch will output a script file, &lt;EM&gt;it is not big-endian as the HD DVD spec requires&lt;/EM&gt;! This is due to a limitation in the &lt;STRONG&gt;FileSystemObject&lt;/STRONG&gt;. You need to open the JS file in Notepad and re-save it with Big Endian encoding. That's why it isn't generated by default… &lt;/P&gt;
&lt;P&gt;So, on to &lt;A class="" title="Download the sample" href="http://blogs.msdn.com/ptorr/attachment/1443007.ashx" mce_href="http://blogs.msdn.com/ptorr/attachment/1443007.ashx"&gt;the enclosed example HDi program&lt;/A&gt;, it is very simple and very ugly. All it shows you is a simple defs file and a simple input markup file. Running the batch file will create the output markup file and then run the result (assuming HdiSim.exe is in your PATH). Clicking on the blue square makes it grow larger. &lt;/P&gt;
&lt;P&gt;&lt;EM&gt;AMAZING! &lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;But what is "cool" about this is that if you edit the defs.ini file and change (eg) the &lt;STRONG&gt;SMALL_W_ANIMATED&lt;/STRONG&gt; value to &lt;STRONG&gt;500&lt;/STRONG&gt; (to make the blue button grow larger) and re-run the batch file, the red button will automatically shift as well. No need to go and tweak its values to compensate for changes in the blue button. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;AMAZING! &lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Well, not so much, but in more complicated projects this is a real time-saver. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1443007" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/ptorr/attachment/1443007.ashx" length="6276" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item><item><title>Script Execution Order in HD DVD</title><link>http://blogs.msdn.com/ptorr/archive/2006/11/08/script-execution-order-in-hd-dvd.aspx</link><pubDate>Thu, 09 Nov 2006 00:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1040084</guid><dc:creator>ptorr</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ptorr/comments/1040084.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ptorr/commentrss.aspx?PostID=1040084</wfw:commentRss><wfw:comment>http://blogs.msdn.com/ptorr/rsscomments.aspx?PostID=1040084</wfw:comment><description>&lt;P&gt;An HDi application can use multiple script files so that you can better manage your code (more manageable files; easier source control; etc.). You do this simply by listing the files inside &lt;STRONG&gt;&amp;lt;Script&amp;gt;&lt;/STRONG&gt; elements inside the manifest (and of course add the appropriate &lt;STRONG&gt;&amp;lt;Resource&amp;gt;&lt;/STRONG&gt; elements if they're not all in an ACA file). Whether or not script code in one file can "see" the script in another file is a common question that I'll address here. &lt;/P&gt;
&lt;H2&gt;Spec Behaviour &lt;/H2&gt;
&lt;P&gt;The HD DVD specification says that you take all the script files, load them in the order they are listed in the manifest, and then start running the script engine. This means that you really have one big "virtual file" that is the concatenation of all the individual files, and so all the code can "see" all the other code. &lt;/P&gt;
&lt;P&gt;This doesn't mean you're &lt;A href="http://www.amazon.com/Home-Dry-Pt-Shop-Boys/dp/B00005YWP7/sr=1-2/qid=1163021217/" mce_href="http://www.amazon.com/Home-Dry-Pt-Shop-Boys/dp/B00005YWP7/sr=1-2/qid=1163021217/"&gt;home and dry&lt;/A&gt;, of course, because there are some other things to be wary of that we'll get to soon. &lt;/P&gt;
&lt;H2&gt;HDiSim Behaviour &lt;/H2&gt;
&lt;P&gt;The spec behaviour was clarified in a fairly recent supplemental change, and so HDiSim currently uses a different approach – it loads each script file and executes it in the order listed in the manifest, similar to how a web browser would load and execute multiple &lt;STRONG&gt;&amp;lt;script&amp;gt;&lt;/STRONG&gt; blocks. What this means is that in HDiSim, code can only "see" code in the files that were listed before it in the manifest. &lt;/P&gt;
&lt;P&gt;Note that this only applies to "global code" that executes as soon as the script is loaded; basically any code outside of any functions (and the code that it calls, etc.) is subject to this rule, but because ECMAScript is a late-bound language, once all your script files have been loaded and your &lt;STRONG&gt;setMarkupLoadedHandler&lt;/STRONG&gt; has been called, all your code can "see" all the other code anyway. &lt;/P&gt;
&lt;P&gt;So it's only during initial startup that you have this problem. &lt;/P&gt;
&lt;H2&gt;Caveats &lt;/H2&gt;
&lt;P&gt;There are still several things to think about though. First let's look at what happens when an ECMAScript interpreter gets hold of a script. It basically does the following: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Scan the file for variable declarations, and make them available (but with the initial value &lt;STRONG&gt;undefined&lt;/STRONG&gt;) &lt;/LI&gt;
&lt;LI&gt;Scan the file for function declarations, and make the &lt;STRONG&gt;Function&lt;/STRONG&gt; objects available &lt;/LI&gt;
&lt;LI&gt;Start running program code &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;This means that you can always call functions declared in the same file, and you can always access variables declared in the same file, but if you access variables before they are initialised you get &lt;STRONG&gt;undefined&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P&gt;Here's a quick example, using &lt;STRONG&gt;Windows Script Host&lt;/STRONG&gt; as an example: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; above = &lt;SPAN style="COLOR: maroon"&gt;"you see this"&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;print(above) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;print(below) &lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt; below = &lt;SPAN style="COLOR: maroon"&gt;"you don't see this" &lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: blue"&gt;function&lt;/SPAN&gt; print(s) { WScript.Echo(String(s)) } &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Running this program will print &lt;STRONG&gt;"you see this"&lt;/STRONG&gt; and &lt;STRONG&gt;"undefined"&lt;/STRONG&gt; on the screen. Note that if you comment out the line &lt;STRONG&gt;"var below=..."&lt;/STRONG&gt; you will get a runtime error because &lt;STRONG&gt;below&lt;/STRONG&gt; is not declared. ECMAScript lets you &lt;EM&gt;assign&lt;/EM&gt; values to undeclared variables, but you cannot &lt;EM&gt;read&lt;/EM&gt; undeclared variables (in broad terms, they can be &lt;A href="http://msdn2.microsoft.com/en-us/library/bkbs2cds.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/bkbs2cds.aspx"&gt;l-values but not r-values&lt;/A&gt;). &lt;/P&gt;
&lt;P&gt;Another HD DVD-specific caveat is that the &lt;STRONG&gt;document&lt;/STRONG&gt; object is not available when your script first executes; it doesn't become valid until the markup document has loaded and your &lt;STRONG&gt;setMarkupLoadedHandler&lt;/STRONG&gt; function has been called. Because of this, you probably want to avoid running too much code at startup anyway; sooner or later you're going to try and access &lt;STRONG&gt;document&lt;/STRONG&gt;, and crash. &lt;/P&gt;
&lt;P&gt;Finally, ECMAScript lets you re-define functions (since they are just objects like anything else). Within the same file, the lexically last definition will win, but in the case where you load multiple files independently (ala HDiSim) you could end up running one version of the function from global code inside one file, then re-defining it in a later file and running different code. Don't do that. &lt;/P&gt;
&lt;H2&gt;The Long and the Short of it &lt;/H2&gt;
&lt;P&gt;So basically what this means is that for maximum compatibility with the spec and with HDiSim, you should just make sure that your script files are listed in a "reasonable" order in the manifest, and that you don't try to do too much work before &lt;STRONG&gt;setMarkupLoadedHandler&lt;/STRONG&gt; is called. At that stage, everything will be available to you. &lt;/P&gt;
&lt;P&gt;Also, never re-define functions unless you &lt;EM&gt;really&lt;/EM&gt; know what you are doing. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1040084" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ptorr/archive/tags/Script/default.aspx">Script</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/HD+DVD/default.aspx">HD DVD</category><category domain="http://blogs.msdn.com/ptorr/archive/tags/iHD/default.aspx">iHD</category></item></channel></rss>