I'm announcing restrict mode for JavaScript, a proper subset of the
language designed for improved program robustness. It's opt-in similar
to ES5 strict mode and enabled with a string literal ("use
restrict";). Continue reading for an explanation of how it works and
why I think it's useful.

Operator semantics in regular (I call it loose) JavaScript are
complex. In many cases the increased capabilities of this complexity
doesn't really outweigh the drawbacks, which include less robust
programs and a language that's both harder to learn for the beginners
and harder to reason about for the experts.

Of course, this is nothing new. The idea of writing programs that for
example perform advanced number arithmetics on operands of type
strings seems silly. Still, the language lets us do exactly that. I'm
arguing that much of the operator semantics complexity in the
language, with corresponding type coercion, is not wished for. If we
could make some of it go away, fewer bugs would hide and our programs
would become more robust. It may also become even more fun to write
and debug them.

This was discovered years ago when people started recommending the use
of the (strict) === operator instead of the (loose) == operator, and
the same for !== vs !=. It's entirely possible to write programs
without using the == operator at all, and many programmers have chosen
to do so. The result? More robust programs that are easier to reason
about. For a beginner, it's also a programming style that's easier to
learn and master.

The problem is that there is no strict version of the (loose) <
operator. Or >, <= , >=, + or - and so on and so forth. Because these
are loose and loose-only, we've kind of accepted them as-is and moved
on. Imagine for a second what would happen if you suddenly had strict
versions of these operators available, with the possibility of making
the strict versions the default for parts of your program. How would
you then define the strict version of <? I bet you wouldn't want it to
accept an operand of primitive type number and another of primitive
type string, since that would most likely be a bug in your program.
Would you want it to accept undefined < 3? I bet not. Perhaps you
would like to get notified as early as possible with an exception if
your strict rules are broken?

Here's the thing. We already limit ourselves to a subset of the
semantics for these operators. At least we try to. We don't mix
strings, numbers and booleans randomly. We don't perform arithmetics
to undefined, on purpose. We try to be in control of when type
conversion happens, and so on. It's just that we don't necessarily use
precisely the same subset, because we haven't really though about what
we should be restricting our programs to. And we don't have any good
means of getting notified as soon as we break that subset. We would
like to, because no matter how good we are at this language, we still
have to fix defects in our code. Defects some of which are related to
breaking the subset.

As you might have guessed by now I've defined such a subset and
created a tool that modifies a JavaScript program so that it throws an
exception whenever the subset is broken. I call the subset restrict
mode for JavaScript and would like to get your feedback on it. It's
opt-in similar to ES5 strict mode, and you can easily opt-out for any
part of your program. The tool is called restricter. It's a plugin for
JSShaper, an extensible framework for JavaScript syntax tree shaping.

The restricter-modified program should be used when running your test
suite. Since restrict mode is a proper subset of regular JavaScript,
you can still deploy the original program.

Here are the restrict mode rules:

0. === and !==
   are already strict by default, with identical semantics in
   restrict mode
1. == and !=
   are restricted to undefined == null (true) and
   undefined != null (false). They are otherwise only allowed
   when the === or !=== operator yields an identical result
2. + < <= >= >
   are restricted to primitive strings or numbers
   (but never a mix)
3. - * / % & | ^ ~v << >> >>> -v ++v v++ --v v--
   are restricted to primitive numbers
4. That's it!
   +v !v && || ?: o[k] and all other operators
   have identical semantics in restrict mode

Many programs already conform to most of these rules, with the notable
exception of the restrict + operator in clause 2. In restrict mode you
can no longer use str + nostr to perform string conversion and
concatenation at the same time. You can easily replace this with a
call to a string-formatting function (I use Fmt) or an explicit
conversion via String(nostr).

Clause 1 is a compromise and may need to change. I'd rather see ==
and != disallowed but there seem to be many programs relying on the
undefined == null behavior. For now I've added a pedantic setting
where it's disallowed.

I'd like to hear your thoughts on all this. Does restrict mode
resonate with you and if so, do the rules define the right subset?

I have a preliminary web site up at http://restrictmode.org/ with more
information. You can try restrict mode live in your browser by
following the "Try restrict mode" link. Source code for JSShaper is
available at https://github.com/olov/jsshaper.


/Olov

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/[email protected]/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/[email protected]/

To unsubscribe from this group, send email to
[email protected]

Reply via email to