diff options
Diffstat (limited to 'node_modules/nyc/lib')
-rw-r--r-- | node_modules/nyc/lib/commands/instrument.js | 55 | ||||
-rw-r--r-- | node_modules/nyc/lib/config-util.js | 253 | ||||
-rw-r--r-- | node_modules/nyc/lib/hash.js | 14 | ||||
-rw-r--r-- | node_modules/nyc/lib/instrumenters/istanbul.js | 49 | ||||
-rw-r--r-- | node_modules/nyc/lib/instrumenters/noop.js | 21 | ||||
-rw-r--r-- | node_modules/nyc/lib/process-args.js | 36 | ||||
-rw-r--r-- | node_modules/nyc/lib/process.js | 98 | ||||
-rw-r--r-- | node_modules/nyc/lib/self-coverage-helper.js | 20 | ||||
-rw-r--r-- | node_modules/nyc/lib/source-maps.js | 57 |
9 files changed, 603 insertions, 0 deletions
diff --git a/node_modules/nyc/lib/commands/instrument.js b/node_modules/nyc/lib/commands/instrument.js new file mode 100644 index 000000000..6ff4a5222 --- /dev/null +++ b/node_modules/nyc/lib/commands/instrument.js @@ -0,0 +1,55 @@ +var NYC +try { + NYC = require('../../index.covered.js') +} catch (e) { + NYC = require('../../index.js') +} + +exports.command = 'instrument <input> [output]' + +exports.describe = 'instruments a file or a directory tree and writes the instrumented code to the desired output location' + +exports.builder = function (yargs) { + return yargs + .usage('$0 instrument <input> [output]') + .option('require', { + alias: 'i', + default: [], + describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., babel-register, babel-polyfill.' + }) + .option('extension', { + alias: 'e', + default: [], + describe: 'a list of extensions that nyc should handle in addition to .js' + }) + .option('source-map', { + default: true, + type: 'boolean', + description: 'should nyc detect and handle source maps?' + }) + .option('instrument', { + default: true, + type: 'boolean', + description: 'should nyc handle instrumentation?' + }) + .example('$0 instrument ./lib ./output', 'instrument all .js files in ./lib with coverage and output in ./output') +} + +exports.handler = function (argv) { + // if instrument is set to false, + // enable a noop instrumenter. + if (!argv.instrument) argv.instrumenter = './lib/instrumenters/noop' + else argv.instrumenter = './lib/instrumenters/istanbul' + + var nyc = new NYC({ + instrumenter: argv.instrumenter, + sourceMap: argv.sourceMap, + extension: argv.extension, + require: argv.require + }) + + nyc.instrumentAllFiles(argv.input, argv.output, function (err) { + if (err) console.error(err.message) + process.exit(1) + }) +} diff --git a/node_modules/nyc/lib/config-util.js b/node_modules/nyc/lib/config-util.js new file mode 100644 index 000000000..62d057a3f --- /dev/null +++ b/node_modules/nyc/lib/config-util.js @@ -0,0 +1,253 @@ +const arrify = require('arrify') +const fs = require('fs') +const path = require('path') +const findUp = require('find-up') +const testExclude = require('test-exclude') +const Yargs = require('yargs/yargs') + +var Config = {} + +// load config from a cascade of sources: +// * command line arguments +// * package.json +// * .nycrc +Config.loadConfig = function (argv, cwd) { + cwd = cwd || process.env.NYC_CWD || process.cwd() + var pkgPath = findUp.sync('package.json', {cwd: cwd}) + var rcPath = findUp.sync('.nycrc', {cwd: cwd}) + var rcConfig = null + + if (rcPath) { + rcConfig = JSON.parse( + fs.readFileSync(rcPath, 'utf-8') + ) + } + + if (pkgPath) { + cwd = path.dirname(pkgPath) + } + + var config = Config.buildYargs(cwd) + .default({ + cwd: cwd + }) + if (rcConfig) config.config(rcConfig) + config = config.parse(argv || []) + + // post-hoc, we convert several of the + // configuration settings to arrays, providing + // a consistent contract to index.js. + config.require = arrify(config.require) + config.extension = arrify(config.extension) + config.exclude = arrify(config.exclude) + config.include = arrify(config.include) + config.cwd = cwd + + return config +} + +// build a yargs object, omitting any settings +// that would cause the application to exit early. +Config.buildYargs = function (cwd) { + return Yargs([]) + .usage('$0 [command] [options]\n\nrun your tests with the nyc bin to instrument them with coverage') + .command('report', 'run coverage report for .nyc_output', function (yargs) { + return yargs + .usage('$0 report [options]') + .option('reporter', { + alias: 'r', + describe: 'coverage reporter(s) to use', + default: 'text' + }) + .option('report-dir', { + describe: 'directory to output coverage reports in', + default: 'coverage' + }) + .option('temp-directory', { + describe: 'directory to read raw coverage information from', + default: './.nyc_output' + }) + .option('show-process-tree', { + describe: 'display the tree of spawned processes', + default: false, + type: 'boolean' + }) + .example('$0 report --reporter=lcov', 'output an HTML lcov report to ./coverage') + }) + .command('check-coverage', 'check whether coverage is within thresholds provided', function (yargs) { + return yargs + .usage('$0 check-coverage [options]') + .option('branches', { + default: 0, + description: 'what % of branches must be covered?' + }) + .option('functions', { + default: 0, + description: 'what % of functions must be covered?' + }) + .option('lines', { + default: 90, + description: 'what % of lines must be covered?' + }) + .option('statements', { + default: 0, + description: 'what % of statements must be covered?' + }) + .example('$0 check-coverage --lines 95', "check whether the JSON in nyc's output folder meets the thresholds provided") + }) + .option('reporter', { + alias: 'r', + describe: 'coverage reporter(s) to use', + default: 'text', + globa: false + }) + .option('report-dir', { + describe: 'directory to output coverage reports in', + default: 'coverage', + global: false + }) + .option('silent', { + alias: 's', + default: false, + type: 'boolean', + describe: "don't output a report after tests finish running", + global: false + }) + .option('all', { + alias: 'a', + default: false, + type: 'boolean', + describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)', + global: false + }) + .option('exclude', { + alias: 'x', + default: testExclude.defaultExclude, + describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded', + global: false + }) + .option('include', { + alias: 'n', + default: [], + describe: 'a list of specific files that should be covered, glob patterns are supported', + global: false + }) + .option('require', { + alias: 'i', + default: [], + describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., babel-register, babel-polyfill.', + global: false + }) + .option('eager', { + default: false, + type: 'boolean', + describe: 'instantiate the instrumenter at startup (see https://git.io/vMKZ9)', + global: false + }) + .option('cache', { + alias: 'c', + default: true, + type: 'boolean', + describe: 'cache instrumentation results for improved performance', + global: false + }) + .option('babel-cache', { + default: false, + type: 'boolean', + describe: 'cache babel transpilation results for improved performance', + global: false + }) + .option('extension', { + alias: 'e', + default: [], + describe: 'a list of extensions that nyc should handle in addition to .js', + global: false + }) + .option('check-coverage', { + type: 'boolean', + default: false, + describe: 'check whether coverage is within thresholds provided', + global: false + }) + .option('branches', { + default: 0, + description: 'what % of branches must be covered?', + global: false + }) + .option('functions', { + default: 0, + description: 'what % of functions must be covered?', + global: false + }) + .option('lines', { + default: 90, + description: 'what % of lines must be covered?', + global: false + }) + .option('statements', { + default: 0, + description: 'what % of statements must be covered?', + global: false + }) + .option('source-map', { + default: true, + type: 'boolean', + description: 'should nyc detect and handle source maps?', + global: false + }) + .option('produce-source-map', { + default: false, + type: 'boolean', + description: "should nyc's instrumenter produce source maps?", + global: false + }) + .option('instrument', { + default: true, + type: 'boolean', + description: 'should nyc handle instrumentation?', + global: false + }) + .option('hook-run-in-context', { + default: true, + type: 'boolean', + description: 'should nyc wrap vm.runInThisContext?', + global: false + }) + .option('show-process-tree', { + describe: 'display the tree of spawned processes', + default: false, + type: 'boolean', + global: false + }) + .option('clean', { + describe: 'should the .nyc_output folder be cleaned before executing tests', + default: true, + type: 'boolean', + global: false + }) + .option('temp-directory', { + describe: 'directory to output raw coverage information to', + default: './.nyc_output', + global: false + }) + .pkgConf('nyc', cwd || process.cwd()) + .example('$0 npm test', 'instrument your tests with coverage') + .example('$0 --require babel-core/register npm test', 'instrument your tests with coverage and babel') + .example('$0 report --reporter=text-lcov', 'output lcov report after running your tests') + .epilog('visit https://git.io/voHar for list of available reporters') + .boolean('help') + .boolean('h') + .boolean('version') +} + +// decorate yargs with all the actions +// that would make it exit: help, version, command. +Config.decorateYargs = function (yargs) { + return yargs + .help('h') + .alias('h', 'help') + .version() + .command(require('../lib/commands/instrument')) +} + +module.exports = Config diff --git a/node_modules/nyc/lib/hash.js b/node_modules/nyc/lib/hash.js new file mode 100644 index 000000000..a36372071 --- /dev/null +++ b/node_modules/nyc/lib/hash.js @@ -0,0 +1,14 @@ +const CACHE_VERSION = require('../package.json').version +const md5hex = require('md5-hex') +const salt = JSON.stringify({ + istanbul: require('istanbul-lib-coverage/package.json').version, + nyc: CACHE_VERSION +}) + +function Hash (code, filename) { + return md5hex([code, filename, salt]) + '_' + CACHE_VERSION +} + +Hash.salt = salt + +module.exports = Hash diff --git a/node_modules/nyc/lib/instrumenters/istanbul.js b/node_modules/nyc/lib/instrumenters/istanbul.js new file mode 100644 index 000000000..c1d4b1338 --- /dev/null +++ b/node_modules/nyc/lib/instrumenters/istanbul.js @@ -0,0 +1,49 @@ +'use strict' + +var convertSourceMap = require('convert-source-map') +var mergeSourceMap = require('merge-source-map') + +function InstrumenterIstanbul (cwd, options) { + var istanbul = InstrumenterIstanbul.istanbul() + var instrumenter = istanbul.createInstrumenter({ + autoWrap: true, + coverageVariable: '__coverage__', + embedSource: true, + noCompact: false, + preserveComments: true, + produceSourceMap: options.produceSourceMap + }) + + return { + instrumentSync: function (code, filename, sourceMap) { + var instrumented = instrumenter.instrumentSync(code, filename) + // the instrumenter can optionally produce source maps, + // this is useful for features like remapping stack-traces. + // TODO: test source-map merging logic. + if (options.produceSourceMap) { + var lastSourceMap = instrumenter.lastSourceMap() + if (lastSourceMap) { + if (sourceMap) { + lastSourceMap = mergeSourceMap( + sourceMap.toObject(), + lastSourceMap + ) + } + instrumented += '\n' + convertSourceMap.fromObject(lastSourceMap).toComment() + } + } + return instrumented + }, + lastFileCoverage: function () { + return instrumenter.lastFileCoverage() + } + } +} + +InstrumenterIstanbul.istanbul = function () { + InstrumenterIstanbul._istanbul || (InstrumenterIstanbul._istanbul = require('istanbul-lib-instrument')) + + return InstrumenterIstanbul._istanbul || (InstrumenterIstanbul._istanbul = require('istanbul')) +} + +module.exports = InstrumenterIstanbul diff --git a/node_modules/nyc/lib/instrumenters/noop.js b/node_modules/nyc/lib/instrumenters/noop.js new file mode 100644 index 000000000..935b587c0 --- /dev/null +++ b/node_modules/nyc/lib/instrumenters/noop.js @@ -0,0 +1,21 @@ +var FileCoverage = require('istanbul-lib-coverage').classes.FileCoverage +var readInitialCoverage = require('istanbul-lib-instrument').readInitialCoverage + +function NOOP () { + return { + instrumentSync: function (code, filename) { + var extracted = readInitialCoverage(code) + if (extracted) { + this.fileCoverage = new FileCoverage(extracted.coverageData) + } else { + this.fileCoverage = null + } + return code + }, + lastFileCoverage: function () { + return this.fileCoverage + } + } +} + +module.exports = NOOP diff --git a/node_modules/nyc/lib/process-args.js b/node_modules/nyc/lib/process-args.js new file mode 100644 index 000000000..df6bcaac1 --- /dev/null +++ b/node_modules/nyc/lib/process-args.js @@ -0,0 +1,36 @@ +const parser = require('yargs-parser') +const commands = [ + 'report', + 'check-coverage', + 'instrument' +] + +module.exports = { + // don't pass arguments that are meant + // for nyc to the bin being instrumented. + hideInstrumenterArgs: function (yargv) { + var argv = process.argv.slice(1) + argv = argv.slice(argv.indexOf(yargv._[0])) + if (argv[0][0] === '-') { + argv.unshift(process.execPath) + } + return argv + }, + // don't pass arguments for the bin being + // instrumented to nyc. + hideInstrumenteeArgs: function () { + var argv = process.argv.slice(2) + var yargv = parser(argv) + if (!yargv._.length) return argv + for (var i = 0, command; (command = yargv._[i]) !== undefined; i++) { + if (~commands.indexOf(command)) return argv + } + + // drop all the arguments after the bin being + // instrumented by nyc. + argv = argv.slice(0, argv.indexOf(yargv._[0])) + argv.push(yargv._[0]) + + return argv + } +} diff --git a/node_modules/nyc/lib/process.js b/node_modules/nyc/lib/process.js new file mode 100644 index 000000000..3976f14ed --- /dev/null +++ b/node_modules/nyc/lib/process.js @@ -0,0 +1,98 @@ +const archy = require('archy') +const libCoverage = require('istanbul-lib-coverage') + +function ProcessInfo (defaults) { + defaults = defaults || {} + + this.pid = String(process.pid) + this.argv = process.argv + this.execArgv = process.execArgv + this.cwd = process.cwd() + this.time = Date.now() + this.ppid = null + this.root = null + this.coverageFilename = null + this.nodes = [] // list of children, filled by buildProcessTree() + + this._coverageMap = null + + for (var key in defaults) { + this[key] = defaults[key] + } +} + +Object.defineProperty(ProcessInfo.prototype, 'label', { + get: function () { + if (this._label) { + return this._label + } + + var covInfo = '' + if (this._coverageMap) { + covInfo = '\n ' + this._coverageMap.getCoverageSummary().lines.pct + ' % Lines' + } + return this.argv.join(' ') + covInfo + } +}) + +ProcessInfo.buildProcessTree = function (infos) { + var treeRoot = new ProcessInfo({ _label: 'nyc' }) + var nodes = { } + + infos = infos.sort(function (a, b) { + return a.time - b.time + }) + + infos.forEach(function (p) { + nodes[p.root + ':' + p.pid] = p + }) + + infos.forEach(function (p) { + if (!p.ppid) { + return + } + + var parent = nodes[p.root + ':' + p.ppid] + if (!parent) { + parent = treeRoot + } + + parent.nodes.push(p) + }) + + return treeRoot +} + +ProcessInfo.prototype.getCoverageMap = function (merger) { + if (this._coverageMap) { + return this._coverageMap + } + + var childMaps = this.nodes.map(function (child) { + return child.getCoverageMap(merger) + }) + + this._coverageMap = merger([this.coverageFilename], childMaps) + + return this._coverageMap +} + +ProcessInfo.prototype.render = function (nyc) { + this.getCoverageMap(function (filenames, maps) { + var map = libCoverage.createCoverageMap({}) + + nyc.loadReports(filenames).forEach(function (report) { + map.merge(report) + }) + + maps.forEach(function (otherMap) { + map.merge(otherMap) + }) + + return map + }) + + return archy(this) +} + +module.exports = ProcessInfo diff --git a/node_modules/nyc/lib/self-coverage-helper.js b/node_modules/nyc/lib/self-coverage-helper.js new file mode 100644 index 000000000..675f9bea9 --- /dev/null +++ b/node_modules/nyc/lib/self-coverage-helper.js @@ -0,0 +1,20 @@ +/* global ___NYC_SELF_COVERAGE___ */ + +const path = require('path') +const fs = require('fs') +const mkdirp = require('mkdirp') +const onExit = require('signal-exit') + +onExit(function () { + var coverage = global.___NYC_SELF_COVERAGE___ + if (typeof ___NYC_SELF_COVERAGE___ === 'object') coverage = ___NYC_SELF_COVERAGE___ + if (!coverage) return + + var selfCoverageDir = path.join(__dirname, '../.self_coverage') + mkdirp.sync(selfCoverageDir) + fs.writeFileSync( + path.join(selfCoverageDir, process.pid + '.json'), + JSON.stringify(coverage), + 'utf-8' + ) +}) diff --git a/node_modules/nyc/lib/source-maps.js b/node_modules/nyc/lib/source-maps.js new file mode 100644 index 000000000..c3238544c --- /dev/null +++ b/node_modules/nyc/lib/source-maps.js @@ -0,0 +1,57 @@ +const convertSourceMap = require('convert-source-map') +const libCoverage = require('istanbul-lib-coverage') +const libSourceMaps = require('istanbul-lib-source-maps') +const fs = require('fs') +const path = require('path') + +// TODO: write some unit tests for this class. +function SourceMaps (opts) { + this.cache = opts.cache + this.cacheDirectory = opts.cacheDirectory + this.sourceMapCache = libSourceMaps.createSourceMapStore() + this.loadedMaps = {} +} + +SourceMaps.prototype.extractAndRegister = function (code, filename, hash) { + var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename)) + if (sourceMap) { + if (this.cache && hash) { + var mapPath = path.join(this.cacheDirectory, hash + '.map') + fs.writeFileSync(mapPath, sourceMap.toJSON()) + } else { + this.sourceMapCache.registerMap(filename, sourceMap.sourcemap) + } + } + return sourceMap +} + +SourceMaps.prototype.remapCoverage = function (obj) { + var transformed = this.sourceMapCache.transformCoverage( + libCoverage.createCoverageMap(obj) + ) + return transformed.map.data +} + +SourceMaps.prototype.reloadCachedSourceMaps = function (report) { + var _this = this + Object.keys(report).forEach(function (absFile) { + var fileReport = report[absFile] + if (fileReport && fileReport.contentHash) { + var hash = fileReport.contentHash + if (!(hash in _this.loadedMaps)) { + try { + var mapPath = path.join(_this.cacheDirectory, hash + '.map') + _this.loadedMaps[hash] = JSON.parse(fs.readFileSync(mapPath, 'utf8')) + } catch (e) { + // set to false to avoid repeatedly trying to load the map + _this.loadedMaps[hash] = false + } + } + if (_this.loadedMaps[hash]) { + _this.sourceMapCache.registerMap(absFile, _this.loadedMaps[hash]) + } + } + }) +} + +module.exports = SourceMaps |