Skip to content

Commit 3b5565d

Browse files
authored
fix(createTokens): follow a {alias} reached through a segment path (#589)
* fix(createTokens): follow a {alias} reached through a segment path The segment-path branch of resolve() assigned a terminal value to the result without following a trailing {alias}, so a dotted-segment lookup landing on an alias string returned the raw '{alias}' instead of its resolved value. The leaf-value branch already re-resolved terminal aliases; the segment branch now mirrors it, reusing the visited set so circular detection still holds. Surfaces through useTheme, which resolves theme colors through a flat: true token table: a palette entry that is itself an alias, referenced by a theme via a dotted alias, previously produced an unresolved {alias} (dropped by the CSS brace guard, or leaked literally to consumers reading theme.colors directly). Ref #566 (Group A, item #1) * test(createTokens): guard segment-path terminal alias resolution Regression tests for the #566 fix: a {alias} reached through a dotted segment lookup must be followed (single hop and multi-hop chain), and a circular reference reached that way must be detected rather than leaking a raw {alias}. All three fail against the pre-fix segment branch.
1 parent 95d2d34 commit 3b5565d

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@vuetify/v0": patch
3+
---
4+
5+
fix(createTokens): follow a `{alias}` reached through a segment path (#566)
6+
7+
`resolve()` now re-resolves an alias that a dotted-segment lookup lands on, instead of returning the raw `'{alias}'` string. This is visible under `flat: true` (where nested groups are stored whole and addressed by segment), so `useTheme` — which resolves theme colors through a `flat: true` token table — no longer drops or leaks an unresolved `{alias}` for a palette entry that is itself an alias. The leaf-value branch already followed terminal aliases; the segment branch now matches it.

packages/0/src/composables/createTokens/index.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,37 @@ describe('createTokens', () => {
12591259
})
12601260
})
12611261

1262+
describe('segment-path terminal alias (#566)', () => {
1263+
it('should follow a {alias} reached through a segment path', () => {
1264+
const context = createTokens({
1265+
colors: { primary: '#00f' },
1266+
group: { blue: '{colors.primary}' },
1267+
}, { flat: true })
1268+
1269+
expect(context.resolve('{group.blue}')).toBe('#00f')
1270+
})
1271+
1272+
it('should follow a multi-hop chain reached through a segment path', () => {
1273+
const context = createTokens({
1274+
colors: { base: '#0f0', primary: '{colors.base}' },
1275+
group: { blue: '{colors.primary}' },
1276+
}, { flat: true })
1277+
1278+
expect(context.resolve('{group.blue}')).toBe('#0f0')
1279+
})
1280+
1281+
it('should detect a circular reference reached through a segment path', () => {
1282+
const context = createTokens({
1283+
a: { x: '{b.y}' },
1284+
b: { y: '{a.x}' },
1285+
}, { flat: true })
1286+
using warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
1287+
1288+
expect(context.resolve('{a.x}')).toBeUndefined()
1289+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Circular alias detected'))
1290+
})
1291+
})
1292+
12621293
describe('cache behavior', () => {
12631294
it('should cache resolved values', () => {
12641295
const tokens: TokenCollection = {

packages/0/src/composables/createTokens/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ export function createTokens<
248248
return undefined
249249
}
250250

251+
if (isString(current) && isAlias(current)) return resolve(current, visited)
252+
251253
result = current
252254
} else {
253255
if (isTokenAlias(current)) {

0 commit comments

Comments
 (0)