Skip to content

Commit

Permalink
Ensure reexported namespaces do not prevent creation of default expor…
Browse files Browse the repository at this point in the history
…t helpers (#5466)

* Add test

* Use better variable name

* Ensure reexported namespaces do not prevent creation of default export helpers
  • Loading branch information
lukastaegert committed Apr 12, 2024
1 parent 2fdfe1c commit cfbaaaa
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 16 deletions.
41 changes: 25 additions & 16 deletions src/Chunk.ts
Expand Up @@ -908,9 +908,14 @@ export default class Chunk {
deconflictedDefault.add(chunk);
}
} else if (
variable.name === '*' &&
namespaceInteropHelpersByInteropType[interop(module.id)]
variable.isNamespace &&
namespaceInteropHelpersByInteropType[interop(module.id)] &&
(this.imports.has(variable) ||
!this.exportNamesByVariable.get(variable)?.every(name => name.startsWith('*')))
) {
// We only need to deconflict it if the namespace is actually
// created as a variable, i.e. because it is used internally or
// because it is reexported as an object
deconflictedNamespace.add(chunk);
}
}
Expand Down Expand Up @@ -1139,30 +1144,34 @@ export default class Chunk {
const reexportSpecifiers = this.getReexportSpecifiers();
const renderedDependencies = new Map<Chunk | ExternalChunk, ChunkDependency>();
const fileName = this.getFileName();
for (const dep of this.dependencies) {
const imports = importSpecifiers.get(dep) || null;
const reexports = reexportSpecifiers.get(dep) || null;
const namedExportsMode = dep instanceof ExternalChunk || dep.exportMode !== 'default';
const importPath = dep.getImportPath(fileName);

renderedDependencies.set(dep, {
attributes: dep instanceof ExternalChunk ? dep.getImportAttributes(this.snippets) : null,
defaultVariableName: dep.defaultVariableName,
for (const dependency of this.dependencies) {
const imports = importSpecifiers.get(dependency) || null;
const reexports = reexportSpecifiers.get(dependency) || null;
const namedExportsMode =
dependency instanceof ExternalChunk || dependency.exportMode !== 'default';
const importPath = dependency.getImportPath(fileName);

renderedDependencies.set(dependency, {
attributes:
dependency instanceof ExternalChunk
? dependency.getImportAttributes(this.snippets)
: null,
defaultVariableName: dependency.defaultVariableName,
globalName:
dep instanceof ExternalChunk &&
dependency instanceof ExternalChunk &&
(this.outputOptions.format === 'umd' || this.outputOptions.format === 'iife') &&
getGlobalName(
dep,
dependency,
this.outputOptions.globals,
(imports || reexports) !== null,
this.inputOptions.onLog
),
importPath,
imports,
isChunk: dep instanceof Chunk,
name: dep.variableName,
isChunk: dependency instanceof Chunk,
name: dependency.variableName,
namedExportsMode,
namespaceVariableName: dep.namespaceVariableName,
namespaceVariableName: dependency.namespaceVariableName,
reexports
});
}
Expand Down
@@ -0,0 +1,27 @@
const assert = require('node:assert');

module.exports = defineTest({
description: 'reexports both a namespace and the default export when using compat interop',
options: {
external: true,
output: { exports: 'named', interop: 'compat' }
},
context: {
require: id => {
if (id === 'external') {
return {
__esModule: true,
default: 'default',
foo: 'foo'
};
}
throw new Error(`Cannot find module ${id}`);
}
},
exports(exports) {
assert.deepStrictEqual(exports, {
default: 'default',
foo: 'foo'
});
}
});
@@ -0,0 +1,2 @@
export * from "external";
export { default } from "external";
@@ -0,0 +1,33 @@
const assert = require('node:assert');

module.exports = defineTest({
description:
'reexports both a namespace, the namespace as a name and the default export when using compat interop',
options: {
external: true,
output: { exports: 'named', interop: 'compat' }
},
context: {
require: id => {
if (id === 'external') {
return {
__esModule: true,
default: 'default',
foo: 'foo'
};
}
throw new Error(`Cannot find module ${id}`);
}
},
exports(exports) {
assert.deepStrictEqual(exports, {
default: 'default',
foo: 'foo',
external: {
__esModule: true,
default: 'default',
foo: 'foo'
}
});
}
});
@@ -0,0 +1,3 @@
export * from "external";
export * as external from 'external';
export { default } from "external";
@@ -0,0 +1,34 @@
const assert = require('node:assert');

module.exports = defineTest({
description: 'reexports both a namespace and the default export when using compat interop',
options: {
external: true,
output: { exports: 'named', interop: 'compat' }
},
context: {
require: id => {
if (id === 'external') {
return {
__esModule: true,
default: 'default',
foo: 'foo'
};
}
throw new Error(`Cannot find module ${id}`);
}
},
exports(exports) {
assert.deepStrictEqual(exports, {
default: 'default',
foo: 'foo',
wrappedExternal: {
external: {
__esModule: true,
default: 'default',
foo: 'foo'
}
}
});
}
});
@@ -0,0 +1,5 @@
export * from 'external';
import * as external from "external";

export const wrappedExternal = { external };
export { default } from 'external';

0 comments on commit cfbaaaa

Please sign in to comment.