Skip to content

Commit 05d294f

Browse files
authored
Ensure reexports are available for namespaces (#4499)
1 parent 0537d93 commit 05d294f

20 files changed

Lines changed: 191 additions & 6 deletions

src/Chunk.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export default class Chunk {
148148
private implicitEntryModules: Module[] = [];
149149
private readonly implicitlyLoadedBefore = new Set<Chunk>();
150150
private readonly imports = new Set<Variable>();
151+
private readonly includedReexportsByModule = new Map<Module, Variable[]>();
151152
private indentString: string = undefined as never;
152153
// This may only be updated in the constructor
153154
private readonly isEmpty: boolean = true;
@@ -164,6 +165,7 @@ export default class Chunk {
164165
private sortedExportNames: string[] | null = null;
165166
private strictFacade = false;
166167
private usedModules: Module[] = undefined as never;
168+
167169
constructor(
168170
private readonly orderedModules: readonly Module[],
169171
private readonly inputOptions: NormalizedInputOptions,
@@ -399,6 +401,9 @@ export default class Chunk {
399401
this.exports.add(module.namespace);
400402
}
401403
}
404+
if (!this.outputOptions.preserveModules) {
405+
this.addNecessaryImportsForFacades();
406+
}
402407
return facades;
403408
}
404409

@@ -832,6 +837,16 @@ export default class Chunk {
832837
}
833838
}
834839

840+
private addNecessaryImportsForFacades() {
841+
for (const [module, variables] of this.includedReexportsByModule) {
842+
if (this.includedNamespaces.has(module)) {
843+
for (const variable of variables) {
844+
this.imports.add(variable);
845+
}
846+
}
847+
}
848+
}
849+
835850
private assignFacadeName({ fileName, name }: FacadeName, facadedModule: Module): void {
836851
if (fileName) {
837852
this.fileName = fileName;
@@ -892,6 +907,7 @@ export default class Chunk {
892907
}
893908

894909
private ensureReexportsAreAvailableForModule(module: Module): void {
910+
const includedReexports: Variable[] = [];
895911
const map = module.getExportNamesByVariable();
896912
for (const exportedVariable of map.keys()) {
897913
const isSynthetic = exportedVariable instanceof SyntheticNamedExportVariable;
@@ -905,13 +921,17 @@ export default class Chunk {
905921
const chunk = this.chunkByModule.get(exportingModule);
906922
if (chunk && chunk !== this) {
907923
chunk.exports.add(importedVariable);
924+
includedReexports.push(importedVariable);
908925
if (isSynthetic) {
909926
this.imports.add(importedVariable);
910927
}
911928
}
912929
}
913930
}
914931
}
932+
if (includedReexports.length) {
933+
this.includedReexportsByModule.set(module, includedReexports);
934+
}
915935
}
916936

917937
private finaliseDynamicImports(
@@ -1345,7 +1365,7 @@ export default class Chunk {
13451365
}
13461366

13471367
private setUpChunkImportsAndExportsForModule(module: Module): void {
1348-
const moduleImports = new Set(module.imports);
1368+
const moduleImports = new Set(module.includedImports);
13491369
// when we are not preserving modules, we need to make all namespace variables available for
13501370
// rendering the namespace object
13511371
if (!this.outputOptions.preserveModules) {

src/Module.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ export default class Module {
206206
readonly importMetas: MetaProperty[] = [];
207207
importedFromNotTreeshaken = false;
208208
readonly importers: string[] = [];
209-
readonly imports = new Set<Variable>();
210209
readonly includedDynamicImporters: Module[] = [];
210+
readonly includedImports = new Set<Variable>();
211211
readonly info: ModuleInfo;
212212
isExecuted = false;
213213
isUserDefinedEntryPoint = false;
@@ -383,7 +383,7 @@ export default class Module {
383383
this.relevantDependencies = new Set<Module | ExternalModule>();
384384
const necessaryDependencies = new Set<Module | ExternalModule>();
385385
const alwaysCheckedDependencies = new Set<Module>();
386-
const dependencyVariables = new Set(this.imports);
386+
const dependencyVariables = new Set(this.includedImports);
387387

388388
if (
389389
this.info.isEntry ||
@@ -1134,12 +1134,12 @@ export default class Module {
11341134
if (module instanceof ExternalModule) {
11351135
const [externalVariable] = module.getVariableForExportName('*');
11361136
externalVariable.include();
1137-
this.imports.add(externalVariable);
1137+
this.includedImports.add(externalVariable);
11381138
externalNamespaces.add(externalVariable);
11391139
} else if (module.info.syntheticNamedExports) {
11401140
const syntheticNamespace = module.getSyntheticNamespace();
11411141
syntheticNamespace.include();
1142-
this.imports.add(syntheticNamespace);
1142+
this.includedImports.add(syntheticNamespace);
11431143
syntheticNamespaces.add(syntheticNamespace);
11441144
}
11451145
}
@@ -1183,7 +1183,7 @@ export default class Module {
11831183
this.includeVariable(variable);
11841184
const variableModule = variable.module;
11851185
if (variableModule && variableModule !== this) {
1186-
this.imports.add(variable);
1186+
this.includedImports.add(variable);
11871187
}
11881188
}
11891189

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
description: 'allows sharing imports between dynamic chunks',
3+
options: {
4+
preserveEntrySignatures: 'allow-extension'
5+
},
6+
exports(exports) {
7+
return exports.promise;
8+
}
9+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
define(['require', 'exports', './main'], (function (require, exports, main) { 'use strict';
2+
3+
const sharedDynamic = true;
4+
5+
new Promise(function (resolve, reject) { require(['./generated-dynamic2'], resolve, reject); });
6+
console.log(sharedDynamic);
7+
8+
var dynamic1 = /*#__PURE__*/Object.freeze({
9+
__proto__: null,
10+
shared: main.shared
11+
});
12+
13+
exports.dynamic1 = dynamic1;
14+
exports.sharedDynamic = sharedDynamic;
15+
16+
}));
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
define(['./generated-dynamic1', './main'], (function (dynamic1, main) { 'use strict';
2+
3+
console.log(dynamic1.sharedDynamic);
4+
5+
}));
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
define(['require', 'exports'], (function (require, exports) { 'use strict';
2+
3+
const shared = true;
4+
5+
new Promise(function (resolve, reject) { require(['./generated-dynamic1'], resolve, reject); }).then(function (n) { return n.dynamic1; });
6+
console.log(shared);
7+
8+
exports.shared = shared;
9+
10+
Object.defineProperty(exports, '__esModule', { value: true });
11+
12+
}));
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
3+
var main = require('./main.js');
4+
5+
const sharedDynamic = true;
6+
7+
Promise.resolve().then(function () { return require('./generated-dynamic2.js'); });
8+
console.log(sharedDynamic);
9+
10+
var dynamic1 = /*#__PURE__*/Object.freeze({
11+
__proto__: null,
12+
shared: main.shared
13+
});
14+
15+
exports.dynamic1 = dynamic1;
16+
exports.sharedDynamic = sharedDynamic;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
3+
var dynamic1 = require('./generated-dynamic1.js');
4+
require('./main.js');
5+
6+
console.log(dynamic1.sharedDynamic);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, '__esModule', { value: true });
4+
5+
const shared = true;
6+
7+
Promise.resolve().then(function () { return require('./generated-dynamic1.js'); }).then(function (n) { return n.dynamic1; });
8+
console.log(shared);
9+
10+
exports.shared = shared;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { s as shared } from './main.js';
2+
3+
const sharedDynamic = true;
4+
5+
import('./generated-dynamic2.js');
6+
console.log(sharedDynamic);
7+
8+
var dynamic1 = /*#__PURE__*/Object.freeze({
9+
__proto__: null,
10+
shared: shared
11+
});
12+
13+
export { dynamic1 as d, sharedDynamic as s };

0 commit comments

Comments
 (0)