dashed-function-cycles.html (8277B)
1 <!DOCTYPE html> 2 <title>Custom Functions: Handling cycles</title> 3 <link rel="help" href="https://drafts.csswg.org/css-mixins-1/#evaluating-custom-functions"> 4 <link rel="help" href="https://drafts.csswg.org/css-values-5/#cyclic-substitution-contexts"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="resources/utils.js"></script> 8 9 <div id=target></div> 10 <div id=main></div> 11 12 <!-- To pass, a test must produce matching computed values for --actual and 13 --expected on #target. --> 14 15 <!-- Locals / Arguments --> 16 17 <template data-name="Local with self-cycle"> 18 <style> 19 @function --f() { 20 --x: var(--x); 21 result: var(--x, PASS); 22 } 23 #target { 24 --actual: --f(); 25 --expected: PASS; 26 } 27 </style> 28 </template> 29 30 <template data-name="Cycle reference without fallback makes result invalid"> 31 <style> 32 @function --f() { 33 --x: var(--x); 34 result: var(--x); 35 } 36 #target { 37 --actual: --f(); 38 /* --expected: <guaranteed-invalid> */ 39 } 40 </style> 41 </template> 42 43 <template data-name="Local with self-cycle in unused fallback"> 44 <style> 45 @function --f() { 46 --y: PASS; 47 --x: var(--y, var(--x)); 48 result: var(--x, FAIL); 49 } 50 #target { 51 --actual: --f(); 52 --expected: PASS; 53 } 54 </style> 55 </template> 56 57 <template data-name="Local shadowing cyclic property --x"> 58 <style> 59 /* The _properties_ --x and --y are in a cycle. 60 However, the _local_ --x is not a cycle with anything. */ 61 @function --f() { 62 --x: var(--y, PASS); 63 result: var(--x); 64 } 65 #target { 66 --x: var(--y); 67 --y: var(--x); 68 --actual: --f(); 69 --expected: PASS; 70 } 71 </style> 72 </template> 73 74 <template data-name="Local shadowing cyclic outer local --x"> 75 <style> 76 /* The locals --x and --y are in a cycle within --f(). */ 77 @function --f() { 78 --x: var(--y); 79 --y: var(--x); 80 result: --g(); 81 } 82 @function --g() { 83 --x: var(--y, PASS); /* Shadows outer --x. */ 84 result: var(--x); 85 } 86 #target { 87 --actual: --f(); 88 --expected: PASS; 89 } 90 </style> 91 </template> 92 93 <template data-name="Argument shadowing cyclic outer local --x"> 94 <style> 95 @function --f() { 96 --x: var(--x); /* Cycle */ 97 result: --g(10px); 98 } 99 @function --g(--x) { 100 result: var(--x); 101 } 102 #target { 103 --actual: --f(); 104 --expected: 10px; 105 } 106 </style> 107 </template> 108 109 <template data-name="Arguments shadowing cyclic properties"> 110 <style> 111 @function --f(--x, --y) { 112 result: var(--x) var(--y); 113 } 114 #target { 115 --x: var(--y); 116 --y: var(--x); 117 --actual: --f(PASS-x, PASS-y); 118 --expected: PASS-x PASS-y; 119 } 120 </style> 121 </template> 122 123 <template data-name="Observing property cycle locally"> 124 <style> 125 @function --f() { 126 result: var(--x, PASS-x) var(--x, PASS-y); 127 } 128 #target { 129 --x: var(--y); 130 --y: var(--x); 131 --actual: --f(); 132 --expected: PASS-x PASS-y; 133 } 134 </style> 135 </template> 136 137 <template data-name="Using cyclic values with no fallback"> 138 <style> 139 @function --f() { 140 --y: var(--x, 1); 141 --x: var(--y, 3); 142 result: var(--x) var(--y); 143 } 144 #target { 145 --actual: --f(); 146 /* --expected: <guaranteed-invalid> */ 147 } 148 </style> 149 </template> 150 151 <template data-name="Self-cycle in non-used local variable"> 152 <style> 153 @function --f() { 154 --x: var(--x); 155 result: PASS; 156 } 157 #target { 158 --actual: --f(); 159 --expected: PASS; 160 } 161 </style> 162 </template> 163 164 <template data-name="Using cyclic value in unused fallback"> 165 <style> 166 @function --f() { 167 --x: PASS; 168 result: var(--x, var(--y)); 169 } 170 #target { 171 --y: var(--y); 172 --actual: --f(); 173 --expected: PASS; 174 } 175 </style> 176 </template> 177 178 <template data-name="Using cyclic value in unused fallback (local)"> 179 <style> 180 @function --f() { 181 --x: PASS; 182 --y: var(--y); 183 result: var(--x, var(--y)); 184 } 185 #target { 186 --actual: --f(); 187 --expected: PASS; 188 } 189 </style> 190 </template> 191 192 <!-- Between <dashed-functions> --> 193 194 <!-- 195 Note that several of these tests call functions via a "--tmp" custom property. 196 This is to be able to trigger a fallback when the function is in a cycle. 197 --> 198 199 <template data-name="Dashed-function, self-cycle"> 200 <style> 201 @function --f() { 202 result: --f(); 203 } 204 #target { 205 --tmp: --f(); 206 --actual: var(--tmp, PASS); 207 --expected: PASS; 208 } 209 </style> 210 </template> 211 212 <template data-name="Cycle through other function (--g)"> 213 <style> 214 @function --f() { 215 result: --g(); 216 } 217 @function --g() { 218 result: --f(); 219 } 220 #target { 221 --tmp: --g(); 222 --actual: var(--tmp, PASS); 223 --expected: PASS; 224 } 225 </style> 226 </template> 227 228 <template data-name="Cycle through other function (--f)"> 229 <style> 230 @function --f() { 231 result: --g(); 232 } 233 @function --g() { 234 result: --f(); 235 } 236 #target { 237 --tmp: --f(); 238 --actual: var(--tmp, PASS); 239 --expected: PASS; 240 } 241 </style> 242 </template> 243 244 <template data-name="Cycle through local, self"> 245 <style> 246 @function --f() { 247 --local: --f(); 248 result: var(--local); 249 } 250 #target { 251 --local: FAIL; 252 --tmp: --f(); 253 --actual: var(--tmp, PASS); 254 --expected: PASS; 255 } 256 </style> 257 </template> 258 259 <template data-name="Cycle through unused local"> 260 <style> 261 @function --f() { 262 --unused: --f(); 263 result: FAIL-result; 264 } 265 #target { 266 --local: FAIL; 267 --tmp: --f(); 268 --actual: var(--tmp, PASS); 269 --expected: PASS; 270 } 271 </style> 272 </template> 273 274 <template data-name="Cycle through global, self"> 275 <style> 276 @function --f() { 277 result: var(--global); 278 } 279 #target { 280 --global: --f(); 281 --tmp: --f(); 282 --actual: var(--tmp, PASS); 283 --expected: PASS; 284 } 285 </style> 286 </template> 287 288 <template data-name="Cycle through local, other function"> 289 <style> 290 @function --f() { 291 result: --g(); 292 } 293 @function --g() { 294 --local: --f(); 295 result: var(--local); 296 } 297 #target { 298 --local: FAIL; 299 --tmp: --g(); 300 --actual: var(--tmp, PASS); 301 --expected: PASS; 302 } 303 </style> 304 </template> 305 306 <template data-name="Cycle through local, other function, fallback in function"> 307 <style> 308 @function --f() { 309 --a: --g(); 310 result: var(--a, PASS); 311 } 312 313 @function --g() { 314 result: var(--a); 315 } 316 #target { 317 --actual: --f(); 318 --expected: PASS; 319 } 320 </style> 321 </template> 322 323 <template data-name="Cycle through various variables and other functions"> 324 <style> 325 @function --f() { 326 --local: --g(); 327 result: var(--local); 328 } 329 @function --g() { 330 --local: FAIL; 331 result: var(--global); 332 } 333 #target { 334 --local: FAIL; 335 --global: --f(); 336 --tmp: --g(); 337 --actual: var(--tmp, PASS); 338 --expected: PASS; 339 } 340 </style> 341 </template> 342 343 <template data-name="Function in a cycle with its own default"> 344 <style> 345 @function --f(--x, --y: --f(13px)) { 346 result: 10px; 347 } 348 #target { 349 --tmp: --f(42px); 350 --actual: var(--tmp, PASS); 351 --expected: PASS; 352 } 353 </style> 354 </template> 355 356 <template data-name="Cyclic defaults"> 357 <style> 358 @function --f(--x, --y: var(--z), --z: var(--y)) { 359 result: var(--x, FAIL) var(--y, PASS-y) var(--z, PASS-z); 360 } 361 #target { 362 --actual: --f(42px); 363 --expected: 42px PASS-y PASS-z; 364 } 365 </style> 366 </template> 367 368 <template data-name="Cyclic outer --b shadows custom property"> 369 <style> 370 @function --f() { 371 --b: var(--b); 372 --a: --g(); 373 result: var(--a); 374 } 375 376 @function --g(--a: var(--b)) { 377 result: var(--a, PASS); 378 } 379 #target { 380 --b: FAIL; 381 --actual: --f(); 382 --expected: PASS; 383 } 384 </style> 385 </template> 386 387 <template data-name="Locals are function specific"> 388 <style> 389 @function --f() { 390 --a: --g(); 391 result: var(--a); 392 } 393 394 @function --g() { 395 --a: 10px; 396 result: var(--a); 397 } 398 #target { 399 /* Nothing is in a cycle here. */ 400 --actual: --f(); 401 --expected: 10px; 402 } 403 </style> 404 </template> 405 406 <script> 407 test_all_templates(); 408 </script>