jsContract – Code contracts for Javascript

I have recently started using code contracts in one of my .net projects and I came to think that since most of the code I produce these days are in Javascript, why don’t I try it there to!

Well, easier said than done – there just is no decent frameworks for this.

During my searching I found some references to libraries such as Cerny.js and ecmaDebug, but these just didn’t make the cut  - they all required heavy (and hard to follow) restructuring of your code to make them work.

So what did I do? Well I made jsContract, a library that is clean and .. wait for it .. extremely easy to use!

If you want a quick view on what Code Contracts can give you, take a look at this example!

The following method comes from the sample code in the link above

    function _internalMethod(a, b){
        Contract.expectNumber(a);
        Contract.expectNumber(b);
        Contract.expectWhen(config.mode === "divide", b > 0, "Divisor cannot be 0");
        Contract.expectWhen(config.mode === "multiply", a > 0 && b > 0, "The multiplicands cannot be 0");
        Contract.guaranteesNumber();
        Contract.guarantees(function(result){
            return result > 0;
        }, "Result must be > 0");

        if (config.mode == "divide") {
            return a / b;
        }
        // At this point config.mode must be "multiply"
        return a * b;
    }

As you can see, the contract statements does not ruin the flow of the code, rather, it helps to document it.
By looking at the contract at the start of the method, you can instantly see what the method expects and what it will return.
This also helps you reduce code since you do not need to check for conditions that are not allowed according to the contract.

Postconditions

So, you might be wondering about how the Contract.guarantees methods work? How can a statement placed in the head of the method possibly check the return value of the method?
Well, the above code will actually not check the return value when run, but by running it through  Contract.instrument we can get code that will!
This is the output created by Contract.instrument for the above code

    function _internalMethod(a, b){
        arguments.callee.isInstrumented = true;
        /*preconditions*/
        Contract.expectNumber(a);
        Contract.expectNumber(b);
        Contract.expectWhen(config.mode === "divide", b > 0, "Divisor cannot be 0");
        Contract.expectWhen(config.mode === "multiply", a > 0 && b > 0, "The multiplicands cannot be 0");
        var __return = (function(a, b){
            if (config.mode == "divide") {
                return a / b;
            }
            // At this point config.mode must be "multiply"
            return a * b;
        }(a, b));
        /*postconditions*/
        Contract.guaranteesNumber(__return);
        Contract.guarantees(__return, function(result){
            return result > 0;
        }, "Result must be > 0");
        return __return;
    }

As you can see the code block has been wrapped in an anonymous function, the postconditions has been moved below this and has been rewritten so that they take the result as an argument.

We now have both pre- and postconditions checking our code!

The framework handles nested functions just as you would expect it to and the only real change to your code is the extra anonymous function that is inserted when the parser finds a postcondition in use.

But now you might be wondering, how do we get the instrumented code in to our applications?

For this you have several options

  • Use tools like this to convert the code for you before pasting it into a js file
  • Use it as a part of you build process for automated generation
    • a commandline tool will be available shortly
  • Use dynamic loading and instrumentation at runtime

The last option is only viable for development scenarios, but that is mainly when code contracts are needed anyways.
To load scripts dynamically you can either use your own AJAX code, or use the built in Contract.load method

The following code is taken from the  example available with the framework

var instrument = (location.search && location.search.indexOf("instrument=true") !== -1);
Contract.load("MyClass.js", instrument, function(){
    try {
        var myClass = new MyClass({
            mode: "multiply"
        });

        var result = myClass.publicMethod(34, 5, 3);
    }
    catch (ex) {
        alert(ex.message);
    }
});

This code loads regular or instrumented code depending on the query string.

Doesn’t it look cool?

Its available at github and will most likely be licensed with an MIT style license.

Anybody want to join in, maybe help with some documentation etc?

Drop me a note if so!

Note: This is the first draft, I started this project today.

The parser is quite naive and strings matching ‘function(‘ etc and unmatched { and } in comments  will break it. But this is a work in progress :)

Update 1 04.02: { and } in comments are now safely handled, and several small issues has been corrected.

Now I only need to validate that the functions the parser finds are not part of a comment.

Update 2 04.02: The parser has now been fixed, it now completely ignores anything in the comments. As far as I know this means that as long as the code validates the parser should be solid as a rock!

Tags: , , ,

This entry was posted on Wednesday, February 3rd, 2010 at 23:01 and is filed under jsContract, programming. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.