Script Execution Order in HD DVD

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 <Script> elements inside the manifest (and of course add the appropriate <Resource> 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.

Spec Behaviour

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.

This doesn't mean you're home and dry, of course, because there are some other things to be wary of that we'll get to soon.

HDiSim Behaviour

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 <script> blocks. What this means is that in HDiSim, code can only "see" code in the files that were listed before it in the manifest.

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 setMarkupLoadedHandler has been called, all your code can "see" all the other code anyway.

So it's only during initial startup that you have this problem.


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:

  1. Scan the file for variable declarations, and make them available (but with the initial value undefined)
  2. Scan the file for function declarations, and make the Function objects available
  3. Start running program code

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 undefined.

Here's a quick example, using Windows Script Host as an example:

var above = "you see this"
var below = "you don't see this"
function print(s) { WScript.Echo(String(s)) }

Running this program will print "you see this" and "undefined" on the screen. Note that if you comment out the line "var below=..." you will get a runtime error because below is not declared. ECMAScript lets you assign values to undeclared variables, but you cannot read undeclared variables (in broad terms, they can be l-values but not r-values).

Another HD DVD-specific caveat is that the document object is not available when your script first executes; it doesn't become valid until the markup document has loaded and your setMarkupLoadedHandler 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 document, and crash.

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.

The Long and the Short of it

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 setMarkupLoadedHandler is called. At that stage, everything will be available to you.

Also, never re-define functions unless you really know what you are doing.