Skip to content

Commit ff73b18

Browse files
authored
fix: source-maps were not being cached in the parent process when --all was being used (#556)
fixes: #537
1 parent 2ff8f3b commit ff73b18

15 files changed

+178
-120
lines changed

bin/nyc.js

-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ if (argv._[0] === 'report') {
4343
if (config.all) nyc.addAllFiles()
4444

4545
var env = {
46-
NYC_CACHE: argv.cache ? 'enable' : 'disable',
4746
NYC_CONFIG: JSON.stringify(config),
4847
NYC_CWD: process.cwd(),
4948
NYC_ROOT_ID: nyc.rootId,

bin/wrap.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ process.env.NYC_PARENT_PID = process.pid
1111

1212
var config = {}
1313
if (process.env.NYC_CONFIG) config = JSON.parse(process.env.NYC_CONFIG)
14-
config.enableCache = process.env.NYC_CACHE === 'enable'
14+
config.isChildProcess = true
15+
1516
config._processInfo = {
1617
ppid: parentPid,
1718
root: process.env.NYC_ROOT_ID

build-tests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mkdirp.sync(path.join(__dirname, 'test/build'))
1515

1616
var testDir = path.join(__dirname, 'test/src')
1717
var buildDir = path.join(__dirname, 'test/build')
18-
var originalTestsFilename = path.join(testDir, 'nyc-test.js')
18+
var originalTestsFilename = path.join(testDir, 'nyc-tap.js')
1919
var originalTestSource = fs.readFileSync(originalTestsFilename, 'utf8')
2020
var individualTests = forkingTap(originalTestSource, {
2121
filename: originalTestsFilename,

index.js

+46-91
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
/* global __coverage__ */
2-
var arrify = require('arrify')
3-
var debugLog = require('debug-log')('nyc')
4-
var fs = require('fs')
5-
var glob = require('glob')
6-
var libCoverage = require('istanbul-lib-coverage')
7-
var libHook = require('istanbul-lib-hook')
8-
var libReport = require('istanbul-lib-report')
9-
var libSourceMaps = require('istanbul-lib-source-maps')
10-
var reports = require('istanbul-reports')
11-
var mkdirp = require('mkdirp')
12-
var Module = require('module')
13-
var cachingTransform = require('caching-transform')
14-
var path = require('path')
15-
var rimraf = require('rimraf')
16-
var onExit = require('signal-exit')
17-
var resolveFrom = require('resolve-from')
18-
var convertSourceMap = require('convert-source-map')
19-
var md5hex = require('md5-hex')
20-
var findCacheDir = require('find-cache-dir')
21-
var js = require('default-require-extensions/js')
22-
var testExclude = require('test-exclude')
2+
3+
const arrify = require('arrify')
4+
const cachingTransform = require('caching-transform')
5+
const debugLog = require('debug-log')('nyc')
6+
const findCacheDir = require('find-cache-dir')
7+
const fs = require('fs')
8+
const glob = require('glob')
9+
const Hash = require('./lib/hash')
10+
const js = require('default-require-extensions/js')
11+
const libCoverage = require('istanbul-lib-coverage')
12+
const libHook = require('istanbul-lib-hook')
13+
const libReport = require('istanbul-lib-report')
14+
const md5hex = require('md5-hex')
15+
const mkdirp = require('mkdirp')
16+
const Module = require('module')
17+
const onExit = require('signal-exit')
18+
const path = require('path')
19+
const reports = require('istanbul-reports')
20+
const resolveFrom = require('resolve-from')
21+
const rimraf = require('rimraf')
22+
const SourceMaps = require('./lib/source-maps')
23+
const testExclude = require('test-exclude')
2324

2425
var ProcessInfo
2526
try {
@@ -29,10 +30,6 @@ try {
2930
ProcessInfo = require('./lib/process.js')
3031
}
3132

32-
// bust cache whenever nyc is upgraded, this prevents
33-
// crashers caused by instrumentation updates.
34-
var CACHE_VERSION = require('./package.json').version
35-
3633
/* istanbul ignore next */
3734
if (/index\.covered\.js$/.test(__filename)) {
3835
require('./lib/self-coverage-helper')
@@ -50,19 +47,22 @@ function NYC (config) {
5047
this._showProcessTree = config.showProcessTree || false
5148
this._eagerInstantiation = config.eager || false
5249
this.cwd = config.cwd || process.cwd()
53-
5450
this.reporter = arrify(config.reporter || 'text')
5551

5652
this.cacheDirectory = config.cacheDir || findCacheDir({name: 'nyc', cwd: this.cwd})
57-
58-
this.enableCache = Boolean(this.cacheDirectory && (config.enableCache === true || process.env.NYC_CACHE === 'enable'))
53+
this.cache = Boolean(this.cacheDirectory && config.cache)
5954

6055
this.exclude = testExclude({
6156
cwd: this.cwd,
6257
include: config.include,
6358
exclude: config.exclude
6459
})
6560

61+
this.sourceMaps = new SourceMaps({
62+
cache: this.cache,
63+
cacheDirectory: this.cacheDirectory
64+
})
65+
6666
// require extensions can be provided as config in package.json.
6767
this.require = arrify(config.require)
6868

@@ -78,32 +78,24 @@ function NYC (config) {
7878
return transforms
7979
}.bind(this), {})
8080

81-
this.sourceMapCache = libSourceMaps.createSourceMapStore()
82-
8381
this.hookRunInContext = config.hookRunInContext
84-
this.hashCache = {}
85-
this.loadedMaps = null
8682
this.fakeRequire = null
8783

8884
this.processInfo = new ProcessInfo(config && config._processInfo)
8985
this.rootId = this.processInfo.root || this.generateUniqueID()
9086
}
9187

9288
NYC.prototype._createTransform = function (ext) {
93-
var _this = this
94-
9589
var opts = {
96-
salt: JSON.stringify({
97-
istanbul: require('istanbul-lib-coverage/package.json').version,
98-
nyc: require('./package.json').version
99-
}),
90+
salt: Hash.salt,
10091
hash: function (code, metadata, salt) {
101-
var hash = md5hex([code, metadata.filename, salt]) + '_' + CACHE_VERSION
102-
_this.hashCache[metadata.filename] = hash
92+
var hash = Hash(code, metadata.filename)
10393
return hash
10494
},
10595
cacheDir: this.cacheDirectory,
106-
disableCache: !this.enableCache,
96+
// when running --all we should not load source-file from
97+
// cache, we want to instead return the fake source.
98+
disableCache: this._disableCachingTransform(),
10799
ext: ext
108100
}
109101
if (this._eagerInstantiation) {
@@ -114,6 +106,10 @@ NYC.prototype._createTransform = function (ext) {
114106
return cachingTransform(opts)
115107
}
116108

109+
NYC.prototype._disableCachingTransform = function () {
110+
return !(this.cache && this.config.isChildProcess)
111+
}
112+
117113
NYC.prototype._loadAdditionalModules = function () {
118114
var _this = this
119115
this.require.forEach(function (r) {
@@ -271,7 +267,7 @@ NYC.prototype._transformFactory = function (cacheDir) {
271267
var filename = metadata.filename
272268
var sourceMap = null
273269

274-
if (_this._sourceMap) sourceMap = _this._handleSourceMap(cacheDir, code, hash, filename)
270+
if (_this._sourceMap) sourceMap = _this.sourceMaps.extractAndRegister(code, filename)
275271

276272
try {
277273
instrumented = instrumenter.instrumentSync(code, filename, sourceMap)
@@ -289,19 +285,6 @@ NYC.prototype._transformFactory = function (cacheDir) {
289285
}
290286
}
291287

292-
NYC.prototype._handleSourceMap = function (cacheDir, code, hash, filename) {
293-
var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename))
294-
if (sourceMap) {
295-
if (hash) {
296-
var mapPath = path.join(cacheDir, hash + '.map')
297-
fs.writeFileSync(mapPath, sourceMap.toJSON())
298-
} else {
299-
this.sourceMapCache.registerMap(filename, sourceMap.sourcemap)
300-
}
301-
}
302-
return sourceMap
303-
}
304-
305288
NYC.prototype._handleJs = function (code, filename) {
306289
var relFile = path.relative(this.cwd, filename)
307290
// ensure the path has correct casing (see istanbuljs/nyc#269 and nodejs/node#6624)
@@ -333,13 +316,14 @@ NYC.prototype.cleanup = function () {
333316
}
334317

335318
NYC.prototype.clearCache = function () {
336-
if (this.enableCache) {
319+
if (this.cache) {
337320
rimraf.sync(this.cacheDirectory)
338321
}
339322
}
340323

341324
NYC.prototype.createTempDirectory = function () {
342325
mkdirp.sync(this.tempDirectory())
326+
mkdirp.sync(this.cacheDirectory)
343327

344328
if (this._showProcessTree) {
345329
mkdirp.sync(this.processInfoDirectory())
@@ -379,14 +363,14 @@ NYC.prototype.writeCoverageFile = function () {
379363
var coverage = coverageFinder()
380364
if (!coverage) return
381365

382-
if (this.enableCache) {
366+
if (this.cache) {
383367
Object.keys(coverage).forEach(function (absFile) {
384-
if (this.hashCache[absFile] && coverage[absFile]) {
385-
coverage[absFile].contentHash = this.hashCache[absFile]
368+
if (this.sourceMaps.hashCache[absFile] && coverage[absFile]) {
369+
coverage[absFile].contentHash = this.sourceMaps.hashCache[absFile]
386370
}
387371
}, this)
388372
} else {
389-
coverage = this.sourceMapTransform(coverage)
373+
coverage = this.sourceMaps.remapCoverage(coverage)
390374
}
391375

392376
var id = this.generateUniqueID()
@@ -411,13 +395,6 @@ NYC.prototype.writeCoverageFile = function () {
411395
)
412396
}
413397

414-
NYC.prototype.sourceMapTransform = function (obj) {
415-
var transformed = this.sourceMapCache.transformCoverage(
416-
libCoverage.createCoverageMap(obj)
417-
)
418-
return transformed.map.data
419-
}
420-
421398
function coverageFinder () {
422399
var coverage = global.__coverage__
423400
if (typeof __coverage__ === 'object') coverage = __coverage__
@@ -431,7 +408,7 @@ NYC.prototype._getCoverageMapFromAllCoverageFiles = function () {
431408
this.loadReports().forEach(function (report) {
432409
map.merge(report)
433410
})
434-
411+
map.data = this.sourceMaps.remapCoverage(map.data)
435412
return map
436413
}
437414

@@ -497,10 +474,6 @@ NYC.prototype.loadReports = function (filenames) {
497474
var _this = this
498475
var files = filenames || fs.readdirSync(this.tempDirectory())
499476

500-
var cacheDir = _this.cacheDirectory
501-
502-
var loadedMaps = this.loadedMaps || (this.loadedMaps = {})
503-
504477
return files.map(function (f) {
505478
var report
506479
try {
@@ -512,25 +485,7 @@ NYC.prototype.loadReports = function (filenames) {
512485
return {}
513486
}
514487

515-
Object.keys(report).forEach(function (absFile) {
516-
var fileReport = report[absFile]
517-
if (fileReport && fileReport.contentHash) {
518-
var hash = fileReport.contentHash
519-
if (!(hash in loadedMaps)) {
520-
try {
521-
var mapPath = path.join(cacheDir, hash + '.map')
522-
loadedMaps[hash] = JSON.parse(fs.readFileSync(mapPath, 'utf8'))
523-
} catch (e) {
524-
// set to false to avoid repeatedly trying to load the map
525-
loadedMaps[hash] = false
526-
}
527-
}
528-
if (loadedMaps[hash]) {
529-
_this.sourceMapCache.registerMap(absFile, loadedMaps[hash])
530-
}
531-
}
532-
})
533-
report = _this.sourceMapTransform(report)
488+
_this.sourceMaps.reloadCachedSourceMaps(report)
534489
return report
535490
})
536491
}

lib/config-util.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
var arrify = require('arrify')
2-
var fs = require('fs')
3-
var path = require('path')
4-
var findUp = require('find-up')
5-
var testExclude = require('test-exclude')
6-
var Yargs = require('yargs/yargs')
1+
const arrify = require('arrify')
2+
const fs = require('fs')
3+
const path = require('path')
4+
const findUp = require('find-up')
5+
const testExclude = require('test-exclude')
6+
const Yargs = require('yargs/yargs')
77

88
var Config = {}
99

lib/hash.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const CACHE_VERSION = require('../package.json').version
2+
const md5hex = require('md5-hex')
3+
const salt = JSON.stringify({
4+
istanbul: require('istanbul-lib-coverage/package.json').version,
5+
nyc: CACHE_VERSION
6+
})
7+
8+
function Hash (code, filename) {
9+
return md5hex([code, filename, salt]) + '_' + CACHE_VERSION
10+
}
11+
12+
Hash.salt = salt
13+
14+
module.exports = Hash

lib/process-args.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
var parser = require('yargs-parser')
2-
var commands = [
1+
const parser = require('yargs-parser')
2+
const commands = [
33
'report',
44
'check-coverage',
55
'instrument'

lib/process.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
'use strict'
2-
var archy = require('archy')
3-
var libCoverage = require('istanbul-lib-coverage')
1+
const archy = require('archy')
2+
const libCoverage = require('istanbul-lib-coverage')
43

54
function ProcessInfo (defaults) {
65
defaults = defaults || {}

lib/self-coverage-helper.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* global ___NYC_SELF_COVERAGE___ */
22

3-
var path = require('path')
4-
var fs = require('fs')
5-
var mkdirp = require('mkdirp')
6-
var onExit = require('signal-exit')
3+
const path = require('path')
4+
const fs = require('fs')
5+
const mkdirp = require('mkdirp')
6+
const onExit = require('signal-exit')
77

88
onExit(function () {
99
var coverage = global.___NYC_SELF_COVERAGE___

0 commit comments

Comments
 (0)