diff --git a/src/Module.ts b/src/Module.ts index 2743a56961e..0ce3ef4e39b 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -232,13 +232,13 @@ export default class Module { private readonly exportAllModules: (Module | ExternalModule)[] = []; private readonly exportAllSources = new Set(); private exportNamesByVariable: Map | null = null; - private readonly exportShimVariable: ExportShimVariable = new ExportShimVariable(this); + private readonly exportShimVariable = new ExportShimVariable(this); private readonly exports = new Map(); private declare magicString: MagicString; - private namespaceReexportsByName: Record< + private readonly namespaceReexportsByName = new Map< string, [variable: Variable | null, indirectExternal?: boolean] - > = Object.create(null); + >(); private readonly reexportDescriptions = new Map(); private relevantDependencies: Set | null = null; private readonly syntheticExports = new Map(); @@ -380,7 +380,8 @@ export default class Module { getDependenciesToBeIncluded(): Set { if (this.relevantDependencies) return this.relevantDependencies; - const relevantDependencies = new Set(); + + this.relevantDependencies = new Set(); const necessaryDependencies = new Set(); const alwaysCheckedDependencies = new Set(); const dependencyVariables = new Set(this.imports); @@ -414,19 +415,19 @@ export default class Module { } if (!this.options.treeshake || this.info.moduleSideEffects === 'no-treeshake') { for (const dependency of this.dependencies) { - relevantDependencies.add(dependency); + this.relevantDependencies.add(dependency); } } else { this.addRelevantSideEffectDependencies( - relevantDependencies, + this.relevantDependencies, necessaryDependencies, alwaysCheckedDependencies ); } for (const dependency of necessaryDependencies) { - relevantDependencies.add(dependency); + this.relevantDependencies.add(dependency); } - return (this.relevantDependencies = relevantDependencies); + return this.relevantDependencies; } getExportNamesByVariable(): Map { @@ -579,14 +580,13 @@ export default class Module { if (name !== 'default') { const foundNamespaceReexport = - name in this.namespaceReexportsByName - ? this.namespaceReexportsByName[name] - : this.getVariableFromNamespaceReexports( - name, - importerForSideEffects, - searchedNamesAndModules - ); - this.namespaceReexportsByName[name] = foundNamespaceReexport; + this.namespaceReexportsByName.get(name) ?? + this.getVariableFromNamespaceReexports( + name, + importerForSideEffects, + searchedNamesAndModules + ); + this.namespaceReexportsByName.set(name, foundNamespaceReexport); if (foundNamespaceReexport[0]) { return foundNamespaceReexport; } diff --git a/test/function/samples/recursive-reexports/_config.js b/test/function/samples/recursive-reexports/_config.js new file mode 100644 index 00000000000..1e1ce84b159 --- /dev/null +++ b/test/function/samples/recursive-reexports/_config.js @@ -0,0 +1,15 @@ +const assert = require('assert'); +module.exports = { + description: 'handles recursive namespace reexports', + exports(exports) { + assert.deepStrictEqual(exports, { main: 'main', other: 'other' }); + }, + warnings: [ + { + code: 'CIRCULAR_DEPENDENCY', + cycle: ['main.js', 'other.js', 'main.js'], + importer: 'main.js', + message: 'Circular dependency: main.js -> other.js -> main.js' + } + ] +}; diff --git a/test/function/samples/recursive-reexports/main.js b/test/function/samples/recursive-reexports/main.js new file mode 100644 index 00000000000..aa89b491fd7 --- /dev/null +++ b/test/function/samples/recursive-reexports/main.js @@ -0,0 +1,2 @@ +export * from './other.js'; +export const main = 'main'; diff --git a/test/function/samples/recursive-reexports/other.js b/test/function/samples/recursive-reexports/other.js new file mode 100644 index 00000000000..3c111285103 --- /dev/null +++ b/test/function/samples/recursive-reexports/other.js @@ -0,0 +1,2 @@ +export * from './main.js'; +export const other = 'other';