mirror of https://github.com/webpack/webpack.git
Compare commits
6 Commits
7ba7bbe7f7
...
a1d92f3758
Author | SHA1 | Date |
---|---|---|
|
a1d92f3758 | |
|
3c08fd105c | |
|
f508e8b705 | |
|
5c11f27b6b | |
|
5e51e31eb8 | |
|
6f3ac96bc1 |
|
@ -214,7 +214,7 @@ jobs:
|
|||
|
||||
# Install old `jest` version and deps for legacy node versions
|
||||
- run: |
|
||||
yarn upgrade jest@^27.5.0 jest-circus@^27.5.0 jest-cli@^27.5.0 jest-diff@^27.5.0 jest-environment-node@^27.5.0 jest-junit@^13.0.0 @types/jest@^27.4.0 pretty-format@^27.0.2 husky@^8.0.3 lint-staged@^13.2.1 cspell@^6.31.1 open-cli@^7.2.0 coffee-loader@^1.0.0 babel-loader@^8.1.0 style-loader@^2.0.0 css-loader@^5.0.1 less-loader@^8.1.1 mini-css-extract-plugin@^1.6.1 nyc@^15.1.0 --ignore-engines
|
||||
yarn upgrade jest@^27.5.0 jest-circus@^27.5.0 jest-cli@^27.5.0 jest-diff@^27.5.0 jest-environment-node@^27.5.0 jest-junit@^13.0.0 @types/jest@^27.4.0 pretty-format@^27.0.2 husky@^8.0.3 lint-staged@^13.2.1 cspell@^6.31.1 open-cli@^7.2.0 coffee-loader@^1.0.0 babel-loader@^8.1.0 style-loader@^2.0.0 css-loader@^5.0.1 less-loader@^8.1.1 mini-css-extract-plugin@^1.6.1 nyc@^15.1.0 memfs@4.14.0 --ignore-engines
|
||||
yarn --frozen-lockfile --ignore-engines
|
||||
if: matrix.node-version == '10.x' || matrix.node-version == '12.x' || matrix.node-version == '14.x'
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ const mime = require("mime-types");
|
|||
const Chunk = require("./Chunk");
|
||||
const Module = require("./Module");
|
||||
const { parseResource } = require("./util/identifier");
|
||||
const nonNumericOnlyHash = require("./util/nonNumericOnlyHash");
|
||||
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
|
||||
|
@ -63,7 +64,7 @@ const hashLength = (replacer, handler, assetInfo, hashName) => {
|
|||
} else {
|
||||
const hash = replacer(match, arg, input);
|
||||
|
||||
result = length ? hash.slice(0, length) : hash;
|
||||
result = length ? nonNumericOnlyHash(hash, length) : hash;
|
||||
}
|
||||
if (assetInfo) {
|
||||
assetInfo.immutable = true;
|
||||
|
|
|
@ -115,7 +115,7 @@ class ImportMetaPlugin {
|
|||
new ModuleDependencyWarning(
|
||||
parser.state.module,
|
||||
new CriticalDependencyWarning(
|
||||
"Accessing import.meta directly is unsupported (only property access or destructuring is supported)"
|
||||
"'import.meta' cannot be used as a standalone expression. For static analysis, its properties must be accessed directly (e.g., 'import.meta.url') or through destructuring."
|
||||
),
|
||||
/** @type {DependencyLocation} */ (metaProperty.loc)
|
||||
)
|
||||
|
|
24
package.json
24
package.json
|
@ -111,16 +111,16 @@
|
|||
"@babel/core": "^7.27.1",
|
||||
"@babel/preset-react": "^7.27.1",
|
||||
"@codspeed/core": "^4.0.1",
|
||||
"@eslint/js": "^9.29.0",
|
||||
"@eslint/markdown": "^7.1.0",
|
||||
"@stylistic/eslint-plugin": "^5.2.2",
|
||||
"@eslint/js": "^9.36.0",
|
||||
"@eslint/markdown": "^7.3.0",
|
||||
"@stylistic/eslint-plugin": "^5.4.0",
|
||||
"@types/glob-to-regexp": "^0.4.4",
|
||||
"@types/graceful-fs": "^4.1.9",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/node": "^24.5.2",
|
||||
"@types/xxhashjs": "^0.2.4",
|
||||
"assemblyscript": "^0.28.5",
|
||||
"assemblyscript": "^0.28.8",
|
||||
"babel-loader": "^10.0.0",
|
||||
"bundle-loader": "^0.5.6",
|
||||
"coffee-loader": "^5.0.0",
|
||||
|
@ -131,13 +131,13 @@
|
|||
"date-fns": "^4.0.0",
|
||||
"es5-ext": "^0.10.53",
|
||||
"es6-promise-polyfill": "^1.2.0",
|
||||
"eslint": "^9.29.0",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-config-prettier": "^10.1.1",
|
||||
"eslint-config-webpack": "^4.5.1",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-jest": "^29.0.1",
|
||||
"eslint-plugin-jsdoc": "^51.2.3",
|
||||
"eslint-plugin-n": "^17.21.0",
|
||||
"eslint-plugin-n": "^17.23.1",
|
||||
"eslint-plugin-prettier": "^5.5.0",
|
||||
"eslint-plugin-unicorn": "^61.0.1",
|
||||
"file-loader": "^6.0.0",
|
||||
|
@ -146,11 +146,11 @@
|
|||
"hash-wasm": "^4.9.0",
|
||||
"husky": "^9.0.11",
|
||||
"istanbul": "^0.4.5",
|
||||
"jest": "^30.1.2",
|
||||
"jest-circus": "^30.1.2",
|
||||
"jest-cli": "^30.1.2",
|
||||
"jest-diff": "^30.1.2",
|
||||
"jest-environment-node": "^30.1.2",
|
||||
"jest": "^30.2.0",
|
||||
"jest-circus": "^30.2.0",
|
||||
"jest-cli": "^30.2.0",
|
||||
"jest-diff": "^30.2.0",
|
||||
"jest-environment-node": "^30.2.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"json5": "^2.1.3",
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
"use strict";
|
||||
|
||||
const TemplatedPathPlugin = require("../lib/TemplatedPathPlugin");
|
||||
|
||||
describe("TemplatedPathPlugin", () => {
|
||||
describe("hash should be non-numeric", () => {
|
||||
// Move capturedPathReplacer to higher scope to be accessible in all describe blocks
|
||||
let capturedPathReplacer;
|
||||
|
||||
// Set up capturedPathReplacer for all tests
|
||||
beforeEach(() => {
|
||||
const mockCompilation = {
|
||||
hooks: {
|
||||
assetPath: {
|
||||
tap: jest.fn((pluginName, pathReplacerFn) => {
|
||||
capturedPathReplacer = pathReplacerFn;
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mockCompiler = {
|
||||
hooks: {
|
||||
compilation: {
|
||||
tap: jest.fn((pluginName, compilationFn) => {
|
||||
compilationFn(mockCompilation);
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Apply the plugin to capture the path replacer function
|
||||
const plugin = new TemplatedPathPlugin();
|
||||
plugin.apply(mockCompiler);
|
||||
});
|
||||
|
||||
it("should prevent numeric-only chunkhash in filename templates", () => {
|
||||
const mockChunk = {
|
||||
id: "test-chunk",
|
||||
name: "test-chunk",
|
||||
renderedHash: "123456789012345678901234567890",
|
||||
hash: "123456789012345678901234567890"
|
||||
};
|
||||
|
||||
const pathData = {
|
||||
chunk: mockChunk,
|
||||
chunkGraph: {},
|
||||
runtime: undefined
|
||||
};
|
||||
|
||||
const result = capturedPathReplacer("[name].[chunkhash:8].js", pathData);
|
||||
|
||||
// Should convert numeric-only hash to include letter prefix
|
||||
expect(result).toBe("test-chunk.b2345678.js");
|
||||
expect(result).toMatch(/^test-chunk\.[a-f]\d{7}\.js$/);
|
||||
expect(result).not.toMatch(/^test-chunk\.\d{8}\.js$/);
|
||||
});
|
||||
|
||||
it("should prevent numeric-only contenthash in filename templates", () => {
|
||||
const mockChunk = {
|
||||
id: "content-chunk",
|
||||
name: "content-chunk",
|
||||
renderedHash: "abc123def456",
|
||||
hash: "abc123def456",
|
||||
contentHash: {
|
||||
javascript: "987654321098765432109876543210"
|
||||
}
|
||||
};
|
||||
|
||||
const pathData = {
|
||||
chunk: mockChunk,
|
||||
contentHashType: "javascript",
|
||||
chunkGraph: {},
|
||||
runtime: undefined
|
||||
};
|
||||
|
||||
const result = capturedPathReplacer(
|
||||
"[name].[contenthash:6].js",
|
||||
pathData
|
||||
);
|
||||
|
||||
// Should convert numeric-only hash to include letter prefix
|
||||
expect(result).toBe("content-chunk.d87654.js");
|
||||
expect(result).toMatch(/^content-chunk\.[a-f]\d{5}\.js$/);
|
||||
expect(result).not.toMatch(/^content-chunk\.\d{6}\.js$/);
|
||||
});
|
||||
|
||||
it("should prevent numeric-only fullhash in filename templates", () => {
|
||||
const pathData = {
|
||||
hash: "111111111111111111111111111111",
|
||||
chunkGraph: {},
|
||||
runtime: undefined
|
||||
};
|
||||
|
||||
const result = capturedPathReplacer("bundle.[fullhash:10].js", pathData);
|
||||
|
||||
// Should convert numeric-only hash to include letter prefix
|
||||
expect(result).toBe("bundle.b111111111.js");
|
||||
expect(result).toMatch(/^bundle\.[a-f]\d{9}\.js$/);
|
||||
expect(result).not.toMatch(/^bundle\.\d{10}\.js$/);
|
||||
});
|
||||
|
||||
it("should preserve alphanumeric hashes unchanged", () => {
|
||||
const mockChunk = {
|
||||
id: "mixed-chunk",
|
||||
name: "mixed-chunk",
|
||||
renderedHash: "abc123def456ghi789jkl012mno345",
|
||||
hash: "abc123def456ghi789jkl012mno345"
|
||||
};
|
||||
|
||||
const pathData = {
|
||||
chunk: mockChunk,
|
||||
chunkGraph: {},
|
||||
runtime: undefined
|
||||
};
|
||||
|
||||
const result = capturedPathReplacer("[name].[chunkhash:8].js", pathData);
|
||||
|
||||
// Should preserve original hash since it contains non-numeric chars
|
||||
expect(result).toBe("mixed-chunk.abc123de.js");
|
||||
});
|
||||
|
||||
it("should handle zero-length hash parameter", () => {
|
||||
const mockChunk = {
|
||||
id: "zero-chunk",
|
||||
name: "zero-chunk",
|
||||
renderedHash: "123456789012345678901234567890",
|
||||
hash: "123456789012345678901234567890"
|
||||
};
|
||||
|
||||
const pathData = {
|
||||
chunk: mockChunk,
|
||||
chunkGraph: {},
|
||||
runtime: undefined
|
||||
};
|
||||
|
||||
const result = capturedPathReplacer("[name].[chunkhash:0].js", pathData);
|
||||
|
||||
// When length is 0, it's treated as falsy and returns the full hash
|
||||
expect(result).toBe("zero-chunk.123456789012345678901234567890.js");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = [[/Critical dependency: Accessing import\.meta/]];
|
||||
module.exports = [
|
||||
[
|
||||
/Critical dependency: 'import\.meta' cannot be used as a standalone expression\. For static analysis, its properties must be accessed directly \(e\.g\., 'import\.meta\.url'\) or through destructuring\./
|
||||
]
|
||||
];
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
module.exports = [
|
||||
[
|
||||
/Accessing import.meta directly is unsupported \(only property access or destructuring is supported\)/
|
||||
/'import\.meta' cannot be used as a standalone expression\. For static analysis, its properties must be accessed directly \(e\.g\., 'import\.meta\.url'\) or through destructuring\./
|
||||
]
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue