Skip to content

Commit

Permalink
clean up caching precompiler (#1077)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadim Demedes authored and sindresorhus committed Oct 17, 2016
1 parent 6165a23 commit 1b214be
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 40 deletions.
6 changes: 5 additions & 1 deletion api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
53 changes: 24 additions & 29 deletions lib/caching-precompiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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,
Expand Down
8 changes: 7 additions & 1 deletion profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 16 additions & 7 deletions test/caching-precompiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ 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();
});

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');

Expand All @@ -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'));

Expand Down Expand Up @@ -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'));
Expand All @@ -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'));
Expand All @@ -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
});

Expand Down
2 changes: 1 addition & 1 deletion test/fork.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion test/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 1b214be

Please sign in to comment.