Olov Lassus

Let's create us some Dart ranges

21 Nov 2011

We recognize the good ol’ for loop from the C-family of programming languages. It is available with the same familiar syntax and semantics in Dart, too:

for (int i = 0; i < 10; i++) {
  print(i);
}

In addition to that, Dart has a for-in loop, similar to Java in semantics (iterator(), hasNext() and next()). for-in is used to conveniently loop over any Iterable sequence, such as a List.

for (int i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
  print(i);
}

If you’re into Python then you know that over there you for loop over sequences exclusively, and use xrange extensively.

for i in xrange(0, 10):
    print(i)

xrange is quite convenient and prevents a lot of variable name stuttering. It takes up to three parameters: start, stop and step. Python xranges exclude the stop endpoint and step is 1 by default. start is 0 by default so you’ll often see xrange(len(seq)) used in Python code to iterate over sequence indices.

Back to Dart. While good ol’ for loops have been working fine for the last few decades or so, perhaps something xrange-like could be fun here too. We’ve already got for-in and iterators after all. Let’s create a Range class that implements the Iterable interface with a corresponding RangeIterator and we’ll be able to do for-in range, with top-level function range being a wrapper around the Range constructor. We’ll include both endpoints so range(0, 9) means [0, 1, .. 9]. Again step defaults to 1 so range(0, 9) is the same as range(0, 9, 1).

for (int i in range(0, 9)) {
  print(i);
}

That looks swell. No surprise it has already been discussed on dart-misc. We can also pass a range to anything that expects an Iterable. Here’s how to generate the List [0, 2, .. 8] using the List.from constructor:

var list = new List<int>.from(range(0, 8, 2));

Iterating over indices is done like so:

var str = "hellojed";
for (int i in range(0, str.length - 1)) {
  print("$i: ${str[i]}");
}

We’ll add a top-level function indices to sweeten it a bit:

for (int i in indices(str)) {
  print("$i: ${str[i]}");
}

We can make range more useful still. The Collection interface (implemented by List and Set among others) contains length, every, filter, forEach, isEmpty and some. Let’s implement those too. Now we can pass around ranges anywhere a Collection is expected, for example to addAll:

var queue = new Queue<int>();
// ...
queue.addAll(range(0, 9));

How about a List with the numbers [0, 1, .. 50] that are perfect squares:

bool isSquare(int n) => Math.pow(Math.sqrt(n).round(), 2) == n;
var squares = range(0, 50).filter(isSquare);

Or the other way around? map isn’t part of Collection but let’s add it anyways:

var squares = range(0, 7).map((e) => e * e);

The original example can also be rewritten like this, using forEach:

range(0, 9).forEach(print);

Not too shabby, all in all. Good ol’ for loops have less overhead than their for-in range equivalent but the difference is nothing to write home about, especially if your loop body does something useful. Your personal style is probably more important - as for myself I consider range a nice complement.

Check out the tests for more examples. The implementation should be easy to follow if you want to learn how to create a Collection of your own. If you want a little Dart exercise then change Range so that it only implements Iterable<int> and remove everything Collection-specific. Then add it back again guided by the unit tests, this time with your own code. Or start from scratch altogether.

Oh and the Dart for-in loop is just (very convenient) syntactic sugar of something similar to this:

for (Iterator it = range(0, 9).iterator(); it.hasNext(); ) {
  int i = it.next();
  print(i);
}

dart-range source available on github.

Show comments (Dart misc)



Dart syntax highlighting support for Pygments

27 Oct 2011

Source code is available at https://gist.github.com/1320163. Install it by appending the gist to Pygments’s agile.py and add the following line to _mapping.py.

    'DartLexer': ('pygments.lexers.agile', 'Dart', ('dart'), ('*.dart',), ('text/x-dart')),

Then run pygmentize -f html -o yourfile.html yourfile.dart to generate markup from your source code. You’ll need to combine it with a style sheet. Feel free to copy my color scheme (syntax.css) if you like it.

Dart syntax highlighting example:

// Greeter example from
// <http://www.dartlang.org/docs/getting-started/interface.html>
class Greeter implements Comparable {
  String prefix = 'Hello,';
  Greeter() {}
  Greeter.withPrefix(this.prefix);
  greet(String name) => print('$prefix $name');

