diff --git a/CHANGELOG.md b/CHANGELOG.md index 641a8f24f27..1c1c597cf18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # rollup changelog +## 2.66.1 + +_2022-01-25_ + +### Bug Fixes + +- Only warn for conflicting names in namespace reexports if it actually causes problems (#4363) +- Only allow explicit exports or reexports as synthetic namespaces and hide them from namespace reexports (#4364) + +### Pull Requests + +- [#4362](https://github.com/rollup/rollup/pull/4362): refactor: convert exportsByName object to map (@lukastaegert) +- [#4363](https://github.com/rollup/rollup/pull/4363): Do not warn unnecessarily for namespace conflicts (@lukastaegert) +- [#4364](https://github.com/rollup/rollup/pull/4364): Do not expose synthetic namespace export in entries and namespaces (@lukastaegert) + ## 2.66.0 _2022-01-22_ diff --git a/package-lock.json b/package-lock.json index e82e457cf88..b86953d1fb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "2.66.0", + "version": "2.66.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ae7ac15141c..1ea2df6e1ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "2.66.0", + "version": "2.66.1", "description": "Next-generation ES module bundler", "main": "dist/rollup.js", "module": "dist/es/rollup.js", diff --git a/src/Chunk.ts b/src/Chunk.ts index 437c7400145..abe85246265 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -143,7 +143,7 @@ export default class Chunk { private dynamicName: string | null = null; private readonly exportNamesByVariable = new Map(); private readonly exports = new Set(); - private readonly exportsByName: Record = Object.create(null); + private readonly exportsByName = new Map(); private fileName: string | null = null; private implicitEntryModules: Module[] = []; private readonly implicitlyLoadedBefore = new Set(); @@ -295,7 +295,7 @@ export default class Chunk { for (const [variable, exportNames] of exportNamesByVariable) { this.exportNamesByVariable.set(variable, [...exportNames]); for (const exportName of exportNames) { - this.exportsByName[exportName] = variable; + this.exportsByName.set(exportName, variable); } remainingExports.delete(variable); } @@ -503,15 +503,11 @@ export default class Chunk { } getChunkName(): string { - return ( - this.name || (this.name = this.outputOptions.sanitizeFileName(this.getFallbackChunkName())) - ); + return (this.name ??= this.outputOptions.sanitizeFileName(this.getFallbackChunkName())); } getExportNames(): string[] { - return ( - this.sortedExportNames || (this.sortedExportNames = Object.keys(this.exportsByName).sort()) - ); + return (this.sortedExportNames ??= Array.from(this.exportsByName.keys()).sort()); } getRenderedHash(): string { @@ -533,7 +529,7 @@ export default class Chunk { hash.update( this.getExportNames() .map(exportName => { - const variable = this.exportsByName[exportName]; + const variable = this.exportsByName.get(exportName)!; return `${relativeId((variable.module as Module).id).replace(/\\/g, '/')}:${ variable.name }:${exportName}`; @@ -741,13 +737,13 @@ export default class Chunk { hasExports, id: this.id, indent: this.indentString, - intro: addons.intro!, + intro: addons.intro, isEntryFacade: this.outputOptions.preserveModules || (this.facadeModule !== null && this.facadeModule.info.isEntry), isModuleFacade: this.facadeModule !== null, namedExportsMode: this.exportMode !== 'default', - outro: addons.outro!, + outro: addons.outro, snippets, usesTopLevelAwait, warn: this.inputOptions.onwarn @@ -868,14 +864,12 @@ export default class Chunk { existingNames: Record ): string { const hash = createHash(); - hash.update( - [addons.intro, addons.outro, addons.banner, addons.footer].map(addon => addon || '').join(':') - ); + hash.update([addons.intro, addons.outro, addons.banner, addons.footer].join(':')); hash.update(options.format); const dependenciesForHashing = new Set([this]); for (const current of dependenciesForHashing) { if (current instanceof ExternalModule) { - hash.update(':' + current.renderPath); + hash.update(`:${current.renderPath}`); } else { hash.update(current.getRenderedHash()); hash.update(current.generateId(addons, options, existingNames, false)); @@ -1013,7 +1007,7 @@ export default class Chunk { for (const exportName of this.getExportNames()) { if (exportName[0] === '*') continue; - const variable = this.exportsByName[exportName]; + const variable = this.exportsByName.get(exportName)!; if (!(variable instanceof SyntheticNamedExportVariable)) { const module = variable.module; if (module && this.chunkByModule.get(module as Module) !== this) continue; @@ -1171,7 +1165,7 @@ export default class Chunk { dependency = this.modulesById.get(id) as ExternalModule; imported = exportName = '*'; } else { - const variable = this.exportsByName[exportName]; + const variable = this.exportsByName.get(exportName)!; if (variable instanceof SyntheticNamedExportVariable) continue; const module = variable.module!; if (module instanceof Module) { @@ -1287,7 +1281,7 @@ export default class Chunk { }: NormalizedOutputOptions) { const syntheticExports = new Set(); for (const exportName of this.getExportNames()) { - const exportVariable = this.exportsByName[exportName]; + const exportVariable = this.exportsByName.get(exportName)!; if ( format !== 'es' && format !== 'system' && diff --git a/src/ExternalModule.ts b/src/ExternalModule.ts index 80e60e26fe1..8071e2c61d9 100644 --- a/src/ExternalModule.ts +++ b/src/ExternalModule.ts @@ -64,13 +64,13 @@ export default class ExternalModule { }; } - getVariableForExportName(name: string): ExternalVariable { + getVariableForExportName(name: string): [variable: ExternalVariable] { let declaration = this.declarations[name]; - if (declaration) return declaration; + if (declaration) return [declaration]; this.declarations[name] = declaration = new ExternalVariable(this, name); this.exportedVariables.set(declaration, name); - return declaration; + return [declaration]; } setRenderPath(options: NormalizedOutputOptions, inputBase: string): string { diff --git a/src/Graph.ts b/src/Graph.ts index 38fc7a0d7cc..df2ed2fb29c 100644 --- a/src/Graph.ts +++ b/src/Graph.ts @@ -243,7 +243,7 @@ export default class Graph { for (const importDescription of Object.values(module.importDescriptions)) { if ( importDescription.name !== '*' && - !importDescription.module.getVariableForExportName(importDescription.name) + !importDescription.module.getVariableForExportName(importDescription.name)[0] ) { module.warn( { diff --git a/src/Module.ts b/src/Module.ts index 93db11d47d6..443d16e9c43 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -134,13 +134,12 @@ function getVariableForExportNameRecursive( name: string, importerForSideEffects: Module | undefined, isExportAllSearch: boolean, - searchedNamesAndModules = new Map>(), - skipExternalNamespaceReexports: boolean | undefined -): Variable | null { + searchedNamesAndModules = new Map>() +): [variable: Variable | null, indirectExternal?: boolean] { const searchedModules = searchedNamesAndModules.get(name); if (searchedModules) { if (searchedModules.has(target)) { - return isExportAllSearch ? null : error(errCircularReexport(name, target.id)); + return isExportAllSearch ? [null] : error(errCircularReexport(name, target.id)); } searchedModules.add(target); } else { @@ -149,8 +148,7 @@ function getVariableForExportNameRecursive( return target.getVariableForExportName(name, { importerForSideEffects, isExportAllSearch, - searchedNamesAndModules, - skipExternalNamespaceReexports + searchedNamesAndModules }); } @@ -200,7 +198,6 @@ export default class Module { execIndex = Infinity; readonly exportAllSources = new Set(); readonly exports: { [name: string]: ExportDescription } = Object.create(null); - readonly exportsAll: { [name: string]: string } = Object.create(null); readonly implicitlyLoadedAfter = new Set(); readonly implicitlyLoadedBefore = new Set(); readonly importDescriptions: { [name: string]: ImportDescription } = Object.create(null); @@ -235,7 +232,10 @@ export default class Module { private exportNamesByVariable: Map | null = null; private readonly exportShimVariable: ExportShimVariable = new ExportShimVariable(this); private declare magicString: MagicString; - private namespaceReexportsByName: Record = Object.create(null); + private namespaceReexportsByName: Record< + string, + [variable: Variable | null, indirectExternal?: boolean] + > = Object.create(null); private relevantDependencies: Set | null = null; private readonly syntheticExports = new Map(); private syntheticNamespace: Variable | null | undefined = null; @@ -351,7 +351,11 @@ export default class Module { if (name !== 'default') allExportNames.add(name); } } - + // We do not count the synthetic namespace as a regular export to hide it + // from entry signatures and namespace objects + if (typeof this.info.syntheticNamedExports === 'string') { + allExportNames.delete(this.info.syntheticNamedExports); + } return allExportNames; } @@ -369,7 +373,7 @@ export default class Module { this.implicitlyLoadedAfter.size > 0 ) { for (const exportName of [...this.getReexports(), ...this.getExports()]) { - const exportedVariable = this.getVariableForExportName(exportName); + const [exportedVariable] = this.getVariableForExportName(exportName); if (exportedVariable) { dependencyVariables.add(exportedVariable); } @@ -412,8 +416,7 @@ export default class Module { } const exportNamesByVariable = new Map(); for (const exportName of this.getAllExportNames()) { - if (exportName === this.info.syntheticNamedExports) continue; - let tracedVariable = this.getVariableForExportName(exportName); + let [tracedVariable] = this.getVariableForExportName(exportName); if (tracedVariable instanceof ExportDefaultVariable) { tracedVariable = tracedVariable.getOriginalVariable(); } @@ -465,7 +468,7 @@ export default class Module { const renderedExports: string[] = []; const removedExports: string[] = []; for (const exportName in this.exports) { - const variable = this.getVariableForExportName(exportName); + const [variable] = this.getVariableForExportName(exportName); (variable && variable.included ? renderedExports : removedExports).push(exportName); } return { removedExports, renderedExports }; @@ -474,10 +477,11 @@ export default class Module { getSyntheticNamespace(): Variable { if (this.syntheticNamespace === null) { this.syntheticNamespace = undefined; - this.syntheticNamespace = this.getVariableForExportName( + [this.syntheticNamespace] = this.getVariableForExportName( typeof this.info.syntheticNamedExports === 'string' ? this.info.syntheticNamedExports - : 'default' + : 'default', + { onlyExplicit: true } ); } if (!this.syntheticNamespace) { @@ -493,19 +497,19 @@ export default class Module { { importerForSideEffects, isExportAllSearch, - searchedNamesAndModules, - skipExternalNamespaceReexports + onlyExplicit, + searchedNamesAndModules }: { importerForSideEffects?: Module; isExportAllSearch?: boolean; + onlyExplicit?: boolean; searchedNamesAndModules?: Map>; - skipExternalNamespaceReexports?: boolean; } = EMPTY_OBJECT - ): Variable | null { + ): [variable: Variable | null, indirectExternal?: boolean] { if (name[0] === '*') { if (name.length === 1) { // export * from './other' - return this.namespace; + return [this.namespace]; } else { // export * from 'external' const module = this.graph.modulesById.get(name.slice(1)) as ExternalModule; @@ -516,15 +520,13 @@ export default class Module { // export { foo } from './other' const reexportDeclaration = this.reexportDescriptions[name]; if (reexportDeclaration) { - const variable = getVariableForExportNameRecursive( + const [variable] = getVariableForExportNameRecursive( reexportDeclaration.module, reexportDeclaration.localName, importerForSideEffects, false, - searchedNamesAndModules, - false + searchedNamesAndModules ); - if (!variable) { return this.error( errMissingExport(reexportDeclaration.localName, this.id, reexportDeclaration.module.id), @@ -534,13 +536,13 @@ export default class Module { if (importerForSideEffects) { setAlternativeExporterIfCyclic(variable, importerForSideEffects, this); } - return variable; + return [variable]; } const exportDeclaration = this.exports[name]; if (exportDeclaration) { if (exportDeclaration === MISSING_EXPORT_SHIM_DESCRIPTION) { - return this.exportShimVariable; + return [this.exportShimVariable]; } const name = exportDeclaration.localName; const variable = this.traceVariable(name, importerForSideEffects)!; @@ -552,7 +554,11 @@ export default class Module { ).add(this); setAlternativeExporterIfCyclic(variable, importerForSideEffects, this); } - return variable; + return [variable]; + } + + if (onlyExplicit) { + return [null]; } if (name !== 'default') { @@ -562,30 +568,23 @@ export default class Module { : this.getVariableFromNamespaceReexports( name, importerForSideEffects, - searchedNamesAndModules, - skipExternalNamespaceReexports + searchedNamesAndModules ); - if (!skipExternalNamespaceReexports) { - this.namespaceReexportsByName[name] = foundNamespaceReexport; - } - if (foundNamespaceReexport) { + this.namespaceReexportsByName[name] = foundNamespaceReexport; + if (foundNamespaceReexport[0]) { return foundNamespaceReexport; } } if (this.info.syntheticNamedExports) { - let syntheticExport = this.syntheticExports.get(name); - if (!syntheticExport) { - const syntheticNamespace = this.getSyntheticNamespace(); - syntheticExport = new SyntheticNamedExportVariable( - this.astContext, + return [ + getOrCreate( + this.syntheticExports, name, - syntheticNamespace - ); - this.syntheticExports.set(name, syntheticExport); - return syntheticExport; - } - return syntheticExport; + () => + new SyntheticNamedExportVariable(this.astContext, name, this.getSyntheticNamespace()) + ) + ]; } // we don't want to create shims when we are just @@ -593,10 +592,10 @@ export default class Module { if (!isExportAllSearch) { if (this.options.shimMissingExports) { this.shimMissingExport(name); - return this.exportShimVariable; + return [this.exportShimVariable]; } } - return null; + return [null]; } hasEffects(): boolean { @@ -619,7 +618,7 @@ export default class Module { for (const exportName of this.getExports()) { if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) { - const variable = this.getVariableForExportName(exportName)!; + const variable = this.getVariableForExportName(exportName)[0]!; variable.deoptimizePath(UNKNOWN_PATH); if (!variable.included) { this.includeVariable(variable); @@ -628,7 +627,7 @@ export default class Module { } for (const name of this.getReexports()) { - const variable = this.getVariableForExportName(name); + const [variable] = this.getVariableForExportName(name); if (variable) { variable.deoptimizePath(UNKNOWN_PATH); if (!variable.included) { @@ -657,11 +656,6 @@ export default class Module { linkImports(): void { this.addModulesToImportDescriptions(this.importDescriptions); this.addModulesToImportDescriptions(this.reexportDescriptions); - for (const name in this.exports) { - if (name !== 'default' && name !== this.info.syntheticNamedExports) { - this.exportsAll[name] = this.id; - } - } const externalExportAllModules: ExternalModule[] = []; for (const source of this.exportAllSources) { const module = this.graph.modulesById.get(this.resolvedIds[source].id)!; @@ -670,13 +664,6 @@ export default class Module { continue; } this.exportAllModules.push(module); - for (const name in module.exportsAll) { - if (name in this.exportsAll) { - this.options.onwarn(errNamespaceConflict(name, this, module)); - } else { - this.exportsAll[name] = module.exportsAll[name]; - } - } } this.exportAllModules.push(...externalExportAllModules); } @@ -757,7 +744,7 @@ export default class Module { moduleContext: this.context, options: this.options, requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true), - traceExport: this.getVariableForExportName.bind(this), + traceExport: (name: string) => this.getVariableForExportName(name)[0], traceVariable: this.traceVariable.bind(this), usesTopLevelAwait: false, warn: this.warn.bind(this) @@ -804,7 +791,7 @@ export default class Module { return otherModule.namespace; } - const declaration = otherModule.getVariableForExportName(importDeclaration.name, { + const [declaration] = otherModule.getVariableForExportName(importDeclaration.name, { importerForSideEffects: importerForSideEffects || this }); @@ -1037,52 +1024,54 @@ export default class Module { private getVariableFromNamespaceReexports( name: string, importerForSideEffects?: Module, - searchedNamesAndModules?: Map>, - skipExternalNamespaceReexports = false - ): Variable | null { + searchedNamesAndModules?: Map> + ): [variable: Variable | null, indirectExternal?: boolean] { let foundSyntheticDeclaration: SyntheticNamedExportVariable | null = null; - const skipExternalNamespaceValues = [{ searchedNamesAndModules, skipExternalNamespaces: true }]; - if (!skipExternalNamespaceReexports) { - const clonedSearchedNamesAndModules = new Map>(); - for (const [name, modules] of searchedNamesAndModules || []) { - clonedSearchedNamesAndModules.set(name, new Set(modules)); + const foundInternalDeclarations = new Map(); + const foundExternalDeclarations = new Set(); + for (const module of this.exportAllModules) { + // Synthetic namespaces should not hide "regular" exports of the same name + if (module.info.syntheticNamedExports === name) { + continue; } - 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) { - const declaration = getVariableForExportNameRecursive( - module, - name, - importerForSideEffects, - true, - searchedNamesAndModules, - skipExternalNamespaces - ); - - if (declaration) { - if (!(declaration instanceof SyntheticNamedExportVariable)) { - foundDeclarations.add(declaration); - } else if (!foundSyntheticDeclaration) { - foundSyntheticDeclaration = declaration; - } - } + const [variable, indirectExternal] = getVariableForExportNameRecursive( + module, + name, + importerForSideEffects, + true, + searchedNamesAndModules + ); + + if (module instanceof ExternalModule || indirectExternal) { + foundExternalDeclarations.add(variable as ExternalVariable); + } else if (variable instanceof SyntheticNamedExportVariable) { + if (!foundSyntheticDeclaration) { + foundSyntheticDeclaration = variable; } + } else if (variable) { + foundInternalDeclarations.set(variable, module); } - if (foundDeclarations.size === 1) { - return [...foundDeclarations][0]; + } + if (foundInternalDeclarations.size > 0) { + const foundDeclarationList = [...foundInternalDeclarations]; + const usedDeclaration = foundDeclarationList[0][0]; + if (foundDeclarationList.length === 1) { + return [usedDeclaration]; } - if (foundDeclarations.size > 1) { - if (skipExternalNamespaces) { - return null; - } - const foundDeclarationList = [...(foundDeclarations as Set)]; - const usedDeclaration = foundDeclarationList[0]; + this.options.onwarn( + errNamespaceConflict( + name, + this.id, + foundDeclarationList.map(([, module]) => module.id) + ) + ); + // TODO we are pretending it was not found while it should behave like "undefined" + return [null]; + } + if (foundExternalDeclarations.size > 0) { + const foundDeclarationList = [...foundExternalDeclarations]; + const usedDeclaration = foundDeclarationList[0]; + if (foundDeclarationList.length > 1) { this.options.onwarn( errAmbiguousExternalNamespaces( name, @@ -1091,13 +1080,13 @@ export default class Module { foundDeclarationList.map(declaration => declaration.module.id) ) ); - return usedDeclaration; } + return [usedDeclaration, true]; } if (foundSyntheticDeclaration) { - return foundSyntheticDeclaration; + return [foundSyntheticDeclaration]; } - return null; + return [null]; } private includeAndGetAdditionalMergedNamespaces(): Variable[] { @@ -1105,7 +1094,7 @@ export default class Module { const syntheticNamespaces = new Set(); for (const module of [this, ...this.exportAllModules]) { if (module instanceof ExternalModule) { - const externalVariable = module.getVariableForExportName('*'); + const [externalVariable] = module.getVariableForExportName('*'); externalVariable.include(); this.imports.add(externalVariable); externalNamespaces.add(externalVariable); diff --git a/src/utils/addons.ts b/src/utils/addons.ts index 87621e62079..1f5bb356793 100644 --- a/src/utils/addons.ts +++ b/src/utils/addons.ts @@ -3,10 +3,10 @@ import { PluginDriver } from './PluginDriver'; import { error } from './error'; export interface Addons { - banner?: string; - footer?: string; - intro?: string; - outro?: string; + banner: string; + footer: string; + intro: string; + outro: string; } const concatSep = (out: string, next: string) => (next ? `${out}\n${next}` : out); diff --git a/src/utils/error.ts b/src/utils/error.ts index 3cf7aa0e8ac..7f583b91fa1 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -340,38 +340,38 @@ export function errMixedExport(facadeModuleId: string, name?: string): RollupLog export function errNamespaceConflict( name: string, - reexportingModule: Module, - additionalExportAllModule: Module + reexportingModuleId: string, + sources: string[] ): RollupWarning { return { code: Errors.NAMESPACE_CONFLICT, message: `Conflicting namespaces: "${relativeId( - reexportingModule.id - )}" re-exports "${name}" from both "${relativeId( - reexportingModule.exportsAll[name] - )}" and "${relativeId(additionalExportAllModule.exportsAll[name])}" (will be ignored)`, + reexportingModuleId + )}" re-exports "${name}" from one of the modules ${printQuotedStringList( + sources.map(moduleId => relativeId(moduleId)) + )} (will be ignored)`, name, - reexporter: reexportingModule.id, - sources: [reexportingModule.exportsAll[name], additionalExportAllModule.exportsAll[name]] + reexporter: reexportingModuleId, + sources }; } export function errAmbiguousExternalNamespaces( name: string, reexportingModule: string, - usedExternalModule: string, - externalModules: string[] + usedModule: string, + sources: string[] ): RollupWarning { return { code: Errors.AMBIGUOUS_EXTERNAL_NAMESPACES, message: `Ambiguous external namespace resolution: "${relativeId( reexportingModule )}" re-exports "${name}" from one of the external modules ${printQuotedStringList( - externalModules.map(module => relativeId(module)) - )}, guessing "${relativeId(usedExternalModule)}".`, + sources.map(module => relativeId(module)) + )}, guessing "${relativeId(usedModule)}".`, name, reexporter: reexportingModule, - sources: externalModules + sources }; } @@ -407,7 +407,7 @@ export function errSyntheticNamedExportsNeedNamespaceExport( syntheticNamedExportsOption )}' needs ${ typeof syntheticNamedExportsOption === 'string' && syntheticNamedExportsOption !== 'default' - ? `an export named "${syntheticNamedExportsOption}"` + ? `an explicit export named "${syntheticNamedExportsOption}"` : 'a default export' } that does not reexport an unresolved named export of the same module.` }; diff --git a/src/utils/exportNames.ts b/src/utils/exportNames.ts index dcb297edc63..880c5f90193 100644 --- a/src/utils/exportNames.ts +++ b/src/utils/exportNames.ts @@ -4,13 +4,13 @@ import { toBase64 } from './base64'; export function assignExportsToMangledNames( exports: ReadonlySet, - exportsByName: Record, + exportsByName: Map, exportNamesByVariable: Map ): void { let nameIndex = 0; for (const variable of exports) { let [exportName] = variable.name; - if (exportsByName[exportName]) { + if (exportsByName.has(exportName)) { do { exportName = toBase64(++nameIndex); // skip past leading number identifiers @@ -18,25 +18,25 @@ export function assignExportsToMangledNames( nameIndex += 9 * 64 ** (exportName.length - 1); exportName = toBase64(nameIndex); } - } while (RESERVED_NAMES.has(exportName) || exportsByName[exportName]); + } while (RESERVED_NAMES.has(exportName) || exportsByName.has(exportName)); } - exportsByName[exportName] = variable; + exportsByName.set(exportName, variable); exportNamesByVariable.set(variable, [exportName]); } } export function assignExportsToNames( exports: ReadonlySet, - exportsByName: Record, + exportsByName: Map, exportNamesByVariable: Map ): void { for (const variable of exports) { let nameIndex = 0; let exportName = variable.name; - while (exportsByName[exportName]) { + while (exportsByName.has(exportName)) { exportName = variable.name + '$' + ++nameIndex; } - exportsByName[exportName] = variable; + exportsByName.set(exportName, variable); exportNamesByVariable.set(variable, [exportName]); } } diff --git a/test/form/samples/merge-namespaces-non-live/_expected.js b/test/form/samples/merge-namespaces-non-live/_expected.js index 4b2dd6e372a..0ccac72f180 100644 --- a/test/form/samples/merge-namespaces-non-live/_expected.js +++ b/test/form/samples/merge-namespaces-non-live/_expected.js @@ -13,10 +13,12 @@ function _mergeNamespaces(n, m) { return Object.freeze(n); } -const __synthetic = { foo: 'foo' }; +const __synthetic$1 = { module: 'synthetic' }; + +const __synthetic = { module: 'reexport' }; var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/_mergeNamespaces({ __proto__: null -}, [__synthetic, external1, external2])); +}, [__synthetic, __synthetic$1, external1, external2])); console.log(ns); diff --git a/test/form/samples/merge-namespaces-non-live/reexport.js b/test/form/samples/merge-namespaces-non-live/reexport.js index 976fee83e08..9204c816376 100644 --- a/test/form/samples/merge-namespaces-non-live/reexport.js +++ b/test/form/samples/merge-namespaces-non-live/reexport.js @@ -1,3 +1,4 @@ export * from 'external1'; export * from './synthetic'; export * from 'external2'; +export const __synthetic = { module: 'reexport' }; diff --git a/test/form/samples/merge-namespaces-non-live/synthetic.js b/test/form/samples/merge-namespaces-non-live/synthetic.js index 7592639d278..b180a18b691 100644 --- a/test/form/samples/merge-namespaces-non-live/synthetic.js +++ b/test/form/samples/merge-namespaces-non-live/synthetic.js @@ -1 +1 @@ -export const __synthetic = { foo: 'foo' }; +export const __synthetic = { module: 'synthetic' }; diff --git a/test/form/samples/merge-namespaces/_expected.js b/test/form/samples/merge-namespaces/_expected.js index 3675738aa02..718fc549bf6 100644 --- a/test/form/samples/merge-namespaces/_expected.js +++ b/test/form/samples/merge-namespaces/_expected.js @@ -16,10 +16,12 @@ function _mergeNamespaces(n, m) { return Object.freeze(n); } -const __synthetic = { foo: 'foo' }; +const __synthetic$1 = { module: 'synthetic' }; + +const __synthetic = { module: 'reexport' }; var ns = /*#__PURE__*/Object.freeze(/*#__PURE__*/_mergeNamespaces({ __proto__: null -}, [__synthetic, external1, external2])); +}, [__synthetic, __synthetic$1, external1, external2])); console.log(ns); diff --git a/test/form/samples/merge-namespaces/reexport.js b/test/form/samples/merge-namespaces/reexport.js index 976fee83e08..9204c816376 100644 --- a/test/form/samples/merge-namespaces/reexport.js +++ b/test/form/samples/merge-namespaces/reexport.js @@ -1,3 +1,4 @@ export * from 'external1'; export * from './synthetic'; export * from 'external2'; +export const __synthetic = { module: 'reexport' }; diff --git a/test/form/samples/merge-namespaces/synthetic.js b/test/form/samples/merge-namespaces/synthetic.js index 7592639d278..b180a18b691 100644 --- a/test/form/samples/merge-namespaces/synthetic.js +++ b/test/form/samples/merge-namespaces/synthetic.js @@ -1 +1 @@ -export const __synthetic = { foo: 'foo' }; +export const __synthetic = { module: 'synthetic' }; diff --git a/test/form/samples/namespace-reexport-name/external-reexport.js b/test/form/samples/namespace-reexport-name/external-reexport.js index c4be4108af2..4953eb6e351 100644 --- a/test/form/samples/namespace-reexport-name/external-reexport.js +++ b/test/form/samples/namespace-reexport-name/external-reexport.js @@ -1,2 +1 @@ export * from 'external'; -export { conflictOverride } from 'external'; diff --git a/test/form/samples/namespace-reexport-name/overrides.js b/test/form/samples/namespace-reexport-name/overrides.js index 172928cbe16..f2cb2622f0d 100644 --- a/test/form/samples/namespace-reexport-name/overrides.js +++ b/test/form/samples/namespace-reexport-name/overrides.js @@ -1,5 +1,4 @@ -import { indirectOverride, ignoredOverride } from './external-reexport'; +import { indirectOverride } from './external-reexport'; export { directOverride as renamedDirectOverride } from './external-reexport'; export const renamedIndirectOverride = indirectOverride; -export const conflictOverride = ignoredOverride; diff --git a/test/function/samples/conflicting-reexports/namespace-import/_config.js b/test/function/samples/conflicting-reexports/namespace-import/_config.js index a83afe3ee0c..def8efa6927 100644 --- a/test/function/samples/conflicting-reexports/namespace-import/_config.js +++ b/test/function/samples/conflicting-reexports/namespace-import/_config.js @@ -6,7 +6,7 @@ module.exports = { { code: 'NAMESPACE_CONFLICT', message: - 'Conflicting namespaces: "reexport.js" re-exports "foo" from both "first.js" and "second.js" (will be ignored)', + 'Conflicting namespaces: "reexport.js" re-exports "foo" from one of the modules "first.js" and "second.js" (will be ignored)', name: 'foo', reexporter: path.join(__dirname, 'reexport.js'), sources: [path.join(__dirname, 'first.js'), path.join(__dirname, 'second.js')] diff --git a/test/function/samples/namespace-override/_config.js b/test/function/samples/namespace-override/_config.js new file mode 100644 index 00000000000..e8fd15a1f05 --- /dev/null +++ b/test/function/samples/namespace-override/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'does not warn when overriding namespace reexports with explicit ones' +}; diff --git a/test/function/samples/namespace-override/a.js b/test/function/samples/namespace-override/a.js new file mode 100644 index 00000000000..4ef4d03891d --- /dev/null +++ b/test/function/samples/namespace-override/a.js @@ -0,0 +1,5 @@ +export const a = 'a'; +export const aExportOverride = 'a'; +export const aReexportOverride = 'a'; +export const hiddenConflictByExport = 'a'; +export const hiddenConflictByReexport = 'a'; diff --git a/test/function/samples/namespace-override/b.js b/test/function/samples/namespace-override/b.js new file mode 100644 index 00000000000..ac9e1189e42 --- /dev/null +++ b/test/function/samples/namespace-override/b.js @@ -0,0 +1,4 @@ +export const b = 'b'; +export const hiddenConflictByExport = 'b'; +export const hiddenConflictByReexport = 'b'; +export * from './a.js'; diff --git a/test/function/samples/namespace-override/exportAll.js b/test/function/samples/namespace-override/exportAll.js new file mode 100644 index 00000000000..229f7033593 --- /dev/null +++ b/test/function/samples/namespace-override/exportAll.js @@ -0,0 +1,5 @@ +export * from './a.js'; +export * from './b.js'; +export const aExportOverride = 'override'; +export const hiddenConflictByExport = 'hidden'; +export { b as aReexportOverride, b as hiddenConflictByReexport } from './b.js'; diff --git a/test/function/samples/namespace-override/main.js b/test/function/samples/namespace-override/main.js new file mode 100644 index 00000000000..0ad3e6b4278 --- /dev/null +++ b/test/function/samples/namespace-override/main.js @@ -0,0 +1,12 @@ +import * as ns from './exportAll.js'; +import { hiddenConflictByExport, hiddenConflictByReexport } from './exportAll.js'; + +assert.deepStrictEqual(ns, { + __proto__: null, + a: 'a', + aExportOverride: 'override', + aReexportOverride: 'b', + b: 'b', + hiddenConflictByExport: 'hidden', + hiddenConflictByReexport: 'b', +}); diff --git a/test/function/samples/shims-missing-exports/dep2.js b/test/function/samples/shims-missing-exports/dep2.js deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/test/function/samples/shims-missing-exports/main.js b/test/function/samples/shims-missing-exports/main.js index cc652c34e2e..7db98642c1c 100644 --- a/test/function/samples/shims-missing-exports/main.js +++ b/test/function/samples/shims-missing-exports/main.js @@ -1,3 +1,3 @@ import { missing } from './dep1.js'; -export {missing} +export { missing }; diff --git a/test/function/samples/synthetic-named-export-entry/_config.js b/test/function/samples/synthetic-named-export-entry/_config.js new file mode 100644 index 00000000000..9722c598584 --- /dev/null +++ b/test/function/samples/synthetic-named-export-entry/_config.js @@ -0,0 +1,39 @@ +const assert = require('assert'); +const path = require('path'); +const ID_MAIN = path.join(__dirname, 'main.js'); +const ID_OVERRIDE = path.join(__dirname, 'override.js'); +const ID_NOOVERRIDE = path.join(__dirname, 'noOverride.js'); +const ID_HIDDENNAMESPACE = path.join(__dirname, 'hiddenNamespace.js'); + +module.exports = { + description: 'does not expose synthetic named exports on entry points', + options: { + plugins: [ + { + transform(code, id) { + switch (id) { + case ID_MAIN: + return { syntheticNamedExports: 'synthMain' }; + case ID_OVERRIDE: + return { syntheticNamedExports: 'synthOverride' }; + case ID_NOOVERRIDE: + return { syntheticNamedExports: 'synthNoOverride' }; + case ID_HIDDENNAMESPACE: + return { syntheticNamedExports: 'synthHiddenNamespace' }; + } + } + } + ] + }, + exports(exports) { + assert.deepStrictEqual(exports, { + explicitReexport: { override: true }, + hiddenNamespace: 'hiddenNamespace', + main: 'main', + noOverride: 'noOverride', + override: 'override', + synthHiddenNamespace: 'hidden in override', + synthOverride: 'overridden' + }); + } +}; diff --git a/test/function/samples/synthetic-named-export-entry/hiddenNamespace.js b/test/function/samples/synthetic-named-export-entry/hiddenNamespace.js new file mode 100644 index 00000000000..97e81d68bdc --- /dev/null +++ b/test/function/samples/synthetic-named-export-entry/hiddenNamespace.js @@ -0,0 +1,2 @@ +export const hiddenNamespace = 'hiddenNamespace'; +export const synthHiddenNamespace = { hiddenNamespace: true }; diff --git a/test/function/samples/synthetic-named-export-entry/main.js b/test/function/samples/synthetic-named-export-entry/main.js new file mode 100644 index 00000000000..cc7963f49ae --- /dev/null +++ b/test/function/samples/synthetic-named-export-entry/main.js @@ -0,0 +1,7 @@ +export const main = 'main'; +export const synthMain = { main: true }; +export * from './noOverride.js'; +export * from './override.js'; +export * from './hiddenNamespace.js'; +export const synthOverride = 'overridden'; +export { synthOverride as explicitReexport } from './override.js'; diff --git a/test/function/samples/synthetic-named-export-entry/noOverride.js b/test/function/samples/synthetic-named-export-entry/noOverride.js new file mode 100644 index 00000000000..205e87552a5 --- /dev/null +++ b/test/function/samples/synthetic-named-export-entry/noOverride.js @@ -0,0 +1,2 @@ +export const noOverride = 'noOverride'; +export const synthNoOverride = { noOverride: true }; diff --git a/test/function/samples/synthetic-named-export-entry/override.js b/test/function/samples/synthetic-named-export-entry/override.js new file mode 100644 index 00000000000..8f40d7ee6ca --- /dev/null +++ b/test/function/samples/synthetic-named-export-entry/override.js @@ -0,0 +1,3 @@ +export const override = 'override'; +export const synthOverride = { override: true }; +export const synthHiddenNamespace = 'hidden in override'; diff --git a/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js b/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js index 35a95977898..89a605bae77 100644 --- a/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js +++ b/test/function/samples/synthetic-named-exports/circular-synthetic-exports/_config.js @@ -15,7 +15,7 @@ module.exports = { error: { code: 'SYNTHETIC_NAMED_EXPORTS_NEED_NAMESPACE_EXPORT', id: path.join(__dirname, 'main.js'), - message: `Module "main.js" that is marked with 'syntheticNamedExports: "__synthetic"' needs an export named "__synthetic" that does not reexport an unresolved named export of the same module.`, + message: `Module "main.js" that is marked with 'syntheticNamedExports: "__synthetic"' needs an explicit export named "__synthetic" that does not reexport an unresolved named export of the same module.`, watchFiles: [path.join(__dirname, 'main.js'), path.join(__dirname, 'dep.js')] } }; diff --git a/test/function/samples/synthetic-named-exports/synthetic-exports-need-fallback-export/_config.js b/test/function/samples/synthetic-named-exports/synthetic-exports-need-fallback-export/_config.js index a11192c4697..7e85c3165ac 100644 --- a/test/function/samples/synthetic-named-exports/synthetic-exports-need-fallback-export/_config.js +++ b/test/function/samples/synthetic-named-exports/synthetic-exports-need-fallback-export/_config.js @@ -17,7 +17,7 @@ module.exports = { error: { code: 'SYNTHETIC_NAMED_EXPORTS_NEED_NAMESPACE_EXPORT', id: DEP_ID, - message: `Module "dep.js" that is marked with 'syntheticNamedExports: "__synthetic"' needs an export named "__synthetic" that does not reexport an unresolved named export of the same module.`, + message: `Module "dep.js" that is marked with 'syntheticNamedExports: "__synthetic"' needs an explicit export named "__synthetic" that does not reexport an unresolved named export of the same module.`, watchFiles: [path.join(__dirname, 'main.js'), DEP_ID] } }; diff --git a/test/function/samples/warn-on-namespace-conflict/_config.js b/test/function/samples/warn-on-namespace-conflict/_config.js index bf046da2768..0f6139a3501 100644 --- a/test/function/samples/warn-on-namespace-conflict/_config.js +++ b/test/function/samples/warn-on-namespace-conflict/_config.js @@ -7,8 +7,8 @@ module.exports = { code: 'NAMESPACE_CONFLICT', name: 'foo', reexporter: path.join(__dirname, 'main.js'), - sources: [path.join(__dirname, 'foo.js'), path.join(__dirname, 'deep.js')], - message: `Conflicting namespaces: "main.js" re-exports "foo" from both "foo.js" and "deep.js" (will be ignored)` + sources: [path.join(__dirname, 'foo.js'), path.join(__dirname, 'bar.js')], + message: `Conflicting namespaces: "main.js" re-exports "foo" from one of the modules "foo.js" and "bar.js" (will be ignored)` } ] };