mirror of https://github.com/status-im/metro.git
metro: introduce asyncRequire function
Reviewed By: davidaurelio Differential Revision: D6498107 fbshipit-source-id: a9c4ab634e60f19b7058205eddcd248f57f63500
This commit is contained in:
parent
636c0ed5c9
commit
2ecf6c9450
|
@ -56,13 +56,11 @@ it('collects asynchronous dependencies', () => {
|
|||
const {dependencies, dependencyMapName} = collectDependencies(ast);
|
||||
expect(dependencies).toEqual([
|
||||
{name: 'some/async/module', isAsync: true},
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
]);
|
||||
expect(codeFromAst(ast)).toEqual(
|
||||
comparableCode(`
|
||||
require(${dependencyMapName}[1], "BundleSegments").loadForModule(${dependencyMapName}[0]).then(function () {
|
||||
return require(${dependencyMapName}[0], "some/async/module");
|
||||
}).then(foo => {});
|
||||
require(${dependencyMapName}[1], "asyncRequire")(${dependencyMapName}[0]).then(foo => {});
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
@ -75,14 +73,12 @@ it('collects mixed dependencies as being sync', () => {
|
|||
const {dependencies, dependencyMapName} = collectDependencies(ast);
|
||||
expect(dependencies).toEqual([
|
||||
{name: 'some/async/module', isAsync: false},
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
]);
|
||||
expect(codeFromAst(ast)).toEqual(
|
||||
comparableCode(`
|
||||
const a = require(${dependencyMapName}[0], "some/async/module");
|
||||
require(${dependencyMapName}[1], "BundleSegments").loadForModule(${dependencyMapName}[0]).then(function () {
|
||||
return require(${dependencyMapName}[0], "some/async/module");
|
||||
}).then(foo => {});
|
||||
require(${dependencyMapName}[1], "asyncRequire")(${dependencyMapName}[0]).then(foo => {});
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
@ -95,13 +91,11 @@ it('collects mixed dependencies as being sync; reverse order', () => {
|
|||
const {dependencies, dependencyMapName} = collectDependencies(ast);
|
||||
expect(dependencies).toEqual([
|
||||
{name: 'some/async/module', isAsync: false},
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
]);
|
||||
expect(codeFromAst(ast)).toEqual(
|
||||
comparableCode(`
|
||||
require(${dependencyMapName}[1], "BundleSegments").loadForModule(${dependencyMapName}[0]).then(function () {
|
||||
return require(${dependencyMapName}[0], "some/async/module");
|
||||
}).then(foo => {});
|
||||
require(${dependencyMapName}[1], "asyncRequire")(${dependencyMapName}[0]).then(foo => {});
|
||||
const a = require(${dependencyMapName}[0], "some/async/module");
|
||||
`),
|
||||
);
|
||||
|
|
|
@ -23,7 +23,7 @@ const DEP_MAP_NAME = 'arbitrary';
|
|||
const DEPS = [
|
||||
{name: 'b/lib/a', isAsync: false},
|
||||
{name: 'do', isAsync: false},
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
{name: 'some/async/module', isAsync: true},
|
||||
{name: 'setup/something', isAsync: false},
|
||||
];
|
||||
|
@ -32,9 +32,7 @@ it('returns dependencies from the transformed AST', () => {
|
|||
const ast = astFromCode(`
|
||||
const a = require(${DEP_MAP_NAME}[0], 'b/lib/a');
|
||||
exports.do = () => require(${DEP_MAP_NAME}[1], "do");
|
||||
require(${DEP_MAP_NAME}[2], "BundleSegments").loadForModule(${DEP_MAP_NAME}[3]).then(function () {
|
||||
return require(${DEP_MAP_NAME}[3], "some/async/module");
|
||||
}).then(foo => {});
|
||||
require(${DEP_MAP_NAME}[2], "asyncRequire")(${DEP_MAP_NAME}[3]).then(foo => {});
|
||||
if (!something) {
|
||||
require(${DEP_MAP_NAME}[4], "setup/something");
|
||||
}
|
||||
|
@ -45,9 +43,7 @@ it('returns dependencies from the transformed AST', () => {
|
|||
comparableCode(`
|
||||
const a = require(${DEP_MAP_NAME}[0]);
|
||||
exports.do = () => require(${DEP_MAP_NAME}[1]);
|
||||
require(${DEP_MAP_NAME}[2]).loadForModule(${DEP_MAP_NAME}[3]).then(function () {
|
||||
return require(${DEP_MAP_NAME}[3]);
|
||||
}).then(foo => {});
|
||||
require(${DEP_MAP_NAME}[2])(${DEP_MAP_NAME}[3]).then(foo => {});
|
||||
if (!something) {
|
||||
require(${DEP_MAP_NAME}[4]);
|
||||
}
|
||||
|
@ -66,20 +62,16 @@ it('strips unused dependencies and translates require() calls', () => {
|
|||
|
||||
it('strips unused dependencies and translates loadForModule() calls', () => {
|
||||
const ast = astFromCode(`
|
||||
require(${DEP_MAP_NAME}[2], "BundleSegments").loadForModule(${DEP_MAP_NAME}[3]).then(function () {
|
||||
return require(${DEP_MAP_NAME}[3], "some/async/module");
|
||||
}).then(foo => {});
|
||||
require(${DEP_MAP_NAME}[2], "asyncRequire")(${DEP_MAP_NAME}[3]).then(foo => {});
|
||||
`);
|
||||
const dependencies = optimizeDependencies(ast, DEPS, DEP_MAP_NAME);
|
||||
expect(dependencies).toEqual([
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
{name: 'some/async/module', isAsync: true},
|
||||
]);
|
||||
expect(codeFromAst(ast)).toEqual(
|
||||
comparableCode(`
|
||||
require(${DEP_MAP_NAME}[0]).loadForModule(${DEP_MAP_NAME}[1]).then(function () {
|
||||
return require(${DEP_MAP_NAME}[1]);
|
||||
}).then(foo => {});
|
||||
require(${DEP_MAP_NAME}[0])(${DEP_MAP_NAME}[1]).then(foo => {});
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
@ -87,27 +79,23 @@ it('strips unused dependencies and translates loadForModule() calls', () => {
|
|||
it('strips unused dependencies and translates loadForModule() calls; different ordering', () => {
|
||||
const ast = astFromCode(`
|
||||
require(${DEP_MAP_NAME}[0], 'something/else');
|
||||
require(${DEP_MAP_NAME}[2], "BundleSegments").loadForModule(${DEP_MAP_NAME}[1]).then(function () {
|
||||
return require(${DEP_MAP_NAME}[1], "some/async/module");
|
||||
}).then(foo => {});
|
||||
require(${DEP_MAP_NAME}[2], "asyncRequire")(${DEP_MAP_NAME}[1]).then(foo => {});
|
||||
`);
|
||||
const deps = [
|
||||
{name: 'something/else', isAsync: false},
|
||||
{name: 'some/async/module', isAsync: true},
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
];
|
||||
const dependencies = optimizeDependencies(ast, deps, DEP_MAP_NAME);
|
||||
expect(dependencies).toEqual([
|
||||
{name: 'something/else', isAsync: false},
|
||||
{name: 'BundleSegments', isAsync: false},
|
||||
{name: 'asyncRequire', isAsync: false},
|
||||
{name: 'some/async/module', isAsync: true},
|
||||
]);
|
||||
expect(codeFromAst(ast)).toEqual(
|
||||
comparableCode(`
|
||||
require(${DEP_MAP_NAME}[0]);
|
||||
require(${DEP_MAP_NAME}[1]).loadForModule(${DEP_MAP_NAME}[2]).then(function () {
|
||||
return require(${DEP_MAP_NAME}[2]);
|
||||
}).then(foo => {});
|
||||
require(${DEP_MAP_NAME}[1])(${DEP_MAP_NAME}[2]).then(foo => {});
|
||||
`),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -54,8 +54,7 @@ function collectDependencies(ast: Ast): CollectedDependencies {
|
|||
return;
|
||||
}
|
||||
if (node.callee.type === 'Import') {
|
||||
const reqNode = processImportCall(context, path, node, depMapIdent);
|
||||
visited.add(reqNode);
|
||||
processImportCall(context, path, node, depMapIdent);
|
||||
return;
|
||||
}
|
||||
if (isRequireCall(node.callee)) {
|
||||
|
@ -81,24 +80,17 @@ function processImportCall(context, path, node, depMapIdent) {
|
|||
const index = assignDependencyIndex(context, name, 'import');
|
||||
const mapLookup = createDepMapLookup(depMapIdent, index);
|
||||
const newImport = makeAsyncRequire({
|
||||
REQUIRE_ARGS: createRequireArgs(mapLookup, nameLiteral),
|
||||
MODULE_ID: mapLookup,
|
||||
BUNDLE_SEGMENTS_PATH: {
|
||||
type: 'StringLiteral',
|
||||
value: 'BundleSegments',
|
||||
},
|
||||
ASYNC_REQUIRE_PATH: {type: 'StringLiteral', value: 'asyncRequire'},
|
||||
});
|
||||
path.replaceWith(newImport);
|
||||
// This is the inner require() call. We return it so it
|
||||
// gets marked as already visited.
|
||||
return newImport.expression.arguments[0].body.body[0].argument;
|
||||
}
|
||||
|
||||
function processRequireCall(context, node, depMapIdent) {
|
||||
const [nameLiteral, name] = getModuleNameFromCallArgs(node);
|
||||
const index = assignDependencyIndex(context, name, 'require');
|
||||
const mapLookup = createDepMapLookup(depMapIdent, index);
|
||||
node.arguments = createRequireArgs(mapLookup, nameLiteral);
|
||||
node.arguments = [mapLookup, nameLiteral];
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -154,15 +146,9 @@ function createDepMapLookup(depMapIndent, index: number) {
|
|||
}
|
||||
|
||||
const makeAsyncRequire = babelTemplate(
|
||||
`require(BUNDLE_SEGMENTS_PATH).loadForModule(MODULE_ID).then(
|
||||
function() { return require(REQUIRE_ARGS); }
|
||||
)`,
|
||||
`require(ASYNC_REQUIRE_PATH)(MODULE_ID)`,
|
||||
);
|
||||
|
||||
function createRequireArgs(mapLookup, moduleNameLiteral) {
|
||||
return [mapLookup, moduleNameLiteral];
|
||||
}
|
||||
|
||||
function invalidRequireOf(type, node) {
|
||||
return new InvalidRequireCallError(
|
||||
`Calls to ${type}() expect exactly 1 string literal argument, ` +
|
||||
|
|
Loading…
Reference in New Issue