This post is over 6 months old. Some details, especially technical, may have changed.

Using CoffeeScript in .NET

I've been playing with node.js for a while now and some of the things coming out of that community are simply amazing.  One of the interesting techs is CoffeeScript which is essentially a JavaScript dialect that compiles into JavaScript.  It's goal is to simplify the JavaScript language by removing all those bad parts that can cause a lot of grief and taking all those common tasks (array manipulation, scoping etc and making them very very easy to achieve.  I have an old post I have yet to publish externally on the subject but I will get it out there ASAP.

CoffeeScript comes in 2 variations - a node.js specific version and a "standalone" version that can be run in browser (pure JavaScript without any of the node.js assumptions basically).  Considering it's parsing one language into another it's not recommended to be running the script client side every time so if you want to use it you want to be doing the parsing server side and possibly using some sort of caching to prevent redoing the parsing on every request.  This is the bad(ish) news for .NET folks because there really isn't any stable JavaScript implementations that can run a script as complex a CoffeeScript (this is essentially a compiler of sorts).  Well at least not until now....  When i first investigated this I tried using a number of JavaScript engines,

  • IronJS: Currently only a partial implementation and doesn't appear to run the CoffeeScript compiler fully.
  • JavaScript.NET: Worked for version 0.9 or so of CoffeeScript but there is a bug that causes version 1.0 to fall over and development appears to have ceased.
  • Command line JScript: Epic fail.  Just wouldn't do what I needed it to.

Then along came yet another JavaScript engine for .NET so I gave it a shot.  On the surface Jurassic appeared to offered everything I needed and upon diving a bit deeper I discovered that, yes, it does indeed offer everything I needed - it runs the CoffeeScript compiler.  Sweet.

So lets write the compiler wrapper.  Pretty basic really,

/// <summary>
/// Processes CoffeeScript files into javascript
/// </summary>
public class CoffeeScriptProcessor
{
    private static readonly string COMPILE_TASK = "CoffeeScript.compile(Source, {bare: true})";

    [ThreadStatic]
    private static ScriptEngine _engine;
    private static object _o = new object();

    private static ScriptEngine Engine
    {
        get
        {
            if (_engine == null)
            {
                _engine = new ScriptEngine();
                _engine.Execute(Resources.CoffeeScriptSource);
            }

            return _engine;
        }
    }

    /// <summary>
    /// Precesses contents as a coffeescript file
    /// </summary>
    /// <param name="contents">The javascript contents</param>
    /// <returns></returns>
    public static string Process(string contents)
    {
        lock (_o)
        {
            try
            {
                Engine.SetGlobalValue("Source", contents);
                return Engine.Evaluate<string>(COMPILE_TASK);
            }
            catch (Exception e)
            {
                return null;
            }
        }
    }
}

Few points worth noting here,

  • I create a ThreadStatic instance of the Jurassic Engine and feed the CoffeeScript compiler source into it once.  The executions/evaluation of that script is quite slow so I only wanted to take the hit once.  Jurassic isn't thread safe so I made the reference ThreadStatic.
  • Just to be extra safe I am locking during the execution of the compilation task.
  • Any errors just return null.  This is a bare bones implementation I have stripped out custom logging and profiling code and an interface that means little in this context.

I have created a VS2010 MVC3 solution that makes use of this processor to generate JavaScript from a simple CoffeeScript example.  Have fun.

https://github.com/kouphax/coffeescript-dotnet

What's Next?

This is obviously only the start - if I wanted to use CoffeeScript in a .NET environment I am going to need to consider how it is used.  When should I be compiling it?  How should I be caching it etc?  The usual things.  Hopefully I'll touch on these in a later post.

So right now this is kind of a request for comments, this was knocked up quite quickly and likely I have forgotten something or made a massive mistake.  Anything you want to offer fire away.

Published in JavaScript .NET on January 17, 2011