Commit b0dacb1
authored
New hash algorithm (#1920)
* feat: use base-62 full-width hash for atomic class names
Replace the base-36, 4-char-truncated atomic class name hash with a
base-62 encoding of the full 32-bit MurmurHash2 value.
- hashBase62(): new encoder sharing the murmur2 core with hash();
fixed-width, zero-padded, byte-identical to atlaspack's to_base62
- atomicify-rules: group hash 6 chars, value hash 4 chars (11-char classes)
- ax(): extract group key via className.length - 4 (fast fixed-offset slice);
old (9-char) and new (11-char) classes are length-disjoint so they never
falsely deduplicate during migration
- unit tests incl. an atlaspack cross-implementation parity guard
Eliminates the ~93K effective hash space and leading-character bias that
caused class name collisions and silent style drops in large apps.
test: collapse multi-line ax() calls in transform helper
Longer atomic class names (11 chars under the base-62 hash scheme) can push
ax([...]) calls past prettier's default printWidth in the test formatter,
causing them to wrap onto multiple lines. This wrapping is purely a cosmetic
artifact of the test helper — the real emitted code is single-line.
Collapse multi-line ax([...]) calls back to a single line after formatting so
generated-code assertions stay stable regardless of class-name length.
test(keyframes): update fixtures for base-62 class names
test(css-prop): update fixtures for base-62 class names
test(styled): update fixtures for base-62 class names
test(css-map): update fixtures for base-62 class names
test(class-names, xcss-prop): update fixtures for base-62 class names
fix(ac, compress): update group hash length for base-62 6-char groups
ac() and compress-class-names-for-runtime.ts hardcoded the atomic group
hash length as 4 chars (5 with the leading underscore). With the new
base-62 hash, the group is 6 chars (7 with the leading underscore).
- ac.ts: import ATOMIC_GROUP_HASH_LENGTH from @compiled/utils instead of
hardcoding 5; update isCompressed check from charCodeAt(5) to
charCodeAt(ATOMIC_GROUP_LENGTH)
- compress-class-names-for-runtime.ts: import ATOMIC_GROUP_HASH_LENGTH
and use it in slice(1, ATOMIC_GROUP_HASH_LENGTH + 1) instead of
hardcoded slice(1, 5)
- ac.test.ts: update synthetic test data from 4-char (_aaaa) to 6-char
(_aaaaaa) group patterns to match new format
test(babel-plugin): update compress and hash-prefix fixtures for base-62
test(babel-plugin): update remaining __tests__ fixtures for base-62 class names
test(strip-runtime, vite-plugin, react, css): update fixtures for base-62 class names
fix(ac): define ATOMIC_GROUP_HASH_LENGTH locally to avoid @compiled/utils runtime dependency
test(react, vite-plugin): update fixtures for base-62 class names
* feat: add collisionResistantHash option (default false) — dual-mechanism migration flag
- Thread collisionResistantHash through babel-plugin types → transform.ts → atomicify-rules.ts
- atomicClassName branches: false = legacy base-36 9-char (unchanged default), true = base-62 11-char
- Default to collisionResistantHash:true in test helpers (babel-plugin test-utils, strip-runtime
transform.ts, root babel.config.json, css/vite-plugin test helpers) so fixtures document
the new output format while shipped default remains legacy
- Add legacy regression suite to atomicify-rules.test.ts proving default=false emits exact
9-char base-36 names unchanged
- Add collision-resistance test to hash.test.ts proving base-62 eliminates collisions
- Remove atlaspack cross-impl parity assertions (not required for correctness)
- Remove inaccurate '~93K effective hash space' claim (actual bias is more complex)
- Downgrade changeset from major to minor (additive opt-in, no breaking change)
* test(atomicify-rules): add real-world collision regression tests
Documents a confirmed collision pair (scrollbar-width vs text-anchor, group _1fjg)
found in large production CSS bundles. Tests assert:
1. Legacy hash DOES produce group collisions on real CSS properties (the confirmed bug)
2. Base-62 6-char hash eliminates those collisions (the fix)
* test(ax, atomicify-rules): add parity tests and improve variable naming
- ax: add legacy/new format dedup parity tests and cross-format no-dedup test
to document correct behaviour during version-skew window. CLEANUP comments
mark legacy-specific tests for removal when collisionResistantHash defaults to true.
- atomicify-rules: rename cr -> collisionResistant, css -> cssDeclaration for clarity.
Remove redundant third collision test case.
* fix(ac, compress): derive atomic group length dynamically for legacy + new hash backward compat
- ac() now locates the compression separator via indexOf and derives the
uncompressed group via length - value hash, handling both the legacy 4-char
group (9-char class) and the collision-resistant 6-char group (11-char class)
- compress-class-names-for-runtime derives group length from the class instead
of hardcoding it, keeping legacy class-name compression backward compatible
- add legacy-format ac() cases and a dedicated compress helper unit test
- remove migration-artifact comment; tighten vite extraction regex
* test(react): migrate ax/style/perf fixtures to real base-62 class names
* feat(babel-plugin, css): require @compiled/react >=1.0.0 as peer floor for new hash
* docs: document collisionResistantHash option and migration guide1 parent 71cb9b1 commit b0dacb1
49 files changed
Lines changed: 1509 additions & 978 deletions
File tree
- .changeset
- packages
- babel-plugin-strip-runtime/src/__tests__
- babel-plugin
- src
- __tests__
- class-names/__tests__
- css-map/__tests__
- css-prop/__tests__
- keyframes/__tests__
- styled/__tests__
- xcss-prop/__tests__
- css
- src
- __tests__
- plugins
- __tests__
- react/src
- __tests__
- runtime/__tests__
- utils/src
- __tests__
- vite-plugin/src/__tests__
- website/packages/docs/src/pages
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
Lines changed: 15 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | | - | |
| 50 | + | |
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
59 | | - | |
| 59 | + | |
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
111 | | - | |
| 111 | + | |
112 | 112 | | |
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
119 | | - | |
| 119 | + | |
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
| |||
156 | 156 | | |
157 | 157 | | |
158 | 158 | | |
159 | | - | |
160 | | - | |
| 159 | + | |
| 160 | + | |
161 | 161 | | |
162 | 162 | | |
163 | 163 | | |
| |||
168 | 168 | | |
169 | 169 | | |
170 | 170 | | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
| |||
208 | 208 | | |
209 | 209 | | |
210 | 210 | | |
211 | | - | |
| 211 | + | |
212 | 212 | | |
213 | 213 | | |
214 | 214 | | |
| |||
346 | 346 | | |
347 | 347 | | |
348 | 348 | | |
349 | | - | |
| 349 | + | |
350 | 350 | | |
351 | 351 | | |
352 | 352 | | |
353 | 353 | | |
354 | | - | |
| 354 | + | |
355 | 355 | | |
356 | 356 | | |
357 | 357 | | |
| |||
Lines changed: 16 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
52 | | - | |
| 51 | + | |
| 52 | + | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
| 78 | + | |
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
| 97 | + | |
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
113 | | - | |
114 | | - | |
| 113 | + | |
| 114 | + | |
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
| |||
137 | 137 | | |
138 | 138 | | |
139 | 139 | | |
140 | | - | |
| 140 | + | |
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
| |||
157 | 157 | | |
158 | 158 | | |
159 | 159 | | |
160 | | - | |
| 160 | + | |
161 | 161 | | |
162 | 162 | | |
163 | 163 | | |
| |||
173 | 173 | | |
174 | 174 | | |
175 | 175 | | |
176 | | - | |
177 | | - | |
| 176 | + | |
| 177 | + | |
178 | 178 | | |
179 | 179 | | |
180 | 180 | | |
| |||
202 | 202 | | |
203 | 203 | | |
204 | 204 | | |
205 | | - | |
| 205 | + | |
206 | 206 | | |
207 | 207 | | |
208 | 208 | | |
| |||
222 | 222 | | |
223 | 223 | | |
224 | 224 | | |
225 | | - | |
| 225 | + | |
226 | 226 | | |
227 | 227 | | |
228 | 228 | | |
| |||
239 | 239 | | |
240 | 240 | | |
241 | 241 | | |
242 | | - | |
243 | | - | |
| 242 | + | |
| 243 | + | |
244 | 244 | | |
245 | 245 | | |
246 | 246 | | |
| |||
268 | 268 | | |
269 | 269 | | |
270 | 270 | | |
271 | | - | |
| 271 | + | |
272 | 272 | | |
273 | 273 | | |
274 | 274 | | |
| |||
Lines changed: 9 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
80 | | - | |
| 79 | + | |
| 80 | + | |
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
100 | | - | |
| 100 | + | |
101 | 101 | | |
102 | 102 | | |
103 | 103 | | |
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | | - | |
| 117 | + | |
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
| |||
129 | 129 | | |
130 | 130 | | |
131 | 131 | | |
132 | | - | |
133 | | - | |
| 132 | + | |
| 133 | + | |
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
| |||
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
155 | | - | |
| 155 | + | |
156 | 156 | | |
157 | 157 | | |
158 | 158 | | |
| |||
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
174 | | - | |
| 174 | + | |
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
| |||
Lines changed: 12 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
32 | | - | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
33 | 44 | | |
34 | 45 | | |
35 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
46 | 49 | | |
47 | 50 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
112 | | - | |
| 112 | + | |
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
134 | | - | |
135 | | - | |
| 134 | + | |
| 135 | + | |
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
142 | | - | |
| 142 | + | |
143 | 143 | | |
144 | 144 | | |
145 | 145 | | |
| |||
0 commit comments