diff --git a/lib/Compilation.js b/lib/Compilation.js index 4e8ff6b45..066b8c1f2 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -182,6 +182,7 @@ const { isSourceEqual } = require("./util/source"); /** * @typedef {Object} ChunkHashContext + * @property {CodeGenerationResults} codeGenerationResults results of code generation * @property {RuntimeTemplate} runtimeTemplate the runtime template * @property {ModuleGraph} moduleGraph the module graph * @property {ChunkGraph} chunkGraph the chunk graph @@ -4137,6 +4138,7 @@ This prevents using hashes of each other and should be avoided.`); chunk.updateHash(chunkHash, chunkGraph); this.hooks.chunkHash.call(chunk, chunkHash, { chunkGraph, + codeGenerationResults: this.codeGenerationResults, moduleGraph: this.moduleGraph, runtimeTemplate: this.runtimeTemplate }); diff --git a/lib/javascript/JavascriptModulesPlugin.js b/lib/javascript/JavascriptModulesPlugin.js index 28ee536d2..42d6f3522 100644 --- a/lib/javascript/JavascriptModulesPlugin.js +++ b/lib/javascript/JavascriptModulesPlugin.js @@ -103,6 +103,7 @@ const printGeneratedCodeForStack = (module, code) => { /** * @typedef {Object} RenderBootstrapContext * @property {Chunk} chunk the chunk + * @property {CodeGenerationResults} codeGenerationResults results of code generation * @property {RuntimeTemplate} runtimeTemplate the runtime template * @property {ModuleGraph} moduleGraph the module graph * @property {ChunkGraph} chunkGraph the chunk graph @@ -332,6 +333,7 @@ class JavascriptModulesPlugin { { hash: "0000", chunk, + codeGenerationResults: context.codeGenerationResults, chunkGraph: context.chunkGraph, moduleGraph: context.moduleGraph, runtimeTemplate: context.runtimeTemplate @@ -344,6 +346,7 @@ class JavascriptModulesPlugin { compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => { const { chunkGraph, + codeGenerationResults, moduleGraph, runtimeTemplate, outputOptions: { @@ -361,6 +364,7 @@ class JavascriptModulesPlugin { { hash: "0000", chunk, + codeGenerationResults, chunkGraph: compilation.chunkGraph, moduleGraph: compilation.moduleGraph, runtimeTemplate: compilation.runtimeTemplate @@ -373,6 +377,7 @@ class JavascriptModulesPlugin { } hooks.chunkHash.call(chunk, hash, { chunkGraph, + codeGenerationResults, moduleGraph, runtimeTemplate }); @@ -978,7 +983,13 @@ class JavascriptModulesPlugin { * @returns {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} the generated source of the bootstrap code */ renderBootstrap(renderContext, hooks) { - const { chunkGraph, moduleGraph, chunk, runtimeTemplate } = renderContext; + const { + chunkGraph, + codeGenerationResults, + moduleGraph, + chunk, + runtimeTemplate + } = renderContext; const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk); @@ -1102,8 +1113,18 @@ class JavascriptModulesPlugin { ); result.allowInlineStartup = false; } + + let data; + if (codeGenerationResults.has(entryModule, chunk.runtime)) { + const result = codeGenerationResults.get( + entryModule, + chunk.runtime + ); + data = result.data; + } if ( result.allowInlineStartup && + (!data || !data.get("topLevelDeclarations")) && (!entryModule.buildInfo || !entryModule.buildInfo.topLevelDeclarations) ) { diff --git a/lib/library/AssignLibraryPlugin.js b/lib/library/AssignLibraryPlugin.js index f9e3d82d3..a4868d563 100644 --- a/lib/library/AssignLibraryPlugin.js +++ b/lib/library/AssignLibraryPlugin.js @@ -222,9 +222,15 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin { * @param {LibraryContext} libraryContext context * @returns {string | undefined} bailout reason */ - embedInRuntimeBailout(module, { chunk }, { options, compilation }) { + embedInRuntimeBailout( + module, + { chunk, codeGenerationResults }, + { options, compilation } + ) { + const { data } = codeGenerationResults.get(module, chunk.runtime); const topLevelDeclarations = - module.buildInfo && module.buildInfo.topLevelDeclarations; + (data && data.get("topLevelDeclarations")) || + (module.buildInfo && module.buildInfo.topLevelDeclarations); if (!topLevelDeclarations) return "it doesn't tell about top level declarations."; const fullNameResolved = this._getResolvedFullName( diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js index 4692b28e9..cfe6c1ca4 100644 --- a/lib/optimize/ConcatenatedModule.js +++ b/lib/optimize/ConcatenatedModule.js @@ -822,10 +822,6 @@ class ConcatenatedModule extends Module { const topLevelDeclarations = this.buildInfo.topLevelDeclarations; if (topLevelDeclarations !== undefined) { for (const decl of m.buildInfo.topLevelDeclarations) { - // reserved names will always be renamed - if (RESERVED_NAMES.has(decl)) continue; - // TODO actually this is incorrect since with renaming there could be more - // We should do the renaming during build topLevelDeclarations.add(decl); } } @@ -1113,6 +1109,8 @@ class ConcatenatedModule extends Module { // List of all used names to avoid conflicts const allUsedNames = new Set(RESERVED_NAMES); + // Updated Top level declarations are created by renaming + const topLevelDeclarations = new Set(); // List of additional names in scope for module references /** @type {Map, alreadyCheckedScopes: Set }>} */ @@ -1257,6 +1255,7 @@ class ConcatenatedModule extends Module { ); allUsedNames.add(newName); info.internalNames.set(name, newName); + topLevelDeclarations.add(newName); const source = info.source; const allIdentifiers = new Set( references.map(r => r.identifier).concat(variable.identifiers) @@ -1283,6 +1282,7 @@ class ConcatenatedModule extends Module { } else { allUsedNames.add(name); info.internalNames.set(name, name); + topLevelDeclarations.add(name); } } let namespaceObjectName; @@ -1300,6 +1300,7 @@ class ConcatenatedModule extends Module { allUsedNames.add(namespaceObjectName); } info.namespaceObjectName = namespaceObjectName; + topLevelDeclarations.add(namespaceObjectName); break; } case "external": { @@ -1311,6 +1312,7 @@ class ConcatenatedModule extends Module { ); allUsedNames.add(externalName); info.name = externalName; + topLevelDeclarations.add(externalName); break; } } @@ -1323,6 +1325,7 @@ class ConcatenatedModule extends Module { ); allUsedNames.add(externalNameInterop); info.interopNamespaceObjectName = externalNameInterop; + topLevelDeclarations.add(externalNameInterop); } if ( info.module.buildMeta.exportsType === "default" && @@ -1336,6 +1339,7 @@ class ConcatenatedModule extends Module { ); allUsedNames.add(externalNameInterop); info.interopNamespaceObject2Name = externalNameInterop; + topLevelDeclarations.add(externalNameInterop); } if ( info.module.buildMeta.exportsType === "dynamic" || @@ -1349,6 +1353,7 @@ class ConcatenatedModule extends Module { ); allUsedNames.add(externalNameInterop); info.interopDefaultAccessName = externalNameInterop; + topLevelDeclarations.add(externalNameInterop); } } @@ -1618,6 +1623,7 @@ ${defineGetters}` const data = new Map(); if (chunkInitFragments.length > 0) data.set("chunkInitFragments", chunkInitFragments); + data.set("topLevelDeclarations", topLevelDeclarations); /** @type {CodeGenerationResult} */ const resultEntry = { diff --git a/test/__snapshots__/StatsTestCases.basictest.js.snap b/test/__snapshots__/StatsTestCases.basictest.js.snap index fa540e27c..164ebf13c 100644 --- a/test/__snapshots__/StatsTestCases.basictest.js.snap +++ b/test/__snapshots__/StatsTestCases.basictest.js.snap @@ -1129,7 +1129,7 @@ chunk (runtime: main) trees.js (trees) 215 bytes [rendered] `; exports[`StatsTestCases should print correct stats for ignore-warnings 1`] = ` -"asset main.js 1.37 KiB [emitted] (name: main) +"asset main.js 989 bytes [emitted] (name: main) orphan modules 617 bytes [orphan] 9 modules ./index.js + 9 modules 790 bytes [built] [code generated] diff --git a/test/configCases/concatenate-modules/issue-13022/a.js b/test/configCases/concatenate-modules/issue-13022/a.js new file mode 100644 index 000000000..a87b4d9f9 --- /dev/null +++ b/test/configCases/concatenate-modules/issue-13022/a.js @@ -0,0 +1,4 @@ +const doc = console; +const setTimeout = 1; + +export default 1; diff --git a/test/configCases/concatenate-modules/issue-13022/index.js b/test/configCases/concatenate-modules/issue-13022/index.js new file mode 100644 index 000000000..5395e7c6b --- /dev/null +++ b/test/configCases/concatenate-modules/issue-13022/index.js @@ -0,0 +1,11 @@ +import "./a"; + +setTimeout(() => {}, 0); + +const doc = console; + +export default 1; + +it("should compile and run", () => { + expect(doc).toBe(console); +}); diff --git a/test/configCases/concatenate-modules/issue-13022/webpack.config.js b/test/configCases/concatenate-modules/issue-13022/webpack.config.js new file mode 100644 index 000000000..dbbdda7ea --- /dev/null +++ b/test/configCases/concatenate-modules/issue-13022/webpack.config.js @@ -0,0 +1,29 @@ +const path = require("path"); + +/** @type {import("../../../../").Configuration[]} */ +module.exports = [ + { + entry: { + index: path.resolve(__dirname, "./index.js") + }, + output: { + library: "[name]", + libraryExport: "default" + }, + optimization: { + concatenateModules: true + } + }, + { + entry: { + index: path.resolve(__dirname, "./index.js") + }, + output: { + library: "[name]_doc", + libraryExport: "default" + }, + optimization: { + concatenateModules: true + } + } +]; diff --git a/types.d.ts b/types.d.ts index 4a6ecdf6c..264827032 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1049,6 +1049,11 @@ declare abstract class ChunkGroup { } type ChunkGroupOptions = RawChunkGroupOptions & { name?: string }; declare interface ChunkHashContext { + /** + * results of code generation + */ + codeGenerationResults: CodeGenerationResults; + /** * the runtime template */ @@ -9221,6 +9226,11 @@ declare interface RenderBootstrapContext { */ chunk: Chunk; + /** + * results of code generation + */ + codeGenerationResults: CodeGenerationResults; + /** * the runtime template */