index.js
  1  "use strict";
  2  
  3  Object.defineProperty(exports, "__esModule", {
  4    value: true
  5  });
  6  exports.default = void 0;
  7  
  8  var _path = _interopRequireDefault(require("path"));
  9  
 10  var _fs = require("fs");
 11  
 12  var _child_process = require("child_process");
 13  
 14  var _helperPluginUtils = require("@babel/helper-plugin-utils");
 15  
 16  var _istanbulLibInstrument = require("istanbul-lib-instrument");
 17  
 18  var _testExclude = _interopRequireDefault(require("test-exclude"));
 19  
 20  var _schema = _interopRequireDefault(require("@istanbuljs/schema"));
 21  
 22  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 23  
 24  function getRealpath(n) {
 25    try {
 26      return (0, _fs.realpathSync)(n) ||
 27      /* istanbul ignore next */
 28      n;
 29    } catch (e) {
 30      /* istanbul ignore next */
 31      return n;
 32    }
 33  }
 34  
 35  const memoize = new Map();
 36  /* istanbul ignore next */
 37  
 38  const memosep = _path.default.sep === '/' ? ':' : ';';
 39  
 40  function loadNycConfig(cwd, opts) {
 41    let memokey = cwd;
 42    const args = [_path.default.resolve(__dirname, 'load-nyc-config-sync.js'), cwd];
 43  
 44    if ('nycrcPath' in opts) {
 45      args.push(opts.nycrcPath);
 46      memokey += memosep + opts.nycrcPath;
 47    }
 48    /* execFileSync is expensive, avoid it if possible! */
 49  
 50  
 51    if (memoize.has(memokey)) {
 52      return memoize.get(memokey);
 53    }
 54  
 55    const result = JSON.parse((0, _child_process.execFileSync)(process.execPath, args));
 56    const error = result['load-nyc-config-sync-error'];
 57  
 58    if (error) {
 59      throw new Error(error);
 60    }
 61  
 62    const config = { ..._schema.default.defaults.babelPluginIstanbul,
 63      cwd,
 64      ...result
 65    };
 66    memoize.set(memokey, config);
 67    return config;
 68  }
 69  
 70  function findConfig(opts) {
 71    const cwd = getRealpath(opts.cwd || process.env.NYC_CWD ||
 72    /* istanbul ignore next */
 73    process.cwd());
 74    const keys = Object.keys(opts);
 75    const ignored = Object.keys(opts).filter(s => s === 'nycrcPath' || s === 'cwd');
 76  
 77    if (keys.length > ignored.length) {
 78      // explicitly configuring options in babel
 79      // takes precedence.
 80      return { ..._schema.default.defaults.babelPluginIstanbul,
 81        cwd,
 82        ...opts
 83      };
 84    }
 85  
 86    if (ignored.length === 0 && process.env.NYC_CONFIG) {
 87      // defaults were already applied by nyc
 88      return JSON.parse(process.env.NYC_CONFIG);
 89    }
 90  
 91    return loadNycConfig(cwd, opts);
 92  }
 93  
 94  function makeShouldSkip() {
 95    let exclude;
 96    return function shouldSkip(file, nycConfig) {
 97      if (!exclude || exclude.cwd !== nycConfig.cwd) {
 98        exclude = new _testExclude.default({
 99          cwd: nycConfig.cwd,
100          include: nycConfig.include,
101          exclude: nycConfig.exclude,
102          extension: nycConfig.extension,
103          // Make sure this is true unless explicitly set to `false`. `undefined` is still `true`.
104          excludeNodeModules: nycConfig.excludeNodeModules !== false
105        });
106      }
107  
108      return !exclude.shouldInstrument(file);
109    };
110  }
111  
112  var _default = (0, _helperPluginUtils.declare)(api => {
113    api.assertVersion(7);
114    const shouldSkip = makeShouldSkip();
115    const t = api.types;
116    return {
117      visitor: {
118        Program: {
119          enter(path) {
120            this.__dv__ = null;
121            this.nycConfig = findConfig(this.opts);
122            const realPath = getRealpath(this.file.opts.filename);
123  
124            if (shouldSkip(realPath, this.nycConfig)) {
125              return;
126            }
127  
128            let {
129              inputSourceMap
130            } = this.opts;
131  
132            if (this.opts.useInlineSourceMaps !== false) {
133              if (!inputSourceMap && this.file.inputMap) {
134                inputSourceMap = this.file.inputMap.sourcemap;
135              }
136            }
137  
138            const visitorOptions = {};
139            Object.entries(_schema.default.defaults.instrumentVisitor).forEach(([name, defaultValue]) => {
140              if (name in this.nycConfig) {
141                visitorOptions[name] = this.nycConfig[name];
142              } else {
143                visitorOptions[name] = _schema.default.defaults.instrumentVisitor[name];
144              }
145            });
146            this.__dv__ = (0, _istanbulLibInstrument.programVisitor)(t, realPath, { ...visitorOptions,
147              inputSourceMap
148            });
149  
150            this.__dv__.enter(path);
151          },
152  
153          exit(path) {
154            if (!this.__dv__) {
155              return;
156            }
157  
158            const result = this.__dv__.exit(path);
159  
160            if (this.opts.onCover) {
161              this.opts.onCover(getRealpath(this.file.opts.filename), result.fileCoverage);
162            }
163          }
164  
165        }
166      }
167    };
168  });
169  
170  exports.default = _default;