Dynamic source maps

2013-01-19

I'm in the middle of the 6th hell called source maps. While still a bit of a black box, I think I figured it out by now. I'll do a writeup soon about my findings which will explain step-by-step how to generate a source map. This is not that writeup, however.

Edit: This is, though not mine. Shortly after my post and demo an addition was made to the spec which allows for dynamic source maps. Huzah, the system works! You can put the source as a data uri inside the sourcesContent field. At the time of adding this update, only Chrome supports this.

What now?


A source map is a mapping between an original source and the source that's the result of translating it somehow. This source map allows a browser to show you where in the original code your error occurred (of course it's then still up to you to figure out whether the bug is in your original source, or a problem with the translation, but that's a different story).

Dynamic source maps


I want to talk about dynamic source maps. Source maps of scripts that were generated at runtime (for what,ever, reason). The current source map spec (v3) doesn't support any of that magic, and it's hindering me a bit during development.

Use cases


I produce scripts that translate some input language to another language. Mostly flavours of JS, but that doesn't even matter here. I seem to be in need of dynamic source maps, but unable to use them that way. I need persistent storage, if I'm to take advantage of them. I have to use cases where I would need them dynamic, and where persistent storage is not really a viable solution:

- Developing without compilation step

I generally just fire up an editor, save, switch to my browser, and refresh. I don't compile anything on save, and don't want to compile anything on save. In production, I would compile once and use that result, of course. But there I wouldn't want to use source maps anyways.

- Application runtime plugin code

I have one app, soon two, where I can edit plugin code inside the app, save it in local storage, and run immediately. I use special (custom) html syntax for that app, which I translate to dom syntax. This all happens on the fly of course, no persistent storage at all (though I can push it to a server, it's not a mandatory step).

So what I would need is a source map that can be dynamically generated and combined with the translated script. And I think it's actually not that difficult to do either! Isn't that great :D

A solution


The solution would be to support a second type of comment "pragma". Currently, the only such pragma supported is:

Code:
//@ sourceMappingURL=

So instead, an obvious solution to my problem would be to add the whole json to that pragma, and include the original source to it as well...

Code:
//@ sourceMapping=

//@ sourceMapping={version:4, source:'function foo(){\n...', names:[...], mappings: 'AAA...'}

Obviously, the file fields become a bit redundant this way. The file field would always be the file you're currently parsing. The sourceRoot would be the JS you find in source. And sources would again always contain just one file, the JS found in source.

Omit source index?


Which brings me to another point, one I made on a separate occasion, but actually makes even more sense in this light; You should be able to omit the source file field from segments. In that (3 field segment) case, the last encountered source should be assumed (not even of the previous line, but of all). And maybe it should assume the first field in the sources array if it was never seen.

Thing is, when translating a single source file, you'll always just be embedding A's in your segments. Such a huge waste :(

Pretty please, .push(++sugar)


Anyways. I hope this reaches the right people. I really want this and it's already going to take too long before it get's implemented (... if at all :/).

In the meantime, Alexander pointed me to createBlobURL, which is an excellent idea. I'll see if I can get it to work that way. No, I did not. There's a chicken-egg problem where you need to set the "url" of the dynamic file with a pragma, but you can only get urls for complete immutable strings. Siiighhh.

Stumbled on this bugzilla report: https://bugzilla.mozilla.org/show_bug.cgi?id=679189

Edit: Again, it is possible now. See this blog post for more information.