  int compareTo(Greeter other) => prefix.compareTo(other.prefix);
}

void main() {
  Greeter greeter = new Greeter();
  Greeter greeter2 = new Greeter.withPrefix('Hi,');

  num result = greeter2.compareTo(greeter);
  if (result == 0) {
    greeter2.greet('you are the same.');
  } else {
    greeter2.greet('you are different.');
  }
}

Show comments (Dart misc)



Describing Live programming (again)

09 Oct 2011

It’s funny how the brain does context switching sometimes. You work really hard on something just to almost forget about it immediately after the release. You then let it be for a few years until you dare to open up that project or document again to figure out why you worked that hard on it in the first place.

Anyways. I wrote my master’s thesis in 2006 and I was really passionate about it at the time. I wanted to describe how to create a better programming environment than what we currently had without falling into the “everything has already been invented in good ol’ Smalltalk and the LISP machines” trap. I specifically focused on enabling the programmer to write and modify code at run-time, thus the name Live programming.

I was satisfied with what I accomplished. I had a prototype running that I used to test that the source code, AST and callstack transformations I described in the thesis were valid. I knew what the next step would be (post thesis) but I also knew that I didn’t have the time to invest into making a full blown implementation, so I let it be.

Almost six years has passed since then and the programming environments people use today haven’t changed much. I’m still passionate about Live programming. I figured it wouldn’t hurt to expose the concept to a new reader or two, thus this blog article.

When I wrote the thesis I was primarily interested in finding out how far I could take the concept. I picked JavaScript as the prototype language because it seemed to have momentum at the time and I guess that choice turned out well. I picked Narcissus because it was the simplest interpreter I could find. The prototype environment uses a heavily modified Narcissus (I turned it stackless/callstack-explicit) and it seems to have bitrot since then but I’ll see if I can beat the code into shape and release it out again if there’s any interest.

I still think that JavaScript is an excellent language for implementing a Live programming environment. I’d love to see one integrated directly in the browser, and also tied together with a node.js environment. It needs to be directly integrated with the JS impl, i.e. the V8, SpiderMonkey or what have you. It’s not a small feat.

So here we go: Describing Live programming using program transformations and a callstack explicit interpreter. Read chapter 1 and 2 for more info about Live programming. Read the other chapters only if you’re interested in how it works under the hood (the transformations).

Oh and I did an s/Johansson/Lassus thing in 2007, in case you wonder.

Show comments (reddit)



Seems like restrict mode found us a jQuery bug

16 Jun 2011

Feel free to skip the first paragraph if you’ve read my previous restrict mode articles.

I’ve created this thing called restrict mode for JavaScript. It’s a definition of a proper subset of the language which I believe is great because I think it increases robustness and makes your program more easy to reason about. It comes with a tool that will check if your program really complies to restrict mode, when you say it does. The tool is called restricter and is a plugin for JSShaper, an extensible framework for JavaScript syntax tree shaping. Restrict mode makes JS programming more enjoyable since it helps you focus on real programming challenges instead of annoyances/defects/inconsistencies of the JS language.

I’ve written about how I made v8bench and JSLint restrict mode clean and I promised to do the same for jQuery.

I’ve tweaked the restrict mode semantics somewhat since then:

Restrict mode is still a proper subset of the JavaScript language and will remain so. It will freeze one day but we’re not there yet.

Back to jQuery. I cloned the jQuery repo, ran it through restricter (with restrict mode forced no matter "use restrict"; directives) and fixed the restrict mode run-time errors until all tests passed again. restricter ran on everything under src/ excluding the Sizzle dependency, to be precise. It should be easy to try it on Sizzle as well, or on something else for that matter.

The required changes to get jQuery restrict mode clean were few and small. They can be partitioned into three classes:

  1. Most were about fixing the str + nostr_nonum antipattern

  2. One fixing str < num

  3. One fixing str + undefined

Neither class 1 or 2 are bugs in jQuery. They represent the current mismatch between the restrict mode subset of JavaScript and the subset that the jQuery developers use. The mismatch seems to be very small, further strengthening the case for restrict mode. I only had to change a total of 9 lines of code, all by explicitly converting a primitive or object into a string using String(expr). The patched version may be a bit easier to reason about and slightly more robust to future changes, especially so for newcomers to the jQuery codebase. Being explicit makes it slightly more verbose.

