all files / src/ MappingProvider.js

97.78% Statements 44/45
96.43% Branches 27/28
100% Functions 6/6
97.67% Lines 42/43
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86           15× 15× 15×   15×           15×   12×   11×     15×     28×   14× 14× 14×   13×     14× 14× 14×   14×     12×           12× 12×     12×     12×               606×        
const path = require('path');
const fs = require('fs');
const { SourceMapConsumer } = require('source-map');
 
const sourceMapRegEx = /(?:\/{2}[#@]{1,2}|\/\*)\s+sourceMappingURL\s*=\s*(data:(?:[^;]+;)+base64,)?(\S+)/;
 
const getMapping = require('./getMapping');
 
class MappingProvider {
  constructor(options, sparceCoverageCollector) {
    this.sparceCoverageCollector = sparceCoverageCollector;
    this.warn = options.warn || console.warn;
 
    this.readJSON = options.readJSON
      || function readJSON(filePath) {
        Iif (!fs.existsSync(filePath)) {
          throw new Error(`Could not find file: "${filePath}"`);
        }
        return JSON.parse(fs.readFileSync(filePath));
      };
 
    this.readFile = options.readFile
      || function readFile(filePath) {
        if (!fs.existsSync(filePath)) {
          this.warn(new Error(`Could not find file: "${filePath}"`));
          return '';
        }
        return fs.readFileSync(filePath);
      };
 
    this.sourceStore = options.sources;
  }
 
  getMappingResolver(filePath, code = false) {
    /* coverage.json can sometimes include the code inline */
    let codeIsArray = true;
    let jsText = code || this.readFile(filePath);
    if (Array.isArray(jsText)) { /* sometimes the source is an array */
      jsText = jsText.join('\n');
    } else {
      codeIsArray = false;
    }
 
    const match = sourceMapRegEx.exec(jsText);
    let sourceMapDir = path.dirname(filePath);
    let rawSourceMap;
 
    if (!match) {
      return false;
    }
 
    if (match[1]) {
      rawSourceMap = JSON.parse((new Buffer(match[2], 'base64').toString('utf8')));
    } else {
      const sourceMapPath = path.join(sourceMapDir, match[2]);
      rawSourceMap = this.readJSON(sourceMapPath);
      sourceMapDir = path.dirname(sourceMapPath);
    }
 
 
    // replace relative paths in source maps with absolute
    rawSourceMap.sources = rawSourceMap.sources.map(
      (srcPath) => path.resolve(sourceMapDir, srcPath)
    );
 
    const sourceMap = new SourceMapConsumer(rawSourceMap);
 
    /* if there are inline sources and a store to put them into, we will populate it */
    if (sourceMap.sourcesContent) {
      sourceMap.sourcesContent.forEach((source, idx) => {
        this.sparceCoverageCollector.setSourceCode(
          sourceMap.sources[idx],
          codeIsArray ? source.split('\n') : source
        );
        if (this.sourceStore) {
          this.sourceStore.set(sourceMap.sources[idx], source);
        }
      });
    }
 
    return (location) => getMapping(sourceMap, location);
  }
}
 
module.exports.MappingProvider = MappingProvider;