@@ -1387,7 +1387,7 @@ Conditional Value Selection: the ''if()'' notation</h3>
13871387
13881388 If a <<style-query>> in |condition| tests the value of a property,
13891389 and a &bs<<;"property", referenced-property-name&bs>> ; [=substitution context=]
1390- would be a [=cyclic substitution context=] ,
1390+ would be [=detect cyclic substitutions|detected=] as a [=cyclic substitution context=] ,
13911391 that query evaluates to false.
13921392
13931393 <div class=example>
@@ -3295,7 +3295,8 @@ Substitution</h3>
32953295 given an optional [=substitution context=] |context|:
32963296
32973297 1. If |context| was provided,
3298- and forms a [=cyclic substitution context=] ,
3298+ [=detect cyclic substitutions=] using |context|.
3299+ If |context| is marked as a [=cyclic substitution context=] ,
32993300 return the [=guaranteed-invalid value=] .
33003301
33013302 2. [=list/For each=] [=arbitrary substitution function=] |func| in |values|
@@ -3309,7 +3310,7 @@ Substitution</h3>
33093310 replace |func| in |values| with the [=guaranteed-invalid value=]
33103311 and [=iteration/continue=] .
33113312
3312- 3. [=CSS/Parse=] |early result| acccording to |func|'s [=argument grammar=] .
3313+ 3. [=CSS/Parse=] |early result| according to |func|'s [=argument grammar=] .
33133314 If this returns failure,
33143315 replace |func| in values with the [=guaranteed-invalid value=]
33153316 and [=iteration/continue=] ;
@@ -3325,7 +3326,12 @@ Substitution</h3>
33253326 replace |func| in |values| with the [=guaranteed-invalid value=] .
33263327 Otherwise, replace |func| in |values| with |result|.
33273328
3328- 3. Return |values|.
3329+ 3. If |context| is marked as a [=cyclic substitution context=] ,
3330+ return the [=guaranteed-invalid value=] .
3331+ <span class=note> Nested [=arbitrary substitution functions=]
3332+ may have marked |context| as [=cyclic substitution context|cyclic=]
3333+ in step 2.</span>
3334+ 4. Return |values|.
33293335 </div>
33303336
33313337 <div algorithm>
@@ -3358,15 +3364,28 @@ Substitution</h3>
33583364 * "attribute", followed by an attribute name
33593365 </div>
33603366
3361- <div algorithm >
3367+ <div>
33623368 As [=substitution=] is recursively invoked
33633369 by nested [=arbitrary substitution functions=] being [=replaced=] ,
33643370 the [=substitution contexts=] passed to each invocation "stack up".
33653371
3366- A <dfn export>cyclic substitution context</dfn>
3367- is a [=substitution context=]
3368- which matches one of the [=substitution contexts=]
3369- established by a [=substitution=] invocation "higher in the stack".
3372+ A [=substitution context=] may be marked
3373+ as a <dfn export>cyclic substitution context</dfn>
3374+ if it's involved in a cycle.
3375+
3376+ <div algorithm>
3377+ To <dfn export>detect cyclic substitutions</dfn> ,
3378+ given a [=substitution context=] |context|:
3379+
3380+ 1. If |context| matches a [=substitution context=] |outer context|
3381+ established by a [=substitution=] invocation "higher in the stack",
3382+ mark |context|,
3383+ |outer context|,
3384+ and any [=substitution context=] in between
3385+ as [=cyclic substitution contexts=] .
3386+ 2. Otherwise,
3387+ do nothing.
3388+ </div>
33703389
33713390 <div class=example>
33723391 For example, given the following style:
@@ -3397,6 +3416,25 @@ Substitution</h3>
33973416 The same happens, in opposite order,
33983417 when performing [=property replacement=] on '--two' .
33993418 </div>
3419+
3420+ <div class=example>
3421+ When a cycle is [=detect cyclic substitutions|detected=] ,
3422+ all participants in the cycle become invalid.
3423+ For example,
3424+ all of the following declarations
3425+ become [=invalid at computed-value time=] .
3426+
3427+ <pre highlight=css>
3428+ .foo {
3429+ --one: var(--two);
3430+ --two: var(--three, baz);
3431+ --three: var(--one);
3432+ }
3433+ </pre>
3434+
3435+ The presence of a fallback in <code> var(--three, baz)</code>
3436+ does not affect the outcome.
3437+ </div>
34003438 </div>
34013439
34023440
0 commit comments