Skip to content
knutkj edited this page Oct 7, 2012 · 2 revisions

First of all you may want to read my blog post with information about Design by Contract (DbC), DbC preconditions and the motivation behind the Call by Contract (CbC) JavaScript library. You can find it here:

http://knutkj.wordpress.com/2012/03/11/call-by-contract-cbc-javascript-library/

Call by Contract is a JavaScript library with function argument assertions, a function parser and assertion wrapper functionality. The interface is fluid and specially optimised for the Visual Studio JavaScript IntelliSense. The library can be installed in Visual Studio with the NuGet Package Manager Console like this:

 Install-Package cbc

Include the JavaScript file Scripts\cbc.js or the minified version Scripts\cbc.min.js for all CbC functionality.

Table of Contents

cbc.assert

The current version contains these assertions:

  • defined: asserts that the parameter has been specified, that the argument is not undefined
  • notNull: asserts that the argument is not null
  • bool: asserts that the argument is of type Boolean if argument is not undefined or null
  • func: same as bool but asserts that the argument is of type Function
  • number: same as bool but asserts that the argument is of type Number
  • object same as bool but asserts that the argument is of type Object
  • string same as bool but asserts that the argument is of type String
  • notEmpty may only be combined with the string assertion and asserts that the argument is not an empty string
Here are some examples:
function showMessage (message) {
    cbc.assert.that.param("message", message).is // .that may be omitted
        .defined()
        .and.notNull()
        .and.string()
        .and.notEmpty(); // May only be specified after string assertion
    alert(message);
}

function incrementCounter (num) {
    $.assert.param("num", num).is // If jQuery is included
        .defined().and.notNull().and.number();
    counter += num;
}

cbc.parse

The cbc.parse namespace contains a function parser. The parser searches for function metadata. It returns a cbc.parse.FuncInfo object. If there are any parameters the FuncInfo object will have a list of cbc.parse.ParamInfo objects. Use the get_params method to get the list.

Here is the complete list of what the function parser searches for:

  • Name of the function
  • Function description (in Visual Studio JavaScript doc comments)
  • Parameters:
    • Name of parameter
    • Type of parameter (in JavaScript doc comments)
    • If the parameter may be null (in JavaScript doc comments)
    • If the parameter is optional (in JavaScript doc comments)
    • Parameter description (in JavaScript doc comments)
  • Function return type (in JavaScript doc comments)
  • Function return description (in JavaScript doc comments)
Here is a sample on how to use the function parser:
cbc.parse.func(cbc.parse.func).toString()
The result of the line above generates API documentation for the cbc.parse.func function:
NAME
    func

SYNOPSIS
    Parses the specified function.

SYNTAX
    <[[FuncInfo object|cbc.parse.FuncInfo]]> func(Function func)

PARAMETERS
    -func <Function>
        The function to parse.

OUTPUTS
    <[[FuncInfo object|cbc.parse.FuncInfo]]>
        A FuncInfo object.

You may also use cbc.parse.getDoc to get a function's Visual Studio doc comments:

NAME
    getDoc

SYNOPSIS
    Get the function's Visual Studio JavaScript doc comments.

SYNTAX
    <String> getDoc(String funcString)

PARAMETERS
    -funcString <String>
        The result of a function's toString.

OUTPUTS
    <String>
        The function's Visual Studio JavaScript doc comments.

cbc.contract

The cbc.contract namespace contains a wrapper function (cbc.contract.wrap). The wrapper function creates a wrapper function with parameter assertions. It uses cbc.assert for assertions. It uses Visual Studio JavaScript doc comments to find out which assertions to apply. It uses cbc.parse to find the doc comments. Here is a sample of its usage:

function toBeWrapped (a) {
    /// <param name="a" type="String" mayBeNull="false" optional="false" />
}

var wrapper = cbc.contract.wrap(toBeWrapped);

try { wrapper(); }
catch (e) { console.log(e.message); }
try { wrapper(null); }
catch (e) { console.log(e.message); }
try { wrapper(1); }
catch (e) { console.log(e.message); }

Here are the messages that was logged to the console:

Parameter a must be specified.
Parameter a must not be null.
Parameter a must be of type string.

The wrapper function looks like this:

function (a) {
    /// <param name="a" type="String" mayBeNull="false" optional="false" />
    cbc.assert.param("a", a).is.defined().and.notNull().and.string();
    return func.apply(this, arguments);
}

Here is the cbc.contract.wrap function's API documentation:

NAME
    wrap

SYNOPSIS
    Wraps the specified function inside a contract.

SYNTAX
    <Function> wrap(Function func)

PARAMETERS
    -func <Function>
        The function to wrap inside a contract.

OUTPUTS
    <Function>
        The wrapped function.

Links

Clone this wiki locally