The class 3 change is more interesting. str + undefined is rarely done on purpose. jQuery.fn.hasClass should guard against missing className properties but doesn’t, and as a consequence element.hasClass("undefined") may return true when it shouldn’t. An easy way to demonstrate this is to change test/unit/attributes.js, line 860. Change ok(!j.hasClass("asdf"), ...) to ok(!j.hasClass("undefined"), ...) and watch the assert blow. Talking about assert feel free to check out C-style assertions in JavaScript via JSShaper.

Seems like restrict mode found us a jQuery bug.

Here’s the patch aggregating the changes above including the bugfix. It applies cleanly against d59b0f3e27827d189b8b2595142ec6bbc3941dd9. And here’s the jQuery forum thread, ticket and pull request.

Want to try restrict mode on your own project? Go to restrictmode.org and feel free to stop by the JSShaper mailing list.

Show comments (reddit)



I made JSLint restrict mode clean. Here's what I found

21 Apr 2011

I’ve created this thing called restrict mode for JavaScript. It’s a definition of a proper subset of the language which I believe is great because I think it increases robustness and makes your program more easy to reason about. It comes with a tool that will check if your program really complies to restrict mode, when you say it does. The tool is called restricter and is a plugin for JSShaper, an extensible framework for JavaScript syntax tree shaping. JSShaper is cool for many other reasons as well but this post is about restrict mode. For me restrict mode makes JS programming more enjoyable since it helps me focus on real programming challenges instead of annoyances/defects/inconsistencies of the JS language. It eases my mind.

I want to know how well the restrict mode subset of JavaScript matches existing programs. I’ve already written about how I made v8bench restrict mode clean. I’ve also done the same to jQuery and Kraken, though I haven’t written about it yet (I’m worse at writing than coding but it’s on my todo-list). When I saw a JSLint discussion on reddit I figured that it would be a great test case, so I decided to make it restrict mode clean and write about what I found. I’m glad I did because it exposed a bug in JSShaper (now fixed). I also think that it serves as a good example of what you can expect from restrict mode.

Here are my findings and how I changed JSLint to make it restrict mode clean. In my checkout of JSLint, commit 99091cd30d354e77cf95 was the latest and greatest so the changes apply cleanly against that revision.

First of all, we need to specify which parts of the program should follow restrict mode. We want it to cover all of JSLint so that the JSShaper restricter plugin can help us catch any issues. JSLint is already enclosed in a function which starts with a "use strict" string. Let’s add "use restrict" as well:

