pmuellr is Patrick Mueller

other pmuellr thangs: home page, twitter, flickr, github

Wednesday, March 16, 2011

WTF are these scoop files?

At some point, someone's going to look at the weinre source code and ask, "WTF are all these .scoop files?"

  • They're almost JavaScript files, intended to preprocessed into legal JavaScript files. The lines of the file which are not indented are "directives" that indicate how the following indented bits are to processed. The indented lines are plain old JavaScript which isn't touched by the preprocessor except to deal with "super" calls.

  • They're my response to wanting to use classical OOP in JavaScript, without dealing with the crufty the way it's typically done in JavaScript. I like JavaScript, but I hate cruft.

  • Since I'm also playing with CommonJS, I ended up folding some goodies for that in too.

Assuming you know JavaScript, and have some familiarity with classical OOP, I suspect you will get the gist of what's going on if you look at one of the weinre .scoop files.

I knew I'd be writing a lot of JavaScript for weinre, so I wrote scoop first to make it a pleasant experience.

The source for scoop is at GitHub. The doc is spartan, but my existing user base hasn't complained too much about that (existing user base == me).

Here's what I learned in the process of using scoop to build weinre:

  • I like it. It's become second nature to author scoop files.

  • The preprocessor runs fast enough that it doesn't impact my build in any significant fashion. In practice, all software I create has some kind of automated build that runs when I touch a source file. Including web sites. Adding one second to that process, if that, doesn't impact me. (weinre builds take 5 seconds, which includes compiling Java source - I could optimize that build more, but haven't needed to)

  • There's no new language to learn. It's just JavaScript with some structuring. Just a few directives to learn, and rules to follow (indent your code). No offense to the altJS crowd - I love all that stuff, but really don't want to invest in learning another language, figure out how to debug it, etc.

  • scoop and the CommonJS module runtime I use (modjewel) both take turns processing the source, but don't change the line or column numbers of the original source. When the JavaScript runtime complains about a syntax or runtime error with a line number, no mental mapping is required to find the line in the scoop source. The meat of code I step through in the debugger, function bodies, is the same as the scoop code I write.

  • Exposing classes as modules seems to work fine, but requires the module system to support overriding the exports value that the module ends up populating. In practice, this works with node.js and modjewel, so, works for me. Specifically, the first class defined in a scoop file is assigned to module.exports, and thus any code which does a require() on that module will get the class as a result.

  • The big downside of overriding module.exports is that recursively require()'d modules don't work right. I added a requireClass directive which will identify this condition at runtime, and fails fast with a decent diagnostic. Fixing these situations typically isn't difficult.

  • Syntax-coloring text editors generally do the right thing for scoop files, once you lie to them and tell them that a scoop file is just a JavaScript file. The directives are usually colored oddly, but that's not a big problem. The actual JavaScript code is always colored correctly, for the text editors I use.

Part of my rationalization of doing this is based on Smalltalk's class structuring story. The Smalltalk language doesn't define any class structuring features like a "class statement" - all that is handled by the tooling and runtime. And it has a great classical OOP story. If Smalltalk can do it, then so can JavaScript.

I have a long laundry list of things I'd like to do with scoop, especially since I consider it just a stepping stone to having a nice, dynamic, live development environment for JavaScript, just like Smalltalk. The current incarnation is the ascii, text-file version of where I want to go. The thing I want to work on first is some read-only browsers for the module system and the class structure, that you can run right in your browser (or debugger). Next would come live editing, etc, etc. Probably would have worked on some of that stuff had my JSConf 2011 proposal for scoop been accepted. The pressure is off on that front though.