metro/react-packager/src/JSTransformer/index.js

167 lines
4.1 KiB
JavaScript
Raw Normal View History

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var fs = require('fs');
var Promise = require('bluebird');
var Cache = require('./Cache');
var workerFarm = require('worker-farm');
var declareOpts = require('../lib/declareOpts');
2015-02-26 04:29:14 +00:00
var util = require('util');
var readFile = Promise.promisify(fs.readFile);
module.exports = Transformer;
Transformer.TransformError = TransformError;
var validateOpts = declareOpts({
projectRoots: {
type: 'array',
required: true,
},
blacklistRE: {
type: 'object', // typeof regex is object
},
polyfillModuleNames: {
type: 'array',
default: [],
},
cacheVersion: {
type: 'string',
default: '1.0',
},
resetCache: {
type: 'boolean',
default: false,
},
transformModulePath: {
type:'string',
required: false,
},
nonPersistent: {
type: 'boolean',
default: false,
},
});
function Transformer(options) {
var opts = validateOpts(options);
this._cache = opts.nonPersistent
? new DummyCache()
: new Cache({
resetCache: options.resetCache,
cacheVersion: options.cacheVersion,
projectRoots: options.projectRoots,
});
if (options.transformModulePath == null) {
this._failedToStart = Promise.reject(new Error('No transfrom module'));
} else {
this._workers = workerFarm(
2015-03-19 19:05:48 +00:00
{autoStart: true, maxConcurrentCallsPerWorker: 1},
options.transformModulePath
);
this._transform = Promise.promisify(this._workers);
}
}
Transformer.prototype.kill = function() {
this._workers && workerFarm.end(this._workers);
return this._cache.end();
};
Transformer.prototype.invalidateFile = function(filePath) {
this._cache.invalidate(filePath);
2015-02-26 04:29:14 +00:00
};
Transformer.prototype.loadFileAndTransform = function(filePath) {
if (this._failedToStart) {
return this._failedToStart;
}
var transform = this._transform;
return this._cache.get(filePath, function() {
return readFile(filePath)
.then(function(buffer) {
var sourceCode = buffer.toString();
return transform({
sourceCode: sourceCode,
filename: filePath,
}).then(
function(res) {
if (res.error) {
throw formatError(res.error, filePath, sourceCode);
}
return {
code: res.code,
sourcePath: filePath,
sourceCode: sourceCode
};
}
);
});
});
};
function TransformError() {}
2015-02-26 04:29:14 +00:00
util.inherits(TransformError, SyntaxError);
function formatError(err, filename, source) {
if (err.lineNumber && err.column) {
return formatEsprimaError(err, filename, source);
} else {
return formatGenericError(err, filename, source);
}
}
function formatGenericError(err, filename) {
var msg = 'TransformError: ' + filename + ': ' + err.message;
var error = new TransformError();
var stack = err.stack.split('\n').slice(0, -1);
stack.push(msg);
error.stack = stack.join('\n');
error.message = msg;
error.type = 'TransformError';
return error;
}
function formatEsprimaError(err, filename, source) {
var stack = err.stack.split('\n');
stack.shift();
var msg = 'TransformError: ' + err.description + ' ' + filename + ':' +
err.lineNumber + ':' + err.column;
var sourceLine = source.split('\n')[err.lineNumber - 1];
var snippet = sourceLine + '\n' + new Array(err.column - 1).join(' ') + '^';
stack.unshift(msg);
var error = new TransformError();
error.message = msg;
error.type = 'TransformError';
error.stack = stack.join('\n');
error.snippet = snippet;
error.filename = filename;
error.lineNumber = err.lineNumber;
error.column = err.column;
error.description = err.description;
return error;
}
function DummyCache() {}
DummyCache.prototype.get = function(filePath, loaderCb) {
return loaderCb();
};
DummyCache.prototype.end =
DummyCache.prototype.invalidate = function(){};