Add `js_file` rule
Reviewed By: matryoshcow Differential Revision: D3900455 fbshipit-source-id: 61384ade035db978ef3ca258e4c0109bcb450692
This commit is contained in:
parent
8622998335
commit
aef3d8128f
|
@ -138,6 +138,7 @@
|
||||||
"art": "^0.10.0",
|
"art": "^0.10.0",
|
||||||
"async": "^2.0.1",
|
"async": "^2.0.1",
|
||||||
"babel-core": "^6.10.4",
|
"babel-core": "^6.10.4",
|
||||||
|
"babel-generator": "^6.14.0",
|
||||||
"babel-plugin-external-helpers": "^6.8.0",
|
"babel-plugin-external-helpers": "^6.8.0",
|
||||||
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
|
"babel-plugin-syntax-trailing-function-commas": "^6.5.0",
|
||||||
"babel-plugin-transform-flow-strip-types": "^6.6.5",
|
"babel-plugin-transform-flow-strip-types": "^6.6.5",
|
||||||
|
|
|
@ -36,6 +36,13 @@ const validateOpts = declareOpts({
|
||||||
type: 'number',
|
type: 'number',
|
||||||
default: DEFAULT_MAX_CALL_TIME,
|
default: DEFAULT_MAX_CALL_TIME,
|
||||||
},
|
},
|
||||||
|
worker: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
type: 'array',
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const maxConcurrentWorkers = ((cores, override) => {
|
const maxConcurrentWorkers = ((cores, override) => {
|
||||||
|
@ -50,33 +57,47 @@ const maxConcurrentWorkers = ((cores, override) => {
|
||||||
return Math.floor(cores * 0.75);
|
return Math.floor(cores * 0.75);
|
||||||
}
|
}
|
||||||
if (cores < 24) {
|
if (cores < 24) {
|
||||||
return Math.floor(3/8 * cores + 3); // between cores *.75 and cores / 2
|
return Math.floor(3 / 8 * cores + 3); // between cores *.75 and cores / 2
|
||||||
}
|
}
|
||||||
return cores / 2;
|
return cores / 2;
|
||||||
})(os.cpus().length, process.env.REACT_NATIVE_MAX_WORKERS);
|
})(os.cpus().length, process.env.REACT_NATIVE_MAX_WORKERS);
|
||||||
|
|
||||||
|
function makeFarm(worker, methods, timeout) {
|
||||||
|
return workerFarm(
|
||||||
|
{
|
||||||
|
autoStart: true,
|
||||||
|
maxConcurrentCallsPerWorker: 1,
|
||||||
|
maxConcurrentWorkers: maxConcurrentWorkers,
|
||||||
|
maxCallsPerWorker: MAX_CALLS_PER_WORKER,
|
||||||
|
maxCallTime: timeout,
|
||||||
|
maxRetries: MAX_RETRIES,
|
||||||
|
},
|
||||||
|
worker,
|
||||||
|
methods,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
class Transformer {
|
class Transformer {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
const opts = this._opts = validateOpts(options);
|
const opts = this._opts = validateOpts(options);
|
||||||
|
|
||||||
const {transformModulePath} = opts;
|
const {transformModulePath} = opts;
|
||||||
|
|
||||||
if (transformModulePath) {
|
if (opts.worker) {
|
||||||
|
this._workers =
|
||||||
|
makeFarm(opts.worker, opts.methods, opts.transformTimeoutInterval);
|
||||||
|
opts.methods.forEach(name => {
|
||||||
|
this[name] = this._workers[name];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (transformModulePath) {
|
||||||
this._transformModulePath = require.resolve(transformModulePath);
|
this._transformModulePath = require.resolve(transformModulePath);
|
||||||
|
|
||||||
this._workers = workerFarm(
|
this._workers = makeFarm(
|
||||||
{
|
|
||||||
autoStart: true,
|
|
||||||
maxConcurrentCallsPerWorker: 1,
|
|
||||||
maxConcurrentWorkers: maxConcurrentWorkers,
|
|
||||||
maxCallsPerWorker: MAX_CALLS_PER_WORKER,
|
|
||||||
maxCallTime: opts.transformTimeoutInterval,
|
|
||||||
maxRetries: MAX_RETRIES,
|
|
||||||
},
|
|
||||||
require.resolve('./worker'),
|
require.resolve('./worker'),
|
||||||
['minify', 'transformAndExtractDependencies']
|
['minify', 'transformAndExtractDependencies'],
|
||||||
|
opts.transformTimeoutInterval,
|
||||||
);
|
);
|
||||||
|
|
||||||
this._transform = Promise.denodeify(this._workers.transformAndExtractDependencies);
|
this._transform = Promise.denodeify(this._workers.transformAndExtractDependencies);
|
||||||
this.minify = Promise.denodeify(this._workers.minify);
|
this.minify = Promise.denodeify(this._workers.minify);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +132,7 @@ class Transformer {
|
||||||
const timeoutErr = new Error(
|
const timeoutErr = new Error(
|
||||||
`TimeoutError: transforming ${fileName} took longer than ` +
|
`TimeoutError: transforming ${fileName} took longer than ` +
|
||||||
`${this._opts.transformTimeoutInterval / 1000} seconds.\n` +
|
`${this._opts.transformTimeoutInterval / 1000} seconds.\n` +
|
||||||
`You can adjust timeout via the 'transformTimeoutInterval' option`
|
'You can adjust timeout via the \'transformTimeoutInterval\' option'
|
||||||
);
|
);
|
||||||
timeoutErr.type = 'TimeoutError';
|
timeoutErr.type = 'TimeoutError';
|
||||||
throw timeoutErr;
|
throw timeoutErr;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2016-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';
|
||||||
|
|
||||||
|
// RUNS UNTRANSFORMED IN A WORKER PROCESS. ONLY USE NODE 4 COMPATIBLE FEATURES!
|
||||||
|
|
||||||
|
const {traverse, types} = require('babel-core');
|
||||||
|
|
||||||
|
const isRequireCall = (callee, firstArg) =>
|
||||||
|
callee.type !== 'Identifier' ||
|
||||||
|
callee.name !== 'require' ||
|
||||||
|
!firstArg ||
|
||||||
|
firstArg.type !== 'StringLiteral';
|
||||||
|
|
||||||
|
function collectDependencies(ast, code) {
|
||||||
|
let nextIndex = 0;
|
||||||
|
const dependencyIndexes = new Map();
|
||||||
|
|
||||||
|
function getIndex(depencyId) {
|
||||||
|
let index = dependencyIndexes.get(depencyId);
|
||||||
|
if (index !== undefined) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = nextIndex++;
|
||||||
|
dependencyIndexes.set(depencyId, index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse(ast, {
|
||||||
|
CallExpression(path) {
|
||||||
|
const node = path.node;
|
||||||
|
const arg = node.arguments[0];
|
||||||
|
if (isRequireCall(node.callee, arg)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.arguments[0] = types.numericLiteral(getIndex(arg.value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Array.from(dependencyIndexes.keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = collectDependencies;
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2016-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';
|
||||||
|
|
||||||
|
// RUNS UNTRANSFORMED IN A WORKER PROCESS. ONLY USE NODE 4 COMPATIBLE FEATURES!
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const dirname = require('path').dirname;
|
||||||
|
|
||||||
|
const babel = require('babel-core');
|
||||||
|
const generate = require('babel-generator').default;
|
||||||
|
const series = require('async/series');
|
||||||
|
const mkdirp = require('mkdirp');
|
||||||
|
|
||||||
|
const collectDependencies = require('../JSTransformer/worker/collect-dependencies');
|
||||||
|
const docblock = require('../node-haste/DependencyGraph/docblock');
|
||||||
|
|
||||||
|
function transformModule(infile, options, outfile, callback) {
|
||||||
|
let code, transform;
|
||||||
|
try {
|
||||||
|
transform = require(options.transform);
|
||||||
|
code = fs.readFileSync(infile, 'utf8');
|
||||||
|
} catch (readError) {
|
||||||
|
callback(readError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = options.filename || infile;
|
||||||
|
const variants = options.variants || {default: {}};
|
||||||
|
|
||||||
|
const tasks = {};
|
||||||
|
Object.keys(variants).forEach(name => {
|
||||||
|
tasks[name] = cb => transform({
|
||||||
|
filename,
|
||||||
|
sourceCode: code,
|
||||||
|
options: variants[name],
|
||||||
|
}, cb);
|
||||||
|
});
|
||||||
|
|
||||||
|
series(tasks, (error, transformed) => {
|
||||||
|
if (error) {
|
||||||
|
callback(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(transformed).forEach(key => {
|
||||||
|
transformed[key] = makeResult(transformed[key].ast, filename, code);
|
||||||
|
});
|
||||||
|
|
||||||
|
const annotations = docblock.parseAsObject(docblock.extract(code));
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
file: filename,
|
||||||
|
code,
|
||||||
|
transformed,
|
||||||
|
hasteID: annotations.providesModule || annotations.provide || null,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
mkdirp.sync(dirname(outfile));
|
||||||
|
fs.writeFileSync(outfile, JSON.stringify(result), 'utf8');
|
||||||
|
} catch (writeError) {
|
||||||
|
callback(writeError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeResult(ast, filename, sourceCode) {
|
||||||
|
const dependencies = collectDependencies(ast);
|
||||||
|
const file = wrapModule(ast);
|
||||||
|
|
||||||
|
const gen = generate(file, {
|
||||||
|
comments: false,
|
||||||
|
compact: true,
|
||||||
|
filename,
|
||||||
|
sourceMaps: true,
|
||||||
|
sourceMapTarget: filename,
|
||||||
|
sourceFileName: filename,
|
||||||
|
}, sourceCode);
|
||||||
|
return {code: gen.code, map: gen.map, dependencies};
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapModule(file) {
|
||||||
|
const p = file.program;
|
||||||
|
const t = babel.types;
|
||||||
|
const factory = t.functionExpression(t.identifier(''), [
|
||||||
|
t.identifier('require'),
|
||||||
|
t.identifier('module'),
|
||||||
|
t.identifier('global'),
|
||||||
|
t.identifier('exports')
|
||||||
|
], t.blockStatement(p.body, p.directives));
|
||||||
|
const def = t.callExpression(t.identifier('__d'), [factory]);
|
||||||
|
return t.file(t.program([t.expressionStatement(def)]));
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.transformModule = transformModule;
|
Loading…
Reference in New Issue