Oh distraction, how I love thee.

Oh distraction, how I love thee; what follows refers to work that actually happened between 2009-11-19 and 27.

I kept on working on my homegrown Javascript module system, starting with some bug stomping. First of all, I discovered that there may not be a default definition for window.onerror, so it’s necessary to do some checking (or substituting) The next order of business was to check for (and prevent) infinite reload attempts when there was a problem loading a dependency (such as a mis-spelled path name)

A browser difference more serious than the existence of the onerror handler is how it handles exceptions. Exceptions matter because the only way I know to abort a file (short of wrapping the whole thing a function or two) is to throw an exception. The relevant context is the entire file, so there is no place to put a try/catch block and the normal result is a message in the browser’s error console. It’s possible to respond to these errors in onerror, (in my case hiding the flow-control messages) but the behavior varies in frustrating ways.

Developing in Firefox, I made a custom object with the appropriate properties; when it was thrown, the message parameter of onerror reflected my custom exception and I could filter it out. In Internet Explorer, however, throwing an unknown object results in a stock error message. IE will pass a message through if you throw an Error object with the message.

However, Firefox has the exact opposite behavior. If you throw an Error or one of it’s derivatives, then you get a stock error message in onerror regardless of what you pass it.

Fortunately, I only needed this feature for essentially cosmetic reasons, so I just left IE to have it’s stock error messages.

JSBuild

The ultimate solution however is a static build system to ensure that ‘releases’ aren’t subject to any of the above browser frailties. This is also where I found out that I really set myself up for trouble with the Module objects. Properly handling the object calls requires that I track the opening and closing of the module closures in order to resolve the paths. All of the options are somewhat distasteful.

1. I could include a complete javascript syntax in order to properly match all the brackets, and just put in the small set of actions I need for my purposes. This feels too heavyweight to me; I worked over a Treetop javascript grammar just long enough to decide it was still going to be a fragile, difficult, thing.

2. Use a full javascript engine like Johnson with a patched version of the module system. The patching process sounds like a very delicate operation, especially since I’m trying to keep Module as a single unit for the sake of minimal setup. And if a grammar feels too large, an entire engine is overkill.

3. Regex hack it. I found that this can be much more efficient in creating my expression language, but it can also be a fragile process itself. Matching up both ends of the module closures is especially problematic.

Currently, I have a build system based on regex hacking, making the assumption of just that syntax and formatting which I’ve been using so far. It’s built in Ruby (which some may have guessed from Treetop/Johnson) since that’s what I’m most familiar with at this point. I’ve built up a test suite, but as I said, I’m aiming for a fairly restrictive sub-grammar and the tests don’t really push it.

CommonJS

And just as I finish up my module (and get subsequently hijacked) CommonJS makes the news, with a ‘standard’ Javascript module system first out of the gate. (Not that I blame them, it’s the first thing I would add, and my own project attests to the importance.) However, it’s ‘different’.

The sad thing is, it’s a lot more like my previous system, based on a ‘require’ function with the other methods attached to it. Of course, I switched to a closure based system to fill in certain missing features, which I’d have to find some other way to support if I switched back.

The CommonJS module spec has a number of other variances. I expect to adopt most if not all of them for the sake of compatibility, though I doubt if I’ll ever be able to provide a perfectly compatible implementation. (It would be easier if I allowed for certain very inefficient loading patterns and danced with global mutable state.)

The CommonJS leaves off file extensions. I believe their reasoning is that local implementations are then free to provide loadable binary modules instead of javascript files, taking advantage of the ability to inspect the filesystem while searching a load path for files. It puts the can on my automatic script/style detection, which I suppose saves me a little code. On the other hand, I’ll probably need (at least) as much code to manage extension/no extension forms.

CommonJS also specifies absolute paths by default, whereas I have relative paths by default. There is a certain amount of sense in their choice since ‘./’ is always available to specify a relative path. On the other hand, I chose relative as default because it’s not only more common, but ‘absolute’ paths are nearly useless to me: I test on a local file system and then expect it to run on a web server, which will have a very different absolute path.

CommonJS specifies that all otherwise global symbols are assigned to the ‘exports’ object, which is in turn returned from ‘require’. The asynchronous script tag method will never be able to return the object. I haven’t set down a definite plan for dealing with exports yet. Currently I assign all ‘globals’ under the CGD namespace. The simplest method would be assign exports.CGD = CGD, but that could result in multiple instances of CGD if it ran in a real CommonJS system. I’m currently leaning towards exports.module = CGD.module. This would cause the exports object to be cluttered with everything in a non-encapsulating module system, but it would be about the same size as the CGD object now.

Posted Thursday, December 17th, 2009 under Devlog.

3 comments