Oh distraction, how I love thee; what follows refers to work that actually happened between 2009-11-19 and 27.
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.
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.
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.
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.)
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.