contracts-js
Version:
A contract library for JavaScript
538 lines (504 loc) • 25.8 kB
HTML
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>Contracts.js Documentation</title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href='http://fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="style/sweetprism.css">
<script type='text/javascript'>
window.onload = function() {
document.body.className = "language-javascript";
Prism.highlightAll();
}
</script>
<link href='style/prism.css' rel='stylesheet' />
<script src="style/prism.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
body {
width: 600px;
margin: 0 auto;
position: relative;
top: 75px;
}
#logo {
float: left;
width: 275px;
}
#content {
float: left;
width: 650px;
padding-bottom:50px;
}
h1,h2,h3 {
font-family: Helvetica Neue;
font-weight: 100;
color: #222;
position: relative;
text-transform: uppercase;
color: #444;
font-family: 'Lato', Helvetica Neue, Helvetica, Arial, sans-serif;
font-weight: 100;
border-bottom: solid 1px #eee;
}
h1 {
font-size: 200%;
}
h2 {
font-size: 150%;
}
h3 {
font-size: 120%;
}
p, li {
font-family: 'Source Sans Pro', sans-serif;
/*font-weight: 400;*/
font-size: large;
}
p code {
font-size: 14px;
}
li code {
font-size: 14px;
}
a {
text-decoration: none;
}
a:hover, a:focus {
text-decoration: underline;
}
.editor { display : none }
/* to display output of macro expansions */
.console {
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
padding: 1em;
margin-top:1em;
white-space: pre;
background: #f5f2f0;
resize: vertical;
max-height: 700px;
overflow: auto;
font-family: Consolas, Monaco, "Andale Mono", monospace;
text-shadow:0 1px white;
display:none;
}
</style>
</head>
<body>
<header>
<h1 class="title">Contracts.js Documentation</h1>
</header>
<nav id="TOC">
<ul>
<li><a href="#introduction"><span class="toc-section-number">1</span> Introduction</a></li>
<li><a href="#installation"><span class="toc-section-number">2</span> Installation</a></li>
<li><a href="#using"><span class="toc-section-number">3</span> Using</a></li>
<li><a href="#contracts"><span class="toc-section-number">4</span> Contracts</a><ul>
<li><a href="#basic-contracts"><span class="toc-section-number">4.1</span> Basic Contracts</a><ul>
<li><a href="#regular-expressions"><span class="toc-section-number">4.1.1</span> Regular Expressions</a></li>
<li><a href="#custom-predicate-contracts"><span class="toc-section-number">4.1.2</span> Custom Predicate Contracts</a></li>
</ul></li>
<li><a href="#function-contracts"><span class="toc-section-number">4.2</span> Function Contracts</a><ul>
<li><a href="#optional-arguments"><span class="toc-section-number">4.2.1</span> Optional Arguments</a></li>
<li><a href="#higher-order-arguments"><span class="toc-section-number">4.2.2</span> Higher-Order Arguments</a></li>
<li><a href="#contracts-on-this"><span class="toc-section-number">4.2.3</span> Contracts on <code>this</code></a></li>
<li><a href="#dependent-contracts"><span class="toc-section-number">4.2.4</span> Dependent Contracts</a></li>
</ul></li>
<li><a href="#object-contracts"><span class="toc-section-number">4.3</span> Object Contracts</a><ul>
<li><a href="#optional-properties"><span class="toc-section-number">4.3.1</span> Optional Properties</a></li>
<li><a href="#method-contracts"><span class="toc-section-number">4.3.2</span> Method Contracts</a></li>
<li><a href="#proxied-objects"><span class="toc-section-number">4.3.3</span> Proxied Objects</a></li>
</ul></li>
<li><a href="#array-contracts"><span class="toc-section-number">4.4</span> Array Contracts</a><ul>
<li><a href="#repeated-fields"><span class="toc-section-number">4.4.1</span> Repeated Fields</a></li>
<li><a href="#proxied-arrays"><span class="toc-section-number">4.4.2</span> Proxied Arrays</a></li>
</ul></li>
<li><a href="#combinators"><span class="toc-section-number">4.5</span> Combinators</a><ul>
<li><a href="#or"><span class="toc-section-number">4.5.1</span> <code>or</code></a></li>
<li><a href="#and"><span class="toc-section-number">4.5.2</span> <code>and</code></a></li>
</ul></li>
<li><a href="#naming-contracts"><span class="toc-section-number">4.6</span> Naming Contracts</a></li>
<li><a href="#recursive-contracts"><span class="toc-section-number">4.7</span> Recursive Contracts</a></li>
<li><a href="#parametric-polymorphism"><span class="toc-section-number">4.8</span> Parametric Polymorphism</a></li>
</ul></li>
<li><a href="#faq"><span class="toc-section-number">5</span> FAQ</a><ul>
<li><a href="#do-i-have-to-use-macros"><span class="toc-section-number">5.1</span> Do I have to use macros?</a></li>
<li><a href="#what-is-up-with-the-import"><span class="toc-section-number">5.2</span> What is up with the import?</a></li>
<li><a href="#what-about-blaming-modules"><span class="toc-section-number">5.3</span> What about blaming modules?</a></li>
<li><a href="#how-can-i-disable-contracts-in-production"><span class="toc-section-number">5.4</span> How can I disable contracts in production?</a></li>
</ul></li>
</ul>
</nav>
<h1 id="introduction"><span class="header-section-number">1</span> Introduction</h1>
<p>Contracts.js is a contract library for JavaScript that allows you to specify invariants between parts of your code and have them checked at runtime for violations.</p>
<h1 id="installation"><span class="header-section-number">2</span> Installation</h1>
<p>Requires <a href="http://sweetjs.org">sweet.js</a> which you can install via npm:</p>
<pre><code>npm install -g sweet.js
npm install contracts-js</code></pre>
<h1 id="using"><span class="header-section-number">3</span> Using</h1>
<p>At the top of your file you will need to use some special syntax to import contracts.js:</p>
<pre class="js"><code>import @ from "contracts.js"
// rest of your code goes here...</code></pre>
<p>This looks like ES6 modules but it's not really and will work with whatever module system you are using (if any). See <a href="#what-is-up-with-the-import">here</a> for details.</p>
<p>Compile your JavaScript file with sweet.js using the contracts.js module:</p>
<pre><code>sjs --module contracts-js/macros -o output.js input.js</code></pre>
<p>Then run your <code>output.js</code> file in any JavaScript environment. Some features of contracts.js (eg. proxied objects and arrays) require ES6 features which not every JavaScript engine supports right now (any recent version of Firefox is fine along with node.js/V8 with the <code>--harmony</code> flag enabled).</p>
<p>If you want to disable contract checking (eg. for a production build) you can use the disabled contracts module:</p>
<pre><code>sjs --module contracts-js/macros/disabled.js -o output.js input.js</code></pre>
<h1 id="contracts"><span class="header-section-number">4</span> Contracts</h1>
<p>Put a contract on a function like this:</p>
<pre class="js"><code>@ (Num) -> Num
function id(x) {
return x;
}</code></pre>
<p>Then when the function's contract is violated you'll get a really nice error message:</p>
<pre class="js"><code>id("a string");
/*
Error: id: contract violation
expected: Num
given: 'a string'
in: the 1st argument of
(Num) -> Num
blaming: (calling context for id)
*/</code></pre>
<h2 id="basic-contracts"><span class="header-section-number">4.1</span> Basic Contracts</h2>
<p>Contracts.js comes with a number of basic contracts that check for first-order properties (things like <code>typeof</code> checks).</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;">Contract</th>
<th style="text-align: left;">Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><code>Num</code></td>
<td style="text-align: left;">A value that is <code>typeof</code> number</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code>Str</code></td>
<td style="text-align: left;">A value that is <code>typeof</code> string</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code>Bool</code></td>
<td style="text-align: left;">A value that is <code>typeof</code> boolean</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code>Odd</code></td>
<td style="text-align: left;">A value that is odd (<code>val % 2 === 1</code>)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code>Even</code></td>
<td style="text-align: left;">A value that is even (<code>val % 1 === 0</code>)</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code>Pos</code></td>
<td style="text-align: left;">A positive number(<code>val >= 0</code>)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code>Nat</code></td>
<td style="text-align: left;">A natural number (<code>val > 0</code>)</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code>Neg</code></td>
<td style="text-align: left;">A negative number (<code>val < 0</code>)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code>Any</code></td>
<td style="text-align: left;">Any value</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code>None</code></td>
<td style="text-align: left;">No value (not terribly useful)</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code>Null</code></td>
<td style="text-align: left;">The <code>null</code> value</td>
</tr>
<tr class="even">
<td style="text-align: left;"><code>Undefined</code></td>
<td style="text-align: left;">The <code>undefined</code> value</td>
</tr>
<tr class="odd">
<td style="text-align: left;"><code>Void</code></td>
<td style="text-align: left;">Either <code>null</code> or <code>undefined</code></td>
</tr>
</tbody>
</table>
<h3 id="regular-expressions"><span class="header-section-number">4.1.1</span> Regular Expressions</h3>
<p>You can test that a value matches a regular expression by using a regular expression literal:</p>
<pre class="js"><code>@ (/username:\s*[a-zA-Z]*$/) -> Bool
function checkUsername(str) {
// ...
return true;
}
checkUsername("username: bob"); // passes
checkUsername("user: bob"); // fails</code></pre>
<h3 id="custom-predicate-contracts"><span class="header-section-number">4.1.2</span> Custom Predicate Contracts</h3>
<p>All of the basic contracts are built with predicates (functions that take a single value and return a boolean) and you can make your own:</p>
<pre class="js"><code>function MyNum(val) {
return typeof val === "number";
}
@ (MyNum) -> MyNum
function id(x) { return x; }</code></pre>
<p>There is also ES6 arrow function shorthand syntax for defining predicate contracts inside of a function or object contract:</p>
<pre class="js"><code>@ ((val) => typeof val === "function") -> Num
function id(x) { return x; }</code></pre>
<h2 id="function-contracts"><span class="header-section-number">4.2</span> Function Contracts</h2>
<p>Function contracts take a comma delimited list of argument contracts and a single return value contract:</p>
<pre class="js"><code>@ (Str, Num, Bool) -> Bool
function foo(s, n, b) { return b; }</code></pre>
<h3 id="optional-arguments"><span class="header-section-number">4.2.1</span> Optional Arguments</h3>
<p>You can make an argument optional with the <code>?</code> prefix:</p>
<pre class="js"><code>@ (Str, ?Bool) -> Str
function foo(s, b) { return s; }
foo("foo"); // fine
foo("foo", false); // fine
foo("foo", "bar"); // error</code></pre>
<h3 id="higher-order-arguments"><span class="header-section-number">4.2.2</span> Higher-Order Arguments</h3>
<p>You can put contracts on functions to functions. And blaming the correct party at fault even works! <a href="#what-about-blaming-modules">Mostly</a>.</p>
<pre class="js"><code>@ (Num, (Num, Num) -> Num) -> Num
function (x, f) { return f(x, x); }</code></pre>
<h3 id="contracts-on-this"><span class="header-section-number">4.2.3</span> Contracts on <code>this</code></h3>
<p>You can put a contract on the <code>this</code> object of a function:</p>
<pre class="js"><code>@ () -> Str
| this: {name: Str}
function f() { return this.name; }
var o = {
nam: "Bob", // typo
f: f
};
o.f();</code></pre>
<p>This will let you know you did something wrong:</p>
<pre style="color: red">
f: contract violation
expected: Str
given: undefined
in: the name property of
the this value of
() -> Str
| this: {name: Str}
function f guarded at line: 3
blaming: (calling context for f)
</pre>
<h3 id="dependent-contracts"><span class="header-section-number">4.2.4</span> Dependent Contracts</h3>
<p>You can also write a function contract who's result depends on the value of its arguments.</p>
<pre class="js"><code>@ (x: Pos) -> res: Num | res <= x
function square_root(x) { return Math.sqrt(x); }</code></pre>
<p>Name each argument and result with the notation <code><name>: <contract></code> and then each name can be referred to in the dependency guard following the <code>|</code>. The guard is an expression the must evaluate to a boolean. If the guard evaluates to <code>true</code> the dependent function contract will pass otherwise it fails.</p>
<p>If you need more than a single boolean expression you can wrap it in curlies:</p>
<pre class="js"><code>@ (x: Pos) -> res: Num | {
var fromlib = Math.sqrt(x);
return res <= x && fromlib === res;
}
function square_root(x) { return Math.sqrt(x); }</code></pre>
<p>Note that guards in a dependent contract could potentially violate a contract on one of the arguments:</p>
<pre class="js"><code>@ (f: (Num) -> Num) -> res: Num | f("foo") > 10
function foo(f) { return f(24) }</code></pre>
<p>In a case like this, the contract itself will be blamed:</p>
<pre style="color:red">
expected: Num
given: 'foo'
in: the 1st argument of
the 1st argument of
(f: (Num) -> Num) -> res: Num | f (foo) > 10
function foo guarded at line: 2
blaming: the contract of foo
</pre>
<p>If you are familiar with contract research, this is the <a href="http://www.ccs.neu.edu/racket/pubs/popl11-dfff.pdf">indy</a> semantics.</p>
<h2 id="object-contracts"><span class="header-section-number">4.3</span> Object Contracts</h2>
<p>Object contracts are built using familiar object literal syntax:</p>
<pre class="js"><code>@ (Str, Num) -> {name: Str, age: Num}
function makePerson(name, age) {
return {
name: name,
age: age
};
}</code></pre>
<p>Note that objects are checked against their contract only once when they cross the contract barrier (in the above example this is when the <code>makePerson</code> function returns). Basic contracts (like <code>Str</code> and <code>Num</code>) are checked immediately while method contracts are deferred until the method is invoked.</p>
<p>If you want to maintain the contract invariants throughout the object's lifetime, use <a href="#proxied-objects">proxied object contracts</a>.</p>
<h3 id="optional-properties"><span class="header-section-number">4.3.1</span> Optional Properties</h3>
<p>The <code>?</code> prefix makes a property optional:</p>
<pre class="js"><code>@ ({name: Str, age: ?Num}) -> Str
function get Name(o) { return o.name; }</code></pre>
<h3 id="method-contracts"><span class="header-section-number">4.3.2</span> Method Contracts</h3>
<p>Function contracts on an object contract will implicitly check that the <code>this</code> object bound to the function obeys the object contract:</p>
<pre class="js"><code>@ ({name: Str, hi: () -> Str}) -> Str
function foo(o) {
var hi = o.hi;
return hi(); // `this` is bound wrong
}
foo({
name: "Bob",
hi: function() {
return this.name;
}
})</code></pre>
<p>This code will give a nice error letting us know that the <code>this</code> object was wrong:</p>
<pre style="color: red">
foo: contract violation
expected: an object with at least 2 keys
given: undefined
in: the this value of
the hi property of
the 1st argument of
({name: Str, hi: () -> Str}) -> Str
function foo guarded at line: 2
blaming: function foo
</pre>
<h3 id="proxied-objects"><span class="header-section-number">4.3.3</span> Proxied Objects</h3>
<p>To maintain the object contract invariant for the entire lifetime of an object, use the <code>!</code> notation:</p>
<pre class="js"><code>@ (Str, Num) -> !{name: Str, age: Num}
function makePerson(name, age) {
return {
name: name,
age: age
};
}
var o = makePerson("Bob", 42);
o.age = "100"; // error</code></pre>
<p>This is more expensive than normal object contracts since the contract must be checked on every property set but this can help to maintain tricky invariants.</p>
<h2 id="array-contracts"><span class="header-section-number">4.4</span> Array Contracts</h2>
<p>Contracts on arrays use the familiar array literal notation:</p>
<pre class="js"><code>@ ([Num, Str]) -> Void
function foo(arr) { /* ... */ }
foo([42, "foo"]); // fine
foo([42]); // error missing field</code></pre>
<h3 id="repeated-fields"><span class="header-section-number">4.4.1</span> Repeated Fields</h3>
<p>Arrays filled with homogeneous data can use the <code>...</code> notation:</p>
<pre class="js"><code>@ ([...Num]) -> Void
function foo(arr) { /* ... */ }
foo([]); // fine
foo([42, 100, 10000, 99]); // fine
foo([42, "foo", 10000, 99]); // error wrong type</code></pre>
<p>You can even mix <code>...</code> with a prefix of normal contracts:</p>
<pre class="js"><code>@ ([Str, Bool, ...Num]) -> Void
function foo(arr) { /* ... */ }
foo(["foo", true, 100, 99]); // fine
foo([100, true, 100, 99]); // error wrong type</code></pre>
<p>The <code>...</code> contract must be the last contract in the array.</p>
<h3 id="proxied-arrays"><span class="header-section-number">4.4.2</span> Proxied Arrays</h3>
<p>Just like objects, arrays can be proxied with the <code>!</code> notation:</p>
<pre class="js"><code>@ (Num, Str) -> ![Num, Str]
function foo(a, b) { return [a, b]; }
var arr = foo(100, "foo");
arr[0] = "string"; // error wrong type</code></pre>
<h2 id="combinators"><span class="header-section-number">4.5</span> Combinators</h2>
<h3 id="or"><span class="header-section-number">4.5.1</span> <code>or</code></h3>
<p>You can combine two or more contracts with the <code>or</code> combinator. If the first contract fails, the combined contract will succeed if the second passes.</p>
<pre class="js"><code>@ (Num or Str) -> Str
function foo(x) { return x.toString(); }
foo(24); // passes
foo("24"); // passes
foo(false); // error not a Num or Str</code></pre>
<p>Note that <code>or</code> only makes sense for at most one higher-order contract. For example, <code>Num or (Num) -> Num</code> is fine but <code>(Num) -> Num or (Str) -> Str</code> will not work.</p>
<h3 id="and"><span class="header-section-number">4.5.2</span> <code>and</code></h3>
<p>You can combine two or more contracts with the <code>and</code> combinator. Both contracts must pass for the combined contract to succeed.</p>
<pre class="js"><code>@ (Num and (x) => x > 5) -> Num
function foo(x) { return x; }
foo(10); // passes
foo("10"); // fails
foo(1); // fails</code></pre>
<h2 id="naming-contracts"><span class="header-section-number">4.6</span> Naming Contracts</h2>
<p>When you have a complicated contract that is repeated in several places it can be convenient to refer to it by a shorter name. For this, you can use <code>let</code> after the <code>@</code> symbol:</p>
<pre class="js"><code>@ let NumId = (Num) -> Num
@ (NumId, Num) -> Num
function (f, x) { return f(x); }</code></pre>
<h2 id="recursive-contracts"><span class="header-section-number">4.7</span> Recursive Contracts</h2>
<p>You can define contracts that have a recursive definition naturally:</p>
<pre class="js"><code>@ let MyObj = Null or {
a: Num,
b: MyObj
}</code></pre>
<p>This definition checks that the <code>b</code> property is either a <code>null</code> or an object that satisfies the <code>{a: Num, b: MyObj}</code> contract. Note that this will explore the entire object each time a value crosses the contract boundary so it could be potentially expensive if the object is deeply nested.</p>
<h2 id="parametric-polymorphism"><span class="header-section-number">4.8</span> Parametric Polymorphism</h2>
<p>Note: requires proxies (so use Firefox out of the box or Chrome/V8/node with the <code>--harmony</code> flag).</p>
<p>Parametric polymorphic functions can be defined using <code>forall</code>:</p>
<pre class="js"><code>@ forall <name (,) ...> <contract></code></pre>
<p>Where each <code>name</code> is a contract variable to be bound in <code>contract</code>. For example, the identity function is defined as:</p>
<pre class="js"><code>@ forall a (a) -> a
function id(x) { return x; }</code></pre>
<p>The contract enforces the invariant that for all types, the value applied to <code>id</code> will be returned from the function. If the function does not obey this invariant a contract violation will be triggered:</p>
<pre class="js"><code>@ forall a (a) -> a
function const5(x) { return 5; }
const5(10);</code></pre>
<p>will throw the error:</p>
<pre style="color:red">
const5: contract violation
expected: an opaque value
given: 5
in: in the type variable a of
the return of
(a) -> a
function const5 guarded at line: 2
blaming: function const5
</pre>
<p>A key idea of parametric polymorphism is that a function cannot inspect the value of a polymorphic type (otherwise it doesn't really work "forall"). For example, the <code>inc_if_odd</code> function behaves like the identity function unless its argument is odd, which violates the parametric invariant:</p>
<pre class="js"><code>@ forall a (a) -> a
function inc_if_odd(x) {
if (x % 2 !== 0) {
return x + 1;
}
return x;
}</code></pre>
<p>So, attempting to invoke <code>inc_if_odd(100)</code> will throw the error:</p>
<pre style="color:red">
inc_if_odd: contract violation
expected: value to not be manipulated
given: 'attempted to inspect the value'
in: in the type variable a of
the 1st argument of
(a) -> a
function inc_if_odd guarded at line: 2
blaming: function inc_if_odd
</pre>
<p>Note that there are a couple of operations on values that contracts.js cannot currently guard against (<code>typeof</code> in particular).</p>
<p>Polymorphic contracts also do contract inference. So, if you have a polymorphic array, contracts.js will check that the array is homogeneous:</p>
<pre class="js"><code>@ forall a ([...a]) -> [...a]
function arrayId(l) {
return l;
}
arrayId([1, 2, "three"]);</code></pre>
<p>This infers that the <code>a</code> should be a <code>Num</code> for this application of <code>arrayId</code> and then throws and error when it discovers <code>"three"</code>:</p>
<pre style="color:red">
arrayId: contract violation
expected: (x) => typeof x === 'number'
given: 'three'
in: in the type variable a of
the 2nd field of
the 1st argument of
([....a]) -> [....a]
function foo guarded at line: 2
blaming: (calling context for arrayId)
</pre>
<p>Contract inference is currently done with simple <code>typeof</code> checks.</p>
<h1 id="faq"><span class="header-section-number">5</span> FAQ</h1>
<h2 id="do-i-have-to-use-macros"><span class="header-section-number">5.1</span> Do I have to use macros?</h2>
<p>No, as a matter of fact. If you'd like to just use the library in vanilla JavaScript you can. Load contracts.js and then use the <code>guard</code> function:</p>
<pre class="js"><code>var id = guard(fun([Num], Num),
function id(x) { return x; },
"id");</code></pre>
<h2 id="what-is-up-with-the-import"><span class="header-section-number">5.2</span> What is up with the import?</h2>
<pre class="js"><code>import @ from "contracts.js"</code></pre>
<p>The short answer is that it's a hack until sweet.js provides proper module support.</p>
<p>This line is actually a macro that expands into contracts.js library code that each contracted function will refer to.</p>
<h2 id="what-about-blaming-modules"><span class="header-section-number">5.3</span> What about blaming modules?</h2>
<p>At the moment contracts.js just supports guarding the interaction of a contracted value and its context rather than tracking blame at the module level. This is because the module story in JavaScript is a bit fractured and incompatible in various ways (CommonJS, Node, AMD, ES6, rolling by hand). Earlier versions of contracts.js had hacky support that only kind of worked but this has been temporarily simplified to what we have right now.</p>
<p>Once sweet.js has good ES6 module support we will do the right thing and track blame at the module level.</p>
<h2 id="how-can-i-disable-contracts-in-production"><span class="header-section-number">5.4</span> How can I disable contracts in production?</h2>
<p>Compile with the <code>disabled.js</code> module:</p>
<pre><code>sjs --module contracts-js/macros/disabled.js -o output.js input.js</code></pre>
</body>
</html>