<?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>Fabulous Adventures In Coding : SimpleScript</title><link>http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx</link><description>Tags: SimpleScript</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>SimpleScript Part Seven: Binder Skeleton</title><link>http://blogs.msdn.com/ericlippert/archive/2004/05/04/125837.aspx</link><pubDate>Tue, 04 May 2004 17:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:125837</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/125837.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=125837</wfw:commentRss><description>&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/04/22/118585.aspx href="/ericlippert/archive/2004/04/22/118585.aspx"&gt;Part Five&lt;/A&gt; I was discussing modules: there is a "global module" and any number of additional modules.&amp;nbsp; Each module is associated with a named item, and the only module which is associated with more than one named item is the global module.&amp;nbsp; This means that each module is going to need its own &lt;B&gt;&lt;SPAN&gt;name table&lt;/SPAN&gt;&lt;/B&gt; to keep track of the functions, the variable names and values, etc, in it.&amp;nbsp; We'll call such devices "binders" because they bind names to values. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;For reasons which will become more clear in future episodes, it is convenient to have the binder implement the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IDispatch&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; interface.&amp;nbsp; Normally if you had to implement &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IDispatch&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; you'd build a type library, and then have your implementation of &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IDispatch&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; call through to the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;ITypeInfo&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; methods which look up dispatch ids, invoke methods, and so on.&amp;nbsp; There's a good reason for that: rolling your own &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IDispatch&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; code can be extremely tricky.&amp;nbsp; But, we're pretty much stuck with it here -- we haven't got the convenience of a known vtable interface to wrap a type library around at compile time.&amp;nbsp; The script engine name tables are going to be extremely dynamic, so we're going to have to roll our own &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IDispatch&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The code isn't nearly done yet, obviously, but I've got a good skeleton in place.&amp;nbsp; Take a look at &lt;A title=http://blogs.msdn.com/ericlippert/articles/125805.aspx href="/ericlippert/articles/125805.aspx"&gt;binder.cpp&lt;/A&gt; for the details. &amp;nbsp;&amp;nbsp;I've pretty much got the high-level semantics of the dispatch interface worked out, but the actual low-level implementation details all return &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;E_NOTIMPL&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; What I need to build here is a special hash table which can efficiently look up values by both numeric id and name.&amp;nbsp; That's not too challenging; what is going to be more difficult is implementing the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_GLOBALMEMBERS&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; feature.&amp;nbsp; We need to be able to add another arbitrary dispatch object to our binder and dynamically aggregate all of its methods, without causing any collision in dispatch ids!&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Default property semantics are a little weird.&amp;nbsp; In the wacky world of late bound objects, an object may have a "default" method.&amp;nbsp; This feature was created so that you could call the Item method of a collection the same way you dereference an array in Visual Basic -- you make it look like a function call.&amp;nbsp; That is, since this code works: 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Dim arr(10)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;arr(1) = 123 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;then so should this code 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;dict = CreateObject("Scripting.Dictionary")&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;dict(1) = 123 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;the last line is the same as 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;dict.item(1) = 123 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Such is the wackiness of VB -- because the array dereference and function call syntax are conflated, they ended up making &lt;EM&gt;function calls on invisible methods be legal on the left hand side of an assignment statement.&lt;/EM&gt;&amp;nbsp; The mind fairly boggles.&amp;nbsp; &amp;nbsp;We'll be good citizens in SimpleScript.&amp;nbsp; If we have an object in our binder and someone attempts to call it, we'll just pass on the arguments to its default method and let it sort out what the right thing to do is.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As you can see, there is a whole lot of parameter validation, and altogether about eleven separate cases that I cover in the implementation of Invoke.&amp;nbsp; The actual implementation in VBScript and JScript is much, much more complex than this because they support IDispatchEx, garbage collection, property accessor functions, and numerous other features that complicate the code.&amp;nbsp; But still, this is the longest function you're likely to see me write in this project; I'll be very surprised if I write any code more complicated than the dispatch logic. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Speaking of garbage collection, I'm not quite sure what kind of garbage collector I'm going to build into SimpleScript.&amp;nbsp; Building a mark-and-sweep collector like JScript has would be instructive, but it would also take a lot of time and effort.&amp;nbsp; What do you guys think?&amp;nbsp; (If you look at &lt;A title=http://blogs.msdn.com/ericlippert/articles/125807.aspx href="/ericlippert/articles/125807.aspx"&gt;invoke.cpp&lt;/A&gt; you'll see that I'm thinking ahead about issues we're going to run into in garbage collection.&amp;nbsp; We're going to run into related issues in the script execution code; it is possible for ill-behaved hosts to shut down the script engine in a callback while it is executing!&amp;nbsp; We need to be robust in the face of such behaviour.) 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The next step is to get the actual guts of the binder working, and then build a list of code blocks to be executed when the script engine goes to started state.&amp;nbsp; The clone semantics for the code blocks are a little tricky, so we'll get that straightened away, and then maybe, just maybe, actually write a language parser.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;UPDATE:&amp;nbsp; For your convenience, I've put a zip file containing all the sources at &lt;A href="http://www.eric.lippert.com/simplescript.zip"&gt;http://www.eric.lippert.com/simplescript.zip&lt;/A&gt;.&amp;nbsp; I'll keep this zip file updated as I change the sources on the blog.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=125837" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript Part Six: Threading Technicalities</title><link>http://blogs.msdn.com/ericlippert/archive/2004/04/26/120756.aspx</link><pubDate>Tue, 27 Apr 2004 03:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:120756</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>20</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/120756.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=120756</wfw:commentRss><description>&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;Refresher Course
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Before you read this, you might want to take a quick refresher on my &lt;A title=http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx HREF="/ericlippert/archive/2003/09/18/53041.aspx"&gt;original posting&lt;/A&gt; on the script engine threading model.&amp;nbsp; That was a somewhat simplified (!) description of the actual script engine contract.&amp;nbsp; Let me just sum up:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;free threaded objects&lt;/STRONG&gt; can be called from any thread at any time; the object is responsible for synchronizing access to shared resources&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;apartment threaded objects&lt;/STRONG&gt; can have multiple instances on multiple threads but once an object is on a thread, it can only be called from that thread.&amp;nbsp; The caller is responsible for always calling an object on the thread on which it was created.&amp;nbsp; The object is responsible for synchronizing access to resources shared across instances.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;STRONG&gt;rental threaded objects&lt;/STRONG&gt; can be called on any thread, but the caller is responsible for ensuring that the object is only called from one thread at a time.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;an &lt;STRONG&gt;initialized&lt;/STRONG&gt; engine is apartment threaded, with a couple exceptions -- &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;InterruptScriptThread&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clone&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; can both be called from any thread on an initialized engine.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;an &lt;STRONG&gt;uninitialized&lt;/STRONG&gt; engine is free-threaded&lt;/LI&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;Things Get More Complicated
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That's actually not quite right.&amp;nbsp; It would be more accurate to say that &lt;B&gt;&lt;SPAN&gt;an&lt;/SPAN&gt;&lt;/B&gt; &lt;B&gt;&lt;SPAN&gt;uninitialized engine is rental threaded&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; Why?&amp;nbsp; Because otherwise it would be legal to do really dumb things like call &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Close&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; on two different threads at the same time.&amp;nbsp; If you look carefully at the code, you'll see that most of the methods are not robust in the face of full-on multithreading.&amp;nbsp; It's the "the host isn't a bozo" threading model!
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This is a ridiculously complex threading contract, I know.&amp;nbsp; From COM's point of view, the script engine is free threaded -- the restrictions are so arcane that clearly the engine has got to be the one enforcing the rules, not COM, which is why you'll see lots of calls to check that the caller is on the right thread in my code.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If you take a look at the registration code, you'll see that I register the script engine as "Both", which means "either free threaded&amp;nbsp;or apartment threaded, we'll sort it out".&amp;nbsp; What the heck is up with that?&amp;nbsp; Why not just call it "free threaded" and be done with it?
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Because again, I oversimplified the description of an apartment in my original posting.&amp;nbsp; A single-threaded-apartment (STA) object is created on a thread and is always called on that thread.&amp;nbsp; Think of a person (an object) in a room (a thread) -- you want to talk to them (call a method), you go to their room.&amp;nbsp; You can put as many people in a room as you'd like, and build as many rooms as you'd like, but you want to call a method, you do it from the thread where the callee lives. That's all fine and good.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;But there&amp;nbsp;is also a multi-threaded apartment!&amp;nbsp;&amp;nbsp;Imagine that you take some of the rooms and you knock holes in the walls.&amp;nbsp; If you're in one room and you want to talk to someone in another room, you don't have to go there, you can just yell through the hole.&amp;nbsp; The guy listening to you is responsible for synchronizing all the shouting going on, but at least he knows that no one is going to be trying to talk through a wall with no hole in it.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In any given process there is one "main" STA, possibly many more secondary STAs, and one MTA.&amp;nbsp; You can't have two distinct sets of rooms that mutually communicate but don't talk to each other.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I briefly described in an &lt;A title=http://weblogs.asp.net/ericlippert/archive/2003/09/18/53050.aspx href="http://weblogs.asp.net/ericlippert/archive/2003/09/18/53050.aspx"&gt;earlier post&lt;/A&gt; the way that COM marshals calls "through the walls" from one apartment to another.&amp;nbsp; Well, if we register the script engine as a free threaded object, COM is going to think that it lives in the default MTA, and that any STA objects created by the process live in their own STAs, and therefore, all calls between the two apartments are going to have to be marshaled by the Free Threaded Marshaler.&amp;nbsp;&amp;nbsp;That extra indirection &lt;STRONG&gt;really screws up your performance numbers&lt;/STRONG&gt;, lemme tell ya.&amp;nbsp; We register as "both" threaded, and COM says "&lt;I&gt;&lt;SPAN&gt;OK, you sort it out then if you're so smart&lt;/SPAN&gt;&lt;/I&gt;", which we do by requiring that the host call us on the right thread and give us objects that are on the right thread.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Even that is still a considerable oversimplification -- there's still the Neutral Threaded Apartment that I haven't talked about yet, and the interactions between the CLR threading model and the COM threading model, and how marshaling really works,&amp;nbsp;but that's getting out of my depth.&amp;nbsp; Go ask &lt;A title=http://blogs.msdn.com/cbrumme HREF="/cbrumme"&gt;Christopher Brumme&lt;/A&gt; if you've got questions about that stuff.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;Honouring Our End Of The Script Engine Contract
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Let's take a look at the script engine contract through the example of one of its objects that we've already implemented -- the named item list.&amp;nbsp; There are only four operations that can be performed on the named item list, and we know when they can be performed according to our contract and implementation:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Add&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; can only be called on an &lt;B&gt;&lt;SPAN&gt;initialized&lt;/SPAN&gt;&lt;/B&gt; engine, and hence only &lt;B&gt;&lt;SPAN&gt;from the engine thread&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Add&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;B&gt;&lt;SPAN&gt;writes&lt;/SPAN&gt;&lt;/B&gt; to the named item list.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Reset&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; can only be called on an &lt;B&gt;&lt;SPAN&gt;initialized&lt;/SPAN&gt;&lt;/B&gt; engine as it is being moved to &lt;B&gt;&lt;SPAN&gt;uninitialized&lt;/SPAN&gt;&lt;/B&gt; state, hence only from the engine thread.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Reset&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;B&gt;&lt;SPAN&gt;writes&lt;/SPAN&gt;&lt;/B&gt; to the named item list by removing non-persisting entries.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clear&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; is only called when the engine is going to &lt;B&gt;&lt;SPAN&gt;closed&lt;/SPAN&gt;&lt;/B&gt; state.&amp;nbsp; The engine might already be in &lt;B&gt;&lt;SPAN&gt;uninitialized&lt;/SPAN&gt;&lt;/B&gt; state and hence, &lt;B&gt;&lt;SPAN&gt;this can be called on any thread if the engine is uninitialized&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; However if the engine is &lt;B&gt;&lt;SPAN&gt;initialized&lt;/SPAN&gt;&lt;/B&gt; then it can only be called from the &lt;B&gt;&lt;SPAN&gt;main engine thread&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clear&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;B&gt;&lt;SPAN&gt;writes&lt;/SPAN&gt;&lt;/B&gt; to the named item list by removing all entries.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clone&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; can be called on any thread, and &lt;B&gt;&lt;SPAN&gt;reads&lt;/SPAN&gt;&lt;/B&gt; from the named item list.&lt;/LI&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What then are the possible threading conflicts?&amp;nbsp; The three writers, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Add&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Reset&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clear&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; cannot be called at the same time on different threads by virtue of the fact that the engine must be initialized if &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Add&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Reset&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; are being called.&amp;nbsp; There are a few cases which for completeness we should get right, but are in reality extremely unlikely.&amp;nbsp; Why would any host be so dumb as to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clone&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; an engine while in the middle of a call to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Add&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;?&amp;nbsp; Or worse, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clone&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; during &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Close&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;?&amp;nbsp; I won't assume that hosts won't pull shens like that, even though they are very unlikely.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What about two &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clones&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; at the same time on two different threads?&amp;nbsp; On the one hand, they're only reading, so why should they block?&amp;nbsp; On the other hand, boy, do I ever not want to implement single-writer-multi-reader mutexes just to make that extremely unlikely case marginally faster.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Therefore, we'll do it the easy way.&amp;nbsp; The only thing we &lt;I&gt;&lt;SPAN&gt;really&lt;/SPAN&gt;&lt;/I&gt; need to worry about practically is one thread doing a &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Clone&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; while another thread is doing a &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Reset&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, but we'll get it right for all the cases.&amp;nbsp; The first thing we'll do when we enter any of those methods is enter a critical section, and the last thing we'll do before we leave is exit it.&amp;nbsp; Rather than mess around with the operating system's somewhat gross critical section code in the object itself, I define a handy object to wrap it.&amp;nbsp; See &lt;A title=http://weblogs.asp.net/ericlippert/articles/116364.aspx href="http://weblogs.asp.net/ericlippert/articles/116364.aspx"&gt;mutex.cpp&lt;/A&gt; for the implementation.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Something to note about this implementation is that it uses &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&lt;A title=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/initializecriticalsectionandspincount.asp href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/initializecriticalsectionandspincount.asp"&gt;InitializeCriticalSectionAndSpinCount&lt;/A&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; to initialize the critical section.&amp;nbsp; The comments there and &lt;A title=http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/initializecriticalsection.asp href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/initializecriticalsection.asp"&gt;here&lt;/A&gt; are &lt;EM&gt;required reading if you need to make critical sections work on heavily loaded &lt;B&gt;&lt;SPAN&gt;pre-Windows-XP&lt;/SPAN&gt;&lt;/B&gt; boxes&lt;/EM&gt;. Earlier versions &lt;B&gt;&lt;SPAN&gt;throw exceptions&lt;/SPAN&gt;&lt;/B&gt; rather than returning error codes, which means that every entry and exit to a critical section has to be protected with &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;__try&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; blocks and you then have to &lt;A title=http://weblogs.asp.net/oldnewthing/archive/2004/04/22/118161.aspx href="http://weblogs.asp.net/oldnewthing/archive/2004/04/22/118161.aspx"&gt;get the exception handling right&lt;/A&gt;!&amp;nbsp; The VBScript and JScript engines have all kinds of totally gross code in them to handle the edge case where a heavily loaded server runs out of memory just as a critical section is about to be entered.&amp;nbsp; (Yes, it happens.&amp;nbsp;Every single out-of-memory&amp;nbsp;case will eventually be exercised by a sufficiently loaded server, I know this from painful experience.)&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm going to skip all that totally gross code here and assume that we all live in the happy world of Windows XP, where the operating system actually returns sensible errors.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm still trying to sort out how all this is going to work once code blocks are throw into the mix.&amp;nbsp; I'll try out a few things and see how it goes.&amp;nbsp; More bulletins as events warrant.&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=120756" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript Part Five: Named Items and Modules</title><link>http://blogs.msdn.com/ericlippert/archive/2004/04/22/118585.aspx</link><pubDate>Fri, 23 Apr 2004 00:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:118585</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/118585.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=118585</wfw:commentRss><description>&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;Named Items
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;"Named items" are what we call the "top level" objects of the host provided object model.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;WScript&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in WSH, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;window&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in Internet Explorer, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Response&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in ASP, are all named items.&amp;nbsp; A host tells an initialized script engine about named items via the aptly named &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;AddNamedItem&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; method on the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScript&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; interface.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;HRESULT ScriptEngine::AddNamedItem(const WCHAR * pszName, DWORD flags)
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;A few things should immediately seem a little weird about this interface.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;The First Four Flags
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;First off, what are the flags?&amp;nbsp; There are six.&amp;nbsp; The first four are pretty straightforward:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_ISVISIBLE&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is set then the name of the named item is added to the global namespace.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Uh, OK&amp;#8230; why would you ever NOT want this set?&amp;nbsp; Didn't I just say that named items were specifically for injecting named object model roots into the engine?&amp;nbsp; What good is a named item if you can't see its name?
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That brings us to the second flag; if &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_GLOBALMEMBERS&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is set then all (immediate) children of the named item are treated as though they are themselves top-level objects/methods.&amp;nbsp; That's how in Internet Explorer you can say
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;window.alert("hello");
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;or 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;alert("hello");
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;and they do the same thing.&amp;nbsp; IE tells the script engine that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;window&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is a visible named item with global members.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now it makes a little more sense why you might want to have an invisible named item.&amp;nbsp; What if you had an object with lots of methods and properties that you wanted available in the global namespace, but the object itself didn&amp;#8217;t have a sensible name?&amp;nbsp; I can't think of any script host offhand that does that, but the capability is there if you need it.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;There's a second reason why you might want a named item to be invisible, but we'll get to that in a minute.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The third flag is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_ISSOURCE&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; If that's set then we know that this object is an event source.&amp;nbsp; If the language supports implicit event binding and the host moves the engine into connected state, we're going to need to know which named items to hook up to which events.&amp;nbsp; It can be very expensive to do that hookup, so this provides a simple optimization.&amp;nbsp; If the host knows that a particular named item does not source events, it can choose to not mark the named item as a source, and we therefore never spend any time trying to hook up event sinks to it.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The fourth flag is &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_ISPERSISTENT&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Recall that I said a while back that when the engine goes back to uninitialized state after being initialized, we throw away "some" named items, where "some" was to be defined later.&amp;nbsp; Now you know -- the engine remembers named items marked as persistent.&amp;nbsp; Information about those named items is not thrown away until the engine is closed.&amp;nbsp; Also, cloning an engine is basically making a copy of the uninitialized state of an engine, so persistent named items get cloned when their engine gets cloned.&amp;nbsp; As we'll see, this fact has implications for our implementation.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;Modules
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm sure you have a general idea of what I mean by a "module", though if you Google &lt;A title=http://www.google.com/search?sourceid=navclient&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;q=define%3Amodule href="http://www.google.com/search?sourceid=navclient&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8&amp;amp;q=define%3Amodule"&gt;define:module&lt;/A&gt; you'll see that everyone has a slightly different definition. &amp;nbsp;Modules in the script engine sense are philosophically fairly straightforward.&amp;nbsp; I often want to have some way to say "this collection of functions can play with each other, but are isolated from this other collection of functions".&amp;nbsp; I want to be able to resolve name collisions by having two methods with the same name coexist in different modules.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Well, I want that stuff in languages designed for "programming in the large".&amp;nbsp; When using script languages, more often than not you simply don't need to chunk stuff into modules.&amp;nbsp; But, bizarrely enough, the script engines support modules, and in a pretty goofy way at that.&amp;nbsp; Of course, any language implementor can implement module semantics however they want, but I see no reason to mess around with the de facto standards.&amp;nbsp; Here's how modules work in VBScript and JScript:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;There is a "global" module.&amp;nbsp; Procedures defined in the global module are callable from any module.&amp;nbsp; This is where the "built in" methods in VBScript and JScript go.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Every named item is associated with a unique module, with some exceptions:&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Named items with global members are associated with the global module.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Named items marked with &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_NOCODE&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;FONT color=#800080&gt;are not associated with any module&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;All visible named items are added to the global namespace, except for named items marked as &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SCRIPTITEM_CODEONLY&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;. &lt;FONT color=#800080&gt;Those are just names of modules and are associated with no object.&lt;/FONT&gt; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Important distinction: though all visible named items are added to the global module's namespace, procedures in the named items' modules are not visible from the global module.&lt;/LI&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Let me try to make this a little more concrete.&amp;nbsp; Let's consider a hypothetical declarative language that supports embedded imperative script.&amp;nbsp; You might want to have something like this:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;application&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function toggle ( x ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;if (x == false) return true else return false&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;form name="fred"&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;checkbox name="chuck" checked="false" /&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;button name="bob"&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;caption&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Hello world!&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;/caption&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;click&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fred.checked = toggle(fred.checked)&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/click&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function foo()&amp;nbsp;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // button-specific code here&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;And so on.&amp;nbsp; Suppose the host defined &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fred &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;as a visible named item with global members, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;bob &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;chuck &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;as named items each with their own module.&amp;nbsp; Then code in &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;bob&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;'s event handlers can access anything in the global application namespace and any member of &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;fred&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; But if we now add script to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;chuck&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;chuck&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;'s module cannot see &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;bob&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;'s code.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;chuck&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is free to define its own function &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;foo&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, which will not collide.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What if &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;bob&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; wants to access code in chuck's module?&amp;nbsp; We'll see in a later entry how &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;chuck&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; can do that -- there are many subtle issues involved and we'll need more infrastructure built into SimpleScript before we can tackle it.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;Where's the Object?&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;One more weird thing -- &lt;B&gt;&lt;SPAN&gt;where's the object&lt;/SPAN&gt;&lt;/B&gt;?&amp;nbsp; The method takes a name and some flags, but no object.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Let me answer that question with another question: suppose a persistent named item's object is thread affinitized, and you clone the engine and initialize the clone on a different thread?&amp;nbsp; That thing can't use the object from the previous thread!&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;To solve this problem, we defer getting the actual object until we need it.&amp;nbsp; The engine calls the site back and asks for the object.&amp;nbsp; I haven't implemented that code yet; I'll talk more about that next time.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=3&gt;&lt;SPAN&gt;The Implementation
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I've added a named item list object to SimpleScript in &lt;A title=http://blogs.msdn.com/ericlippert/articles/116369.aspx href="http://blogs.msdn.com/ericlippert/articles/116369.aspx"&gt;nameditemlist.cpp&lt;/A&gt; but I haven't quite figured out how I want to implement modules yet.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As you can see, I've rolled my own hash table rather than using &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;hash_map&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; There was quite a long series of &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/04/15/114094.aspx#114135 href="http://blogs.msdn.com/ericlippert/archive/2004/04/15/114094.aspx#114135"&gt;comments&lt;/A&gt; the other day about the pros and cons.&amp;nbsp; I chose to roll my own rather than using an off-the-shelf solution for several reasons:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL type=disc&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;the implementation does not require a rocket-science hash table.&amp;nbsp; It's very unlikely that we're going to get a huge number of named items in a script engine.&amp;nbsp; Even very complex web pages seldom add more than a couple dozen named items.&amp;nbsp; (In IE, every button, form, etc, is a named item.)&amp;nbsp; Thus, I've implemented a fixed-number-of-buckets hashing-with-chaining table with a very simple string hashing algorithm. &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I really have no clue how &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;hash_map&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;FONT color=#800080&gt;works, and I want to spend zero time debugging my way through acres of template code if there's a problem.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I realized that I was starting to succumb to &lt;A title=http://weblogs.asp.net/ericlippert/archive/2004/03/31/105329.aspx#106869 HREF="/ericlippert/archive/2004/03/31/105329.aspx#106869"&gt;Object Happiness&lt;/A&gt; as I was building a templatized hash table of my own.&amp;nbsp; I'm going to need two or three hash tables in this project all told.&amp;nbsp; And its not like templates actually make the generated code smaller or more efficient (though in C#, generics can -- but that's another story.)&amp;nbsp; I'm going to keep it simple and avoid getting Happy.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;hash_map&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;FONT color=#800080&gt;requires that&lt;/FONT&gt; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;new&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;FONT color=#800080&gt;throw exceptions.&amp;nbsp; As I've &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/03/25/96373.aspx"&gt;mentioned before&lt;/A&gt;, that gives me the shakes.&amp;nbsp; I don't like mixing C++ exception handling into what is fundamentally a COM program.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I &lt;I&gt;&lt;SPAN&gt;think&lt;/SPAN&gt;&lt;/I&gt; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;hash_map&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt; &lt;FONT color=#800080&gt;is threadsafe for the applications I'm going to use it in.&amp;nbsp; I'm not &lt;I&gt;&lt;SPAN&gt;sure&lt;/SPAN&gt;&lt;/I&gt;.&amp;nbsp; That makes me nervous.&amp;nbsp; I &lt;I&gt;&lt;SPAN&gt;am&lt;/SPAN&gt;&lt;/I&gt; sure that my own code is going to be a lot more amenable to analysis with respect to the goofy script engine threading contract.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;FONT color=#800080&gt;I ended up spending WAAAY&amp;nbsp;more time&amp;nbsp;&lt;STRONG&gt;investigating&lt;/STRONG&gt;&amp;nbsp;the template code than it took me&amp;nbsp;to write the hash table &lt;STRONG&gt;from scratch&lt;/STRONG&gt;.&amp;nbsp; I'm doing this in my&amp;nbsp;spare time here folks...&lt;/FONT&gt;&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;All those things totally outweigh the negligible benefits of re-using an existing generic map, no matter how bulletproof and performant it is.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That reminds me, I wanted to talk more about the script engine threading model.&amp;nbsp; My &lt;A title=http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx href="http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx"&gt;earlier post&lt;/A&gt; on the subject glossed over some important details.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;My team hit our Whidbey Beta One Zero Bug Bounce yesterday, so I'm off for a long weekend far, far away from computers.&amp;nbsp; I'll cut it short right now; next week I'll pick it up again and talk a bit more about the threading model, the implications of engine cloning, and I'll kick around some ideas about how to implement modules and code blocks.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=118585" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript Part Four: Finite State Machines and Script Engines</title><link>http://blogs.msdn.com/ericlippert/archive/2004/04/10/111028.aspx</link><pubDate>Sun, 11 Apr 2004 00:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:111028</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/111028.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=111028</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/04/05/108086.aspx href="/ericlippert/archive/2004/04/05/108086.aspx"&gt;Last time&lt;/A&gt; I said that I'd discuss finite state machines (also sometimes called finite state automata, same thing.)&amp;nbsp; The FSM is a fundamental idea in theoretical computer science because it models computing machinery in a very simple, abstract and general way.&amp;nbsp; Basically it goes like this:&amp;nbsp; an FSM has a &lt;B&gt;&lt;SPAN&gt;finite&lt;/SPAN&gt;&lt;/B&gt; number of &lt;B&gt;&lt;SPAN&gt;states&lt;/SPAN&gt;&lt;/B&gt; (duh).&amp;nbsp; Each state accepts a finite number of &lt;B&gt;&lt;SPAN&gt;inputs&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; Each state has &lt;B&gt;&lt;SPAN&gt;rules&lt;/SPAN&gt;&lt;/B&gt; which describe the &lt;B&gt;&lt;SPAN&gt;action&lt;/SPAN&gt;&lt;/B&gt; of the machine for every input.&amp;nbsp; An input may cause the machine to change state. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That's extremely general, I know.&amp;nbsp; Let's consider a specific example -- a machine which has two inputs: a slot that can take in quarters, and a button.&amp;nbsp; It has two outputs: quarters and gumballs.&amp;nbsp; And it has two states: GOTQUARTER and NOQUARTER.&amp;nbsp; We can chart the actions given a certain input: &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" size=2&gt;&lt;SPAN&gt;&lt;FONT color=#000080&gt;Insert Quarter&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;FONT color=#000080&gt;Press Button&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;FONT color=#000080&gt;NOQUARTER&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Change state to GOTQUARTER&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;FONT color=#000080&gt;GOTQUARTER&lt;/FONT&gt; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Output the quarter 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Output gumball, 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Change state to NOQUARTER&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That's a pretty darn simple machine.&amp;nbsp; Modern CPU's are also finite state machines -- after all, every bit in a machine can only be in two states, and there are only so many possible binary inputs from mice, keyboards, hard disks, and so on.&amp;nbsp; The number of possible states a modern computer can be in is mind-bogglingly huge -- far more than the total number of particles in the universe -- but because the rules for the state transitions are very well defined it all works out nicely.&amp;nbsp; (Because the number of states is so large, it is often more helpful to model machines as "Turing machines", which can have unlimited internal storage.&amp;nbsp; But I'm digressing.) 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The script engines use this idea of finite state machines explicitly.&amp;nbsp; A script engine has six possible states, and it performs certain actions as it transitions between those states based on "inputs".&amp;nbsp; In this case, the inputs are via calls to the various methods on the script engine.&amp;nbsp; The six states are &lt;B&gt;&lt;SPAN&gt;Uninitialized&lt;/SPAN&gt;&lt;/B&gt;, &lt;B&gt;&lt;SPAN&gt;Initialized&lt;/SPAN&gt;&lt;/B&gt;, &lt;B&gt;&lt;SPAN&gt;Started&lt;/SPAN&gt;&lt;/B&gt;, &lt;B&gt;&lt;SPAN&gt;Connected&lt;/SPAN&gt;&lt;/B&gt;, &lt;B&gt;&lt;SPAN&gt;Disconnected&lt;/SPAN&gt;&lt;/B&gt; and &lt;B&gt;&lt;SPAN&gt;Closed&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; A script engine is created by a host -- Windows Script Host, Internet Explorer, Active Server Pages, whatever.&amp;nbsp; The host is responsible for changing the script engine state as it sees fit, within the rules I'll describe over the next few entries. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The script engine begins life &lt;B&gt;&lt;SPAN&gt;Uninitialized&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; An uninitialized engine does not know anything about its host, and therefore cannot call any methods provided by the host.&amp;nbsp; There's very little you can do to an uninitialized engine, but what little you can do, you can do from any thread, subject to the rental model.&amp;nbsp; I'll talk more about threading issues later. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;There's only one way to initialize an engine, and that's to pass a pointer to the host into &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SetScriptSite&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Once an engine is &lt;B&gt;&lt;SPAN&gt;Initialized&lt;/SPAN&gt;&lt;/B&gt; it becomes apartment threaded, with a few exceptions that I'll talk about later.&amp;nbsp; There is a lot more you can do with an initialized engine -- add named items (again, more on those in the future), add script source code, and so on.&amp;nbsp; However, the code cannot actually run yet.&amp;nbsp; At this point, the most commonly used input that affects the script engine state is the appropriately named &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SetScriptState&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; method.&amp;nbsp; More on that below. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;A &lt;B&gt;&lt;SPAN&gt;Started&lt;/SPAN&gt;&lt;/B&gt; engine actually runs the script code, but does not hook up event handlers.&amp;nbsp; (I discussed implicit event binding &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/04/05/108086.aspx href="/ericlippert/archive/2004/04/05/108086.aspx"&gt;last time&lt;/A&gt;.)&amp;nbsp; Moving the engine into &lt;B&gt;&lt;SPAN&gt;Connected&lt;/SPAN&gt;&lt;/B&gt; state hooks up the event handlers.&amp;nbsp; If the host wants the event handlers to temporarily stop handling events, the hose can move the engine into &lt;B&gt;&lt;SPAN&gt;Disconnected&lt;/SPAN&gt;&lt;/B&gt; state. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That's the usual order in which things happen at startup.&amp;nbsp; To tear down the engine, the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScript::Close&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; method tears down event handlers, throws away compiled state, throws away the reference to the host and moves the engine to &lt;B&gt;&lt;SPAN&gt;Closed&lt;/SPAN&gt;&lt;/B&gt; state.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The actions associated with &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SetScriptState&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; are easiest to summarize in a table.&amp;nbsp; (Except for illegal calls, this also sets the engine state to the new value.) &lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Old State&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=1476 colSpan=6&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;New State passed to SetScriptState&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Uninitialized&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Initialized&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Started&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Connected&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Disconnected&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P align=center&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Closed&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Uninitialized&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error -- use SetScriptSite&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error - can't start an uninitialized engine&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error -- can't disconnect an unconnected engine&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Initialized&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard some named items 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Throw away host information&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Execute script code 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Execute script code 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Bind events&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard all named items and script blocks 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Throw away host information&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Started&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard some script blocks, and as above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard some script blocks&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Bind Events 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As above 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Connected&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard event bindings, and as above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard event bindings, and as above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard event bindings, execute code&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Suspend event handling&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Discard event bindings, and as above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Disconnected&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Resume event handling&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As above&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=navy size=2&gt;&lt;SPAN&gt;Closed&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error -- use SetScriptSite&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Error&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD vAlign=top width=246&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do nothing&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As you can see, I've written methods that implement these state semantics in &lt;A title=http://blogs.msdn.com/ericlippert/articles/108025.aspx href="/ericlippert/articles/108025.aspx"&gt;engine.cpp&lt;/A&gt;, though plenty of them are still stubbed out. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Next time, I want to talk more about the threading model, explain away a few oddities, and then we'll change gears for a bit and implement a simple language.&amp;nbsp; That'll get us into language design, how to expose syntax errors, and so on.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=111028" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript Part Three: Engine Skeleton</title><link>http://blogs.msdn.com/ericlippert/archive/2004/04/05/108086.aspx</link><pubDate>Tue, 06 Apr 2004 00:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:108086</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/108086.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=108086</wfw:commentRss><description>&lt;DIV&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Before I get into today's topic I want to quickly address a minor defect that Raymond Chen (who apparently spends his holiday in &lt;A title=http://www.plif.com/archive/wc146.gif href="http://www.plif.com/archive/wc146.gif"&gt;Sweden&lt;/A&gt; doing remote code-reviews, oddly enough) was good enough to point out to me.&amp;nbsp; &lt;B&gt;&lt;SPAN&gt;It is legal to unload a DLL if the only objects that depend on that DLL which are still outstanding are class factories&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; &lt;B&gt;&lt;SPAN&gt;Therefore, creating the class factory shouldn't add a reference to the DLL&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; If the consumer of the class factory wants to explicitly lock the DLL in memory, they can use the locking mechanism.&amp;nbsp; This code is wrong:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;ClassFactory::ClassFactory()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_cref = 1;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DLLAddRef();&lt;BR&gt;}
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Why is that the case?&amp;nbsp; Why not just use the convention that class factory instances lock the DLL, and if you want the DLL locked, you keep the class factory alive?&amp;nbsp; Because, though that logic makes perfect sense if the class factory is constructing in-process objects, it does not work if the factory is for a local (out of process) server.&amp;nbsp; How's that?&amp;nbsp; Because a local server creates class factories immediately when it starts up and destroys them only when it shuts down.&amp;nbsp; If creating a class factory locked the local server in memory, then there's an obvious circular reference; the local server would never be shut down.&amp;nbsp; Thus, the convention for all class factories is that they never lock the code in memory unless asked to, whether they're in-proc or not.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I've fixed the defect.&amp;nbsp; Thanks again, Raymond.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I've uploaded two new files, &lt;A title=http://blogs.msdn.com/ericlippert/articles/108025.aspx HREF="/ericlippert/articles/108025.aspx"&gt;engine.cpp&lt;/A&gt; and &lt;A title=http://blogs.msdn.com/ericlippert/articles/108026.aspx HREF="/ericlippert/articles/108026.aspx"&gt;engine.h&lt;/A&gt; (and hooked it up to the class factory).&amp;nbsp; Right now the engine code just knows how to create and destroy itself; no interfaces other than &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IUnknown&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; are implemented.&amp;nbsp; As you can see, over the next few entries I'm going to flesh out &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScript&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParse&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IObjectSafety&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; I already covered the purpose of &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IObjectSafety&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in detail in my series "Script and IE Security", which you can read in full by going to my &lt;A title=http://blogs.msdn.com/ericlippert/category/2574.aspx?Show=All HREF="/ericlippert/category/2574.aspx?Show=All"&gt;security archive&lt;/A&gt;.&amp;nbsp; &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/01/13/58403.aspx HREF="/ericlippert/archive/2004/01/13/58403.aspx"&gt;Part Two&lt;/A&gt; has a description of the interface.&amp;nbsp; Why are there three script interfaces instead of one, and what's with that "2"?&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;When the &lt;I&gt;&lt;SPAN&gt;original&lt;/SPAN&gt;&lt;/I&gt; script team -- this is before my time! -- designed the interfaces they realized that there were some things that were going to be common to every possible engine.&amp;nbsp; Every engine would need a way to communicate back to the host (&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SetScriptSite&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;), start and stop the engine (&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;SetScriptState&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;) and perform various threading tasks (&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;GetScriptThreadId&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, etc.)&amp;nbsp; But how do the script engines do compilation-model dependent things such as compiling up new source code?&amp;nbsp; Different engines might expose different interfaces to do these kinds of things, so the interface designers left one "base" interface, and if the host wants to use a particular compilation feature, the host and the engine can negotiate via &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;QueryInterface&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Thus,&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt; IActiveScriptParse&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; exposes two methods which expose compilation model features.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;ParseScriptText&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; takes in raw source code, parses it, and adds the resulting code to the internal state of the script engine.&amp;nbsp; If the code contains "global code" it might run, and if it contains procedures then they become available.&amp;nbsp; This is what is called when you stick a chunk of script inside a plain vanilla &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;script&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; tag in Internet Explorer.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;ParseScriptlet&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is very similar, but different -- it takes in source code for the &lt;B&gt;&lt;SPAN&gt;body of an&lt;/SPAN&gt;&lt;/B&gt; &lt;B&gt;&lt;SPAN&gt;event handler procedure&lt;/SPAN&gt;&lt;/B&gt; and adds a new event handler to the internal state.&amp;nbsp; This is what happens when you have a &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;script for="&amp;#8230;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; block.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;ParseProcedureText&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, on the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; interface is similar to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;ParseScriptlet&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in that it takes the body of a procedure.&amp;nbsp; It not only adds the function to the global state, it returns an object which, when invoked, calls the function.&amp;nbsp; In .NET-speak, it returns a &lt;B&gt;&lt;SPAN&gt;delegate&lt;/SPAN&gt;&lt;/B&gt;. This is handy in the IE event binding model where you bind events to an object by assigning a delegate to a property on the object.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The reason for the "2" is perfectly straightforward.&amp;nbsp; When we first implemented &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, we left the "name" argument off of the method.&amp;nbsp; In a later release, we got a feature request to allow the host to control the name of the delegate, so we created a new interface and called it "2".&amp;nbsp; That's all straightforward.&amp;nbsp; But if you look in the activscp header file, you'll see &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure&lt;STRONG&gt;Old&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; What's up with that, and which ones should we implement?
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The reason why we have &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedureOld&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; was going to be yet another entry in the &lt;A title=http://blogs.msdn.com/ericlippert/archive/2004/03/10/87384.aspx HREF="/ericlippert/archive/2004/03/10/87384.aspx"&gt;Aargh!&lt;/A&gt; series, but I might as well just tell the tale of woe now.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;A good design rule in COM is "&lt;I&gt;&lt;SPAN&gt;never make an important decision based on the &lt;B&gt;&lt;SPAN&gt;absence&lt;/SPAN&gt;&lt;/B&gt; of an interface&lt;/SPAN&gt;&lt;/I&gt;."&amp;nbsp; Why?&amp;nbsp; Because if you do, then yo&lt;B&gt;&lt;SPAN&gt;u are risking that your program breaks if someone implements that interface in the future.&lt;/SPAN&gt;&lt;/B&gt;&amp;nbsp; I learned this rule the hard way because very early versions of Internet Explorer made exactly that mistake.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In the early days, VBScript did not support the "delegate" model of event binding at all; VBScript uses what we call the "implicit" event binding mechanism whereby we scan the VBScript code looking for procedures with names that match the pattern "objectname underbar eventname".&amp;nbsp; When we find them, we construct the appropriate hookup code internally and everything is just fine.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;However, doing that search has a &lt;B&gt;&lt;SPAN&gt;potentially large performance cost&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; If the host decides that it doesn't need the implicit event binding model, the script engine exposes a way to prevent it from happening.&amp;nbsp; We'll discuss the details later, but for now, I'll just say that if the host wants the feature they "connect" the engine and if they don't, they "start" the engine.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Also back in the early days, JScript did not support the "implicit" model.&amp;nbsp; The IE developers therefore implemented the following (bad!) logic:
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;B&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If the engine &lt;I&gt;&lt;SPAN&gt;does not&lt;/SPAN&gt;&lt;/I&gt; support "delegate" event binding, then "connect" the engine, otherwise "start" the engine.
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/B&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That was the logic that shipped with IE4.&amp;nbsp; One day the IE5 team came to me with a feature request -- they wanted to add "delegate" style event binding to VBScript in IE5.&amp;nbsp; Piece of cake -- it was actually very easy to implement it in VBScript.&amp;nbsp; A few lines of code, add the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; interface implementation, fire it up, and&amp;#8230; uh oh.&amp;nbsp; &lt;B&gt;&lt;SPAN&gt;Implicit event binding suddenly stopped working in VBScript&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; Aargh!&amp;nbsp; It was drivin' me nuts!&amp;nbsp; By making a decision to turn a feature &lt;B&gt;&lt;SPAN&gt;off&lt;/SPAN&gt;&lt;/B&gt; based on the &lt;B&gt;&lt;SPAN&gt;absence&lt;/SPAN&gt;&lt;/B&gt; of an interface, IE ensured that we could not implement that interface, ever!
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The first thing that came to mind was "let's fix that in IE5", which, of course, we did -- IE5 used a much more sensible algorithm to determine whether to connect the engine or not.&amp;nbsp; Problem solved?&amp;nbsp; No.&amp;nbsp; That wasn't good enough, because at the time it was a supported, legal, by-design scenario to install new script engines without installing a new browser.&amp;nbsp; That meant that if an IE4 customer got the new VBScript engine, their implicit event handlers would stop working!
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;What we needed to do was to retire the old interfaces and ensure that no one would ever use them again.&amp;nbsp; &lt;I&gt;&lt;SPAN&gt;Normally&lt;/SPAN&gt;&lt;/I&gt; we'd create &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure3&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, but I wanted to ensure that no one accidentally use the old interface, so I renamed &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; to &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedureOld&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, and created a new, different &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Only JScript implements &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; and &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedureOld&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; If you implement those interfaces then IE3 and IE4 will not connect your engine.&amp;nbsp; But given that IE3 and IE4 are a pretty small percentage of the browser market these days, we will dispense with them entirely and only use the new &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IActiveScriptParseProcedure2&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I've seen this same mistake in persistence code.&amp;nbsp;(In fact, I think I may have made this same mistake myself in the VSTO2 persistence code.&amp;nbsp; I need to double check that...)&amp;nbsp; It's very easy to say &amp;#8220;If this object doesn't support such and such an interface, reconstitute it as follows&amp;#8220; and then have the reconstitution code broken when a later version&amp;nbsp;of the object adds that interface.&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Coming up: soon I'll start to flesh out the engine a little more, and add some multi-threading support.&amp;nbsp; I'll also discuss the theory and practice of the "state machine" style of programming and how the host initializes the engine.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=108086" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript Part Two: Class Factories Are Also Boring</title><link>http://blogs.msdn.com/ericlippert/archive/2004/04/01/106128.aspx</link><pubDate>Fri, 02 Apr 2004 04:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:106128</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/106128.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=106128</wfw:commentRss><description>&lt;DIV&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Before I get into it, a Lambda poster pointed me at the &lt;A href="http://www.iwebthereforeiam.com/projects/NullScript.asp" target=_blank&gt;NullScript&lt;/A&gt; project, which is a very interesting illustration of how reverse engineering works.&amp;nbsp; It's an implementation of a "null" script engine -- an engine with no language -- in ATL, which the intrepid developer created in order to try and understand how ASP works.&amp;nbsp; Typical programmer! They could have just &lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/09/18/53046.aspx" target=_blank&gt;asked me,&lt;/A&gt; but where's the fun in that?&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face=Wingdings color=purple size=2&gt;&lt;SPAN&gt;J&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I want to go well beyond the scope of the NullScript project, in several ways.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;First off, someone asked &lt;EM&gt;why not use ATL&lt;/EM&gt;?&amp;nbsp; Aside from my general distaste for the ATL style of programming, the more fundamental reason is that ATL is all about &lt;B&gt;&lt;SPAN&gt;hiding&lt;/SPAN&gt;&lt;/B&gt; the details of how COM works from you.&amp;nbsp; One of the points of this exercise is to show &lt;B&gt;&lt;SPAN&gt;how&lt;/SPAN&gt;&lt;/B&gt; it works.&amp;nbsp; In ATL, you see &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; COM_INTERFACE_ENTRY(IDispatch)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;And what does that tell you?&amp;nbsp; It's just a black box, and when you open it up, it's full of weird macros that I don't understand.&amp;nbsp; I'd much rather show you guys how this works at a &lt;B&gt;&lt;SPAN&gt;much less abstract&lt;/SPAN&gt;&lt;/B&gt; level.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Second, the point of NullScript was to have the smallest feature set that still worked, because it was being used as a probing tool, not a language tool.&amp;nbsp; I want to actually talk about practical concerns here, like good language design, how to implement IDispatch correctly, etc, not just write a logging tool.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Today, more boilerplate code.&amp;nbsp; I've added a class factory. &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;For those of you who don't know much about COM internals, you might wonder how instantiating a COM object works.&amp;nbsp; Basically, it goes like this.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;First, there's a progid -- the human-readable string that describes the object you want to create.&amp;nbsp; As I mentioned yesterday, we create registry keys for the progid that map it to a class id&amp;#8230;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;HKCR\&lt;FONT color=#006400&gt;SimpleScript&lt;/FONT&gt;\CLSID\(Default) = "&lt;FONT color=#008000&gt;{...}&lt;/FONT&gt;"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&amp;#8230; and then map that class id to a DLL&amp;#8230;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;HKCR\CLSID\&lt;FONT color=#008000&gt;{...}&lt;/FONT&gt;\InprocServer32\(Default) = "&lt;FONT color=#008000&gt;c:\simplescript.dll&lt;/FONT&gt;"&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Thus, the registry has enough information to determine everything you need to know to actually get the code in memory -- the location of the code and the unique identifier for the class.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;To create the object, COM loads up the DLL and calls &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;DllGetClassObject&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; in &lt;A href="http://blogs.msdn.com/ericlippert/articles/105188.aspx" target=_blank&gt;dllmain.cpp&lt;/A&gt;. &amp;nbsp;It doesn't ask for an object instance, as you might expect.&amp;nbsp; Instead, it asks for a class factory -- an object that creates objects.&amp;nbsp; The class factory in &lt;A href="http://blogs.msdn.com/ericlippert/articles/105858.aspx" target=_blank&gt;classfac.cpp&lt;/A&gt; then knows how to create the actual object. &amp;nbsp;Why this indirection?&amp;nbsp; Because &amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;DllGetClassObject&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; is &lt;I&gt;&lt;SPAN&gt;fundamentally not extensible&lt;/SPAN&gt;&lt;/I&gt; but COM objects are extensible -- you can add any interface on that you like -- thus the convention is to create a COM object that does the creation work rather than put more smarts into the entrypoint.&amp;nbsp; For example, the object might implement &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_c_641e.asp" target=_blank&gt;IClassFactory2&lt;/A&gt;, which enables licensing semantics.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If you take a look at the implementation, you'll see that we have your basic class factory going here.&amp;nbsp; There's nothing fancy.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;You might wonder what the locking mechanism is for --&amp;nbsp; this is for the scenario where you know that you're going to be creating a whole bunch of objects and need to ensure that you're not unloading the DLL unnecessarily.&amp;nbsp; That's an extremely unlikely scenario for us, but I've implemented the code anyway because its cheap, easy and the right thing to do.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;As you can see, all of the objects are thread safe so far.&amp;nbsp; We'll get into the threading model of the script engine in more detail later, but as a refresher, you might want to read &lt;A href="http://blogs.msdn.com/ericlippert/archive/2003/09/18/53041.aspx" target=_blank&gt;this&lt;/A&gt;.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The class factory does everything but actually create the engine -- that's still &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;E_NOTIMPL&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;How far can we get now?&amp;nbsp; If we compile up the code, register the DLL and run it through WSH:&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;job&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;script language="SimpleScript"&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Testing&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;/script&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;&amp;lt;/job&amp;gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Then we get the DLL loaded, the class factory created, and a call to create the engine, which fails:&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;Windows Script Host: An unimplemented function was called : SimpleScript&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;We're doing pretty well so far, but we're still a long way from computing 2 + 2 or writing "hello world".&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Next time, I'll talk about the engine and site interfaces, engine state, and a skeleton of the engine interfaces, which I'll then flesh out over several entries.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=106128" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript Part One: DllMain is Boring</title><link>http://blogs.msdn.com/ericlippert/archive/2004/03/31/105329.aspx</link><pubDate>Thu, 01 Apr 2004 06:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:105329</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/105329.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=105329</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In talking with our support engineer it's just become more muddled.&amp;nbsp; I'm pretty sure now actually that the customer does not want to build a script engine, but whether they want to build a script editor, a script host or a script debugger is unclear.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Before I go on, let me take this opportunity to say that anyone who wants to create a script debugger from scratch really &lt;I&gt;&lt;SPAN&gt;is&lt;/SPAN&gt;&lt;/I&gt; crazy.&amp;nbsp; It took us &lt;I&gt;&lt;SPAN&gt;many&lt;/SPAN&gt;&lt;/I&gt; programmer-years to implement the Microsoft Script Debugger.&amp;nbsp; There are dozens of interfaces that you need to get right.&amp;nbsp; A debugger, even a simple, basic one like the MSD is a very complex piece of software.&amp;nbsp;&lt;EM&gt; I&lt;/EM&gt; don't understand how the MSD works, and therefore I'm not about to try and explain it to anyone else!&amp;nbsp; Unless you have a lot of experience developing debugging technologies and understand it inside out, I'd recommend against going anywhere near the script debugger interfaces from the debugger side.&amp;nbsp; From the engine and host sides, maybe, but not the debugger side.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm going to forge boldly ahead with my plan to develop a script engine from scratch.&amp;nbsp; And if that works out, maybe we'll do a script host as well. This will take some time, be warned.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm going to post the code so far as "articles" so that they don't show up in the feed, and then call out any "interesting" parts of the code as posts.&amp;nbsp; I've just dropped in the first few files.&amp;nbsp; So far we can register and unregister the script engine, but not actually create the engine yet.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The code should compile against VC6 or above, and I'm only testing it on Windows XP.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I don't normally like to get all legal, but I think this would be a good time to point out that standard disclaimers apply.&amp;nbsp; This code is provided as a public service.&amp;nbsp; I'm writing it from scratch in my spare time, and I don't have a phalanx of Microsoft testers ensuring that everything works.&amp;nbsp; Code is provided as-is, with no warranties expressed or implied, if you compile it and run it and the world ends, that's not my problem, etc, etc, etc.&amp;nbsp; Aside from that, you're free to do whatever you want to this code.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;OK, now that we've got that out of the way, let's take a look at what's going on here.&amp;nbsp; So far this is just your basic Windows DLL.&amp;nbsp; This is pretty boring, but hey, we're just getting going here.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In &lt;A href="http://blogs.msdn.com/ericlippert/articles/105179.aspx"&gt;simplescript.def&lt;/A&gt; we've got some boilerplate export code that says that this DLL exports the four standard functions to start up, register, unregister and shut down the DLL.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In &lt;A href="http://blogs.msdn.com/ericlippert/articles/105182.aspx"&gt;guids.h&lt;/A&gt; I define some useful guids.&amp;nbsp; So far the only thing there is the class ID for our new engine, because we'll need that when we register it.&amp;nbsp; Since the guid is a structure, it must both be declared as a symbol in the header, and somewhere actually turned into object code.&amp;nbsp; The very short &lt;A href="http://blogs.msdn.com/ericlippert/articles/105184.aspx"&gt;guids.cpp&lt;/A&gt; performs the latter task.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;In &lt;A href="http://blogs.msdn.com/ericlippert/articles/105181.aspx"&gt;headers.h&lt;/A&gt; we've got your straightforward "include the world" header file.&amp;nbsp; It might be wise to turn this into a precompiled header when this thing starts getting huge, but we'll cross that bridge when we come to it.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I am paranoid about putting assertions into my code.&amp;nbsp; The point of an assertion is to document in an active way what is known to be true about a program -- not what we hope is true, not what is true most of the time, but what must logically be true.&amp;nbsp; Assertions are better than comments because assertions will tell you if they are ever violated -- comments will not!&amp;nbsp; In &lt;A href="http://blogs.msdn.com/ericlippert/articles/105183.aspx"&gt;assert.h&lt;/A&gt; you'll see that I define a macro that determines whether a given condition is true, and some special-purpose macros that check for things like "is this memory valid?"&amp;nbsp; More on those in a minute.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I sense the outrage -- didn't &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/03/10/87384.aspx"&gt;I just say that I hated macros&lt;/A&gt;? Indeed I do, but in this case, I really like the ability to automatically determine the file and line number, and I want this stuff to be zero-impact in the retail build, so in this case they're worth it.&amp;nbsp; Notice also that I am using macros in a very specific way.&amp;nbsp; I'm not introducing new control flow primitives, etc.&amp;nbsp; No one is ever going to use this thing in an expression.&amp;nbsp; Also note that, where possible, the macro immediately calls a method which can be debugged.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;If you take a look at those methods in &lt;A href="http://blogs.msdn.com/ericlippert/articles/105186.aspx"&gt;assert.cpp&lt;/A&gt; you'll notice a few oddities.&amp;nbsp; First off, you'll notice that I do not call &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=purple size=2&gt;&lt;SPAN&gt;&lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/isbadwriteptr.asp"&gt;IsBadWritePtr&lt;/A&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; or &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=purple size=2&gt;&lt;SPAN&gt;&lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/isbadreadptr.asp"&gt;IsBadReadPtr&lt;/A&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;, because these guys are incredibly gross.&amp;nbsp; Basically, the way that &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IsBadFooPtr&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; works is that it simply attempts to do the action, wraps the attempt in a try-catch, and returns true if an exception is thrown.&amp;nbsp; If the memory really is bad because you're at the end of the stack then this can potentially fault the stack in a bad way.&amp;nbsp; If you're in a multi-threaded scenario then &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IsBadWritePtr&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; can mess up your program due to race conditions.&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Now, I realize that in this case we're talking about some debug-only code here -- if either of these ever return true then there's a major bug that's got to be fixed!&amp;nbsp; But still, they give me the shivers.&amp;nbsp; I would much rather have my assertions actually ask the operating system whether that's a good pointer than "try it an see" the way &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IsBadFooPtr&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; does.&amp;nbsp; (And in fact there &lt;EM&gt;is&lt;/EM&gt; some code in the script engines that needs to check whether a pointer is bad, and it is a main-line common scenario that it will be -- in a not-debug-only scenario like that you cannot rely on the &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;IsBad&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt; methods.&amp;nbsp; Why we have to do that is another story, which I may blog about some time.)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;And finally we come to the first bit of code that actually has semantic import -- the DLL startup, shutdown and registration code in &lt;A href="http://blogs.msdn.com/ericlippert/articles/105188.aspx"&gt;dllmain.cpp&lt;/A&gt;.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The shutdown code is straightforward -- as you will see in the next episode, we will maintain a reference count on the DLL and only shut it down when there are no outstanding references.&amp;nbsp; The startup code is even more straightforward -- we simply cache the module handle in a global variable.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;It is &lt;B&gt;&lt;SPAN&gt;extremely important&lt;/SPAN&gt;&lt;/B&gt; that the startup and shutdown code be &lt;B&gt;&lt;SPAN&gt;boring, boring, boring&lt;/SPAN&gt;&lt;/B&gt;.&amp;nbsp; If you don't understand why that is, or you feel tempted to put something cool in there, read &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/dllmain.asp"&gt;this&lt;/A&gt;, &lt;A href="http://blogs.gotdotnet.com/cbrumme/permalink.aspx/dac5ba4a-f0c8-42bb-a5cf-097efb25d1a9"&gt;this&lt;/A&gt;, &lt;A href="http://weblogs.asp.net/oleglv/archive/2003/12/12/43068.aspx"&gt;this&lt;/A&gt;, &lt;A href="http://weblogs.asp.net/oleglv/archive/2003/12/12/43069.aspx"&gt;this&lt;/A&gt;, &lt;A href="http://weblogs.asp.net/oldnewthing/archive/2004/01/27/63401.aspx"&gt;this&lt;/A&gt; and &lt;A href="http://weblogs.asp.net/oldnewthing/archive/2004/01/28/63880.aspx"&gt;this&lt;/A&gt;. &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The registration code is the only code that's interesting at all here, and even it is pretty boring.&amp;nbsp; First off, take a look at the coding style of &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;DllRegisterServer&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;.&amp;nbsp; Except in some specific exceptions, the code I write in this sample is going to be brain-dead obvious insofar as the error code paths and object lifetimes are concerned.&amp;nbsp; Almost every method I write will follow this pattern:&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;if internal method, assert arguments are good.&amp;nbsp; If public method, check arguments for validity.&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Initialize everything that needs to be freed later to NULL.&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Initialize out parameters to NULL.&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Do stuff.&amp;nbsp; If you get an error, go to the bottom of the function&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Fill in &amp;#8220;out&amp;#8221; parameters&lt;/SPAN&gt;&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Free everything &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Glancing through the code now, I see that there are a few places where I forgot to assert that input strings were valid.&amp;nbsp; I'll fix those up later.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Does this technique produce long, boring routines that emphasize the error handling and make it harder to see what the function is doing in the mainline case?&amp;nbsp; Yes.&amp;nbsp; But error handling and cleanup is sufficiently important that it is worth calling out -- I need to make sure that it is right, and the best way I know to do that is to make it obvious what everything is doing.&amp;nbsp; And besides, I'm going to keep the routines short enough that it should be fairly easy to see what they're doing even if every line of &amp;#8220;main line&amp;#8220; code has three lines of error handling to go with it.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The registration code creates these keys:&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Console" color=navy size=2&gt;&lt;SPAN&gt;HKCR\SimpleScript\(Default) = "SimpleScript Language Engine"&lt;BR&gt;HKCR\SimpleScript\OLEScript&lt;BR&gt;HKCR\SimpleScript\CLSID\(Default) = "{...}"&lt;BR&gt;HKCR\CLSID\{...}\(Default) = "SimpleScript Language Engine"&lt;BR&gt;HKCR\CLSID\{...}\OLEScript&amp;nbsp;&lt;BR&gt;HKCR\CLSID\{...}\ProgID\(Default) = "SimpleScript"&lt;BR&gt;HKCR\CLSID\{...}\InprocServer32\(Default) = "c:\simplescript.dll"&lt;BR&gt;HKCR\CLSID\{...}\InprocServer32\ThreadingModel = "Both"&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;as well as some category keys that say "this thing is a script engine".&amp;nbsp; The "OLEScript" tags are for backwards compatibility with VERY old script hosts, like in the Win16 timeframe -- strictly speaking I would imagine that they are no longer necessary, but it doesn't hurt.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;The only thing interesting about the unregister code is that it &lt;STRONG&gt;fails silently&lt;/STRONG&gt;.&amp;nbsp; Actually writing code that checks the error conditions, determines whether the keys couldn't be deleted because (a) they're not there, (b) they are there but you can't see them because you don't have access or (c) they are there but you don't have access to delete them is a pain in the rear.&amp;nbsp; It's not great that this fails silently when a non-admin tries to unregister the engine, but I'm not going to lose any sleep over it.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Next time, I'll build on this foundation a bit by adding a class factory and the skeleton of a script engine.&amp;nbsp; Then we can get into the actual script interfaces.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=105329" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item><item><title>SimpleScript, Part Zero</title><link>http://blogs.msdn.com/ericlippert/archive/2004/03/29/101254.aspx</link><pubDate>Mon, 29 Mar 2004 17:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:101254</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/101254.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=101254</wfw:commentRss><description>&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm going to embark upon something ambitious here.&amp;nbsp; I got an email from Mike, our friendly support engineer on the east coast with the subject line "&lt;B&gt;&lt;SPAN&gt;Need lots of info&lt;/SPAN&gt;&lt;/B&gt;".&amp;nbsp; Apparently he was contacted by a customer who wants to implement a &lt;STRONG&gt;new script engine&lt;/STRONG&gt; that &lt;STRONG&gt;supports debugging&lt;/STRONG&gt;, and, here's the part that you've got to really grit your teeth over: &lt;STRONG&gt;in C#.&lt;/STRONG&gt;&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;My initial response was, of course, &lt;EM&gt;"They're crazy -- talk them out of it!"&lt;/EM&gt;&amp;nbsp; Not to put too fine a point on it, that's an immense amount of work in any language.&amp;nbsp; But C#? The script interfaces were designed long, long before there was managed code.&amp;nbsp; It's quite likely that it's going to be very hard to write a straightforward interop layer for those interfaces.&amp;nbsp; "Could they use the managed IVsa interfaces instead?" I asked Mike. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I haven't heard back yet, but I got to thinking last night that maybe it would be interesting to develop a script engine from scratch, describing every interface as I implement it, giving some of the design history behind the interfaces, etc, etc, etc.&amp;nbsp; I could start it in C++ and then see whether there were ways to make it work well in managed code, etc. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I could then blog a little bit of the code every few days.&amp;nbsp; This would keep me in blog topics for weeks, certainly.&amp;nbsp; Probably months.&amp;nbsp; All of this stuff happens in my spare time, and I have precious little of that, particularly given the number of bugs I have to fix before the Whidbey beta.&amp;nbsp; But I'll see what I can do. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;I'm not sure that a piecemeal daily blog approach is even the right way to handle this kind of material, but I'm willing to make the experiment.&amp;nbsp; 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;This is probably how it will go: 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Phase One: Basic Infrastructure&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;dll entrypoints&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;registration&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;class factory&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;engine skeleton 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Phase Two: Building the engine&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;script engines as state machines&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;threading concerns&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;named items&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;event handling 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Phase Three: Processing the language&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;grammar&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;lexer&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;parser&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;code generator&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;interpreter&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;runtime library 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Phase Four: Debugger support&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;breakpoints&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;evaluation&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;syntax colouring&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;context 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;Phase Five: Managed Code&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;SPAN&gt;-&lt;FONT face="Times New Roman" size=1&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;? 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Lucida Sans Unicode" color=purple size=2&gt;&lt;SPAN&gt;That's just off the top of my head.&amp;nbsp; We'll probably mix it up a bit as we go. 
&lt;P&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=101254" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/COM+Programming/default.aspx">COM Programming</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/SimpleScript/default.aspx">SimpleScript</category></item></channel></rss>