From d808d04d26348b0d1516883c6e5e540d33a9e7d9 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 12 Apr 2021 20:53:25 +0200 Subject: [PATCH 1/3] attach the chunk graph to RuntimeModules --- lib/Compilation.js | 2 +- lib/RuntimeModule.js | 6 +++++- lib/container/RemoteRuntimeModule.js | 3 ++- lib/node/ReadFileChunkLoadingRuntimeModule.js | 4 ++-- lib/node/RequireChunkLoadingRuntimeModule.js | 4 ++-- lib/runtime/CompatRuntimeModule.js | 3 +-- lib/runtime/GetChunkFilenameRuntimeModule.js | 5 +++-- lib/runtime/RuntimeIdRuntimeModule.js | 3 +-- lib/runtime/StartupChunkDependenciesRuntimeModule.js | 4 ++-- lib/sharing/ConsumeSharedRuntimeModule.js | 7 ++----- lib/sharing/ShareRuntimeModule.js | 4 ++-- lib/wasm-sync/WasmChunkLoadingRuntimeModule.js | 4 ++-- lib/web/JsonpChunkLoadingRuntimeModule.js | 3 +-- lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js | 2 +- types.d.ts | 3 ++- 15 files changed, 29 insertions(+), 28 deletions(-) diff --git a/lib/Compilation.js b/lib/Compilation.js index 467ad3efa63..b7c8ace0bde 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -2828,7 +2828,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o } // attach runtime module - module.attach(this, chunk); + module.attach(this, chunk, chunkGraph); // Setup internals const exportsInfo = this.moduleGraph.getExportsInfo(module); diff --git a/lib/RuntimeModule.js b/lib/RuntimeModule.js index a0c21e287da..2788eda0f7d 100644 --- a/lib/RuntimeModule.js +++ b/lib/RuntimeModule.js @@ -41,6 +41,8 @@ class RuntimeModule extends Module { this.compilation = undefined; /** @type {Chunk} */ this.chunk = undefined; + /** @type {ChunkGraph} */ + this.chunkGraph = undefined; this.fullHash = false; /** @type {string} */ this._cachedGeneratedCode = undefined; @@ -49,11 +51,13 @@ class RuntimeModule extends Module { /** * @param {Compilation} compilation the compilation * @param {Chunk} chunk the chunk + * @param {ChunkGraph} chunkGraph the chunk graph * @returns {void} */ - attach(compilation, chunk) { + attach(compilation, chunk, chunkGraph = compilation.chunkGraph) { this.compilation = compilation; this.chunk = chunk; + this.chunkGraph = chunkGraph; } /** diff --git a/lib/container/RemoteRuntimeModule.js b/lib/container/RemoteRuntimeModule.js index a1dc075439f..90948f2737c 100644 --- a/lib/container/RemoteRuntimeModule.js +++ b/lib/container/RemoteRuntimeModule.js @@ -20,7 +20,8 @@ class RemoteRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { runtimeTemplate, chunkGraph, moduleGraph } = this.compilation; + const { compilation, chunkGraph } = this; + const { runtimeTemplate, moduleGraph } = compilation; const chunkToRemotesMapping = {}; const idToExternalAndNameMapping = {}; for (const chunk of this.chunk.getAllAsyncChunks()) { diff --git a/lib/node/ReadFileChunkLoadingRuntimeModule.js b/lib/node/ReadFileChunkLoadingRuntimeModule.js index 827b689248b..97492b93981 100644 --- a/lib/node/ReadFileChunkLoadingRuntimeModule.js +++ b/lib/node/ReadFileChunkLoadingRuntimeModule.js @@ -25,8 +25,8 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { chunk } = this; - const { chunkGraph, runtimeTemplate } = this.compilation; + const { chunkGraph, chunk } = this; + const { runtimeTemplate } = this.compilation; const fn = RuntimeGlobals.ensureChunkHandlers; const withBaseURI = this.runtimeRequirements.has(RuntimeGlobals.baseURI); const withExternalInstallChunk = this.runtimeRequirements.has( diff --git a/lib/node/RequireChunkLoadingRuntimeModule.js b/lib/node/RequireChunkLoadingRuntimeModule.js index 2e7ca9213f8..699d9d0051b 100644 --- a/lib/node/RequireChunkLoadingRuntimeModule.js +++ b/lib/node/RequireChunkLoadingRuntimeModule.js @@ -25,8 +25,8 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { chunk } = this; - const { chunkGraph, runtimeTemplate } = this.compilation; + const { chunkGraph, chunk } = this; + const { runtimeTemplate } = this.compilation; const fn = RuntimeGlobals.ensureChunkHandlers; const withBaseURI = this.runtimeRequirements.has(RuntimeGlobals.baseURI); const withExternalInstallChunk = this.runtimeRequirements.has( diff --git a/lib/runtime/CompatRuntimeModule.js b/lib/runtime/CompatRuntimeModule.js index d4c627d1586..ed9d9aff984 100644 --- a/lib/runtime/CompatRuntimeModule.js +++ b/lib/runtime/CompatRuntimeModule.js @@ -19,9 +19,8 @@ class CompatRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { chunk, compilation } = this; + const { chunkGraph, chunk, compilation } = this; const { - chunkGraph, runtimeTemplate, mainTemplate, moduleTemplates, diff --git a/lib/runtime/GetChunkFilenameRuntimeModule.js b/lib/runtime/GetChunkFilenameRuntimeModule.js index 203c296f2af..632407264d3 100644 --- a/lib/runtime/GetChunkFilenameRuntimeModule.js +++ b/lib/runtime/GetChunkFilenameRuntimeModule.js @@ -39,6 +39,7 @@ class GetChunkFilenameRuntimeModule extends RuntimeModule { const { global, chunk, + chunkGraph, contentType, getFilenameForChunk, allChunks, @@ -90,12 +91,12 @@ class GetChunkFilenameRuntimeModule extends RuntimeModule { for (const c of chunk.getAllAsyncChunks()) { addChunk(c); } - const includeEntries = compilation.chunkGraph + const includeEntries = chunkGraph .getTreeRuntimeRequirements(chunk) .has(RuntimeGlobals.ensureChunkIncludeEntries); if (includeEntries) { includedChunksMessages.push("sibling chunks for the entrypoint"); - for (const c of compilation.chunkGraph.getChunkEntryDependentChunksIterable( + for (const c of chunkGraph.getChunkEntryDependentChunksIterable( chunk )) { addChunk(c); diff --git a/lib/runtime/RuntimeIdRuntimeModule.js b/lib/runtime/RuntimeIdRuntimeModule.js index 7e046eb6e8f..ca2313c7de5 100644 --- a/lib/runtime/RuntimeIdRuntimeModule.js +++ b/lib/runtime/RuntimeIdRuntimeModule.js @@ -16,8 +16,7 @@ class RuntimeIdRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { chunk, compilation } = this; - const { chunkGraph } = compilation; + const { chunkGraph, chunk } = this; const runtime = chunk.runtime; if (typeof runtime !== "string") throw new Error("RuntimeIdRuntimeModule must be in a single runtime"); diff --git a/lib/runtime/StartupChunkDependenciesRuntimeModule.js b/lib/runtime/StartupChunkDependenciesRuntimeModule.js index efcc1c22b33..5097b4d681f 100644 --- a/lib/runtime/StartupChunkDependenciesRuntimeModule.js +++ b/lib/runtime/StartupChunkDependenciesRuntimeModule.js @@ -19,8 +19,8 @@ class StartupChunkDependenciesRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { chunk, compilation } = this; - const { chunkGraph, runtimeTemplate } = compilation; + const { chunkGraph, chunk, compilation } = this; + const { runtimeTemplate } = compilation; const chunkIds = Array.from( chunkGraph.getChunkEntryDependentChunksIterable(chunk) ).map(chunk => { diff --git a/lib/sharing/ConsumeSharedRuntimeModule.js b/lib/sharing/ConsumeSharedRuntimeModule.js index 3dbf4f3f3e4..180c1ae0a9c 100644 --- a/lib/sharing/ConsumeSharedRuntimeModule.js +++ b/lib/sharing/ConsumeSharedRuntimeModule.js @@ -30,11 +30,8 @@ class ConsumeSharedRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { - runtimeTemplate, - chunkGraph, - codeGenerationResults - } = this.compilation; + const { compilation, chunkGraph } = this; + const { runtimeTemplate, codeGenerationResults } = compilation; const chunkToModuleMapping = {}; /** @type {Map} */ const moduleIdToSourceMapping = new Map(); diff --git a/lib/sharing/ShareRuntimeModule.js b/lib/sharing/ShareRuntimeModule.js index d5a36b5d338..3d9f7bd5d84 100644 --- a/lib/sharing/ShareRuntimeModule.js +++ b/lib/sharing/ShareRuntimeModule.js @@ -22,12 +22,12 @@ class ShareRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { + const { compilation, chunkGraph } = this; const { runtimeTemplate, - chunkGraph, codeGenerationResults, outputOptions: { uniqueName } - } = this.compilation; + } = compilation; /** @type {Map>>} */ const initCodePerScope = new Map(); for (const chunk of this.chunk.getAllReferencedChunks()) { diff --git a/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js b/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js index f55f917f47c..274251babea 100644 --- a/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +++ b/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js @@ -200,8 +200,8 @@ class WasmChunkLoadingRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { compilation, chunk, mangleImports } = this; - const { chunkGraph, moduleGraph, outputOptions } = compilation; + const { chunkGraph, compilation, chunk, mangleImports } = this; + const { moduleGraph, outputOptions } = compilation; const fn = RuntimeGlobals.ensureChunkHandlers; const wasmModules = getAllWasmModules(moduleGraph, chunkGraph, chunk); const declarations = []; diff --git a/lib/web/JsonpChunkLoadingRuntimeModule.js b/lib/web/JsonpChunkLoadingRuntimeModule.js index 726c00f84d3..a19c413a81a 100644 --- a/lib/web/JsonpChunkLoadingRuntimeModule.js +++ b/lib/web/JsonpChunkLoadingRuntimeModule.js @@ -55,10 +55,9 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule { * @returns {string} runtime code */ generate() { - const { compilation, chunk } = this; + const { chunkGraph, compilation, chunk } = this; const { runtimeTemplate, - chunkGraph, outputOptions: { globalObject, chunkLoadingGlobal, diff --git a/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js b/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js index c43ed5c742d..77c26863b10 100644 --- a/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +++ b/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js @@ -27,8 +27,8 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule { generate() { const { chunk, + chunkGraph, compilation: { - chunkGraph, runtimeTemplate, outputOptions: { globalObject, chunkLoadingGlobal, hotUpdateGlobal } } diff --git a/types.d.ts b/types.d.ts index 3e7f37dfb74..0f729823ce7 100644 --- a/types.d.ts +++ b/types.d.ts @@ -9352,8 +9352,9 @@ declare class RuntimeModule extends Module { stage: number; compilation: Compilation; chunk: Chunk; + chunkGraph: ChunkGraph; fullHash: boolean; - attach(compilation: Compilation, chunk: Chunk): void; + attach(compilation: Compilation, chunk: Chunk, chunkGraph?: ChunkGraph): void; generate(): string; getGeneratedCode(): string; shouldIsolate(): boolean; From 24c59023746445cb85590848d217687fc3127ddb Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 14 Apr 2021 14:37:00 +0200 Subject: [PATCH 2/3] add interceptModuleExecution, module cache and improve error messages --- lib/Compilation.js | 48 +++++++++++++++-------- lib/javascript/JavascriptModulesPlugin.js | 38 ++++++++++++++---- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/lib/Compilation.js b/lib/Compilation.js index b7c8ace0bde..20941d00a1e 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -4152,29 +4152,45 @@ This prevents using hashes of each other and should be avoided.`); strictModuleErrorHandling, strictModuleExceptionHandling } = this.outputOptions; - const moduleCache = new Map(); const __webpack_require__ = id => { + const cached = moduleCache[id]; + if (cached !== undefined) { + if (cached.error) throw cached.error; + return cached.exports; + } const module = modulesById.get(id); return __webpack_require_module__(module, id); }; + const interceptModuleExecution = (__webpack_require__[ + RuntimeGlobals.interceptModuleExecution.replace( + "__webpack_require__.", + "" + ) + ] = []); + const moduleCache = (__webpack_require__[ + RuntimeGlobals.moduleCache.replace("__webpack_require__.", "") + ] = {}); + /** * * @param {Module} module the module - * @param {string} id id + * @param {string=} id id * @returns {any} exports */ const __webpack_require_module__ = (module, id) => { - const cached = moduleCache.get(module); - if (cached !== undefined) { - if (cached.error) throw cached.error; - return cached.exports; - } - const moduleObject = { + var execOptions = { id, - exports: {}, - loaded: false, - error: undefined + module: { + id, + exports: {}, + loaded: false, + error: undefined + }, + require: __webpack_require__ }; + interceptModuleExecution.forEach(handler => + handler(execOptions) + ); this.buildTimeExecutedModules.add(module); module.addCacheDependencies( fileDependencies, @@ -4191,8 +4207,9 @@ This prevents using hashes of each other and should be avoided.`); }); } } + const moduleObject = execOptions.module; try { - moduleCache.set(module, moduleObject); + if (id) moduleCache[id] = moduleObject; const codeGenerationResult = codeGenerationResults.get( module, runtime @@ -4213,7 +4230,7 @@ This prevents using hashes of each other and should be avoided.`); return moduleObject.exports; } catch (e) { if (strictModuleExceptionHandling) { - moduleCache.delete(module); + if (id) delete moduleCache[id]; } else if (strictModuleErrorHandling) { moduleObject.error = e; } @@ -4233,10 +4250,7 @@ This prevents using hashes of each other and should be avoided.`); for (const runtimeModule of chunkGraph.getChunkRuntimeModulesInOrder( chunk )) { - __webpack_require_module__( - runtimeModule, - runtimeModule.identifier() - ); + __webpack_require_module__(runtimeModule); } exports = __webpack_require__(module.identifier()); } catch (e) { diff --git a/lib/javascript/JavascriptModulesPlugin.js b/lib/javascript/JavascriptModulesPlugin.js index 7b93fc878c6..2971f5b8a29 100644 --- a/lib/javascript/JavascriptModulesPlugin.js +++ b/lib/javascript/JavascriptModulesPlugin.js @@ -52,6 +52,17 @@ const chunkHasJs = (chunk, chunkGraph) => { : false; }; +const printGeneratedCodeForStack = (module, code) => { + const lines = code.split("\n"); + const n = `${lines.length}`.length; + return `\n\nGenerated code for ${module.identifier()}\n${lines + .map((line, i, lines) => { + const iStr = `${i + 1}`; + return `${" ".repeat(n - iStr.length)}${iStr} | ${line}`; + }) + .join("\n")}`; +}; + /** * @typedef {Object} RenderContext * @property {Chunk} chunk the chunk @@ -397,12 +408,17 @@ class JavascriptModulesPlugin { lineOffset: -1 } ); - fn.call( - moduleObject.exports, - moduleObject, - moduleObject.exports, - context.__webpack_require__ - ); + try { + fn.call( + moduleObject.exports, + moduleObject, + moduleObject.exports, + context.__webpack_require__ + ); + } catch (e) { + e.stack += printGeneratedCodeForStack(options.module, code); + throw e; + } } ); compilation.hooks.executeModule.tap( @@ -410,7 +426,8 @@ class JavascriptModulesPlugin { (options, context) => { const source = options.codeGenerationResult.sources.get("runtime"); if (source === undefined) return; - const code = source.source(); + let code = source.source(); + if (typeof code !== "string") code = code.toString(); const fn = vm.runInThisContext( `(function(__webpack_require__) {\n${code}\n/**/})`, @@ -419,7 +436,12 @@ class JavascriptModulesPlugin { lineOffset: -1 } ); - fn.call(null, context.__webpack_require__); + try { + fn.call(null, context.__webpack_require__); + } catch (e) { + e.stack += printGeneratedCodeForStack(options.module, code); + throw e; + } } ); } From f46e816a382bd5976a9a13ccc1fb2f302c39cabf Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 14 Apr 2021 14:37:11 +0200 Subject: [PATCH 3/3] add HMR test case and fix problems with it --- lib/Compilation.js | 270 ++++++++++-------- lib/asset/AssetModulesPlugin.js | 2 +- lib/dependencies/LoaderPlugin.js | 2 + .../loader-import-module/css/colors.js | 5 + .../loader-import-module/css/file.jpg | Bin 0 -> 6027 bytes .../loader-import-module/css/file.png | Bin 0 -> 14910 bytes .../loader-import-module/css/index.js | 26 ++ .../loader-import-module/css/loader.js | 6 + .../css/stylesheet.css.js | 29 ++ .../css/webpack.config.js | 39 +++ types.d.ts | 9 +- 11 files changed, 273 insertions(+), 115 deletions(-) create mode 100644 test/hotCases/loader-import-module/css/colors.js create mode 100644 test/hotCases/loader-import-module/css/file.jpg create mode 100644 test/hotCases/loader-import-module/css/file.png create mode 100644 test/hotCases/loader-import-module/css/index.js create mode 100644 test/hotCases/loader-import-module/css/loader.js create mode 100644 test/hotCases/loader-import-module/css/stylesheet.css.js create mode 100644 test/hotCases/loader-import-module/css/webpack.config.js diff --git a/lib/Compilation.js b/lib/Compilation.js index 20941d00a1e..f96e0287f6e 100644 --- a/lib/Compilation.js +++ b/lib/Compilation.js @@ -12,7 +12,8 @@ const { SyncBailHook, SyncWaterfallHook, AsyncSeriesHook, - AsyncSeriesBailHook + AsyncSeriesBailHook, + AsyncParallelHook } = require("tapable"); const util = require("util"); const { CachedSource } = require("webpack-sources"); @@ -183,6 +184,7 @@ const { isSourceEqual } = require("./util/source"); /** * @typedef {Object} ExecuteModuleResult * @property {any} exports + * @property {boolean} cacheable * @property {Map} assets * @property {LazySet} fileDependencies * @property {LazySet} contextDependencies @@ -193,7 +195,8 @@ const { isSourceEqual } = require("./util/source"); /** * @typedef {Object} ExecuteModuleArgument * @property {Module} module - * @property {object} moduleObject + * @property {{ id: string, exports: any, loaded: boolean }=} moduleObject + * @property {any} preparedInfo * @property {CodeGenerationResult} codeGenerationResult */ @@ -202,7 +205,7 @@ const { isSourceEqual } = require("./util/source"); * @property {Map} assets * @property {Chunk} chunk * @property {ChunkGraph} chunkGraph - * @property {Function} __webpack_require__ + * @property {function(string): any=} __webpack_require__ */ /** @@ -574,6 +577,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si /** @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */ executeModule: new SyncHook(["options", "context"]), + /** @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */ + prepareModuleExecution: new AsyncParallelHook(["options", "context"]), /** @type {AsyncSeriesHook<[Iterable]>} */ finishModules: new AsyncSeriesHook(["modules"]), @@ -4025,6 +4030,7 @@ This prevents using hashes of each other and should be avoided.`); const entrypoint = new Entrypoint({ runtime, + chunkLoading: "none", ...options.entryOptions }); chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint); @@ -4034,13 +4040,9 @@ This prevents using hashes of each other and should be avoided.`); const chunks = new Set([chunk]); - /** @type {Map} */ - const modulesById = new Map(); - // Assign ids to modules and modules to the chunk for (const module of modules) { const id = module.identifier(); - modulesById.set(id, module); chunkGraph.setModuleId(module, id); chunkGraph.connectChunkAndModule(chunk, module); } @@ -4120,6 +4122,7 @@ This prevents using hashes of each other and should be avoided.`); // Hash runtime modules for (const module of runtimeModules) { + modules.add(module); this._createModuleHash( module, chunkGraph, @@ -4136,7 +4139,11 @@ This prevents using hashes of each other and should be avoided.`); if (err) return callback(err); reportErrors(); - let exports; + /** @type {Map} */ + const moduleArgumentsMap = new Map(); + /** @type {Map} */ + const moduleArgumentsById = new Map(); + /** @type {ExecuteModuleResult["fileDependencies"]} */ const fileDependencies = new LazySet(); /** @type {ExecuteModuleResult["contextDependencies"]} */ @@ -4145,59 +4152,47 @@ This prevents using hashes of each other and should be avoided.`); const missingDependencies = new LazySet(); /** @type {ExecuteModuleResult["buildDependencies"]} */ const buildDependencies = new LazySet(); + /** @type {ExecuteModuleResult["assets"]} */ const assets = new Map(); - try { - const { - strictModuleErrorHandling, - strictModuleExceptionHandling - } = this.outputOptions; - const __webpack_require__ = id => { - const cached = moduleCache[id]; - if (cached !== undefined) { - if (cached.error) throw cached.error; - return cached.exports; - } - const module = modulesById.get(id); - return __webpack_require_module__(module, id); - }; - const interceptModuleExecution = (__webpack_require__[ - RuntimeGlobals.interceptModuleExecution.replace( - "__webpack_require__.", - "" - ) - ] = []); - const moduleCache = (__webpack_require__[ - RuntimeGlobals.moduleCache.replace("__webpack_require__.", "") - ] = {}); - - /** - * - * @param {Module} module the module - * @param {string=} id id - * @returns {any} exports - */ - const __webpack_require_module__ = (module, id) => { - var execOptions = { - id, - module: { - id, - exports: {}, - loaded: false, - error: undefined - }, - require: __webpack_require__ - }; - interceptModuleExecution.forEach(handler => - handler(execOptions) + + let cacheable = true; + + /** @type {ExecuteModuleContext} */ + const context = { + assets, + __webpack_require__: undefined, + chunk, + chunkGraph + }; + + // Prepare execution + asyncLib.eachLimit( + modules, + 10, + (module, callback) => { + const codeGenerationResult = codeGenerationResults.get( + module, + runtime ); - this.buildTimeExecutedModules.add(module); + /** @type {ExecuteModuleArgument} */ + const moduleArgument = { + module, + codeGenerationResult, + preparedInfo: undefined, + moduleObject: undefined + }; + moduleArgumentsMap.set(module, moduleArgument); + moduleArgumentsById.set(module.identifier(), moduleArgument); module.addCacheDependencies( fileDependencies, contextDependencies, missingDependencies, buildDependencies ); + if (module.buildInfo.cacheable === false) { + cacheable = false; + } if (module.buildInfo && module.buildInfo.assets) { const { assets: moduleAssets, assetsInfo } = module.buildInfo; for (const assetName of Object.keys(moduleAssets)) { @@ -4207,71 +4202,122 @@ This prevents using hashes of each other and should be avoided.`); }); } } - const moduleObject = execOptions.module; + this.hooks.prepareModuleExecution.callAsync( + moduleArgument, + context, + callback + ); + }, + err => { + if (err) return callback(err); + + let exports; try { - if (id) moduleCache[id] = moduleObject; - const codeGenerationResult = codeGenerationResults.get( - module, - runtime - ); - tryRunOrWebpackError( - () => - this.hooks.executeModule.call( - { - codeGenerationResult, - module, - moduleObject - }, - context - ), - "Compilation.hooks.executeModule" - ); - moduleObject.loaded = true; - return moduleObject.exports; - } catch (e) { - if (strictModuleExceptionHandling) { - if (id) delete moduleCache[id]; - } else if (strictModuleErrorHandling) { - moduleObject.error = e; + const { + strictModuleErrorHandling, + strictModuleExceptionHandling + } = this.outputOptions; + const __webpack_require__ = id => { + const cached = moduleCache[id]; + if (cached !== undefined) { + if (cached.error) throw cached.error; + return cached.exports; + } + const moduleArgument = moduleArgumentsById.get(id); + return __webpack_require_module__(moduleArgument, id); + }; + const interceptModuleExecution = (__webpack_require__[ + RuntimeGlobals.interceptModuleExecution.replace( + "__webpack_require__.", + "" + ) + ] = []); + const moduleCache = (__webpack_require__[ + RuntimeGlobals.moduleCache.replace( + "__webpack_require__.", + "" + ) + ] = {}); + + context.__webpack_require__ = __webpack_require__; + + /** + * @param {ExecuteModuleArgument} moduleArgument the module argument + * @param {string=} id id + * @returns {any} exports + */ + const __webpack_require_module__ = (moduleArgument, id) => { + var execOptions = { + id, + module: { + id, + exports: {}, + loaded: false, + error: undefined + }, + require: __webpack_require__ + }; + interceptModuleExecution.forEach(handler => + handler(execOptions) + ); + const module = moduleArgument.module; + this.buildTimeExecutedModules.add(module); + const moduleObject = execOptions.module; + moduleArgument.moduleObject = moduleObject; + try { + if (id) moduleCache[id] = moduleObject; + + tryRunOrWebpackError( + () => + this.hooks.executeModule.call( + moduleArgument, + context + ), + "Compilation.hooks.executeModule" + ); + moduleObject.loaded = true; + return moduleObject.exports; + } catch (e) { + if (strictModuleExceptionHandling) { + if (id) delete moduleCache[id]; + } else if (strictModuleErrorHandling) { + moduleObject.error = e; + } + if (!e.module) e.module = module; + throw e; + } + }; + + for (const runtimeModule of chunkGraph.getChunkRuntimeModulesInOrder( + chunk + )) { + __webpack_require_module__( + moduleArgumentsMap.get(runtimeModule) + ); } - if (!e.module) e.module = module; - throw e; + exports = __webpack_require__(module.identifier()); + } catch (e) { + const err = new WebpackError( + `Execution of module code from module graph (${module.readableIdentifier( + this.requestShortener + )}) failed: ${e.message}` + ); + err.stack = e.stack; + err.module = e.module; + return callback(err); } - }; - - /** @type {ExecuteModuleContext} */ - const context = { - assets, - __webpack_require__, - chunk, - chunkGraph - }; - for (const runtimeModule of chunkGraph.getChunkRuntimeModulesInOrder( - chunk - )) { - __webpack_require_module__(runtimeModule); + callback(null, { + exports, + assets, + cacheable, + fileDependencies, + contextDependencies, + missingDependencies, + buildDependencies + }); } - exports = __webpack_require__(module.identifier()); - } catch (e) { - const err = new WebpackError( - `Execution of module code from module graph (${module.readableIdentifier( - this.requestShortener - )}) failed: ${e.message}` - ); - err.stack = e.stack; - err.module = e.module; - return callback(err); - } - - callback(null, { - exports, - assets, - fileDependencies, - contextDependencies, - missingDependencies, - buildDependencies - }); + ); }); }); } diff --git a/lib/asset/AssetModulesPlugin.js b/lib/asset/AssetModulesPlugin.js index e46aa945c30..d708b46f2fb 100644 --- a/lib/asset/AssetModulesPlugin.js +++ b/lib/asset/AssetModulesPlugin.js @@ -177,7 +177,7 @@ class AssetModulesPlugin { return result; }); - compilation.hooks.executeModule.tap( + compilation.hooks.prepareModuleExecution.tap( "AssetModulesPlugin", (options, context) => { const { codeGenerationResult } = options; diff --git a/lib/dependencies/LoaderPlugin.js b/lib/dependencies/LoaderPlugin.js index c0a3de7b35d..9386bb3efb7 100644 --- a/lib/dependencies/LoaderPlugin.js +++ b/lib/dependencies/LoaderPlugin.js @@ -214,6 +214,8 @@ class LoaderPlugin { for (const d of result.buildDependencies) { loaderContext.addBuildDependency(d); } + if (result.cacheable === false) + loaderContext.cacheable(false); for (const [name, { source, info }] of result.assets) { const { buildInfo } = loaderContext._module; if (!buildInfo.assets) { diff --git a/test/hotCases/loader-import-module/css/colors.js b/test/hotCases/loader-import-module/css/colors.js new file mode 100644 index 00000000000..61cfd6f0cbb --- /dev/null +++ b/test/hotCases/loader-import-module/css/colors.js @@ -0,0 +1,5 @@ +export const color = "#f00"; +--- +export const color = "#0f0"; +--- +export const color = "#0f0"; diff --git a/test/hotCases/loader-import-module/css/file.jpg b/test/hotCases/loader-import-module/css/file.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe5c6eefa791be68586c8eb05cd98a25265f15af GIT binary patch literal 6027 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 Cke5#Y literal 0 HcmV?d00001 diff --git a/test/hotCases/loader-import-module/css/file.png b/test/hotCases/loader-import-module/css/file.png new file mode 100644 index 0000000000000000000000000000000000000000..fb53b9dedd3b409ea93b7db98a2c34454bf95fee GIT binary patch literal 14910 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
ci;+pI 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 { + expect(stylesheet).toBe( + 'body { background: url("https://test.cases/path/assets/file.png"); color: #f00; }' + ); + NEXT( + require("../../update")(done, true, stats => { + expect(stylesheet).toBe( + 'body { background: url("https://test.cases/path/assets/file.png"); color: #0f0; }' + ); + NEXT( + require("../../update")(done, true, stats => { + expect(stylesheet).toBe( + 'body { background: url("https://test.cases/path/assets/file.jpg"); color: #0f0; }' + ); + done(); + }) + ); + }) + ); +}); + +if (import.meta.webpackHot) { + import.meta.webpackHot.accept("./stylesheet.css.js"); +} diff --git a/test/hotCases/loader-import-module/css/loader.js b/test/hotCases/loader-import-module/css/loader.js new file mode 100644 index 00000000000..927bbc669c6 --- /dev/null +++ b/test/hotCases/loader-import-module/css/loader.js @@ -0,0 +1,6 @@ +exports.pitch = async function (remaining) { + const result = await this.importModule( + this.resourcePath + ".webpack[javascript/auto]" + "!=!" + remaining + ); + return (result.default || result)(); +}; diff --git a/test/hotCases/loader-import-module/css/stylesheet.css.js b/test/hotCases/loader-import-module/css/stylesheet.css.js new file mode 100644 index 00000000000..dec22b62b3c --- /dev/null +++ b/test/hotCases/loader-import-module/css/stylesheet.css.js @@ -0,0 +1,29 @@ +import { color } from "./colors.js"; +export default () => + `body { background: url("${ + new URL("./file.png", import.meta.url).href + }"); color: ${color}; }`; + +if (import.meta.webpackHot) { + import.meta.webpackHot.accept("./colors.js"); +} +--- +import { color } from "./colors.js"; +export default () => + `body { background: url("${ + new URL("./file.png", import.meta.url).href + }"); color: ${color}; }`; + +if (import.meta.webpackHot) { + import.meta.webpackHot.accept("./colors.js"); +} +--- +import { color } from "./colors.js"; +export default () => + `body { background: url("${ + new URL("./file.jpg", import.meta.url).href + }"); color: ${color}; }`; + +if (import.meta.webpackHot) { + import.meta.webpackHot.accept("./colors.js"); +} diff --git a/test/hotCases/loader-import-module/css/webpack.config.js b/test/hotCases/loader-import-module/css/webpack.config.js new file mode 100644 index 00000000000..d142ebdf35b --- /dev/null +++ b/test/hotCases/loader-import-module/css/webpack.config.js @@ -0,0 +1,39 @@ +/** @type {import("../../../../").Configuration} */ +module.exports = { + module: { + generator: { + asset: { + filename: "assets/[name][ext]" + } + }, + rules: [ + { + test: /\.css\.js$/, + use: "./loader", + type: "asset/source" + } + ] + }, + experiments: { + executeModule: true + }, + plugins: [ + compiler => + compiler.hooks.done.tap("test case", stats => { + const png = stats.compilation.getAsset("assets/file.png"); + const jpg = stats.compilation.getAsset("assets/file.jpg"); + if (png) { + expect(jpg).toBe(undefined); + expect(png).toHaveProperty( + "info", + expect.objectContaining({ sourceFilename: "file.png" }) + ); + } else { + expect(jpg).toHaveProperty( + "info", + expect.objectContaining({ sourceFilename: "file.jpg" }) + ); + } + }) + ] +}; diff --git a/types.d.ts b/types.d.ts index 0f729823ce7..f11a9244d51 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1251,6 +1251,9 @@ declare class Compilation { [(string[] | ReferencedExport)[], Dependency, RuntimeSpec] >; executeModule: SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>; + prepareModuleExecution: AsyncParallelHook< + [ExecuteModuleArgument, ExecuteModuleContext] + >; finishModules: AsyncSeriesHook<[Iterable]>; finishRebuildingModule: AsyncSeriesHook<[Module]>; unseal: SyncHook<[]>; @@ -3137,20 +3140,22 @@ declare class EvalSourceMapDevToolPlugin { } declare interface ExecuteModuleArgument { module: Module; - moduleObject: object; + moduleObject?: { id: string; exports: any; loaded: boolean }; + preparedInfo: any; codeGenerationResult: CodeGenerationResult; } declare interface ExecuteModuleContext { assets: Map; chunk: Chunk; chunkGraph: ChunkGraph; - __webpack_require__: Function; + __webpack_require__?: (arg0: string) => any; } declare interface ExecuteModuleOptions { entryOptions?: EntryOptions; } declare interface ExecuteModuleResult { exports: any; + cacheable: boolean; assets: Map; fileDependencies: LazySet; contextDependencies: LazySet;