Visitar URL original
fix: prevent stack overflows in ESM star reexport cycles (#22080) · webpack/webpack@b0446fd · GitHub
Skip to content

Commit b0446fd

Browse files
authored
fix: prevent stack overflows in ESM star reexport cycles (#22080)
1 parent e87d6b8 commit b0446fd

8 files changed

Lines changed: 58 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"webpack": patch
3+
---
4+
5+
Fix stack overflows in ESM library star reexport cycles with externals.

‎lib/library/ModuleLibraryPlugin.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,14 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
418418
const moduleRequests = new Set();
419419
/** @type {Map<string, string | InlinedUsedName>} */
420420
const unknownProvidedExports = new Map();
421+
/** @type {Set<Module>} */
422+
const visitedReexportModules = new Set();
421423

422424
/**
423425
* Resolves dynamic star reexport.
424426
* @param {Module} module the module
425427
* @param {boolean} isDynamicReexport if module is dynamic reexported
428+
* @returns {void}
426429
*/
427430
const resolveDynamicStarReexport = (module, isDynamicReexport) => {
428431
for (const connection of moduleGraph.getOutgoingConnections(module)) {
@@ -446,7 +449,8 @@ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
446449
// Handle export * from 'external'
447450
if (importedModule instanceof ExternalModule) {
448451
moduleRequests.add(importedModule.userRequest);
449-
} else {
452+
} else if (!visitedReexportModules.has(importedModule)) {
453+
visitedReexportModules.add(importedModule);
450454
resolveDynamicStarReexport(importedModule, true);
451455
}
452456
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./library.js";
2+
export * from "external";
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as library from "./library.mjs";
2+
3+
it("should preserve external and local exports through circular star reexports", () => {
4+
expect(library.externalValue).toBe(42);
5+
expect(library.localValue).toBe(1);
6+
expect(Object.keys(library)).toEqual(["externalValue", "localValue"]);
7+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./cycle.js";
2+
export * from "./local.js";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const localValue = 1;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"use strict";
2+
3+
module.exports = {
4+
/**
5+
* @param {number} index configuration index
6+
* @returns {string} emitted test bundle
7+
*/
8+
findBundle(index) {
9+
return `main${index}.mjs`;
10+
},
11+
modules: {
12+
external: { externalValue: 42 }
13+
}
14+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use strict";
2+
3+
/** @type {import("../../../../").Configuration[]} */
4+
module.exports = [
5+
{ type: "module", minimize: false },
6+
{ type: "module", minimize: true },
7+
{ type: "modern-module", minimize: false },
8+
{ type: "modern-module", minimize: true }
9+
].map(({ type, minimize }, index) => ({
10+
mode: minimize ? "production" : "development",
11+
entry: {
12+
main: "./index.js",
13+
library: { import: "./library.js", library: { type } }
14+
},
15+
output: { module: true, filename: `[name]${index}.mjs` },
16+
externalsType: "module",
17+
externals: {
18+
"./library.mjs": `./library${index}.mjs`,
19+
external: "external"
20+
},
21+
optimization: { minimize }
22+
}));

0 commit comments

Comments
 (0)