Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up caching precompiler #1077

Merged
merged 1 commit into from
Oct 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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