Skip to content

Commit c7db752

Browse files
authored
feat: generate more collision resistant for locals
1 parent a56bd94 commit c7db752

6 files changed

+2008
-1792
lines changed

src/utils.js

+22-13
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ function defaultGetLocalIdent(
319319
) {
320320
let relativeMatchResource = "";
321321

322-
const { context } = options;
322+
const { context, hashSalt } = options;
323323
const { resourcePath } = loaderContext;
324324

325325
// eslint-disable-next-line no-underscore-dangle
@@ -359,21 +359,30 @@ function defaultGetLocalIdent(
359359
);
360360
}
361361

362-
// eslint-disable-next-line no-underscore-dangle
363-
const hash = loaderContext._compiler.webpack.util.createHash(hashFunction);
364-
const { hashSalt } = options;
362+
let localIdentHash = "";
363+
for (let tier = 0; localIdentHash.length < hashDigestLength; tier++) {
364+
// eslint-disable-next-line no-underscore-dangle
365+
const hash = loaderContext._compiler.webpack.util.createHash(hashFunction);
365366

366-
if (hashSalt) {
367-
hash.update(hashSalt);
368-
}
367+
if (hashSalt) {
368+
hash.update(hashSalt);
369+
}
370+
371+
const tierSalt = Buffer.allocUnsafe(4);
372+
tierSalt.writeUInt32LE(tier);
373+
hash.update(tierSalt);
369374

370-
hash.update(options.content);
375+
hash.update(options.content);
371376

372-
const localIdentHash = hash
373-
.digest(hashDigest)
374-
.slice(0, hashDigestLength)
375-
.replace(/[/+]/g, "_")
376-
.replace(/^\d/g, "_");
377+
localIdentHash = (localIdentHash + hash.digest(hashDigest))
378+
// Remove all leading digits
379+
.replace(/^\d+/, "")
380+
// Replace all slashes with underscores (same as in base64url)
381+
.replace(/\//g, "_")
382+
// Remove everything that is not an alphanumeric or underscore
383+
.replace(/[^A-Za-z0-9_]+/g, "")
384+
.slice(0, hashDigestLength);
385+
}
377386

378387
// TODO need improve on webpack side, we should allow to pass hash/contentHash without chunk property, also `data` for `getPath` should be looks good without chunk property
379388
const ext = path.extname(resourcePath);

test/__snapshots__/esModule-option.test.js.snap

+8-8
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,10 @@ var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_S
155155
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
156156
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
157157
// Module
158-
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.Yz6vxyapD7cLc0x63wym {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
158+
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.OZJqogC5EaF_wROug7zE {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
159159
// Exports
160160
___CSS_LOADER_EXPORT___.locals = {
161-
\\"class\\": \\"Yz6vxyapD7cLc0x63wym\\"
161+
\\"class\\": \\"OZJqogC5EaF_wROug7zE\\"
162162
};
163163
export default ___CSS_LOADER_EXPORT___;
164164
"
@@ -168,7 +168,7 @@ exports[`"esModule" option should work with a value equal to "true" and the "mod
168168
Array [
169169
Array [
170170
"../../src/index.js??ruleSet[1].rules[0].use[0]!./es-module/imported.css",
171-
".rJenlm2lw3fBBPGxPidc {
171+
".EB7DBFwH4lzwZcKIj2OA {
172172
color: red;
173173
}
174174
",
@@ -180,7 +180,7 @@ Array [
180180
181181
/* Comment */
182182
183-
.Yz6vxyapD7cLc0x63wym {
183+
.OZJqogC5EaF_wROug7zE {
184184
color: red;
185185
background: url(replaced_file_protocol_/webpack/public/path/img.png);
186186
}
@@ -205,10 +205,10 @@ var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_S
205205
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
206206
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
207207
// Module
208-
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.Yz6vxyapD7cLc0x63wym {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
208+
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.OZJqogC5EaF_wROug7zE {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
209209
// Exports
210210
___CSS_LOADER_EXPORT___.locals = {
211-
\\"class\\": \\"Yz6vxyapD7cLc0x63wym\\"
211+
\\"class\\": \\"OZJqogC5EaF_wROug7zE\\"
212212
};
213213
export default ___CSS_LOADER_EXPORT___;
214214
"
@@ -218,7 +218,7 @@ exports[`"esModule" option should work with a value equal to "true" and the "mod
218218
Array [
219219
Array [
220220
"../../src/index.js??ruleSet[1].rules[0].use[0]!./es-module/imported.css",
221-
".rJenlm2lw3fBBPGxPidc {
221+
".EB7DBFwH4lzwZcKIj2OA {
222222
color: red;
223223
}
224224
",
@@ -230,7 +230,7 @@ Array [
230230
231231
/* Comment */
232232
233-
.Yz6vxyapD7cLc0x63wym {
233+
.OZJqogC5EaF_wROug7zE {
234234
color: red;
235235
background: url(replaced_file_protocol_/webpack/public/path/img.png);
236236
}

0 commit comments

Comments
 (0)