Testing Source Maps

October 2nd, 2013

"How do I test the source maps my compiler/transpiler/build tool creates?"

I have seen this question come up a few times, and unfortunately, people usually don't find an answer, give up, and don't test their source maps. However, testing source maps isn't too hard if you are using Node.js and the mozilla/source-map library. If you aren't using Node.js and the mozilla/source-map library, you can still use the following techniques, but you will need to implement a source map consumer.

Your tool most likely has a function that generates both the JavaScript that will be executed by the browser's JavaScript engine/Node/whatever, and a source map. Something like this:

var result = compile(input, { url: inputUrl, sourceMap: true });
result.code;      // The JavaScript code
result.sourceMap; // The source map

It is easiest to base your tests around this function.

To test generated source maps:

  1. Create some test input to compile.

  2. Select some different bits of code in the test input and record their { url, line, column } locations. Generally, a "bit of code" should be a specific token, function invocation, etc.

  3. Compile and generate a source map for the test input.

  4. Create a SourceMapConsumer for the generated source map.

    var smc = new SourceMapConsumer(result.sourceMap);
  5. Inspect the compiled code and find the generated code that corresponds to the bits of code you selected in step (2). For each of the { line, column } locations in the compiled code, add an assertion to your test that smc.originalPositionFor(location) is equal to the expected location in your original source.

There is another approach, that is easier for compilers targeting JavaScript than for build tools, which can be used when you don't want to inspect the generated JavaScript at all.

  1. You can add a location debugging statement to your language that compiles to JavaScript code similar to:

    // SpiderMonkey (Firefox)
    (function (e) { console.log(e.lineNumber, e.columnNumber); }(new Error()));
    // In other engines, you need to parse the first frame from the error's
    // stack property yourself
    (function (e) { console.log(parseLocation(e.stack)); }(new Error()));
  2. Create test input which has one or more of these location debugging statements.

  3. Compile the test input and create a SourceMapConsumer for your generated source map.

  4. Run the compiled input and read its output.

  5. Assert that querying the SourceMapConsumer for the original location(s) of that output points to the expected location(s) in your original test input source.

For reference, here are some existing source map test suites from various projects (hopefully this post helps them expand their tests as well):

« Previous Entry

Next Entry »

Recent Entries

Memory Management in Oxischeme on February 22nd, 2015

Naming `eval` Scripts with the `//# sourceURL` Directive on December 5th, 2014

wu.js 2.0 on August 7th, 2014

Come work with me on Firefox Developer Tools on July 8th, 2014

Debugging Web Performance with Firefox DevTools - Velocity 2014 on June 26th, 2014

Beyond Source Maps on March 12th, 2014

Memory Tooling in Firefox Developer Tools in 2014 on March 4th, 2014

Hiding Implementation Details with ECMAScript 6 WeakMaps on January 13th, 2014

Re-evaluate Individual Functions in Firefox Developer Tools' Scratchpad on November 22nd, 2013

Testing Source Maps on October 2nd, 2013

Creative Commons License

Fork me on GitHub