diff --git a/src/Module.ts b/src/Module.ts index 75b35e99cd5..0d415a4b4b5 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -307,7 +307,13 @@ export default class Module { ); } - getReexports() { + getReexports(walkedModuleIds = new Set()) { + // avoid infinite recursion when using circular `export * from X` + if (walkedModuleIds.has(this.id)) { + return []; + } + walkedModuleIds.add(this.id); + const reexports = Object.create(null); for (const name in this.reexports) { @@ -320,7 +326,9 @@ export default class Module { return; } - for (const name of (module).getExports().concat((module).getReexports())) { + for (const name of (module) + .getExports() + .concat((module).getReexports(walkedModuleIds))) { if (name !== 'default') reexports[name] = true; } }); diff --git a/test/function/samples/cycles-export-star/_config.js b/test/function/samples/cycles-export-star/_config.js new file mode 100644 index 00000000000..c58ddefedd0 --- /dev/null +++ b/test/function/samples/cycles-export-star/_config.js @@ -0,0 +1,18 @@ +const assert = require('assert'); + +module.exports = { + description: 'does not stack overflow on `export * from X` cycles', + code(code) { + assert.equal( + code, + `'use strict';\n\nfunction b() {\n\treturn 'b';\n}\n\nassert.equal(b(), 'b');\n` + ); + }, + warnings: [ + { + code: 'CIRCULAR_DEPENDENCY', + importer: 'a.js', + message: 'Circular dependency: a.js -> b.js -> a.js' + } + ] +}; diff --git a/test/function/samples/cycles-export-star/a.js b/test/function/samples/cycles-export-star/a.js new file mode 100644 index 00000000000..710a0d4c760 --- /dev/null +++ b/test/function/samples/cycles-export-star/a.js @@ -0,0 +1,5 @@ +export * from './b.js'; + +export function a() { + return 'a'; +} diff --git a/test/function/samples/cycles-export-star/b.js b/test/function/samples/cycles-export-star/b.js new file mode 100644 index 00000000000..f8cd8b45005 --- /dev/null +++ b/test/function/samples/cycles-export-star/b.js @@ -0,0 +1,5 @@ +export * from './a.js'; + +export function b() { + return 'b'; +} diff --git a/test/function/samples/cycles-export-star/main.js b/test/function/samples/cycles-export-star/main.js new file mode 100644 index 00000000000..ab1f86b8695 --- /dev/null +++ b/test/function/samples/cycles-export-star/main.js @@ -0,0 +1,3 @@ +import { b } from './a.js'; + +assert.equal(b(), 'b');