Comparing version 5.0.1 to 5.1.0
#!/usr/bin/env node | ||
var foreground = require('foreground-child') | ||
var NYC = require('../') | ||
var NYC | ||
try { | ||
NYC = require('../index.covered.js') | ||
} catch (e) { | ||
NYC = require('../index.js') | ||
} | ||
var path = require('path') | ||
@@ -9,10 +15,6 @@ var sw = require('spawn-wrap') | ||
;(new NYC({ | ||
require: process.env.NYC_REQUIRE ? process.env.NYC_REQUIRE.split(',') : [] | ||
require: process.env.NYC_REQUIRE ? process.env.NYC_REQUIRE.split(',') : [], | ||
enableCache: process.env.NYC_CACHE === 'enable' | ||
})).wrap() | ||
// make sure we can run coverage on | ||
// our own index.js, I like turtles. | ||
var name = require.resolve('../') | ||
delete require.cache[name] | ||
sw.runMain() | ||
@@ -83,2 +85,8 @@ } else { | ||
}) | ||
.option('c', { | ||
alias: 'cache', | ||
default: false, | ||
type: 'boolean', | ||
describe: 'cache instrumentation results for improved performance' | ||
}) | ||
.help('h') | ||
@@ -121,3 +129,4 @@ .alias('h', 'help') | ||
NYC_CWD: process.cwd(), | ||
NYC_REQUIRE: argv.require.join(',') | ||
NYC_REQUIRE: argv.require.join(','), | ||
NYC_CACHE: argv.cache ? 'enable' : 'disable' | ||
}) | ||
@@ -124,0 +133,0 @@ |
## Change Log | ||
### v5.1.0 (2015/12/27 20:36 -08:00) | ||
- [#108](https://github.com/bcoe/nyc/pull/108) Adds cache functionality. this is a big one, thanks! (@jamestalmage) | ||
- [#118](https://github.com/bcoe/nyc/pull/118) Stop bundling spawn-wrap dependency (@bcoe) | ||
- [#114](https://github.com/bcoe/nyc/pull/114) Update to latest versions of tap, glob, rimraf (@isaacs) | ||
- [#107](https://github.com/bcoe/nyc/pull/107) Get test-suite running on Windows (@bcoe) | ||
### v5.0.1 (2015/12/14 09:09 -07:00) | ||
@@ -4,0 +11,0 @@ |
310
index.js
/* global __coverage__ */ | ||
var _ = require('lodash') | ||
var fs = require('fs') | ||
@@ -7,3 +6,4 @@ var glob = require('glob') | ||
var mkdirp = require('mkdirp') | ||
var Module = require('module') | ||
var appendTransform = require('append-transform') | ||
var cachingTransform = require('caching-transform') | ||
var path = require('path') | ||
@@ -13,19 +13,22 @@ var rimraf = require('rimraf') | ||
var stripBom = require('strip-bom') | ||
var resolveFrom = require('resolve-from') | ||
var arrify = require('arrify') | ||
var SourceMapCache = require('./lib/source-map-cache') | ||
var convertSourceMap = require('convert-source-map') | ||
var md5hex = require('md5-hex') | ||
/* istanbul ignore next */ | ||
if (/index\.covered\.js$/.test(__filename)) { | ||
require('./lib/self-coverage-helper') | ||
} | ||
function NYC (opts) { | ||
_.extend(this, { | ||
subprocessBin: path.resolve( | ||
__dirname, | ||
'./bin/nyc.js' | ||
), | ||
tempDirectory: './.nyc_output', | ||
cwd: process.env.NYC_CWD || process.cwd(), | ||
reporter: 'text', | ||
istanbul: require('istanbul'), | ||
sourceMapCache: new SourceMapCache(), | ||
require: [] | ||
}, opts) | ||
opts = opts || {} | ||
if (!Array.isArray(this.reporter)) this.reporter = [this.reporter] | ||
this._istanbul = opts.istanbul | ||
this.subprocessBin = opts.subprocessBin || path.resolve(__dirname, './bin/nyc.js') | ||
this._tempDirectory = opts.tempDirectory || './.nyc_output' | ||
this._cacheDirectory = opts.cacheDirectory || './node_modules/.cache/nyc' | ||
this.cwd = opts.cwd || process.env.NYC_CWD || process.cwd() | ||
this.reporter = arrify(opts.reporter || 'text') | ||
@@ -37,30 +40,64 @@ // you can specify config in the nyc stanza of package.json. | ||
// load exclude stanza from config. | ||
this.include = config.include || ['**'] | ||
this.include = this._prepGlobPatterns(this.include) | ||
this.include = false | ||
if (config.include) { | ||
this.include = this._prepGlobPatterns(arrify(config.include)) | ||
} | ||
this.exclude = ['**/node_modules/**'].concat(config.exclude || ['test/**', 'test{,-*}.js']) | ||
if (!Array.isArray(this.exclude)) this.exclude = [this.exclude] | ||
this.exclude = this._prepGlobPatterns(this.exclude) | ||
this.exclude = this._prepGlobPatterns( | ||
['**/node_modules/**'].concat(arrify(config.exclude || ['test/**', 'test{,-*}.js'])) | ||
) | ||
this.enableCache = opts.enableCache === true || process.env.NYC_CACHE === 'enable' | ||
// require extensions can be provided as config in package.json. | ||
this.require = config.require ? config.require : this.require | ||
this.require = arrify(config.require || opts.require) | ||
this.instrumenter = this._createInstrumenter() | ||
this._createOutputDirectory() | ||
this._createDatastoreDirectories() | ||
this.transform = this._createTransform() | ||
this.sourceMapCache = new SourceMapCache() | ||
this.hashCache = {} | ||
this.loadedMaps = null | ||
} | ||
NYC.prototype._createTransform = function () { | ||
var _this = this | ||
return cachingTransform({ | ||
salt: JSON.stringify({ | ||
istanbul: require('istanbul/package.json').version, | ||
nyc: require('./package.json').version | ||
}), | ||
hash: function (code, metadata, salt) { | ||
var hash = md5hex([code, metadata.filename, salt]) | ||
_this.hashCache['./' + metadata.relFile] = hash | ||
return hash | ||
}, | ||
factory: this._transformFactory.bind(this), | ||
cacheDir: this.cacheDirectory(), | ||
disableCache: !this.enableCache, | ||
ext: '.js' | ||
}) | ||
} | ||
NYC.prototype._loadAdditionalModules = function () { | ||
var _this = this | ||
this.require.forEach(function (r) { | ||
try { | ||
// first attempt to require the module relative to | ||
// the directory being instrumented. | ||
require(path.resolve(_this.cwd, './node_modules', r)) | ||
} catch (e) { | ||
// now try other locations, .e.g, the nyc node_modules folder. | ||
require(r) | ||
// first attempt to require the module relative to | ||
// the directory being instrumented. | ||
var p = resolveFrom(_this.cwd, r) | ||
if (p) { | ||
require(p) | ||
return | ||
} | ||
// now try other locations, .e.g, the nyc node_modules folder. | ||
require(r) | ||
}) | ||
} | ||
NYC.prototype.instrumenter = function () { | ||
return this._instrumenter || (this._instrumenter = this._createInstrumenter()) | ||
} | ||
NYC.prototype._createInstrumenter = function () { | ||
@@ -71,5 +108,7 @@ var configFile = path.resolve(this.cwd, './.istanbul.yml') | ||
var instrumenterConfig = this.istanbul.config.loadFile(configFile).instrumentation.config | ||
var istanbul = this.istanbul() | ||
return new this.istanbul.Instrumenter({ | ||
var instrumenterConfig = istanbul.config.loadFile(configFile).instrumentation.config | ||
return new istanbul.Instrumenter({ | ||
coverageVariable: '__coverage__', | ||
@@ -85,45 +124,30 @@ embedSource: instrumenterConfig['embed-source'], | ||
var directories = [] | ||
patterns = _.map(patterns, function (pattern) { | ||
var result = [] | ||
function add (pattern) { | ||
if (result.indexOf(pattern) === -1) { | ||
result.push(pattern) | ||
} | ||
} | ||
patterns.forEach(function (pattern) { | ||
// Allow gitignore style of directory exclusion | ||
if (!_.endsWith(pattern, '/**')) { | ||
directories.push(pattern.replace(/\/$/, '').concat('/**')) | ||
if (!/\/\*\*$/.test(pattern)) { | ||
add(pattern.replace(/\/$/, '') + '/**') | ||
} | ||
return pattern | ||
add(pattern) | ||
}) | ||
return _.union(patterns, directories) | ||
} | ||
NYC.prototype.addFile = function (filename, returnImmediately) { | ||
var relFile = path.relative(this.cwd, filename) | ||
var instrument = this.shouldInstrumentFile(filename, relFile) | ||
var content = stripBom(fs.readFileSync(filename, 'utf8')) | ||
if (instrument) { | ||
this.sourceMapCache.add(filename, content) | ||
content = this.instrumenter.instrumentSync(content, './' + relFile) | ||
} else if (returnImmediately) { | ||
return {} | ||
} | ||
return { | ||
instrument: instrument, | ||
content: content, | ||
relFile: relFile | ||
} | ||
return result | ||
} | ||
NYC.prototype.addContent = function (filename, content) { | ||
NYC.prototype.addFile = function (filename) { | ||
var relFile = path.relative(this.cwd, filename) | ||
var instrument = this.shouldInstrumentFile(filename, relFile) | ||
if (instrument) { | ||
content = this.instrumenter.instrumentSync(content, './' + relFile) | ||
} | ||
var source = stripBom(fs.readFileSync(filename, 'utf8')) | ||
var instrumentedSource = this._maybeInstrumentSource(source, filename, relFile) | ||
return { | ||
instrument: instrument, | ||
content: content, | ||
relFile: relFile | ||
instrument: !!instrumentedSource, | ||
relFile: relFile, | ||
content: instrumentedSource || source | ||
} | ||
@@ -135,3 +159,3 @@ } | ||
return (micromatch.any(filename, this.include) || micromatch.any(relFile, this.include)) && | ||
return (!this.include || micromatch.any(filename, this.include) || micromatch.any(relFile, this.include)) && | ||
!(micromatch.any(filename, this.exclude) || micromatch.any(relFile, this.exclude)) | ||
@@ -143,4 +167,2 @@ } | ||
this._createOutputDirectory() | ||
glob.sync('**/*.js', {nodir: true, ignore: this.exclude}).forEach(function (filename) { | ||
@@ -150,3 +172,3 @@ var obj = _this.addFile(filename, true) | ||
module._compile( | ||
_this.instrumenter.getPreamble(obj.content, obj.relFile), | ||
_this.instrumenter().getPreamble(obj.content, obj.relFile), | ||
filename | ||
@@ -160,64 +182,55 @@ ) | ||
NYC.prototype._wrapRequire = function () { | ||
NYC.prototype._maybeInstrumentSource = function (code, filename, relFile) { | ||
var instrument = this.shouldInstrumentFile(filename, relFile) | ||
if (!instrument) { | ||
return null | ||
} | ||
return this.transform(code, {filename: filename, relFile: relFile}) | ||
} | ||
NYC.prototype._transformFactory = function (cacheDir) { | ||
var _this = this | ||
var instrumenter = this.instrumenter() | ||
var defaultHook = function (module, filename) { | ||
// instrument the required file. | ||
var obj = _this.addFile(filename, false) | ||
return function (code, metadata, hash) { | ||
var filename = metadata.filename | ||
var relFile = './' + metadata.relFile | ||
// always use node's original _compile method to compile the instrumented | ||
// code. if a custom hook invoked the default hook the code should not be | ||
// compiled using the custom hook. | ||
Module.prototype._compile.call(module, obj.content, filename) | ||
} | ||
var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename)) | ||
var wrapCustomHook = function (hook) { | ||
return function (module, filename) { | ||
// override the _compile method so the code can be instrumented first. | ||
module._compile = function (compiledSrc) { | ||
_this.sourceMapCache.add(filename, compiledSrc) | ||
// now instrument the compiled code. | ||
var obj = _this.addContent(filename, compiledSrc) | ||
Module.prototype._compile.call(module, obj.content, filename) | ||
if (sourceMap) { | ||
if (hash) { | ||
var mapPath = path.join(cacheDir, hash + '.map') | ||
fs.writeFileSync(mapPath, sourceMap.toJSON()) | ||
} else { | ||
_this.sourceMapCache.addMap(relFile, sourceMap.toJSON()) | ||
} | ||
} | ||
// allow the custom hook to compile the code. it can fall back to the | ||
// default hook if necessary (accessed via require.extensions['.js'] prior | ||
// to setting itself) | ||
hook(module, filename) | ||
} | ||
return instrumenter.instrumentSync(code, relFile) | ||
} | ||
} | ||
var requireHook = defaultHook | ||
// track existing hooks so they can be restored without wrapping them a second | ||
// time. | ||
var hooks = [requireHook] | ||
// use a getter and setter to capture any external require hooks that are | ||
// registered, e.g., babel-core/register | ||
require.extensions.__defineGetter__('.js', function () { | ||
return requireHook | ||
NYC.prototype._wrapRequire = function () { | ||
var _this = this | ||
appendTransform(function (code, filename) { | ||
var relFile = path.relative(_this.cwd, filename) | ||
return _this._maybeInstrumentSource(code, filename, relFile) || code | ||
}) | ||
require.extensions.__defineSetter__('.js', function (hook) { | ||
var restoreIndex = hooks.indexOf(hook) | ||
if (restoreIndex !== -1) { | ||
requireHook = hook | ||
hooks.splice(restoreIndex + 1, hooks.length) | ||
} else { | ||
requireHook = wrapCustomHook(hook) | ||
hooks.push(requireHook) | ||
} | ||
}) | ||
} | ||
NYC.prototype.cleanup = function () { | ||
if (!process.env.NYC_CWD) rimraf.sync(this.tmpDirectory()) | ||
if (!process.env.NYC_CWD) rimraf.sync(this.tempDirectory()) | ||
} | ||
NYC.prototype._createOutputDirectory = function () { | ||
mkdirp.sync(this.tmpDirectory()) | ||
NYC.prototype.clearCache = function () { | ||
rimraf.sync(this.cacheDirectory()) | ||
} | ||
NYC.prototype._createDatastoreDirectories = function () { | ||
mkdirp.sync(this.tempDirectory()) | ||
} | ||
NYC.prototype._wrapExit = function () { | ||
@@ -245,5 +258,15 @@ var _this = this | ||
if (this.enableCache) { | ||
Object.keys(coverage).forEach(function (relFile) { | ||
if (this.hashCache[relFile] && coverage[relFile]) { | ||
coverage[relFile].contentHash = this.hashCache[relFile] | ||
} | ||
}, this) | ||
} else { | ||
this.sourceMapCache.applySourceMaps(coverage) | ||
} | ||
fs.writeFileSync( | ||
path.resolve(this.tmpDirectory(), './', process.pid + '.json'), | ||
JSON.stringify(this.sourceMapCache.applySourceMaps(coverage)), | ||
path.resolve(this.tempDirectory(), './', process.pid + '.json'), | ||
JSON.stringify(coverage), | ||
'utf-8' | ||
@@ -253,7 +276,12 @@ ) | ||
NYC.prototype.istanbul = function () { | ||
return this._istanbul || (this._istanbul = require('istanbul')) | ||
} | ||
NYC.prototype.report = function (cb, _collector, _reporter) { | ||
cb = cb || function () {} | ||
var collector = _collector || new this.istanbul.Collector() | ||
var reporter = _reporter || new this.istanbul.Reporter() | ||
var istanbul = this.istanbul() | ||
var collector = _collector || new istanbul.Collector() | ||
var reporter = _reporter || new istanbul.Reporter() | ||
@@ -273,8 +301,13 @@ this._loadReports().forEach(function (report) { | ||
var _this = this | ||
var files = fs.readdirSync(this.tmpDirectory()) | ||
var files = fs.readdirSync(this.tempDirectory()) | ||
return _.map(files, function (f) { | ||
var cacheDir = _this.cacheDirectory() | ||
var loadedMaps = this.loadedMaps || (this.loadedMaps = {}) | ||
return files.map(function (f) { | ||
var report | ||
try { | ||
return JSON.parse(fs.readFileSync( | ||
path.resolve(_this.tmpDirectory(), './', f), | ||
report = JSON.parse(fs.readFileSync( | ||
path.resolve(_this.tempDirectory(), './', f), | ||
'utf-8' | ||
@@ -285,9 +318,34 @@ )) | ||
} | ||
Object.keys(report).forEach(function (relFile) { | ||
var fileReport = report[relFile] | ||
if (fileReport && fileReport.contentHash) { | ||
var hash = fileReport.contentHash | ||
if (!(hash in loadedMaps)) { | ||
try { | ||
var mapPath = path.join(cacheDir, hash + '.map') | ||
loadedMaps[hash] = JSON.parse(fs.readFileSync(mapPath, 'utf8')) | ||
} catch (e) { | ||
// set to false to avoid repeatedly trying to load the map | ||
loadedMaps[hash] = false | ||
} | ||
} | ||
if (loadedMaps[hash]) { | ||
_this.sourceMapCache.addMap(relFile, loadedMaps[hash]) | ||
} | ||
} | ||
}) | ||
_this.sourceMapCache.applySourceMaps(report) | ||
return report | ||
}) | ||
} | ||
NYC.prototype.tmpDirectory = function () { | ||
return path.resolve(this.cwd, './', this.tempDirectory) | ||
NYC.prototype.tempDirectory = function () { | ||
return path.resolve(this.cwd, './', this._tempDirectory) | ||
} | ||
NYC.prototype.cacheDirectory = function () { | ||
return path.resolve(this.cwd, './', this._cacheDirectory) | ||
} | ||
NYC.prototype.mungeArgs = function (yargv) { | ||
@@ -294,0 +352,0 @@ var argv = process.argv.slice(1) |
@@ -1,24 +0,17 @@ | ||
var _ = require('lodash') | ||
var path = require('path') | ||
var convertSourceMap = require('convert-source-map') | ||
var SourceMapConsumer = require('source-map').SourceMapConsumer | ||
function SourceMapCache (opts) { | ||
_.extend(this, { | ||
cache: {}, | ||
cwd: process.env.NYC_CWD || process.cwd() | ||
}, opts) | ||
function SourceMapCache () { | ||
this.cache = {} | ||
} | ||
SourceMapCache.prototype.add = function (filename, source) { | ||
var sourceMap = convertSourceMap.fromSource(source) || convertSourceMap.fromMapFileSource(source, path.dirname(filename)) | ||
if (sourceMap) this.cache['./' + path.relative(this.cwd, filename)] = new SourceMapConsumer(sourceMap.sourcemap) | ||
SourceMapCache.prototype.addMap = function (relFile, map) { | ||
this.cache[relFile] = new SourceMapConsumer(map) | ||
} | ||
SourceMapCache.prototype.applySourceMaps = function (coverage) { | ||
SourceMapCache.prototype.applySourceMaps = function (report) { | ||
var _this = this | ||
var mappedCoverage = _.cloneDeep(coverage) | ||
Object.keys(coverage).forEach(function (key) { | ||
var sourceMap = _this.cache[key] | ||
Object.keys(report).forEach(function (relFile) { | ||
var sourceMap = _this.cache[relFile] | ||
if (!sourceMap) { | ||
@@ -28,26 +21,69 @@ return | ||
var fileCoverage = mappedCoverage[key] | ||
_this._rewritePath(mappedCoverage, fileCoverage, sourceMap) | ||
_this._rewriteStatements(fileCoverage, sourceMap) | ||
_this._rewriteFunctions(fileCoverage, sourceMap) | ||
_this._rewriteBranches(fileCoverage, sourceMap) | ||
var fileReport = report[relFile] | ||
_this._rewritePath(report, fileReport, sourceMap) | ||
_this._rewriteStatements(fileReport, sourceMap) | ||
_this._rewriteFunctions(fileReport, sourceMap) | ||
_this._rewriteBranches(fileReport, sourceMap) | ||
}) | ||
} | ||
return mappedCoverage | ||
// Maps the coverage location based on the source map. Adapted from getMapping() | ||
// in remap-istanbul: | ||
// <https://github.com/SitePen/remap-istanbul/blob/30b67ad3f24ba7e0da8b8888d5a7c3c8480d48b2/lib/remap.js#L55:L108>. | ||
function mapLocation (sourceMap, location) { | ||
var start = sourceMap.originalPositionFor(location.start) | ||
var end = sourceMap.originalPositionFor(location.end) | ||
/* istanbul ignore if: edge case too hard to test for */ | ||
if (!start || !end) { | ||
return null | ||
} | ||
if (!start.source || !end.source || start.source !== end.source) { | ||
return null | ||
} | ||
/* istanbul ignore if: edge case too hard to test for */ | ||
if (start.line === null || start.column === null) { | ||
return null | ||
} | ||
/* istanbul ignore if: edge case too hard to test for */ | ||
if (end.line === null || end.column === null) { | ||
return null | ||
} | ||
if (start.line === end.line && start.column === end.column) { | ||
end = sourceMap.originalPositionFor({ | ||
line: location.end.line, | ||
column: location.end.column, | ||
bias: 2 | ||
}) | ||
end.column = end.column - 1 | ||
} | ||
return { | ||
start: { | ||
line: start.line, | ||
column: start.column | ||
}, | ||
end: { | ||
line: end.line, | ||
column: end.column | ||
}, | ||
skip: location.skip | ||
} | ||
} | ||
SourceMapCache.prototype._rewritePath = function (mappedCoverage, coverage, sourceMap) { | ||
SourceMapCache.prototype._rewritePath = function (report, fileReport, sourceMap) { | ||
// only rewrite the path if the file comes from a single source | ||
if (sourceMap.sources.length !== 1) return | ||
var originalPath = './' + path.join(path.dirname(coverage.path), sourceMap.sources[0]) | ||
delete mappedCoverage[coverage.path] | ||
coverage.path = originalPath | ||
mappedCoverage[originalPath] = coverage | ||
var originalPath = './' + path.join(path.dirname(fileReport.path), sourceMap.sources[0]) | ||
report[fileReport.path] = undefined // Hack for Windows tests, until we can normalize paths. | ||
delete report[fileReport.path] | ||
fileReport.path = originalPath | ||
report[originalPath] = fileReport | ||
} | ||
SourceMapCache.prototype._rewriteStatements = function (coverage, sourceMap) { | ||
var start = null | ||
var end = null | ||
SourceMapCache.prototype._rewriteStatements = function (fileReport, sourceMap) { | ||
var s = {} | ||
@@ -57,11 +93,7 @@ var statementMap = {} | ||
Object.keys(coverage.statementMap).forEach(function (k) { | ||
start = sourceMap.originalPositionFor({line: coverage.statementMap[k].start.line, column: coverage.statementMap[k].start.column}) | ||
end = sourceMap.originalPositionFor({line: coverage.statementMap[k].end.line, column: coverage.statementMap[k].end.column}) | ||
if (start.line && end.line) { | ||
s[index + ''] = coverage.s[k] | ||
statementMap[index + ''] = { | ||
start: {line: start.line, column: start.column}, | ||
end: {line: end.line, column: end.column} | ||
} | ||
Object.keys(fileReport.statementMap).forEach(function (k) { | ||
var mapped = mapLocation(sourceMap, fileReport.statementMap[k]) | ||
if (mapped) { | ||
s[index + ''] = fileReport.s[k] | ||
statementMap[index + ''] = mapped | ||
index++ | ||
@@ -71,11 +103,7 @@ } | ||
coverage.statementMap = statementMap | ||
coverage.s = s | ||
fileReport.statementMap = statementMap | ||
fileReport.s = s | ||
} | ||
SourceMapCache.prototype._rewriteFunctions = function (coverage, sourceMap) { | ||
var start = null | ||
var end = null | ||
var line = null | ||
SourceMapCache.prototype._rewriteFunctions = function (fileReport, sourceMap) { | ||
var f = {} | ||
@@ -85,16 +113,10 @@ var fnMap = {} | ||
Object.keys(coverage.fnMap).forEach(function (k) { | ||
start = sourceMap.originalPositionFor({line: coverage.fnMap[k].loc.start.line, column: coverage.fnMap[k].loc.start.column}) | ||
end = sourceMap.originalPositionFor({line: coverage.fnMap[k].loc.end.line, column: coverage.fnMap[k].loc.end.column}) | ||
line = sourceMap.originalPositionFor({line: coverage.fnMap[k].line, column: null}) | ||
if (line.line && start.line && end.line) { | ||
f[index + ''] = coverage.f[k] | ||
Object.keys(fileReport.fnMap).forEach(function (k) { | ||
var mapped = mapLocation(sourceMap, fileReport.fnMap[k].loc) | ||
if (mapped) { | ||
f[index + ''] = fileReport.f[k] | ||
fnMap[index + ''] = { | ||
name: coverage.fnMap[k].name, | ||
line: line.line, | ||
loc: { | ||
start: {line: start.line, column: start.column}, | ||
end: {line: end.line, column: end.column} | ||
} | ||
name: fileReport.fnMap[k].name, | ||
line: mapped.start.line, | ||
loc: mapped | ||
} | ||
@@ -105,11 +127,7 @@ index++ | ||
coverage.fnMap = fnMap | ||
coverage.f = f | ||
fileReport.fnMap = fnMap | ||
fileReport.f = f | ||
} | ||
SourceMapCache.prototype._rewriteBranches = function (coverage, sourceMap) { | ||
var start = null | ||
var end = null | ||
var line = null | ||
SourceMapCache.prototype._rewriteBranches = function (fileReport, sourceMap) { | ||
var b = {} | ||
@@ -119,22 +137,22 @@ var branchMap = {} | ||
Object.keys(coverage.branchMap).forEach(function (k) { | ||
line = sourceMap.originalPositionFor({line: coverage.branchMap[k].line, column: null}) | ||
if (line.line) { | ||
b[index + ''] = [] | ||
Object.keys(fileReport.branchMap).forEach(function (k) { | ||
var item = fileReport.branchMap[k] | ||
var locations = [] | ||
item.locations.every(function (location) { | ||
var mapped = mapLocation(sourceMap, location) | ||
if (mapped) { | ||
locations.push(mapped) | ||
return true | ||
} | ||
}) | ||
if (locations.length > 0) { | ||
b[index + ''] = fileReport.b[k] | ||
branchMap[index + ''] = { | ||
line: line.line, | ||
type: coverage.branchMap[k].type, | ||
locations: [] | ||
line: locations[0].start.line, | ||
type: item.type, | ||
locations: locations | ||
} | ||
for (var i = 0, location; (location = coverage.branchMap[k].locations[i]) !== undefined; i++) { | ||
start = sourceMap.originalPositionFor({line: location.start.line, column: location.start.column}) | ||
end = sourceMap.originalPositionFor({line: location.end.line, column: location.end.column}) | ||
if (start.line && end.line) { | ||
b[index + ''].push(coverage.b[k][i]) | ||
branchMap[index + ''].locations.push({ | ||
start: {source: location.source, line: start.line, column: start.column}, | ||
end: {source: location.source, line: end.line, column: end.column} | ||
}) | ||
} | ||
} | ||
index++ | ||
@@ -144,6 +162,6 @@ } | ||
coverage.branchMap = branchMap | ||
coverage.b = b | ||
fileReport.branchMap = branchMap | ||
fileReport.b = b | ||
} | ||
module.exports = SourceMapCache |
{ | ||
"name": "nyc", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"description": "a code coverage tool that works well with subprocesses.", | ||
@@ -8,3 +8,10 @@ "main": "index.js", | ||
"pretest": "standard", | ||
"test": "tap --coverage ./test/*.js" | ||
"test": "npm run cover", | ||
"clean": "rimraf ./.nyc_output ./node_modules/.cache ./.self_coverage ./test/fixtures/.nyc_output ./test/fixtures/node_modules/.cache *covered.js ./lib/*covered.js", | ||
"build": "node ./build-tests", | ||
"instrument": "node ./build-self-coverage.js", | ||
"run-tests": "tap --no-cov -b ./test/build/*.js ./test/src/source-map-cache.js", | ||
"report": "istanbul report --include=./.self_coverage/*.json lcov text", | ||
"cover": "npm run clean && npm run build && npm run instrument && npm run run-tests && npm run report", | ||
"dev": "npm run clean && npm run build && npm run run-tests" | ||
}, | ||
@@ -14,2 +21,8 @@ "bin": { | ||
}, | ||
"files": [ | ||
"index.js", | ||
"bin/*.js", | ||
"lib/*.js", | ||
"!**/*covered.js" | ||
], | ||
"config": { | ||
@@ -22,4 +35,6 @@ "nyc": { | ||
"test/fixtures/coverage.js", | ||
"test/build/*", | ||
"test/nyc-test.js", | ||
"test/source-map-cache.js", | ||
"index.covered.js", | ||
"test/fixtures/_generateCoverage.js" | ||
@@ -31,3 +46,4 @@ ] | ||
"ignore": [ | ||
"**/fixtures/**" | ||
"**/fixtures/**", | ||
"**/test/build/*" | ||
] | ||
@@ -54,13 +70,17 @@ }, | ||
"dependencies": { | ||
"append-transform": "^0.2.0", | ||
"arrify": "^1.0.1", | ||
"caching-transform": "^1.0.0", | ||
"convert-source-map": "^1.1.2", | ||
"foreground-child": "^1.3.0", | ||
"glob": "^5.0.14", | ||
"glob": "^6.0.2", | ||
"istanbul": "^0.4.1", | ||
"lodash": "^3.10.0", | ||
"md5-hex": "^1.2.0", | ||
"micromatch": "~2.1.6", | ||
"mkdirp": "^0.5.0", | ||
"rimraf": "^2.4.2", | ||
"resolve-from": "^2.0.0", | ||
"rimraf": "^2.5.0", | ||
"signal-exit": "^2.1.1", | ||
"source-map": "^0.5.3", | ||
"spawn-wrap": "^1.0.1", | ||
"spawn-wrap": "^1.1.0", | ||
"strip-bom": "^2.0.0", | ||
@@ -70,11 +90,19 @@ "yargs": "^3.15.0" | ||
"devDependencies": { | ||
"any-path": "^1.3.0", | ||
"chai": "^3.0.0", | ||
"coveralls": "^2.11.4", | ||
"forking-tap": "^0.1.1", | ||
"is-windows": "^0.1.0", | ||
"lodash": "^3.10.0", | ||
"newline-regex": "^0.2.1", | ||
"sanitize-filename": "^1.5.3", | ||
"sinon": "^1.15.3", | ||
"source-map-fixtures": "^0.2.0", | ||
"source-map-fixtures": "^0.4.0", | ||
"source-map-support": "^0.4.0", | ||
"split-lines": "^1.0.0", | ||
"standard": "^5.2.1", | ||
"tap": "^1.3.4" | ||
"tap": "^2.3.5", | ||
"win-spawn": "^2.0.0", | ||
"zero-fill": "^2.2.1" | ||
}, | ||
"bundleDependencies": [ | ||
"spawn-wrap" | ||
], | ||
"repository": { | ||
@@ -81,0 +109,0 @@ "type": "git", |
@@ -6,3 +6,5 @@ # nyc | ||
[](https://www.npmjs.com/package/nyc) | ||
[](https://ci.appveyor.com/project/bcoe/nyc) | ||
```shell | ||
@@ -73,17 +75,3 @@ nyc npm test | ||
```shell | ||
--------------------|-----------|-----------|-----------|-----------| | ||
File | % Stmts |% Branches | % Funcs | % Lines | | ||
--------------------|-----------|-----------|-----------|-----------| | ||
./ | 85.96 | 50 | 75 | 92.31 | | ||
index.js | 85.96 | 50 | 75 | 92.31 | | ||
./test/ | 98.08 | 50 | 95 | 98.04 | | ||
nyc-test.js | 98.08 | 50 | 95 | 98.04 | | ||
./test/fixtures/ | 100 | 100 | 100 | 100 | | ||
sigint.js | 100 | 100 | 100 | 100 | | ||
sigterm.js | 100 | 100 | 100 | 100 | | ||
--------------------|-----------|-----------|-----------|-----------| | ||
All files | 91.89 | 50 | 86.11 | 95.24 | | ||
--------------------|-----------|-----------|-----------|-----------| | ||
``` | ||
<img width="500" src="screen.png"> | ||
@@ -196,2 +184,2 @@ you can use any reporters that are supported by istanbul: | ||
> Note: by default coveralls.io adds comments to pull-requests on GitHub, this can feel intrusive. To disable this, click on your repo on coveralls.io and uncheck `LEAVE COMMENTS?`._ | ||
> Note: by default coveralls.io adds comments to pull-requests on GitHub, this can feel intrusive. To disable this, click on your repo on coveralls.io and uncheck `LEAVE COMMENTS?`. |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
0
14
1
33670
17
16
8
575
183
+ Addedappend-transform@^0.2.0
+ Addedarrify@^1.0.1
+ Addedcaching-transform@^1.0.0
+ Addedmd5-hex@^1.2.0
+ Addedresolve-from@^2.0.0
+ Addedappend-transform@0.2.2(transitive)
+ Addedarrify@1.0.1(transitive)
+ Addedcaching-transform@1.0.1(transitive)
+ Addedglob@6.0.4(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedimurmurhash@0.1.4(transitive)
+ Addedmd5-hex@1.3.0(transitive)
+ Addedmd5-o-matic@0.1.1(transitive)
+ Addedos-homedir@1.0.2(transitive)
+ Addedresolve-from@2.0.0(transitive)
+ Addedslide@1.1.6(transitive)
+ Addedspawn-wrap@1.4.3(transitive)
+ Addedwrite-file-atomic@1.3.4(transitive)
- Removedlodash@^3.10.0
- Removedlodash@3.10.1(transitive)
Updatedglob@^6.0.2
Updatedrimraf@^2.5.0
Updatedspawn-wrap@^1.1.0