mirror of https://github.com/status-im/metro.git
Always read the module source code from the worker
Reviewed By: jeanlauliac Differential Revision: D7894133 fbshipit-source-id: bf5c366d31e6e30d0cc82bd32fa9668040aea081
This commit is contained in:
parent
42652b1ed8
commit
51dd867f45
|
@ -217,7 +217,6 @@ class Bundler {
|
||||||
|
|
||||||
async _cachedTransformCode(
|
async _cachedTransformCode(
|
||||||
module: Module,
|
module: Module,
|
||||||
code: ?string,
|
|
||||||
transformCodeOptions: WorkerOptions,
|
transformCodeOptions: WorkerOptions,
|
||||||
): Promise<TransformedCode> {
|
): Promise<TransformedCode> {
|
||||||
const cache = this._cache;
|
const cache = this._cache;
|
||||||
|
@ -229,6 +228,7 @@ class Bundler {
|
||||||
dev,
|
dev,
|
||||||
hot,
|
hot,
|
||||||
inlineRequires,
|
inlineRequires,
|
||||||
|
isScript,
|
||||||
minify,
|
minify,
|
||||||
platform,
|
platform,
|
||||||
projectRoot: _projectRoot, // Blacklisted property.
|
projectRoot: _projectRoot, // Blacklisted property.
|
||||||
|
@ -257,6 +257,7 @@ class Bundler {
|
||||||
dev,
|
dev,
|
||||||
hot,
|
hot,
|
||||||
inlineRequires,
|
inlineRequires,
|
||||||
|
isScript,
|
||||||
minify,
|
minify,
|
||||||
platform,
|
platform,
|
||||||
]);
|
]);
|
||||||
|
@ -272,8 +273,6 @@ class Bundler {
|
||||||
: await this._transformer.transform(
|
: await this._transformer.transform(
|
||||||
module.path,
|
module.path,
|
||||||
module.localPath,
|
module.localPath,
|
||||||
code,
|
|
||||||
module.isPolyfill(),
|
|
||||||
transformCodeOptions,
|
transformCodeOptions,
|
||||||
this._opts.assetExts,
|
this._opts.assetExts,
|
||||||
this._opts.assetRegistryPath,
|
this._opts.assetRegistryPath,
|
||||||
|
|
|
@ -127,7 +127,7 @@ describe('Bundler', function() {
|
||||||
result: {},
|
result: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
await bundlerInstance._cachedTransformCode(module, null, {});
|
await bundlerInstance._cachedTransformCode(module, {});
|
||||||
|
|
||||||
// We got the SHA-1 of the file from the dependency graph.
|
// We got the SHA-1 of the file from the dependency graph.
|
||||||
expect(depGraph.getSha1).toBeCalledWith('/root/foo.js');
|
expect(depGraph.getSha1).toBeCalledWith('/root/foo.js');
|
||||||
|
|
|
@ -86,8 +86,6 @@ module.exports = class Transformer {
|
||||||
async transform(
|
async transform(
|
||||||
filename: string,
|
filename: string,
|
||||||
localPath: LocalPath,
|
localPath: LocalPath,
|
||||||
code: ?string,
|
|
||||||
isScript: boolean,
|
|
||||||
options: WorkerOptions,
|
options: WorkerOptions,
|
||||||
assetExts: $ReadOnlyArray<string>,
|
assetExts: $ReadOnlyArray<string>,
|
||||||
assetRegistryPath: string,
|
assetRegistryPath: string,
|
||||||
|
@ -99,9 +97,7 @@ module.exports = class Transformer {
|
||||||
const data = await this._worker.transform(
|
const data = await this._worker.transform(
|
||||||
filename,
|
filename,
|
||||||
localPath,
|
localPath,
|
||||||
code,
|
|
||||||
this._transformModulePath,
|
this._transformModulePath,
|
||||||
isScript,
|
|
||||||
options,
|
options,
|
||||||
assetExts,
|
assetExts,
|
||||||
assetRegistryPath,
|
assetRegistryPath,
|
||||||
|
|
|
@ -68,13 +68,10 @@ describe('Transformer', function() {
|
||||||
|
|
||||||
it('passes transform data to the worker farm when transforming', async () => {
|
it('passes transform data to the worker farm when transforming', async () => {
|
||||||
const transformOptions = {arbitrary: 'options'};
|
const transformOptions = {arbitrary: 'options'};
|
||||||
const code = 'arbitrary(code)';
|
|
||||||
|
|
||||||
await new Transformer(opts).transform(
|
await new Transformer(opts).transform(
|
||||||
fileName,
|
fileName,
|
||||||
localPath,
|
localPath,
|
||||||
code,
|
|
||||||
false,
|
|
||||||
transformOptions,
|
transformOptions,
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
@ -84,9 +81,7 @@ describe('Transformer', function() {
|
||||||
expect(api.transform).toBeCalledWith(
|
expect(api.transform).toBeCalledWith(
|
||||||
fileName,
|
fileName,
|
||||||
localPath,
|
localPath,
|
||||||
code,
|
|
||||||
transformModulePath,
|
transformModulePath,
|
||||||
false,
|
|
||||||
transformOptions,
|
transformOptions,
|
||||||
[],
|
[],
|
||||||
'',
|
'',
|
||||||
|
@ -102,7 +97,7 @@ describe('Transformer', function() {
|
||||||
const snippet = 'snippet';
|
const snippet = 'snippet';
|
||||||
|
|
||||||
api.transform.mockImplementation(
|
api.transform.mockImplementation(
|
||||||
(filename, localPth, code, transformPath, opts) => {
|
(filename, localPth, transformPath, opts) => {
|
||||||
const babelError = new SyntaxError(message);
|
const babelError = new SyntaxError(message);
|
||||||
|
|
||||||
babelError.type = 'SyntaxError';
|
babelError.type = 'SyntaxError';
|
||||||
|
|
|
@ -78,6 +78,7 @@ export type WorkerOptions = {|
|
||||||
+dev: boolean,
|
+dev: boolean,
|
||||||
+hot: boolean,
|
+hot: boolean,
|
||||||
+inlineRequires: boolean,
|
+inlineRequires: boolean,
|
||||||
|
+isScript: boolean,
|
||||||
+minify: boolean,
|
+minify: boolean,
|
||||||
+platform: ?string,
|
+platform: ?string,
|
||||||
+projectRoot: string,
|
+projectRoot: string,
|
||||||
|
@ -124,9 +125,7 @@ function getDynamicDepsBehavior(
|
||||||
async function transformCode(
|
async function transformCode(
|
||||||
filename: string,
|
filename: string,
|
||||||
localPath: LocalPath,
|
localPath: LocalPath,
|
||||||
sourceCode: ?string,
|
|
||||||
transformerPath: string,
|
transformerPath: string,
|
||||||
isScript: boolean,
|
|
||||||
options: WorkerOptions,
|
options: WorkerOptions,
|
||||||
assetExts: $ReadOnlyArray<string>,
|
assetExts: $ReadOnlyArray<string>,
|
||||||
assetRegistryPath: string,
|
assetRegistryPath: string,
|
||||||
|
@ -142,17 +141,13 @@ async function transformCode(
|
||||||
start_timestamp: process.hrtime(),
|
start_timestamp: process.hrtime(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let data;
|
const data = fs.readFileSync(filename);
|
||||||
|
const sourceCode = data.toString('utf8');
|
||||||
let type = 'js/module';
|
let type = 'js/module';
|
||||||
|
|
||||||
if (sourceCode == null) {
|
|
||||||
data = fs.readFileSync(filename);
|
|
||||||
sourceCode = data.toString('utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
const sha1 = crypto
|
const sha1 = crypto
|
||||||
.createHash('sha1')
|
.createHash('sha1')
|
||||||
.update(data || sourceCode)
|
.update(data)
|
||||||
.digest('hex');
|
.digest('hex');
|
||||||
|
|
||||||
if (filename.endsWith('.json')) {
|
if (filename.endsWith('.json')) {
|
||||||
|
@ -226,7 +221,7 @@ async function transformCode(
|
||||||
// dependency graph and it code will just be prepended to the bundle modules),
|
// dependency graph and it code will just be prepended to the bundle modules),
|
||||||
// we need to wrap it differently than a commonJS module (also, scripts do
|
// we need to wrap it differently than a commonJS module (also, scripts do
|
||||||
// not have dependencies).
|
// not have dependencies).
|
||||||
if (isScript) {
|
if (options.isScript) {
|
||||||
dependencies = [];
|
dependencies = [];
|
||||||
wrappedAst = JsFileWrapping.wrapPolyfill(ast);
|
wrappedAst = JsFileWrapping.wrapPolyfill(ast);
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`code transformation worker: reports filename when encountering unsupported dynamic dependency 1`] = `"arbitrary/file.js:3:10: calls to \`require\` expect exactly 1 string literal argument, but this was found: \`require(a)\`."`;
|
exports[`code transformation worker: reports filename when encountering unsupported dynamic dependency 1`] = `"/root/local/file.js:3:10: calls to \`require\` expect exactly 1 string literal argument, but this was found: \`require(a)\`."`;
|
||||||
|
|
|
@ -21,19 +21,45 @@ jest
|
||||||
.mock('metro-minify-uglify');
|
.mock('metro-minify-uglify');
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const transformCode = require('..').transform;
|
|
||||||
const {InvalidRequireCallError} = require('..');
|
const transformerPath = require.resolve('metro/src/transformer.js');
|
||||||
|
const transformerContents = require('fs').readFileSync(transformerPath);
|
||||||
|
|
||||||
|
const babelRcPath = require.resolve('metro/rn-babelrc.json');
|
||||||
|
const babelRcContents = require('fs').readFileSync(babelRcPath);
|
||||||
|
|
||||||
|
let fs;
|
||||||
|
let mkdirp;
|
||||||
|
let transformCode;
|
||||||
|
let InvalidRequireCallError;
|
||||||
|
|
||||||
describe('code transformation worker:', () => {
|
describe('code transformation worker:', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
|
||||||
|
jest.mock('fs', () => new (require('metro-memory-fs'))());
|
||||||
|
|
||||||
|
fs = require('fs');
|
||||||
|
mkdirp = require('mkdirp');
|
||||||
|
({transform: transformCode, InvalidRequireCallError} = require('..'));
|
||||||
|
fs.reset();
|
||||||
|
|
||||||
|
mkdirp.sync('/root/local');
|
||||||
|
mkdirp.sync(path.dirname(transformerPath));
|
||||||
|
fs.writeFileSync(transformerPath, transformerContents);
|
||||||
|
fs.writeFileSync(babelRcPath, babelRcContents);
|
||||||
|
});
|
||||||
|
|
||||||
it('transforms a simple script', async () => {
|
it('transforms a simple script', async () => {
|
||||||
|
fs.writeFileSync('/root/local/file.js', 'someReallyArbitrary(code)');
|
||||||
|
|
||||||
const {result} = await transformCode(
|
const {result} = await transformCode(
|
||||||
'arbitrary/file.js',
|
'/root/local/file.js',
|
||||||
`local/file.js`,
|
`local/file.js`,
|
||||||
'someReallyArbitrary(code)',
|
transformerPath,
|
||||||
require.resolve('metro/src/transformer.js'),
|
|
||||||
true,
|
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
|
isScript: true,
|
||||||
transform: {},
|
transform: {},
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
|
@ -56,14 +82,15 @@ describe('code transformation worker:', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('transforms a simple module', async () => {
|
it('transforms a simple module', async () => {
|
||||||
|
fs.writeFileSync('/root/local/file.js', 'arbitrary(code)');
|
||||||
|
|
||||||
const {result} = await transformCode(
|
const {result} = await transformCode(
|
||||||
'arbitrary/file.js',
|
'/root/local/file.js',
|
||||||
`local/file.js`,
|
`local/file.js`,
|
||||||
'arbitrary(code)',
|
transformerPath,
|
||||||
require.resolve('metro/src/transformer.js'),
|
|
||||||
false,
|
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
|
isScript: false,
|
||||||
transform: {},
|
transform: {},
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
|
@ -86,9 +113,8 @@ describe('code transformation worker:', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`transforms a module with dependencies`, async () => {
|
it(`transforms a module with dependencies`, async () => {
|
||||||
const {result} = await transformCode(
|
fs.writeFileSync(
|
||||||
'arbitrary/file.js',
|
'/root/local/file.js',
|
||||||
`local/file.js`,
|
|
||||||
[
|
[
|
||||||
"'use strict';",
|
"'use strict';",
|
||||||
'require("./a");',
|
'require("./a");',
|
||||||
|
@ -96,8 +122,12 @@ describe('code transformation worker:', () => {
|
||||||
'const b = require("b");',
|
'const b = require("b");',
|
||||||
'import c from "./c";',
|
'import c from "./c";',
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
require.resolve('metro/src/transformer.js'),
|
);
|
||||||
false,
|
|
||||||
|
const {result} = await transformCode(
|
||||||
|
'/root/local/file.js',
|
||||||
|
`local/file.js`,
|
||||||
|
transformerPath,
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
transform: {},
|
transform: {},
|
||||||
|
@ -134,17 +164,20 @@ describe('code transformation worker:', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('reports filename when encountering unsupported dynamic dependency', async () => {
|
it('reports filename when encountering unsupported dynamic dependency', async () => {
|
||||||
|
fs.writeFileSync(
|
||||||
|
'/root/local/file.js',
|
||||||
|
[
|
||||||
|
'require("./a");',
|
||||||
|
'let a = arbitrary(code);',
|
||||||
|
'const b = require(a);',
|
||||||
|
].join('\n'),
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await transformCode(
|
await transformCode(
|
||||||
'arbitrary/file.js',
|
'/root/local/file.js',
|
||||||
`local/file.js`,
|
`local/file.js`,
|
||||||
[
|
transformerPath,
|
||||||
'require("./a");',
|
|
||||||
'let a = arbitrary(code);',
|
|
||||||
'const b = require(a);',
|
|
||||||
].join('\n'),
|
|
||||||
path.join(__dirname, '../../../transformer.js'),
|
|
||||||
false,
|
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
transform: {},
|
transform: {},
|
||||||
|
@ -165,12 +198,13 @@ describe('code transformation worker:', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports dynamic dependencies from within `node_modules`', async () => {
|
it('supports dynamic dependencies from within `node_modules`', async () => {
|
||||||
|
mkdirp.sync('/root/node_modules/foo');
|
||||||
|
fs.writeFileSync('/root/node_modules/foo/bar.js', 'require(foo.bar);');
|
||||||
|
|
||||||
await transformCode(
|
await transformCode(
|
||||||
'/root/node_modules/bar/file.js',
|
'/root/node_modules/foo/bar.js',
|
||||||
`node_modules/bar/file.js`,
|
`node_modules/foo/bar.js`,
|
||||||
'require(global.something);\n',
|
transformerPath,
|
||||||
path.join(__dirname, '../../../transformer.js'),
|
|
||||||
false,
|
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
transform: {},
|
transform: {},
|
||||||
|
@ -185,13 +219,13 @@ describe('code transformation worker:', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('minifies the code correctly', async () => {
|
it('minifies the code correctly', async () => {
|
||||||
|
fs.writeFileSync('/root/local/file.js', 'arbitrary(code);');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(await transformCode(
|
(await transformCode(
|
||||||
'/root/node_modules/bar/file.js',
|
'/root/local/file.js',
|
||||||
`node_modules/bar/file.js`,
|
`local/file.js`,
|
||||||
'arbitrary(code);',
|
transformerPath,
|
||||||
path.join(__dirname, '../../../transformer.js'),
|
|
||||||
false,
|
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
minify: true,
|
minify: true,
|
||||||
|
@ -214,13 +248,13 @@ describe('code transformation worker:', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('minifies a JSON file', async () => {
|
it('minifies a JSON file', async () => {
|
||||||
|
fs.writeFileSync('/root/local/file.json', 'arbitrary(code);');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(await transformCode(
|
(await transformCode(
|
||||||
'/root/node_modules/bar/file.json',
|
'/root/local/file.json',
|
||||||
`node_modules/bar/file.js`,
|
`local/file.json`,
|
||||||
'arbitrary(code);',
|
transformerPath,
|
||||||
path.join(__dirname, '../../../transformer.js'),
|
|
||||||
false,
|
|
||||||
{
|
{
|
||||||
dev: true,
|
dev: true,
|
||||||
minify: true,
|
minify: true,
|
||||||
|
|
|
@ -36,6 +36,7 @@ async function calcTransformerOptions(
|
||||||
dev: options.dev,
|
dev: options.dev,
|
||||||
hot: options.hot,
|
hot: options.hot,
|
||||||
inlineRequires: false,
|
inlineRequires: false,
|
||||||
|
isScript: options.type === 'script',
|
||||||
minify: options.minify,
|
minify: options.minify,
|
||||||
platform: options.platform,
|
platform: options.platform,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
|
|
|
@ -24,7 +24,6 @@ type ReadResult = {
|
||||||
|
|
||||||
export type TransformCode = (
|
export type TransformCode = (
|
||||||
module: Module,
|
module: Module,
|
||||||
sourceCode: ?string,
|
|
||||||
transformOptions: WorkerOptions,
|
transformOptions: WorkerOptions,
|
||||||
) => Promise<TransformedCode>;
|
) => Promise<TransformedCode>;
|
||||||
|
|
||||||
|
@ -74,7 +73,6 @@ class Module {
|
||||||
async read(transformOptions: WorkerOptions): Promise<ReadResult> {
|
async read(transformOptions: WorkerOptions): Promise<ReadResult> {
|
||||||
const result: TransformedCode = await this._transformCode(
|
const result: TransformedCode = await this._transformCode(
|
||||||
this,
|
this,
|
||||||
null, // Source code is read on the worker
|
|
||||||
transformOptions,
|
transformOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue