Compare commits

...

6 Commits

Author SHA1 Message Date
Le Minh Duc a1d92f3758
Merge 5e51e31eb8 into 3c08fd105c 2025-09-30 16:52:34 -04:00
Kevin Brey 3c08fd105c
fix(warnings): update import.meta warning messages for clarity (#19961)
Github Actions / lint (push) Waiting to run Details
Github Actions / validate-legacy-node (push) Waiting to run Details
Github Actions / benchmark (1/4) (push) Waiting to run Details
Github Actions / benchmark (2/4) (push) Waiting to run Details
Github Actions / benchmark (3/4) (push) Waiting to run Details
Github Actions / benchmark (4/4) (push) Waiting to run Details
Github Actions / basic (push) Waiting to run Details
Github Actions / unit (push) Waiting to run Details
Github Actions / integration (10.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Blocked by required conditions Details
2025-09-30 17:32:35 +03:00
Alexander Akait f508e8b705
chore: pin memfs for old node.js version (#19963) 2025-09-30 17:32:09 +03:00
Alexander Akait 5c11f27b6b
chore(deps): update (#19960)
Github Actions / lint (push) Waiting to run Details
Github Actions / validate-legacy-node (push) Waiting to run Details
Github Actions / benchmark (1/4) (push) Waiting to run Details
Github Actions / benchmark (2/4) (push) Waiting to run Details
Github Actions / benchmark (3/4) (push) Waiting to run Details
Github Actions / benchmark (4/4) (push) Waiting to run Details
Github Actions / basic (push) Waiting to run Details
Github Actions / unit (push) Waiting to run Details
Github Actions / integration (10.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Blocked by required conditions Details
2025-09-30 12:55:30 +03:00
Duc Le 5e51e31eb8
add test 2025-09-15 15:03:04 +07:00
Le Minh Duc 6f3ac96bc1
fix: prevent numeric-only content hashes in filename templates 2025-09-10 15:32:06 +07:00
8 changed files with 590 additions and 354 deletions

View File

@ -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'

View File

@ -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;

View File

@ -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)
)

View File

@ -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",

View File

@ -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");
});
});
});

View File

@ -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\./
]
];

View File

@ -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\./
]
];

762
yarn.lock

File diff suppressed because it is too large Load Diff