var JSLINT = (function () {
-    "use strict";
+    "use strict"; "use restrict";

To show what I changed I’ve included the diff’s (ceremony removed). Red - lines are what I removed, green + lines are what I added. Scroll down for full patch.

With that change in place, I ran jslint.js through JSShaper (restricter): js run-restricter.js -- JSLint/jslint.js > JSLint/jslint_restrict.js. I tweaked the jslint.html file to use the restrict mode checked version and to dump the errors to console instead of throwing exceptions. To make JSLint restrict mode clean I just had to inspect the errors (when running JSLint) and fix the issues. I iterated on this, and here’s what I found and changed:

First change is to fix a coercion-happy String.prototype.isAlpha. When "hello".isAlpha() or str.isAlpha() is evaluated the expression left of the dot is first boxed into a temporary String object, effectively the same as (new String("hello")).isAlpha() or (new String(str)).isAlpha(). In the String.prototype.isAlpha function, the temporary object is bound to this. [This behavior was then changed in ES5 strict mode to further add to the confusion since it’s not backwards compatible, which is another reason for First change]. If this is used as an operand like below it will trigger coercion, sometimes with unexpected results. You can get the primitive value from a String object by applying the valueOf method or String function. Let’s do that, so that the <= and >= operators won’t need to coerce their operands any longer:

String.prototype.isAlpha = function() {
-            return (this >= 'a' && this <= 'z\uffff') ||
-                (this >= 'A' && this <= 'Z\uffff');
+            var v = this.valueOf();
+            return (v >= 'a' && v <= 'z\uffff') ||
+                (v >= 'A' && v <= 'Z\uffff');
         };

Second change is to do the same for String.prototype.isDigit:

String.prototype.isDigit = function () {
-            return (this >= '0' && this <= '9');
+            var v = this.valueOf();
+            return (v >= '0' && v <= '9');
         };

Third change is to fix String.prototype.name. It used to return this sometimes, which is not the right thing to do. I described above how primitives get boxed into temporary objects. Returning these objects is almost always bad for two reasons: It spreads the coercion disease, and it’s not what the user of the function expects (because now sometimes the function returns strings, sometimes it returns String objects). Let’s fix that by returning this.valueOf(). Let’s also use the primitive value with the + operator, and the coercion is gone. Here we go:

String.prototype.name = function () {
-            if (ix.test(this)) {
-                return this;
+            var v = this.valueOf();
+            if (ix.test(v)) {
+                return v;
             }
-            if (nx.test(this)) {
-                return '"' + this.replace(nxg, function (a) {
+            if (nx.test(v)) {
+                return '"' + v.replace(nxg, function (a) { // this.replace works too
                     if (escapes[a]) {
                         return escapes[a];
                     }
                     return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);
                 }) + '"';
             }
-            return '"' + this + '"';
+            return '"' + v + '"';
         };

Fourth and final change is to fix the report function which performs a lot of string formatting relying on numbers being coerced into strings (str + nostr). It’s a fine example of code that would greatly benefit from using Fmt or something similar. There’s also the option to bail out of restrict mode for the entire report function by annotating it with /*@loose*/. For this example I fixed it in the least obtrusive manner by applying the String function to the numbers. Here we go:

@@ -6523,7 +6526,7 @@ loop:   for (;;) {
-                            warning.line + ' character ' + warning.character : '') +
+                            String(warning.line) + ' character ' + String(warning.character) : 
@@ -6536,7 +6539,7 @@ loop:   for (;;) {
-                        data.implieds[i].line + '</i>';
+                        String(data.implieds[i].line) + '</i>';
@@ -6545,7 +6548,7 @@ loop:   for (;;) {
-                        data.unused[i].line + ' </i> <small>' +
+                        String(data.unused[i].line) + ' </i> <small>' +
@@ -6583,7 +6586,7 @@ loop:   for (;;) {
-                output.push('<br><div class=function><i>' + the_function.line + '</i> ' +
+                output.push('<br><div class=function><i>' + String(the_function.line) + '</i> ' +

And that’s it. JSLint is now restrict mode clean, as far as I can tell. I didn’t find any tests but I’ve tested it manually with a few programs, including JSLint itself.

What have we learned?

For a start, it’s another step in the right direction in verifying that the restrict mode subset of JavaScript is sane and well enough matches the JS subset people already use in practice. It took little effort to get JSLint restrict mode clean, and it required no prior experience with that code base. We had to change a few lines of code as expected, and the signal vs noise was very high.

Did we find any real defects? We caught String.prototype.name sometimes returning temporary boxed objects which I classify as a defect, even though it doesn’t cause any harm at the moment. Fixing that is a keeper.

Even if we don’t buy into the idea restrict mode, is there something else that we’d like to keep? I’d suggest the fixes for coercion happiness examplified in change two and three. Especially so if you follow the recommendation of preferring === over == (I do). Think about it: It would be a bit weird to see this >= '0' && this <= '0' yield true when v is a temporary boxed String object (it will coerce), but have this === '0' yield false (it won’t coerce). Leaving it as it is will increase the risk of future bugs. If you don’t prefer === over == then you’re likely not to care about this change.

And some of you would perhaps consider keeping the changes for our fourth finding as well (str + nostr) even if you didn’t yet buy in on restrict mode, because quite frankly the string formatting code in that function is not the most beautiful or easiest code to follow. Using Fmt or something similar could greatly improve it. Many will consider the code fine as-is and won’t change it unless they go restrict.

To summarize: Of our four findings/changes, three seem noteworthy enough that I think many would consider applying the changes even if they don’t care about restrict mode. Not bad for a few hours of work of which the majority went into writing this post.

If you choose to keep all changes as well as the "use restrict" directive, then you can easily run the program through JSShaper (restricter) again in the future and perhaps find more stuff. It could help you during development, and it could help your program become more robust. You can choose to run the checked version only once in a while, every time your unit tests run or all the time. It’s totally up to you.

A program complying to the subset of JavaScript defined by restrict mode (i.e. a restrict mode clean program) is also much easier to reason about compared to a program that (may) use the entire spectra of loose JS semantics. That may help you when debugging tomorrow or when coming back to your old code one year from now. If you read your friend’s code and happen to find the "use restrict” directive in there, you may find yourself relieved knowing that not only will you faster and more accurately understand what it does and how, chances are that your friend accurately understands his/her own program too.

The JSLint restrict mode experiment exceeded my expectations. Why don’t you try applying restrict mode to one of your own programs? What’s to lose?

There’s more info available on restrictmode.org. If you have any questions about restrict mode or JSShaper then post a message to the JSShaper mailing list and I’ll help you out. You can also contact me directly.

Here’s the patch for everything described above (jslint.html and jslint.js).

Show comments (reddit)



JavaScript modules in shells, browsers, everywhere!

04 Apr 2011

This is the technique I’m using to get JavaScript module support in the console and in the browser, with the same code base. It’s tested with the following JS shells: js (SpiderMonkey), jsc (JavaScriptCore), v8/d8 and node. It’s useful since it lets you stay in the console as much as you want to and it enables you write once, run everywhere (that’s what they said).

I’m using it in JSShaper. Do you find it useful? Do you know of a better way? Let me know!

In your program top-level file, define require as follows. It’s now either defined as the built-in require or a version of the built-in load that returns nothing.

var require = require || function(f) { load(f); };

In all other files, when you need to import a module such as Fmt, do it like this. The first || clause is truthy (and thus assigned) when Fmt is already defined in the global namespace, the second when require is CommonJS-style and the third when require wraps load (thus Fmt is now in the global namespace).

var Fmt = Fmt || require("./fmt.js") || Fmt;

Finally, your modules should have the following structure, for example Fmt:

var Fmt = (function() {
    // ...
    return ...;
})();
if (typeof exports !== "undefined") {
    module.exports = Fmt;
}

Voila, your module-separated program now works in the JS shells and the browsers! For the browsers, just include (or concatenate) the scripts in dependency-order. This isn’t a dynamic JS loader - if you want one there’s gazillions of them.

Here are the underpinnings for the curious:

Show comments (reddit)



Making v8bench restrict mode clean

01 Apr 2011

I’d like to know how well the restrict mode subset of JavaScript matches existing programs. I decided to test it on Google’s v8bench. I checked out the latest revision from SVN, and slapped "use restrict"; on top of every file. I ran that through restricter (part of JSShaper) before executing v8bench.

The benchmark then threw an exception whenever restrict mode detected that things were going on outside of its rules. I tweaked the v8bench source, and iterated.

I had to change only 8 lines of code to get v8bench restrict mode clean, i.e. have it complete without throwing any restrict mode exceptions. That’s 8 lines out of 11208, or 0.07%! 99.93% was already valid restrict mode. It’s a step in the right direction in verifying that the restrict mode subset of JavaScript is sane and well enough matches the JS subset people already use in practice.

Oh, and if the same procedure is applied to r2537 instead of HEAD, one defect in the splay benchmark (converting the same numeric key to a string over and over again) stands out and is easily corrected. That defect was later fixed in version 6 of the benchmark. Can restrict mode help you catch similar or other defects in your program?

To learn more about restrict mode read the case for restrict mode and then visit restrictmode.org.

Here’s the full diff:

Index: run.js
===================================================================
--- run.js (revision 7463)
+++ run.js (working copy)
@@ -38,7 +38,7 @@
 var success = true;
  
 function PrintResult(name, result) {
-  print(name + ': ' + result);
+  print(name + ': ' + String(result));
 }
  
  
Index: raytrace.js
===================================================================
--- raytrace.js (revision 7463)
+++ raytrace.js (working copy)
@@ -617,8 +617,8 @@
                 rayDepth: 2
             }, options || {});
  
-        this.options.canvasHeight /= this.options.pixelHeight;
-        this.options.canvasWidth /= this.options.pixelWidth;
+        this.options.canvasHeight /= Number(this.options.pixelHeight);
+        this.options.canvasWidth /= Number(this.options.pixelWidth);
  
         /* TODO: dynamically include other scripts */
     },
Index: base.js
===================================================================
--- base.js (revision 7463)
+++ base.js (working copy)
@@ -201,10 +201,10 @@
 BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
   function Measure(data) {
     var elapsed = 0;
-    var start = new Date();
+    var start = Number(new Date());
     for (var n = 0; elapsed < 1000; n++) {
       benchmark.run();
-      elapsed = new Date() - start;
+      elapsed = Number(new Date()) - start;
     }
     if (data != null) {
       data.runs += n;
Index: deltablue.js
===================================================================
--- deltablue.js (revision 7463)
+++ deltablue.js (working copy)
@@ -800,7 +800,7 @@
  
   // Build chain of n equality constraints
   for (var i = 0; i <= n; i++) {
-    var name = "v" + i;
+    var name = "v" + String(i);
     var v = new Variable(name);
     if (prev != null)
       new EqualityConstraint(prev, v, Strength.REQUIRED);
@@ -836,8 +836,8 @@
  
   var dests = new OrderedCollection();
   for (var i = 0; i < n; i++) {
-    src = new Variable("src" + i, i);
-    dst = new Variable("dst" + i, i);
+    src = new Variable("src" + String(i), i);
+    dst = new Variable("dst" + String(i), i);
     dests.add(dst);
     new StayConstraint(src, Strength.NORMAL);
     new ScaleConstraint(src, scale, offset, dst, Strength.REQUIRED);

Show comments (reddit)



C-style assertions in JavaScript via JSShaper

30 Mar 2011

Earlier today I created asserter, a new plugin for the JSShaper framework that provides you C-style assertions in JavaScript.

Here’s a common style of doing JS assertions:

function myfn(x) {
    assertTrue(x >= 0, "argument x must be positive or zero");
}

When failing (let’s say x is -1) it will print something like this, perhaps with some kind of cleaned up stack trace:

assertTrue() failed: argument x must be positive or zero

This is what you would write instead when using asserter:

function myfn(x) {
    Assert(x >= 0);
}

When failing, it will print this:

Assertion failed: x >= 0, function myfn, file prog.js, line 2

I know which version I prefer. Thanks to the JSShaper framework I was able to create the asserter plugin in no time, using only 34 29 (edit: shorter and easier with declarative matching) lines of code.

Here’s how it works. asserter searches the syntax tree for calls to the Assert function. It adds an extra string argument containing the assert condition expression (in text form), the enclosing function name (or <anonymous> or <script>), the filename and lineno. Here’s what it would be replaced with:

Assert(x >= 0, "x >= 0, function myfn, file prog.js, line 2");

The Assert function could look like this. Note that it will execute just fine even if you didn’t run your program through asserter, although in that case it will just print a falsy value.

function Assert(condition, str) {
    if (!condition) {
        log("Assertion failed: "+ (str || String(condition)));
        quit(-1);
    }
}

Asserting preconditions in JS has never been simpler, no?

In C you would disable assertions in your release-build (allowed since assertions mustn’t contain side effects). In JS we could do the same by simply creating another JSShaper pass that removes the Assert calls.

Show comments (reddit)



The case for restrict mode

28 Mar 2011

I sent this mail to the JSMentors list yesterday [full thread]:

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

Show comments (reddit)



Announcing restrict mode for JavaScript

27 Mar 2011

Welcome redditors! I’m answering your questions in the comment thread.

"use restrict";

Add that to the top of your JavaScript program. Run it through the JSShaper restricter plugin, then combine it with the restrictmode.js prelude and run it. Then hook it up with your units tests.

Try restrict mode directly in your browser (Firefox, Chrome or Safari)!

For semantics and rationale visit restrictmode.org. It’s not set in stone so let me know what you think.

I’ll write more about JSShaper in time. It’s an extensible framework for JavaScript syntax tree shaping and we’re going to be able to do lots of nifty things with it.

Show comments (reddit)



↑ Home    Newer posts »