From 7080da6e28987e6291833e7b3830d9481db93cca Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Tue, 29 Jun 2021 21:38:20 +0200 Subject: [PATCH] Properly handle double reexports from external namespaces --- src/Module.ts | 21 +++++++++++++++---- .../double-namespace-reexport/_config.js | 17 +++++++++++++++ .../double-namespace-reexport/first.js | 1 + .../samples/double-namespace-reexport/main.js | 1 + .../double-namespace-reexport/second.js | 1 + 5 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 test/function/samples/double-namespace-reexport/_config.js create mode 100644 test/function/samples/double-namespace-reexport/first.js create mode 100644 test/function/samples/double-namespace-reexport/main.js create mode 100644 test/function/samples/double-namespace-reexport/second.js diff --git a/src/Module.ts b/src/Module.ts index 494ffc7eef9..7f27f22f156 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -533,12 +533,15 @@ export default class Module { const foundNamespaceReexport = name in this.namespaceReexportsByName ? this.namespaceReexportsByName[name] - : (this.namespaceReexportsByName[name] = this.getVariableFromNamespaceReexports( + : this.getVariableFromNamespaceReexports( name, importerForSideEffects, searchedNamesAndModules, skipExternalNamespaceReexports - )); + ); + if (!skipExternalNamespaceReexports) { + this.namespaceReexportsByName[name] = foundNamespaceReexport; + } if (foundNamespaceReexport) { return foundNamespaceReexport; } @@ -1012,8 +1015,18 @@ export default class Module { skipExternalNamespaceReexports = false ): Variable | null { let foundSyntheticDeclaration: SyntheticNamedExportVariable | null = null; - const skipExternalNamespaceValues = new Set([true, skipExternalNamespaceReexports]); - for (const skipExternalNamespaces of skipExternalNamespaceValues) { + const skipExternalNamespaceValues = [{ searchedNamesAndModules, skipExternalNamespaces: true }]; + if (!skipExternalNamespaceReexports) { + const clonedSearchedNamesAndModules = new Map>(); + for (const [name, modules] of searchedNamesAndModules || []) { + clonedSearchedNamesAndModules.set(name, new Set(modules)); + } + skipExternalNamespaceValues.push({ + searchedNamesAndModules: clonedSearchedNamesAndModules, + skipExternalNamespaces: false + }); + } + for (const { skipExternalNamespaces, searchedNamesAndModules } of skipExternalNamespaceValues) { const foundDeclarations = new Set(); for (const module of this.exportAllModules) { if (module instanceof Module || !skipExternalNamespaces) { diff --git a/test/function/samples/double-namespace-reexport/_config.js b/test/function/samples/double-namespace-reexport/_config.js new file mode 100644 index 00000000000..41edda36e9a --- /dev/null +++ b/test/function/samples/double-namespace-reexport/_config.js @@ -0,0 +1,17 @@ +const assert = require('assert'); + +module.exports = { + description: 'handles chained namespace reexports from externals', + options: { + external: 'external' + }, + context: { + require(id) { + assert.strictEqual(id, 'external'); + return { foo: 42 }; + } + }, + exports({ foo }) { + assert.strictEqual(foo, 42); + } +}; diff --git a/test/function/samples/double-namespace-reexport/first.js b/test/function/samples/double-namespace-reexport/first.js new file mode 100644 index 00000000000..853dbb4b2f2 --- /dev/null +++ b/test/function/samples/double-namespace-reexport/first.js @@ -0,0 +1 @@ +export * from './second.js'; diff --git a/test/function/samples/double-namespace-reexport/main.js b/test/function/samples/double-namespace-reexport/main.js new file mode 100644 index 00000000000..2d9fdc01be5 --- /dev/null +++ b/test/function/samples/double-namespace-reexport/main.js @@ -0,0 +1 @@ +export { foo } from './first.js'; diff --git a/test/function/samples/double-namespace-reexport/second.js b/test/function/samples/double-namespace-reexport/second.js new file mode 100644 index 00000000000..4953eb6e351 --- /dev/null +++ b/test/function/samples/double-namespace-reexport/second.js @@ -0,0 +1 @@ +export * from 'external';