Metro: Keep from naively seeing all requires as commonjs requires.

Reviewed By: mjesun

Differential Revision: D7992887

fbshipit-source-id: b54f910d0c3430e067660c32ab8df04c59999b21
This commit is contained in:
Coby White 2018-05-14 16:48:34 -07:00 committed by Facebook Github Bot
parent 4a1e4f7646
commit 1c43bd841b
2 changed files with 52 additions and 3 deletions

View File

@ -215,6 +215,49 @@ it('exposes a string as `dependencyMapName` even without collecting dependencies
expect(collectDependencies(ast, opts).dependencyMapName).toEqual(any(String));
});
it('ignores require functions defined defined by lower scopes', () => {
const ast = astFromCode(`
const a = require('b/lib/a');
exports.do = () => require("do");
if (!something) {
require("setup/something");
}
require('do');
function testA(require) {
const b = require('nonExistantModule');
}
{
const require = function(foo) {
return;
}
require('nonExistantModule');
}
`);
const {dependencies, dependencyMapName} = collectDependencies(ast, opts);
expect(dependencies).toEqual([
{name: 'b/lib/a', isAsync: false},
{name: 'do', isAsync: false},
{name: 'setup/something', isAsync: false},
]);
expect(codeFromAst(ast)).toEqual(
comparableCode(`
const a = require(${dependencyMapName}[0], 'b/lib/a');
exports.do = () => require(${dependencyMapName}[1], "do");
if (!something) {
require(${dependencyMapName}[2], "setup/something");
}
require(${dependencyMapName}[1], 'do');
function testA(require) {
const b = require('nonExistantModule');
}
{
const require = function (foo) { return; };
require('nonExistantModule');
}
`),
);
});
function astFromCode(code) {
return babylon.parse(code, {plugins: ['dynamicImport']});
}

View File

@ -74,7 +74,7 @@ function collectDependencies(
processImportCall(context, path, node, depMapIdent);
return;
}
if (isRequireCall(node.callee)) {
if (isNativeRequireCall(path)) {
const reqNode = processRequireCall(context, path, node, depMapIdent);
visited.add(reqNode);
}
@ -88,8 +88,14 @@ function collectDependencies(
};
}
function isRequireCall(callee) {
return callee.type === 'Identifier' && callee.name === 'require';
function isNativeRequireCall(path) {
const node = path.node;
const callee = node.callee;
return (
callee.type === 'Identifier' &&
callee.name === 'require' &&
path.scope.bindings['require'] == null
);
}
function processImportCall(context, path, node, depMapIdent) {