24

I have a file that has been transpiled from ES6 to ES5 using Babel. I have sourcemap. I am assuming I can restore the original file (the way it looked when written in ES6) using these resources.

How is it done?

Is there a CLI tool to do this?

Gajus
  • 69,002
  • 70
  • 275
  • 438

4 Answers4

16

Open up the source map in a text editor, and you’ll see that it’s mostly just a simple JSON object. The “sources” field contains an array of URLs/paths to all source files, which can help you to find them. There is also an optional “sourcesContent” field, which also is an array, where each item contains the contents of the file at the same index in the “sources” array; if so, you could find the original code right in the source map.

A CLI tool? Well, there’s source-map-visualize which tries to find all original sources and pre-loads them into this online source map visualization.

lydell
  • 1,147
  • 12
  • 16
  • 3
    I think the most basic way is to use Mozilla `source-map` package, https://github.com/mozilla/source-map/#consuming-a-source-map, e.g. `sourcemap.SourceMapConsumer(map).sourcesContent[0]`. Consider adding that to your answer . – Gajus Sep 03 '15 at 19:44
  • 2
    @GajusKuizinas there is absolutely no need to use the `source-map` package for this task. `JSON.parse(map).sourcesContent[0]` would do the same thing. – lydell Sep 03 '15 at 19:53
  • Did not realise that. Thank you. – Gajus Sep 03 '15 at 19:54
5

Very simple NodeJS implementation which I wrote for my needs.

const fs = require('fs');
const { SourceMapConsumer } = require("source-map");

fs.readFile('./example.js', 'utf8' , (err, data) => {
  if (err) return console.error(err);

  const sourceMapData = data.split('//# sourceMappingURL=data:application/json;base64,')[1];
  let buff = new Buffer.from(sourceMapData, 'base64');
  let rawSourceMap = buff.toString('ascii');

  const parsed = SourceMapConsumer(rawSourceMap);

  fs.writeFile('example.ts', parsed.sourcesContent, function (err) {
    if (err) return console.log(err);
  });
});
Dmitri
  • 3,551
  • 1
  • 18
  • 9
2

There's a nice web service to do that: http://sokra.github.io/source-map-visualization/

  • Click on "Custom"
  • Select your *.js file
  • Select the corresponding *.js.map file
  • Browse the non-minified code on the right

There might be a lot of noise from webpack:///node_modules/ modules that you're probably not interested in. You can try to find the I found that simply searching for webpack:///src usually brings up the actual source code within the whole snippet.

Benedikt Köppel
  • 4,853
  • 4
  • 32
  • 42
0

i wrote a script as well that came handy to me. I'll share it here it might come handy to someone this script assumes that the .map.(js|css) has a structure like

{
    "version": 3,
    "file": "static/js/15.80b7f5e4.chunk.js",
    "mappings": "iOAkCA,UAzBqB",
    "sources": [
        "path/to/afile.js"
    ],
    "sourcesContent": [
        "content of the file"
    ],
    "names": [
        "post",
        "useState"
    ],
    "sourceRoot": ""
}

thou i didn't make use of names and mapping entry on the map file i just mapped sources with sourceContent and recreated the file structure.

const fs = require("fs");
const path = require("path");

function parseIfMap(filePath, content) {
  console.log("working on:", filePath);
  if (filePath.includes(".map")) {
    const jsonContent = JSON.parse(content);
    jsonContent.sources.forEach(function (value, index) {
      const parsed = path.parse(value);
      if (parsed.dir) {
        fs.mkdirSync(parsed.dir, { recursive: true });
      }
      fs.writeFile(
        value,
        jsonContent.sourcesContent[index],
        (path) => path && console.log(value, path)
      );
    });
  }
}

function readFiles(dirname, onError) {
  fs.readdir(dirname, function (err, filenames) {
    if (err) {
      onError(dirname, err);
      return;
    }
    filenames.forEach(function (filename) {
      const filePath = dirname + path.sep + filename;
      if (fs.lstatSync(filePath).isFile()) {
        fs.readFile(filePath, "utf-8", function (err, content) {
          if (err) {
            onError(err);
            return;
          }
          parseIfMap(filePath, content);
        });
      } else {
        readFiles(filePath, parseIfMap, onError);
      }
    });
  });
}
// change with you own file path
readFiles("static", console.log);

Amir Heshmati
  • 550
  • 1
  • 8
  • 19
  • `working on: /root/app/service.js.map /root/index.js:15 jsonContent.sourcesContent[index], ^` `TypeError: Cannot read properties of undefined (reading '0') at /root/index.js:15:35` ` at Array.forEach ()` ` at parseIfMap (/root/index.js:8:25)` ` at /root/index.js:36:11 at FSReqCallback.readFileAfterClose [as oncomplete] `(node:internal/fs/read_file_context:68:3)` – Got To Figure Jan 25 '23 at 22:59