diff --git a/api.js b/api.js index 058ab6523..92ccfcebd 100644 --- a/api.js +++ b/api.js @@ -127,7 +127,11 @@ Api.prototype._setupPrecompiler = function (files) { this.options.cacheDir = cacheDir; var isPowerAssertEnabled = this.options.powerAssert !== false; - this.precompiler = new CachingPrecompiler(cacheDir, this.options.babelConfig, isPowerAssertEnabled); + this.precompiler = new CachingPrecompiler({ + path: cacheDir, + babel: this.options.babelConfig, + powerAssert: isPowerAssertEnabled + }); }; Api.prototype._run = function (files, options) { diff --git a/lib/caching-precompiler.js b/lib/caching-precompiler.js index f543f5dfa..d355372e2 100644 --- a/lib/caching-precompiler.js +++ b/lib/caching-precompiler.js @@ -3,24 +3,26 @@ var path = require('path'); var fs = require('fs'); var convertSourceMap = require('convert-source-map'); var cachingTransform = require('caching-transform'); -var stripBom = require('strip-bom'); -var md5Hex = require('md5-hex'); var packageHash = require('package-hash'); +var stripBom = require('strip-bom'); var autoBind = require('auto-bind'); +var md5Hex = require('md5-hex'); var babelConfigHelper = require('./babel-config'); -function CachingPrecompiler(cacheDirPath, babelConfig, powerAssert) { +function CachingPrecompiler(options) { if (!(this instanceof CachingPrecompiler)) { throw new TypeError('Class constructor CachingPrecompiler cannot be invoked without \'new\''); } - this.babelConfig = babelConfigHelper.validate(babelConfig); - this.powerAssert = powerAssert; - this.cacheDirPath = cacheDirPath; - this.fileHashes = {}; - autoBind(this); + options = options || {}; + + this.babelConfig = babelConfigHelper.validate(options.babel); + this.cacheDirPath = options.path; + this.powerAssert = Boolean(options.powerAssert); + this.fileHashes = {}; + this.transform = this._createTransform(); } @@ -37,14 +39,10 @@ CachingPrecompiler.prototype.precompileFile = function (filePath) { }; // conditionally called by caching-transform when precompiling is required -CachingPrecompiler.prototype._factory = function () { - this._init(); - - return this._transform; -}; - CachingPrecompiler.prototype._init = function () { this.babel = require('babel-core'); + + return this._transform; }; CachingPrecompiler.prototype._transform = function (code, filePath, hash) { @@ -57,15 +55,8 @@ CachingPrecompiler.prototype._transform = function (code, filePath, hash) { var mapPath = path.join(this.cacheDirPath, hash + '.js.map'); fs.writeFileSync(mapPath, JSON.stringify(result.map)); - // When loading the test file, test workers intercept the require call and - // load the cached code instead. Libraries like nyc may also be intercepting - // require calls, however they won't know that different code was loaded. - // They may then attempt to resolve a source map from the original file - // location. - // - // Add a source map file comment to the cached code. The file path is - // relative from the directory of the original file to where the source map - // is cached. This will allow the source map to be resolved. + // append source map comment to transformed code + // so that other libraries (like nyc) can find the source map var dirPath = path.dirname(filePath); var relativeMapPath = path.relative(dirPath, mapPath); var comment = convertSourceMap.generateMapFileComment(relativeMapPath); @@ -74,14 +65,18 @@ CachingPrecompiler.prototype._transform = function (code, filePath, hash) { }; CachingPrecompiler.prototype._createTransform = function () { - var salt = packageHash.sync( - [require.resolve('../package.json')].concat(babelConfigHelper.pluginPackages), - JSON.stringify(this.babelConfig), - process.version.split('.')[0] - ); + var pluginPackages = babelConfigHelper.pluginPackages; + var avaPackage = require.resolve('../package.json'); + var packages = [avaPackage].concat(pluginPackages); + + var majorNodeVersion = process.version.split('.')[0]; + var babelConfig = JSON.stringify(this.babelConfig); + var packageSalt = babelConfig + majorNodeVersion; + + var salt = packageHash.sync(packages, packageSalt); return cachingTransform({ - factory: this._factory, + factory: this._init, cacheDir: this.cacheDirPath, hash: this._generateHash, salt: salt, diff --git a/profile.js b/profile.js index 3cda7afef..786f19226 100644 --- a/profile.js +++ b/profile.js @@ -60,8 +60,14 @@ var cacheDir = findCacheDir({ name: 'ava', files: [file] }) || uniqueTempDir(); + +var precompiler = new CachingPrecompiler({ + path: cacheDir, + babel: conf.babel +}); + var precompiled = {}; -precompiled[file] = new CachingPrecompiler(cacheDir, conf.babel).precompileFile(file); +precompiled[file] = precompiler.precompileFile(file); var opts = { file: file, diff --git a/test/caching-precompiler.js b/test/caching-precompiler.js index 502e3d320..0ab717c8f 100644 --- a/test/caching-precompiler.js +++ b/test/caching-precompiler.js @@ -25,7 +25,7 @@ sinon.spy(babel, 'transform'); test('creation with new', function (t) { var tempDir = uniqueTempDir(); - var precompiler = new CachingPrecompiler(tempDir, null); + var precompiler = new CachingPrecompiler({path: tempDir}); t.is(precompiler.cacheDirPath, tempDir); t.end(); }); @@ -33,14 +33,14 @@ test('creation with new', function (t) { test('must be called with new', function (t) { t.throws(function () { var cachingPrecompiler = CachingPrecompiler; - cachingPrecompiler(uniqueTempDir(), null); + cachingPrecompiler({path: uniqueTempDir()}); }, {message: 'Class constructor CachingPrecompiler cannot be invoked without \'new\''}); t.end(); }); test('adds files and source maps to the cache directory as needed', function (t) { var tempDir = uniqueTempDir(); - var precompiler = new CachingPrecompiler(tempDir, null); + var precompiler = new CachingPrecompiler({path: tempDir}); t.false(fs.existsSync(tempDir), 'cache directory is not created before it is needed'); @@ -56,7 +56,7 @@ test('adds files and source maps to the cache directory as needed', function (t) test('adds a map file comment to the cached files', function (t) { var tempDir = uniqueTempDir(); - var precompiler = new CachingPrecompiler(tempDir, null); + var precompiler = new CachingPrecompiler({path: tempDir}); precompiler.precompileFile(fixture('es2015.js')); @@ -84,7 +84,11 @@ test('adds a map file comment to the cached files', function (t) { test('uses default babel options when babelConfig === "default"', function (t) { var tempDir = uniqueTempDir(); - var precompiler = new CachingPrecompiler(tempDir, 'default'); + var precompiler = new CachingPrecompiler({ + path: tempDir, + babel: 'default' + }); + babel.transform.reset(); precompiler.precompileFile(fixture('es2015.js')); @@ -104,7 +108,11 @@ test('uses default babel options when babelConfig === "default"', function (t) { test('allows babel config from package.json/babel when babelConfig === "inherit"', function (t) { var tempDir = uniqueTempDir(); - var precompiler = new CachingPrecompiler(tempDir, 'inherit'); + var precompiler = new CachingPrecompiler({ + path: tempDir, + babel: 'inherit' + }); + babel.transform.reset(); precompiler.precompileFile(fixture('es2015.js')); @@ -122,7 +130,8 @@ test('allows babel config from package.json/babel when babelConfig === "inherit" test('does not modify plugins array in babelConfig', function (t) { var plugins = []; - var precompiler = new CachingPrecompiler(uniqueTempDir(), { + var precompiler = new CachingPrecompiler({ + path: uniqueTempDir(), plugins: plugins }); diff --git a/test/fork.js b/test/fork.js index f21f71945..2314e6a80 100644 --- a/test/fork.js +++ b/test/fork.js @@ -5,7 +5,7 @@ var _fork = require('../lib/fork.js'); var CachingPrecompiler = require('../lib/caching-precompiler'); var cacheDir = path.join(__dirname, '../node_modules/.cache/ava'); -var precompiler = new CachingPrecompiler(cacheDir); +var precompiler = new CachingPrecompiler({path: cacheDir}); function fork(testPath) { var hash = precompiler.precompileFile(testPath); diff --git a/test/hooks.js b/test/hooks.js index 82b612052..31aac8cca 100644 --- a/test/hooks.js +++ b/test/hooks.js @@ -6,7 +6,7 @@ var _fork = require('../lib/fork.js'); var CachingPrecompiler = require('../lib/caching-precompiler'); var cacheDir = path.join(__dirname, '../node_modules/.cache/ava'); -var precompiler = new CachingPrecompiler(cacheDir); +var precompiler = new CachingPrecompiler({path: cacheDir}); function fork(testPath) { var hash = precompiler.precompileFile(testPath);