diff --git a/packages/metro-bundler/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js b/packages/metro-bundler/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js index 3c49f941..53191a0d 100644 --- a/packages/metro-bundler/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js +++ b/packages/metro-bundler/src/ModuleGraph/worker/__tests__/collect-dependencies-test.js @@ -37,6 +37,20 @@ describe('dependency collection from ASTs:', () => { ]); }); + it('collects asynchronous dependencies', () => { + const ast = astFromCode(` + const a = require('b/lib/a'); + if (!something) { + require.async("some/async/module").then(foo => {}); + } + `); + + expect(collectDependencies(ast).dependencies).toEqual([ + 'b/lib/a', + 'some/async/module', + ]); + }); + it('supports template literals as arguments', () => { const ast = astFromCode('require(`left-pad`)'); @@ -101,11 +115,12 @@ describe('Dependency collection from optimized ASTs:', () => { ast = astFromCode(` const a = require(${dependencyMapName}[0], 'b/lib/a'); exports.do = () => require(${dependencyMapName}[1], "do"); + require.async(${dependencyMapName}[2], 'some/async/module').then(foo => {}); if (!something) { - require(${dependencyMapName}[2], "setup/something"); + require(${dependencyMapName}[3], "setup/something"); } `); - names = ['b/lib/a', 'do', 'setup/something']; + names = ['b/lib/a', 'do', 'some/async/module', 'setup/something']; }); it('passes the `dependencyMapName` through', () => { @@ -130,8 +145,9 @@ describe('Dependency collection from optimized ASTs:', () => { comparableCode(` const a = require(${dependencyMapName}[0]); exports.do = () => require(${dependencyMapName}[1]); + require.async(${dependencyMapName}[2]).then(foo => {}); if (!something) { - require(${dependencyMapName}[2]); + require(${dependencyMapName}[3]); } `), ); diff --git a/packages/metro-bundler/src/ModuleGraph/worker/collect-dependencies.js b/packages/metro-bundler/src/ModuleGraph/worker/collect-dependencies.js index 571936c1..6b7c8efd 100644 --- a/packages/metro-bundler/src/ModuleGraph/worker/collect-dependencies.js +++ b/packages/metro-bundler/src/ModuleGraph/worker/collect-dependencies.js @@ -132,6 +132,16 @@ function createMapLookup(dependencyMapIdentifier, propertyIdentifier) { function collectDependencies(ast, replacement, dependencyMapIdentifier) { const visited = new WeakSet(); const traversalState = {dependencyMapIdentifier}; + function processRequireCall(node, state, isAsync) { + const arg = replacement.getRequireCallArg(node); + const index = replacement.getIndex(arg); + node.arguments = replacement.makeArgs( + types.numericLiteral(index), + arg, + state.dependencyMapIdentifier, + ); + visited.add(node); + } traverse( ast, { @@ -148,14 +158,9 @@ function collectDependencies(ast, replacement, dependencyMapIdentifier) { return; } if (isRequireCall(node.callee)) { - const arg = replacement.getRequireCallArg(node); - const index = replacement.getIndex(arg); - node.arguments = replacement.makeArgs( - types.numericLiteral(index), - arg, - state.dependencyMapIdentifier, - ); - visited.add(node); + processRequireCall(node, state, false); + } else if (isAsyncRequireCall(node.callee)) { + processRequireCall(node, state, true); } }, }, @@ -180,6 +185,15 @@ function isRequireCall(callee) { return callee.type === 'Identifier' && callee.name === 'require'; } +function isAsyncRequireCall(callee) { + return ( + callee.type === 'MemberExpression' && + !callee.computed && + callee.property.name === 'async' && + isRequireCall(callee.object) + ); +} + class InvalidRequireCallError extends Error { constructor(message) { super(message);