diff --git a/packages/metro-bundler/src/JSTransformer/worker/__tests__/extract-dependencies-test.js b/packages/metro-bundler/src/JSTransformer/worker/__tests__/extract-dependencies-test.js index e021f6ce..78b6ff5d 100644 --- a/packages/metro-bundler/src/JSTransformer/worker/__tests__/extract-dependencies-test.js +++ b/packages/metro-bundler/src/JSTransformer/worker/__tests__/extract-dependencies-test.js @@ -102,6 +102,22 @@ describe('Dependency extraction:', () => { ); }); + it('throws on calls to require with non-static arguments, nested deeper than one level inside of a try block', () => { + const code = "try { if (1) { require('foo/' + bar) } } catch (e) { }"; + + expect(() => extractDependencies(code)).toThrowError( + 'require() must have a single string literal argument', + ); + }); + + it('does not throw on calls to require with non-static arguments, nested directly inside of a try block', () => { + const code = "try { require('foo/' + bar) } catch (e) { }"; + + const {dependencies, dependencyOffsets} = extractDependencies(code); + expect(dependencies).toEqual([]); + expect(dependencyOffsets).toEqual([]); + }); + it('does not get confused by previous states', () => { // yes, this was a bug const code = 'require("a");/* a comment */ var a = /[a]/.test(\'a\');'; diff --git a/packages/metro-bundler/src/JSTransformer/worker/extract-dependencies.js b/packages/metro-bundler/src/JSTransformer/worker/extract-dependencies.js index b38dc448..024855dc 100644 --- a/packages/metro-bundler/src/JSTransformer/worker/extract-dependencies.js +++ b/packages/metro-bundler/src/JSTransformer/worker/extract-dependencies.js @@ -33,9 +33,13 @@ function extractDependencies(code: string) { const dependencies = new Set(); const dependencyOffsets = []; - function pushDependency(nodeArgs) { + function pushDependency(nodeArgs, parentType) { const arg = nodeArgs[0]; if (nodeArgs.length != 1 || arg.type !== 'StringLiteral') { + // Dynamic requires directly inside of a try statement are considered optional dependencies + if (parentType === 'TryStatement') { + return; + } throw new Error('require() must have a single string literal argument'); } dependencyOffsets.push(arg.start); @@ -46,8 +50,9 @@ function extractDependencies(code: string) { CallExpression(path) { const node = path.node; const callee = node.callee; + const parent = path.scope.parentBlock; if (callee.type === 'Identifier' && callee.name === 'require') { - pushDependency(node.arguments); + pushDependency(node.arguments, parent.type); } if (callee.type !== 'MemberExpression') { return;