bebraw
9/29/2011 - 3:39 PM

Invariant checker for JavaScript

Invariant checker for JavaScript

var someObject = {
    swap: function(from, to) {
        var amount = this.getAmount();
        var gotError = checkArguments({
            from: [
                {invariant: from < 0, error: 'too small'},
                {invariant: from >= amount, error: 'too big'}
            ],
            to: [
                {invariant: to < 0, error: 'too small'},
                {invariant: to >= amount, error: 'too big'}
            ]
        }, 'someObject.swap');

        // you could throw an exception instead if you want to
        if(gotError) {
            return false;
        }

        // logic goes here
        ...
    },
    ...
};
var items = [1, 2, 3];
var index = 1;

checkIndex(index, items.length, 'items');
function checkIndex(index, amount, errorPrefix, suppressWarning) {
    function defined(value) {
        return typeof(value) !== 'undefined';
    }

    return checkArguments({
        index: [
            {invariant: !defined(index), error: 'not defined'},
            {invariant: index < 0, error: 'too small'},
            {invariant: index >= amount, error: 'too big'}
        ]
    }, errorPrefix, suppressWarning);
};
function checkArguments(errors, errorPrefix, suppressWarning) {
    errorPrefix = errorPrefix? errorPrefix + ': ': '';

    var gotError = false;

    for(var argName in errors) {
        // remember to attach forEach to Array or replace this with a more generic
        // definition
        errors[argName].forEach(function(check) {
            if(check.invariant) {
                if(!suppressWarning) {
                    var warning = errorPrefix + argName + ' ' + check.error + '.';

                    console.warn(warning);
                }

                gotError = true;
            }
        })
    }

    return gotError;
};