metro-bundler: extract calls to require.async()

Reviewed By: davidaurelio

Differential Revision: D5639493

fbshipit-source-id: d74aae95a238cf97b7daafad41ce9cbdccc84c1b
This commit is contained in:
Jean Lauliac 2017-08-17 06:33:48 -07:00 committed by Facebook Github Bot
parent 66182916de
commit c6794aabd9
4 changed files with 47 additions and 8 deletions

View File

@ -30,6 +30,14 @@ describe('Dependency extraction:', () => {
expect(dependencyOffsets).toEqual([8, 46, 147, 203]); expect(dependencyOffsets).toEqual([8, 46, 147, 203]);
}); });
it('can extract calls to require.async', () => {
const code = `foo();
require.async('bar').then(() => {});`;
const {dependencies, dependencyOffsets} = extractDependencies(code);
expect(dependencies).toEqual(['bar']);
expect(dependencyOffsets).toEqual([27]);
});
it('does not extract require method calls', () => { it('does not extract require method calls', () => {
const code = ` const code = `
require('a'); require('a');

View File

@ -33,19 +33,34 @@ function extractDependencies(code: string) {
const dependencies = new Set(); const dependencies = new Set();
const dependencyOffsets = []; const dependencyOffsets = [];
function pushDependency(nodeArgs) {
const arg = nodeArgs[0];
if (nodeArgs.length != 1 || arg.type !== 'StringLiteral') {
throw new Error('require() must have a single string literal argument');
}
dependencyOffsets.push(arg.start);
dependencies.add(arg.value);
}
babel.traverse(ast, { babel.traverse(ast, {
CallExpression(path) { CallExpression(path) {
const node = path.node; const node = path.node;
const callee = node.callee; const callee = node.callee;
if (callee.type === 'Identifier' && callee.name === 'require') { if (callee.type === 'Identifier' && callee.name === 'require') {
const arg = node.arguments[0]; pushDependency(node.arguments);
if (arg == null || arg.type !== 'StringLiteral') { }
throw new Error( if (callee.type !== 'MemberExpression') {
'require() must have a single string literal argument', return;
); }
} const obj = callee.object;
dependencyOffsets.push(arg.start); const prop = callee.property;
dependencies.add(arg.value); if (
obj.type === 'Identifier' &&
obj.name === 'require' &&
!callee.computed &&
prop.name === 'async'
) {
pushDependency(node.arguments);
} }
}, },
}); });

View File

@ -110,6 +110,10 @@ function require(moduleId: ModuleID | VerboseModuleNameForDev) {
: guardedLoadModule(moduleIdReallyIsNumber, module); : guardedLoadModule(moduleIdReallyIsNumber, module);
} }
require.async = function(moduleId: ModuleID | VerboseModuleNameForDev) {
return Promise.resolve().then(() => require(moduleId));
};
let inGuard = false; let inGuard = false;
function guardedLoadModule(moduleId: ModuleID, module) { function guardedLoadModule(moduleId: ModuleID, module) {
if (!inGuard && global.ErrorUtils) { if (!inGuard && global.ErrorUtils) {

View File

@ -57,6 +57,12 @@ function _require(moduleId) {
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module); return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
} }
_require.async = function (moduleId) {
return Promise.resolve().then(function () {
return _require(moduleId);
});
};
var inGuard = false; var inGuard = false;
function guardedLoadModule(moduleId, module) { function guardedLoadModule(moduleId, module) {
if (!inGuard && global.ErrorUtils) { if (!inGuard && global.ErrorUtils) {
@ -324,6 +330,12 @@ function _require(moduleId) {
return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module); return module && module.isInitialized ? module.exports : guardedLoadModule(moduleIdReallyIsNumber, module);
} }
_require.async = function (moduleId) {
return Promise.resolve().then(function () {
return _require(moduleId);
});
};
var inGuard = false; var inGuard = false;
function guardedLoadModule(moduleId, module) { function guardedLoadModule(moduleId, module) {
if (!inGuard && global.ErrorUtils) { if (!inGuard && global.ErrorUtils) {