Skip to content

Commit

Permalink
add caching
Browse files Browse the repository at this point in the history
  • Loading branch information
jamestalmage committed Dec 22, 2015
1 parent 30831a8 commit c738c78
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 78 deletions.
10 changes: 3 additions & 7 deletions api.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var chalk = require('chalk');
var assign = require('object-assign');
var fork = require('./lib/fork');
var formatter = require('./lib/enhance-assert').formatter();
var precompileTest = require('./lib/test-transformer');
var precompile = require('./lib/test-transformer');

function Api(files, options) {
if (!(this instanceof Api)) {
Expand Down Expand Up @@ -43,14 +43,11 @@ module.exports = Api;

Api.prototype._runFile = function (file) {
var precompiled = {};
precompiled[file.testPath] = {
sourcePath: file.tempPath,
mapPath: file.mapPath
};
precompiled[file] = precompile(file);
var options = assign({}, this.options, {
precompiled: precompiled
});
return fork(file.testPath, options)
return fork(file, options)
.on('stats', this._handleStats)
.on('test', this._handleTest)
.on('unhandledRejections', this._handleRejections)
Expand Down Expand Up @@ -139,7 +136,6 @@ Api.prototype.run = function () {
.map(function (file) {
return path.resolve(file);
})
.map(precompileTest)
.then(function (files) {
if (files.length === 0) {
return Promise.reject(new Error('Couldn\'t find any files to test'));
Expand Down
6 changes: 4 additions & 2 deletions lib/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ var loudRejection = require('loud-rejection/api')(process);
var serializeError = require('serialize-error');
var send = require('./send');
var installPrecompiler = require('require-precompiled');
var path = require('path');
var cacheDir = path.join(module.paths[1], '.cache', 'ava');

var testPath = opts.file;

Expand All @@ -50,8 +52,8 @@ exports.avaRequired = false;
installPrecompiler(function (filename) {
var precompiled = opts.precompiled[filename];
if (precompiled) {
sourceMapCache[filename] = precompiled.mapPath;
return fs.readFileSync(precompiled.sourcePath, 'utf8');
sourceMapCache[filename] = path.join(cacheDir, precompiled + '.map');
return fs.readFileSync(path.join(cacheDir, precompiled + '.js'), 'utf8');
}
return null;
});
Expand Down
112 changes: 54 additions & 58 deletions lib/test-transformer.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,64 @@
var createEspowerPlugin = require('babel-plugin-espower/create');
var sourceMapSupport = require('source-map-support');
var babel = require('babel-core');
var Promise = require('bluebird');
var tempWrite = require('temp-write');
var transformFile = Promise.promisify(babel.transformFile);
var enhanceAssert = require('./enhance-assert');
var cachingTransform = require('caching-transform');
var fs = require('fs');
var path = require('path');
var crypto = require('crypto');
var cacheDir = path.join(module.paths[1], '.cache', 'ava');
var filenameToHash = {};

var cache = {};
function factory(cacheDir) {
var createEspowerPlugin = require('babel-plugin-espower/create');
var babel = require('babel-core');
var enhanceAssert = require('./enhance-assert');
var convertSourceMap = require('convert-source-map');

module.exports = precompile;
module.exports.sync = sync;

function precompile(testPath) {
return cache[testPath] || (cache[testPath] = _precompile(testPath));
}

function buildOptions(testPath) {
// initialize power-assert
var powerAssert = createEspowerPlugin(babel, {
patterns: enhanceAssert.PATTERNS
});
function buildOptions(filename, code) {
// initialize power-assert
var powerAssert = createEspowerPlugin(babel, {
patterns: enhanceAssert.PATTERNS
});

// if generators are not supported, use regenerator
var options = {
presets: [require('babel-preset-stage-2'), require('babel-preset-es2015')],
plugins: [powerAssert, require('babel-plugin-transform-runtime')],
sourceMaps: true,
ast: false,
inputSourceMap: null
};
var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename));

// try to load an input source map for the test file, in case the file was
// already compiled once by the user
var inputSourceMap = sourceMapSupport.retrieveSourceMap(testPath);
if (inputSourceMap) {
// source-map-support returns the source map as a json-encoded string, but
// babel requires an actual object
options.inputSourceMap = JSON.parse(inputSourceMap.map);
return {
presets: [require('babel-preset-stage-2'), require('babel-preset-es2015')],
plugins: [powerAssert, require('babel-plugin-transform-runtime')],
filename: filename,
sourceMaps: true,
ast: false,
inputSourceMap: sourceMap && sourceMap.toObject()
};
}

return options;
return function (code, filename, hash) {
var options = buildOptions(filename, code);
var result = babel.transform(code, options);
var mapFile = path.join(cacheDir, hash + '.map');
fs.writeFileSync(mapFile, JSON.stringify(result.map));
return result.code;
};
}

function _precompile(testPath) {
return transformFile(testPath, buildOptions(testPath))
.then(function (result) {
return Promise.all([
tempWrite(result.code, testPath),
tempWrite(JSON.stringify(result.map), testPath + '.map')
])
.spread(function (tempPath, mapPath) {
result.mapPath = mapPath;
result.tempPath = tempPath;
result.testPath = testPath;
return result;
});
});
}
var transform = cachingTransform({
factory: factory,
cacheDir: cacheDir,
ext: '.js',
hash: function (code, filename, salt) {
var hash = crypto
.createHash('md5')
.update(code, 'utf8')
.update(filename || 'unknown file', 'utf8')
.update(salt || '', 'utf8')
.digest('hex');

function sync(testPath) {
var result = babel.transformFileSync(testPath, buildOptions(testPath));
result.tempPath = tempWrite.sync(result.code, testPath);
result.mapPath = tempWrite.sync(JSON.stringify(result.map), testPath + '.map');
result.testPath = testPath;
return result;
}
filenameToHash[filename] = hash;

return hash;
}
});

module.exports = function (filename) {
if (!filenameToHash[filename]) {
transform(fs.readFileSync(filename, 'utf8'), filename);
}
return filenameToHash[filename];
};
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"node": ">=0.10.0"
},
"scripts": {
"pretest": "rm -rf ./node_modules/.cache",
"test": "xo && nyc --reporter=lcov tap --no-cov --timeout=150 test/*.js",
"test-win": "tap --no-cov --timeout=150 test/*.js"
},
Expand Down Expand Up @@ -87,8 +88,10 @@
"babel-preset-stage-2": "^6.3.13",
"babel-runtime": "^6.3.19",
"bluebird": "^3.0.0",
"caching-transform": "0.0.3",
"chalk": "^1.0.0",
"co-with-promise": "^4.6.0",
"convert-source-map": "^1.1.2",
"core-assert": "^0.1.0",
"debug": "^2.2.0",
"deeper": "^2.1.0",
Expand Down Expand Up @@ -116,7 +119,6 @@
"set-immediate-shim": "^1.0.1",
"source-map-support": "^0.4.0",
"squeak": "^1.2.0",
"temp-write": "^2.1.0",
"time-require": "^0.1.2",
"update-notifier": "^0.5.0"
},
Expand Down
6 changes: 1 addition & 5 deletions test/fork.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ function fixture(name) {
}

function fork(testPath) {
var result = precompile.sync(testPath);
var precompiled = {};
precompiled[testPath] = {
sourcePath: result.tempPath,
mapPath: result.mapPath
};
precompiled[testPath] = precompile(testPath);
return _fork(testPath, {precompiled: precompiled});
}

Expand Down
6 changes: 1 addition & 5 deletions test/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ var _fork = require('../lib/fork');
var precompile = require('../lib/test-transformer');

function fork(testPath) {
var result = precompile.sync(testPath);
var precompiled = {};
precompiled[testPath] = {
sourcePath: result.tempPath,
mapPath: result.mapPath
};
precompiled[testPath] = precompile(testPath);
return _fork(testPath, {precompiled: precompiled});
}

Expand Down

0 comments on commit c738c78

Please sign in to comment.