From cb93228ce5d6bf146f4a808b23d54bc6eaa5c55e Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:39:02 +0300 Subject: [PATCH] fix: use `xxhash64` for `cache.hashAlgorithm` when `experiments.futureDefaults` (#19323) --- lib/ChunkGraph.js | 3 +- lib/CodeGenerationResults.js | 3 +- lib/DependencyTemplates.js | 3 +- lib/ExternalModule.js | 8 +- lib/FileSystemInfo.js | 3 +- lib/ModuleFilenameHelpers.js | 5 +- lib/cache/getLazyHashedEtag.js | 5 +- lib/config/defaults.js | 20 ++- lib/ids/HashedModuleIdsPlugin.js | 3 +- lib/optimize/ConcatenatedModule.js | 5 +- lib/serialization/FileMiddleware.js | 5 +- lib/serialization/ObjectMiddleware.js | 3 +- lib/util/serialization.js | 3 +- test/Defaults.unittest.js | 173 ++++++++++++++++++++++++++ 14 files changed, 223 insertions(+), 19 deletions(-) diff --git a/lib/ChunkGraph.js b/lib/ChunkGraph.js index 9e2a0601a..4fc6a9986 100644 --- a/lib/ChunkGraph.js +++ b/lib/ChunkGraph.js @@ -8,6 +8,7 @@ const util = require("util"); const Entrypoint = require("./Entrypoint"); const ModuleGraphConnection = require("./ModuleGraphConnection"); +const { DEFAULTS } = require("./config/defaults"); const { first } = require("./util/SetHelpers"); const SortableSet = require("./util/SortableSet"); const { @@ -245,7 +246,7 @@ class ChunkGraph { * @param {ModuleGraph} moduleGraph the module graph * @param {string | Hash} hashFunction the hash function to use */ - constructor(moduleGraph, hashFunction = "md4") { + constructor(moduleGraph, hashFunction = DEFAULTS.HASH_FUNCTION) { /** * @private * @type {WeakMap} diff --git a/lib/CodeGenerationResults.js b/lib/CodeGenerationResults.js index 551d21259..c2afed9e9 100644 --- a/lib/CodeGenerationResults.js +++ b/lib/CodeGenerationResults.js @@ -5,6 +5,7 @@ "use strict"; +const { DEFAULTS } = require("./config/defaults"); const { getOrInsert } = require("./util/MapHelpers"); const { first } = require("./util/SetHelpers"); const createHash = require("./util/createHash"); @@ -21,7 +22,7 @@ class CodeGenerationResults { /** * @param {string | Hash} hashFunction the hash function to use */ - constructor(hashFunction = "md4") { + constructor(hashFunction = DEFAULTS.HASH_FUNCTION) { /** @type {Map>} */ this.map = new Map(); this._hashFunction = hashFunction; diff --git a/lib/DependencyTemplates.js b/lib/DependencyTemplates.js index c0c09b816..4eeaa0e05 100644 --- a/lib/DependencyTemplates.js +++ b/lib/DependencyTemplates.js @@ -5,6 +5,7 @@ "use strict"; +const { DEFAULTS } = require("./config/defaults"); const createHash = require("./util/createHash"); /** @typedef {import("./Dependency")} Dependency */ @@ -17,7 +18,7 @@ class DependencyTemplates { /** * @param {string | Hash} hashFunction the hash function to use */ - constructor(hashFunction = "md4") { + constructor(hashFunction = DEFAULTS.HASH_FUNCTION) { /** @type {Map} */ this._map = new Map(); /** @type {string} */ diff --git a/lib/ExternalModule.js b/lib/ExternalModule.js index fdb4e20d7..ac6c2711a 100644 --- a/lib/ExternalModule.js +++ b/lib/ExternalModule.js @@ -19,6 +19,7 @@ const { const { JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("./ModuleTypeConstants"); const RuntimeGlobals = require("./RuntimeGlobals"); const Template = require("./Template"); +const { DEFAULTS } = require("./config/defaults"); const StaticExportsDependency = require("./dependencies/StaticExportsDependency"); const createHash = require("./util/createHash"); const extractUrlAndGlobal = require("./util/extractUrlAndGlobal"); @@ -236,7 +237,12 @@ class ModuleExternalInitFragment extends InitFragment { * @param {ImportDependencyMeta=} dependencyMeta the dependency meta * @param {string | HashConstructor=} hashFunction the hash function to use */ - constructor(request, ident, dependencyMeta, hashFunction = "md4") { + constructor( + request, + ident, + dependencyMeta, + hashFunction = DEFAULTS.HASH_FUNCTION + ) { if (ident === undefined) { ident = Template.toIdentifier(request); if (ident !== request) { diff --git a/lib/FileSystemInfo.js b/lib/FileSystemInfo.js index 4808515c1..82bdf9fae 100644 --- a/lib/FileSystemInfo.js +++ b/lib/FileSystemInfo.js @@ -9,6 +9,7 @@ const { create: createResolver } = require("enhanced-resolve"); const nodeModule = require("module"); const asyncLib = require("neo-async"); const { isAbsolute } = require("path"); +const { DEFAULTS } = require("./config/defaults"); const AsyncQueue = require("./util/AsyncQueue"); const StackedCacheMap = require("./util/StackedCacheMap"); const createHash = require("./util/createHash"); @@ -1067,7 +1068,7 @@ class FileSystemInfo { managedPaths = [], immutablePaths = [], logger, - hashFunction = "md4" + hashFunction = DEFAULTS.HASH_FUNCTION } = {} ) { this.fs = fs; diff --git a/lib/ModuleFilenameHelpers.js b/lib/ModuleFilenameHelpers.js index cd5a6c3b7..1a9653794 100644 --- a/lib/ModuleFilenameHelpers.js +++ b/lib/ModuleFilenameHelpers.js @@ -6,6 +6,7 @@ "use strict"; const NormalModule = require("./NormalModule"); +const { DEFAULTS } = require("./config/defaults"); const createHash = require("./util/createHash"); const memoize = require("./util/memoize"); @@ -79,7 +80,7 @@ const getBefore = (strFn, token) => () => { * @returns {ReturnStringCallback} a function that returns the hash of the string */ const getHash = - (strFn, hashFunction = "md4") => + (strFn, hashFunction = DEFAULTS.HASH_FUNCTION) => () => { const hash = createHash(hashFunction); hash.update(strFn()); @@ -126,7 +127,7 @@ ModuleFilenameHelpers.createFilename = ( // eslint-disable-next-line default-param-last module = "", options, - { requestShortener, chunkGraph, hashFunction = "md4" } + { requestShortener, chunkGraph, hashFunction = DEFAULTS.HASH_FUNCTION } ) => { const opts = { namespace: "", diff --git a/lib/cache/getLazyHashedEtag.js b/lib/cache/getLazyHashedEtag.js index 2f651e70f..3007754db 100644 --- a/lib/cache/getLazyHashedEtag.js +++ b/lib/cache/getLazyHashedEtag.js @@ -5,6 +5,7 @@ "use strict"; +const { DEFAULTS } = require("../config/defaults"); const createHash = require("../util/createHash"); /** @typedef {import("../util/Hash")} Hash */ @@ -20,7 +21,7 @@ class LazyHashedEtag { * @param {HashableObject} obj object with updateHash method * @param {string | HashConstructor} hashFunction the hash function to use */ - constructor(obj, hashFunction = "md4") { + constructor(obj, hashFunction = DEFAULTS.HASH_FUNCTION) { this._obj = obj; this._hash = undefined; this._hashFunction = hashFunction; @@ -50,7 +51,7 @@ const mapObjects = new WeakMap(); * @param {(string | HashConstructor)=} hashFunction the hash function to use * @returns {LazyHashedEtag} etag */ -const getter = (obj, hashFunction = "md4") => { +const getter = (obj, hashFunction = DEFAULTS.HASH_FUNCTION) => { let innerMap; if (typeof hashFunction === "string") { innerMap = mapStrings.get(hashFunction); diff --git a/lib/config/defaults.js b/lib/config/defaults.js index e288d6410..321e29295 100644 --- a/lib/config/defaults.js +++ b/lib/config/defaults.js @@ -79,6 +79,10 @@ const { const NODE_MODULES_REGEXP = /[\\/]node_modules[\\/]/i; const DEFAULT_CACHE_NAME = "default"; +const DEFAULTS = { + // TODO webpack 6 - use xxhash64 + HASH_FUNCTION: "md4" +}; /** * Sets a constant default value when undefined @@ -221,6 +225,7 @@ const applyWebpackOptionsDefaults = (options, compilerIndex) => { mode: mode || "production", development, cacheUnaffected: options.experiments.cacheUnaffected, + futureDefaults, compilerIndex }); const cache = Boolean(options.cache); @@ -398,6 +403,7 @@ const applyExperimentsDefaults = ( * @param {object} options options * @param {string} options.name name * @param {Mode} options.mode mode + * @param {boolean} options.futureDefaults is future defaults enabled * @param {boolean} options.development is development mode * @param {number} [options.compilerIndex] index of compiler * @param {Experiments["cacheUnaffected"]} options.cacheUnaffected the cacheUnaffected experiment is enabled @@ -405,7 +411,7 @@ const applyExperimentsDefaults = ( */ const applyCacheDefaults = ( cache, - { name, mode, development, cacheUnaffected, compilerIndex } + { name, mode, development, cacheUnaffected, compilerIndex, futureDefaults } ) => { if (cache === false) return; switch (cache.type) { @@ -448,7 +454,7 @@ const applyCacheDefaults = ( /** @type {NonNullable} */ (cache.name) ) ); - D(cache, "hashAlgorithm", "md4"); + D(cache, "hashAlgorithm", futureDefaults ? "xxhash64" : "md4"); D(cache, "store", "pack"); D(cache, "compression", false); D(cache, "profile", false); @@ -1277,7 +1283,14 @@ const applyOutputDefaults = ( ); D(output, "workerPublicPath", ""); D(output, "chunkLoadTimeout", 120000); - D(output, "hashFunction", futureDefaults ? "xxhash64" : "md4"); + F(output, "hashFunction", () => { + if (futureDefaults) { + DEFAULTS.HASH_FUNCTION = "xxhash64"; + return "xxhash64"; + } + + return "md4"; + }); D(output, "hashDigest", "hex"); D(output, "hashDigestLength", futureDefaults ? 16 : 20); D(output, "strictModuleErrorHandling", false); @@ -1724,3 +1737,4 @@ const applyInfrastructureLoggingDefaults = infrastructureLogging => { module.exports.applyWebpackOptionsBaseDefaults = applyWebpackOptionsBaseDefaults; module.exports.applyWebpackOptionsDefaults = applyWebpackOptionsDefaults; +module.exports.DEFAULTS = DEFAULTS; diff --git a/lib/ids/HashedModuleIdsPlugin.js b/lib/ids/HashedModuleIdsPlugin.js index e3891a469..4d3ac8df6 100644 --- a/lib/ids/HashedModuleIdsPlugin.js +++ b/lib/ids/HashedModuleIdsPlugin.js @@ -5,6 +5,7 @@ "use strict"; +const { DEFAULTS } = require("../config/defaults"); const { compareModulesByPreOrderIndexOrIdentifier } = require("../util/comparators"); @@ -37,7 +38,7 @@ class HashedModuleIdsPlugin { /** @type {HashedModuleIdsPluginOptions} */ this.options = { context: undefined, - hashFunction: "md4", + hashFunction: DEFAULTS.HASH_FUNCTION, hashDigest: "base64", hashDigestLength: 4, ...options diff --git a/lib/optimize/ConcatenatedModule.js b/lib/optimize/ConcatenatedModule.js index 13fbfba99..b9954851b 100644 --- a/lib/optimize/ConcatenatedModule.js +++ b/lib/optimize/ConcatenatedModule.js @@ -20,6 +20,7 @@ const { JS_TYPES } = require("../ModuleSourceTypesConstants"); const { JAVASCRIPT_MODULE_TYPE_ESM } = require("../ModuleTypeConstants"); const RuntimeGlobals = require("../RuntimeGlobals"); const Template = require("../Template"); +const { DEFAULTS } = require("../config/defaults"); const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency"); const JavascriptParser = require("../javascript/JavascriptParser"); const { equals } = require("../util/ArrayHelpers"); @@ -623,7 +624,7 @@ class ConcatenatedModule extends Module { runtime, compilation, associatedObjectForCache, - hashFunction = "md4" + hashFunction = DEFAULTS.HASH_FUNCTION ) { const identifier = ConcatenatedModule._createIdentifier( rootModule, @@ -1049,7 +1050,7 @@ class ConcatenatedModule extends Module { rootModule, modules, associatedObjectForCache, - hashFunction = "md4" + hashFunction = DEFAULTS.HASH_FUNCTION ) { const cachedMakePathsRelative = makePathsRelative.bindContextCache( /** @type {string} */ (rootModule.context), diff --git a/lib/serialization/FileMiddleware.js b/lib/serialization/FileMiddleware.js index be9772866..87e90e2ef 100644 --- a/lib/serialization/FileMiddleware.js +++ b/lib/serialization/FileMiddleware.js @@ -13,6 +13,7 @@ const { createGunzip, constants: zConstants } = require("zlib"); +const { DEFAULTS } = require("../config/defaults"); const createHash = require("../util/createHash"); const { dirname, join, mkdirp } = require("../util/fs"); const memoize = require("../util/memoize"); @@ -107,7 +108,7 @@ const serialize = async ( data, name, writeFile, - hashFunction = "md4" + hashFunction = DEFAULTS.HASH_FUNCTION ) => { /** @type {(Buffer[] | Buffer | Promise)[]} */ const processedData = []; @@ -434,7 +435,7 @@ class FileMiddleware extends SerializerMiddleware { * @param {IntermediateFileSystem} fs filesystem * @param {string | Hash} hashFunction hash function to use */ - constructor(fs, hashFunction = "md4") { + constructor(fs, hashFunction = DEFAULTS.HASH_FUNCTION) { super(); this.fs = fs; this._hashFunction = hashFunction; diff --git a/lib/serialization/ObjectMiddleware.js b/lib/serialization/ObjectMiddleware.js index 8e07b41cb..d4519b040 100644 --- a/lib/serialization/ObjectMiddleware.js +++ b/lib/serialization/ObjectMiddleware.js @@ -4,6 +4,7 @@ "use strict"; +const { DEFAULTS } = require("../config/defaults"); const createHash = require("../util/createHash"); const ArraySerializer = require("./ArraySerializer"); const DateObjectSerializer = require("./DateObjectSerializer"); @@ -204,7 +205,7 @@ class ObjectMiddleware extends SerializerMiddleware { * @param {(context: ObjectSerializerContext | ObjectDeserializerContext) => void} extendContext context extensions * @param {string | Hash} hashFunction hash function to use */ - constructor(extendContext, hashFunction = "md4") { + constructor(extendContext, hashFunction = DEFAULTS.HASH_FUNCTION) { super(); this.extendContext = extendContext; this._hashFunction = hashFunction; diff --git a/lib/util/serialization.js b/lib/util/serialization.js index 99a029263..95211a909 100644 --- a/lib/util/serialization.js +++ b/lib/util/serialization.js @@ -4,6 +4,7 @@ "use strict"; +const { DEFAULTS } = require("../config/defaults"); const memoize = require("./memoize"); /** @typedef {import("../serialization/BinaryMiddleware").MEASURE_END_OPERATION_TYPE} MEASURE_END_OPERATION */ @@ -97,7 +98,7 @@ module.exports = { ); }; } - }, "md4"), + }, DEFAULTS.HASH_FUNCTION), binaryMiddleware ])); }, diff --git a/test/Defaults.unittest.js b/test/Defaults.unittest.js index bf47ab2d5..00c5a7ab0 100644 --- a/test/Defaults.unittest.js +++ b/test/Defaults.unittest.js @@ -1945,6 +1945,179 @@ describe("snapshots", () => { + "cache": true, `) ); + test( + "cache filesystem and futureDefaults", + { cache: { type: "filesystem" }, experiments: { futureDefaults: true } }, + e => + e.toMatchInlineSnapshot(` + - Expected + + Received + + @@ ... @@ + - "cache": false, + + "cache": Object { + + "allowCollectingMemory": false, + + "buildDependencies": Object { + + "defaultWebpack": Array [ + + "/lib/", + + ], + + }, + + "cacheDirectory": "/node_modules/.cache/webpack", + + "cacheLocation": "/node_modules/.cache/webpack/default-none", + + "compression": false, + + "hashAlgorithm": "xxhash64", + + "idleTimeout": 60000, + + "idleTimeoutAfterLargeChanges": 1000, + + "idleTimeoutForInitialStore": 5000, + + "maxAge": 5184000000, + + "maxMemoryGenerations": Infinity, + + "memoryCacheUnaffected": false, + + "name": "default-none", + + "profile": false, + + "readonly": false, + + "store": "pack", + + "type": "filesystem", + + "version": "", + + }, + @@ ... @@ + - "asyncWebAssembly": false, + - "backCompat": true, + + "asyncWebAssembly": true, + + "backCompat": false, + @@ ... @@ + - "cacheUnaffected": false, + - "css": undefined, + - "futureDefaults": false, + + "cacheUnaffected": true, + + "css": true, + + "futureDefaults": true, + @@ ... @@ + + }, + + Object { + + "rules": Array [ + + Object { + + "descriptionData": Object { + + "type": "module", + + }, + + "resolve": Object { + + "fullySpecified": true, + + }, + + }, + + ], + + "test": /\\.wasm$/i, + + "type": "webassembly/async", + + }, + + Object { + + "mimetype": "application/wasm", + + "rules": Array [ + + Object { + + "descriptionData": Object { + + "type": "module", + + }, + + "resolve": Object { + + "fullySpecified": true, + + }, + + }, + + ], + + "type": "webassembly/async", + + }, + + Object { + + "resolve": Object { + + "fullySpecified": true, + + "preferRelative": true, + + }, + + "test": /\\.css$/i, + + "type": "css/auto", + + }, + + Object { + + "mimetype": "text/css+module", + + "resolve": Object { + + "fullySpecified": true, + + "preferRelative": true, + + }, + + "type": "css/module", + + }, + + Object { + + "mimetype": "text/css", + + "resolve": Object { + + "fullySpecified": true, + + "preferRelative": true, + + }, + + "type": "css", + @@ ... @@ + + "css": Object { + + "esModule": true, + + "exportsOnly": false, + + }, + + "css/auto": Object { + + "exportsConvention": "as-is", + + "localIdentName": "[uniqueName]-[id]-[local]", + + }, + + "css/global": Object { + + "exportsConvention": "as-is", + + "localIdentName": "[uniqueName]-[id]-[local]", + + }, + + "css/module": Object { + + "exportsConvention": "as-is", + + "localIdentName": "[uniqueName]-[id]-[local]", + + }, + @@ ... @@ + + }, + @@ ... @@ + + "css": Object { + + "import": true, + + "namedExports": true, + + "url": true, + @@ ... @@ + + "exportsPresence": "error", + @@ ... @@ + - "unsafeCache": false, + + "unsafeCache": [Function anonymous], + @@ ... @@ + - "__dirname": "mock", + - "__filename": "mock", + - "global": true, + + "__dirname": "warn-mock", + + "__filename": "warn-mock", + + "global": "warn", + @@ ... @@ + + "css", + @@ ... @@ + - "charset": true, + + "charset": false, + @@ ... @@ + - "hashDigestLength": 20, + - "hashFunction": "md4", + + "hashDigestLength": 16, + + "hashFunction": "xxhash64", + @@ ... @@ + + "css-import": Object { + + "conditionNames": Array [ + + "webpack", + + "production", + + "style", + + ], + + "extensions": Array [ + + ".css", + + ], + + "mainFields": Array [ + + "style", + + "...", + + ], + + "mainFiles": Array [], + + "preferRelative": true, + + }, + @@ ... @@ + - "cache": false, + + "cache": true, + @@ ... @@ + - "cache": false, + + "cache": true, + @@ ... @@ + - "/node_modules/", + + /^(.+?[\\\\/]node_modules[\\\\/])/, + `) + ); test( "disable",