Global State On Servers Considered Harmful

Global State On Servers Considered Harmful

  • Comments 5

The other day I noted that extending the built-in objects in JScript .NET is no longer legal in "fast mode".  Of course, this is still legal in "compatibility mode" if you need it, but why did we take it out of fast mode?

 

As several readers have pointed out, this is actually a kind of compelling feature.  It's nice to be able to add new methods to prototypes:

 

String.prototype.frobnicate = function(){/* whatever */}

var s1 = "hello";

var s2 = s1.frobnicate();

 

It would be nice to extend the Math object, or change the implementation of toLocaleString on Date objects, or whatever.

 

Unfortunately, it also breaks ASP.NET, which is the prime reason we developed fast mode in the first place.  Ironically, it is not the additional compiler optimizations that a static object model enables which motivated this change!  Rather, it is the compilation model of ASP.NET.

 

I discussed earlier how ASP uses the script engines -- ASP translates the marked-up page into a script, which it compiles once and runs every time the page is served up.  ASP.NET's compilation model is similar, but somewhat different.  ASP.NET takes the marked-up page and translates it into a class that extends a standard page class.  It compiles the derived class once, and then every time the page is served up it creates a new instance of the class and calls the Render method on the class. 

 

So what's the difference?  The difference is that multiple instances of multiple page classes may be running in the same application domain.  In the ASP Classic model, each script engine is an entirely independent entity.  In the ASP.NET model, page classes in the same application may run in the same domain, and hence can affect each other.  We don't want them to affect each other though -- the information served up by one page should not depend on stuff being served up at the same time by other pages.

 

Now I'm sure you see where this is going.  Those built-in objects are shared by all instances of all JScript objects in the same application domain.  Imagine the chaos if you had a page that said:

 

String.prototype.username = FetchUserName();

String.prototype.appendUserName = function() { return this + this.username; };

var greeting = "hello";

Response.Write(greeting.appendUserName());

 

Oh dear me.  We've set up a race condition.  Multiple instances of the page class running on multiple threads in the same appdomain might all try to change the prototype object at the same time, and the last one is going to win.  Suddenly you've got pages that serve up the wrong data!  That data might be highly sensitive, or the race condition may introduce logical errors in the script processing -- errors which will be nigh-impossible to reproduce and debug.

 

A global writable object model in a multi-threaded appdomain where class instances should not interact is a recipe for disaster, so we made the global object model read-only in this scenario.  If you need the convenience of a writable object model, there is always compatibility mode.

  • Question 1: Is this the reason you also enforce the use of var in fast mode? Question 2: Doesn't this make the term "fast mode" a bit of a misnomer? Shouldn't it be "ASP.NET mode"? Question 3: Out of curiosity - can you say how JScript.NET is fairing in the ASP.NET world vs. C# and VB.NET ?
  • 1) Yes -- enforcing var improves clarity, improves optimizations and prevents accidental fouling of the global namespace. 2) Don't be silly. I mean, we could have called them "incompatibility mode" and "slow mode" too, but obviously we wouldn't. Fast mode was motivated by the requirements of ASP.NET, but the benefits go beyond ASP.NET scenarios. 3) I have not the faintest idea. Remember, I haven't actually worked on JS.NET for over two years now, and even if I was, I'm a developer, not a market researcher. (I can tell you that as far as throughput performance goes, JScript.NET on ASP.NET performs about as well as VB.NET, and both are 5%-10% slower than the equivalent C# in common scenarios -- or, at least that was the case when I last ran the numbers.)
  • Ignore me I am testing.
  • Perhaps a compromise could be reached for a future version of the language. It seems most of the interesting reasons for modifying the prototypes of the built in objects are all cases that are one-time setup. If these prototypes were writable only at appdomain creation time and read-only there after I think both sides could be happy? (Not that there's any current way to implement a .cctor in JS.NET that I'm aware of.)
  • "ASP.NET mode" may be ridiculously specific, but it still seems like "fast mode" doesn't say enough: it doesn't say anything about allowing the script engine to be longer-lived or shared...

    Maybe it should be called something like "static mode"?

Page 1 of 1 (5 items)