tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scope-evaluation.html (11521B)


      1 <!DOCTYPE html>
      2 <title>@scope - evaluation</title>
      3 <link rel="help" href="https://drafts.csswg.org/css-cascade-6/#scope-atrule">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script>
      7 
      8 function test_scope(script_element, callback_fn, description) {
      9  test((t) => {
     10    // The provided <script> element must be an immedate subsequent sibling of
     11    // a <template> element.
     12    let template_element = script_element.previousElementSibling;
     13    assert_equals(template_element.tagName, 'TEMPLATE');
     14 
     15    t.add_cleanup(() => main.replaceChildren());
     16 
     17    main.append(template_element.content.cloneNode(true));
     18 
     19    callback_fn();
     20  }, description);
     21 }
     22 
     23 function assert_green(selector) {
     24  assert_equals(getComputedStyle(main.querySelector(selector)).backgroundColor, 'rgb(0, 128, 0)');
     25 }
     26 function assert_not_green(selector) {
     27  assert_equals(getComputedStyle(main.querySelector(selector)).backgroundColor, 'rgb(0, 0, 0)');
     28 }
     29 </script>
     30 <style>
     31  :where(main *) {
     32    background-color: black;
     33  }
     34 </style>
     35 <main id=main>
     36 </main>
     37 
     38 <!-- Tests follow -->
     39 
     40 <template>
     41  <style>
     42    @scope (.a) {
     43      span { background-color: green; }
     44    }
     45  </style>
     46  <div class=a>
     47    <span>green</span>
     48  </div>
     49  <div class=b>
     50    <span>not green</span>
     51  </div>
     52  <span>not green</span>
     53 </template>
     54 <script>
     55 test_scope(document.currentScript, () => {
     56  assert_green('.a > span');
     57  assert_not_green('.b > span');
     58  assert_not_green(':scope > span');
     59 }, 'Single scope');
     60 </script>
     61 
     62 <template>
     63  <style>
     64    @scope (.a) {
     65      .a { background-color: green; }
     66    }
     67  </style>
     68  <div class=a> <!-- green -->
     69    <span>not green</span>
     70  </div>
     71 </template>
     72 <script>
     73 test_scope(document.currentScript, () => {
     74  assert_not_green('.a');
     75  assert_not_green('.a > span');
     76 }, 'Scope can not match its own root without :scope');
     77 </script>
     78 
     79 <template>
     80  <style>
     81    @scope (.a) {
     82      :scope { background-color: green; }
     83    }
     84  </style>
     85  <div class=a> <!-- green -->
     86    <span>not green</span>
     87  </div>
     88 </template>
     89 <script>
     90 test_scope(document.currentScript, () => {
     91  assert_green('.a');
     92  assert_not_green('.a > span');
     93 }, 'Selecting self with :scope');
     94 </script>
     95 
     96 <template>
     97  <style>
     98    @scope (.a) to (.c) {
     99      span { background-color: green; }
    100    }
    101  </style>
    102  <div class=a>
    103    <div class=b>
    104      <span>green</span>
    105    </div>
    106    <div class=c>
    107      <span>not green</span>
    108    </div>
    109  </div>
    110 </template>
    111 <script>
    112 test_scope(document.currentScript, () => {
    113  assert_green('.b > span');
    114  assert_not_green('.c > span');
    115 }, 'Single scope with limit');
    116 </script>
    117 
    118 <template>
    119  <style>
    120    @scope (.a) {
    121      :scope > span { background-color: green; }
    122    }
    123  </style>
    124  <div class=a>
    125    <span>green</span>
    126    <div class=b>
    127      <span>not green</span>
    128    </div>
    129  </div>
    130 </template>
    131 <script>
    132 test_scope(document.currentScript, () => {
    133  assert_green('.a > span');
    134  assert_not_green('.b > span');
    135 }, 'Single scope, :scope pseudo in main selector');
    136 </script>
    137 
    138 <template>
    139  <style>
    140    @scope (.a) to (:scope > .b) {
    141      span { background-color: green; }
    142    }
    143  </style>
    144  <div class=a>
    145    <div class=b>
    146      <span>not green</span>
    147    </div>
    148    <div class=c>
    149      <div class=b>
    150        <span>green</span>
    151      </div>
    152    </div>
    153  </div>
    154 </template>
    155 <script>
    156 test_scope(document.currentScript, () => {
    157  assert_not_green('.a > .b > span');
    158  assert_green('.a > .c > .b > span');
    159 }, 'Single scope, :scope pseudo in to-selector');
    160 </script>
    161 
    162 <template>
    163  <style>
    164    @scope (.a) to (:scope > .b) {
    165      span { background-color: green; }
    166    }
    167  </style>
    168  <div class=a>
    169    <div class=b>
    170      <span>not green</span>
    171    </div>
    172    <div class=a>
    173      <div class=b>
    174        <span>green</span>
    175      </div>
    176    </div>
    177  </div>
    178 </template>
    179 <script>
    180 test_scope(document.currentScript, () => {
    181  assert_not_green('.a > .b > span');
    182  // Note that this span is in the outer .a-scope, but not in the inner scope.
    183  assert_green('.a > .a > .b > span');
    184 }, 'Multiple scopes, :scope pseudo in to-selector');
    185 </script>
    186 
    187 <template>
    188  <style>
    189    @scope (.a) {
    190      @scope (:scope > .b) {
    191        span { background-color: green; }
    192      }
    193    }
    194  </style>
    195  <div class=a>
    196    <div class=b>
    197      <span>green</span>
    198    </div>
    199    <div>
    200      <div class=b>
    201        <span>not green</span>
    202      </div>
    203    </div>
    204  </div>
    205 </template>
    206 <script>
    207 test_scope(document.currentScript, () => {
    208  assert_green('.a > .b > span');
    209  assert_not_green('.a > div > .b > span');
    210 }, 'Inner @scope with :scope in from-selector');
    211 </script>
    212 
    213 <template>
    214  <style>
    215    @scope (.a) to (:scope > .b) {
    216      .c { background-color: green; }
    217    }
    218  </style>
    219  <div class=a>
    220    <div>
    221      <div class=a>
    222        <div class=b>
    223          <div class=c></div>
    224        </div>
    225      </div>
    226    </div>
    227  </div>
    228 </template>
    229 <script>
    230 test_scope(document.currentScript, () => {
    231  // Not in the inner scope, but is in the outer scope.
    232  assert_green('.c');
    233 }, 'Multiple scopes from same @scope-rule, only one limited');
    234 </script>
    235 
    236 <template>
    237  <style>
    238    @scope (.a) to (.b) {
    239      .c { background-color: green; }
    240    }
    241  </style>
    242  <div class=a>
    243    <div>
    244      <div class=a>
    245        <div class=b>
    246          <div class=c></div>
    247        </div>
    248      </div>
    249    </div>
    250  </div>
    251 </template>
    252 <script>
    253 test_scope(document.currentScript, () => {
    254  assert_not_green('.c');
    255 }, 'Multiple scopes from same @scope-rule, both limited');
    256 </script>
    257 
    258 <template>
    259  <style>
    260    @scope (.a) {
    261      @scope (.b) {
    262        span { background-color: green; }
    263      }
    264    }
    265  </style>
    266  <div class=a>
    267    <div class=b>
    268      <span>green</span>
    269    </div>
    270    <span>not green</span>
    271  </div>
    272  <div class=b>
    273    <span>not green</span>
    274  </div>
    275 </template>
    276 <script>
    277 test_scope(document.currentScript, () => {
    278  assert_green('.a > .b > span');
    279  assert_not_green('.a > span');
    280  assert_not_green(':scope > .b > span');
    281 }, 'Nested scopes');
    282 </script>
    283 
    284 <template>
    285  <style>
    286    @scope (.b) {
    287      @scope (.a) {
    288        span { background-color: green; }
    289      }
    290    }
    291  </style>
    292  <div class=a>
    293    <div class=b>
    294      <span>not green</span>
    295    </div>
    296    <span>not green</span>
    297  </div>
    298 </template>
    299 <script>
    300 test_scope(document.currentScript, () => {
    301  assert_not_green('.a > .b > span');
    302  assert_not_green('.a > span');
    303 }, 'Nested scopes, reverse');
    304 </script>
    305 
    306 
    307 <template>
    308  <style>
    309    @scope (.a) {
    310      @scope (.b) to (.c) {
    311        span { background-color: green; }
    312      }
    313    }
    314  </style>
    315  <div class=a>
    316    <div class=b>
    317      <span>green</span>
    318    </div>
    319    <div class=b>
    320      <div class=c>
    321        <span>not green</span>
    322      </div>
    323    </div>
    324    <span>not green</span>
    325  </div>
    326  <div class=b>
    327    <span>not green</span>
    328  </div>
    329 </template>
    330 <script>
    331 test_scope(document.currentScript, () => {
    332  assert_green('.a > .b > span');
    333  assert_not_green('.a > span');
    334  assert_not_green('.a > .b > .c > span');
    335  assert_not_green(':scope > .b > span');
    336 }, 'Nested scopes, with to-selector');
    337 </script>
    338 
    339 <template>
    340  <style>
    341    @scope (.a) {
    342      :scope { background-color: green; }
    343    }
    344  </style>
    345  <div class=a></div>
    346 </template>
    347 <script>
    348 test_scope(document.currentScript, () => {
    349  assert_green('.a');
    350 }, ':scope selecting itself');
    351 </script>
    352 
    353 <template>
    354  <style>
    355    @scope (.a) to (.b) {
    356      * { background-color: green; }
    357    }
    358  </style>
    359  <div id=above>
    360    <div class=a>
    361      <div>
    362        <div class=b>
    363          <div id=below></div>
    364        </div>
    365      </div>
    366    </div>
    367    <div id=adjacent></div>
    368  </div>
    369 </template>
    370 <script>
    371 test_scope(document.currentScript, () => {
    372  assert_not_green('#above');
    373  assert_not_green('#adjacent');
    374  assert_not_green('.a');
    375  assert_green('.a > div');
    376  assert_not_green('.b');
    377  assert_not_green('#below');
    378 }, 'The scoping limit is not in scope');
    379 </script>
    380 
    381 <template>
    382  <style>
    383    @scope (.a) to (.b > *) {
    384      * { background-color: green; }
    385    }
    386  </style>
    387  <div id=above>
    388    <div class=a>
    389      <div>
    390        <div class=b>
    391          <div id=limit></div>
    392        </div>
    393      </div>
    394    </div>
    395    <div id=adjacent></div>
    396  </div>
    397 </template>
    398 <script>
    399 test_scope(document.currentScript, () => {
    400  assert_not_green('#above');
    401  assert_not_green('#adjacent');
    402  assert_not_green('.a');
    403  assert_green('.a > div');
    404  assert_green('.b');
    405  assert_not_green('#limit');
    406 }, 'Simulated inclusive scoping limit');
    407 </script>
    408 
    409 <template>
    410  <style>
    411    @scope (.a) to (:scope) {
    412      * { background-color: green; }
    413    }
    414  </style>
    415  <div id=above>
    416    <div class=a>
    417      <div>
    418        <div class=b>
    419          <div id=inner></div>
    420        </div>
    421      </div>
    422    </div>
    423    <div id=adjacent></div>
    424  </div>
    425 </template>
    426 <script>
    427 test_scope(document.currentScript, () => {
    428  assert_not_green('#above');
    429  assert_not_green('#adjacent');
    430  assert_not_green('.a');
    431  assert_not_green('.a > div');
    432  assert_not_green('.b');
    433  assert_not_green('#inner');
    434 }, 'Scope with no elements');
    435 </script>
    436 
    437 
    438 <template>
    439  <style>
    440    @scope (.a) {
    441      :scope + .c { background-color: green; }
    442    }
    443  </style>
    444  <div class=a>
    445    <div class=a></div>
    446    <div class=c></div>
    447  </div>
    448 </template>
    449 <script>
    450 test_scope(document.currentScript, () => {
    451  // A :scope sibling can never match, as the scoping element must
    452  // be on the ancestor chain.
    453  assert_not_green('.c');
    454 }, ':scope direct adjacent sibling');
    455 </script>
    456 
    457 
    458 <template>
    459  <style>
    460    @scope (.a) {
    461      :scope + .c { background-color: green; }
    462    }
    463  </style>
    464  <div class=a>
    465    <div class=a></div>
    466    <div></div>
    467    <div class=c></div>
    468  </div>
    469 </template>
    470 <script>
    471 test_scope(document.currentScript, () => {
    472  // A :scope sibling can never match, as the scoping element must
    473  // be on the ancestor chain.
    474  assert_not_green('.c');
    475 }, ':scope indirect adjacent sibling');
    476 </script>
    477 
    478 
    479 <template>
    480  <style>
    481    @scope (.a) {
    482      > span { background-color: green; }
    483    }
    484  </style>
    485  <div class=a>
    486    <span>green</span>
    487  </div>
    488 </template>
    489 <script>
    490 test_scope(document.currentScript, () => {
    491  assert_green('.a > span');
    492 }, 'Relative selector inside @scope');
    493 </script>
    494 
    495 
    496 <template>
    497  <style>
    498    @scope (.a) {
    499      /* Can never match anything. */
    500      :scope > :scope { background-color: green; }
    501    }
    502  </style>
    503  <div class=a>
    504    <div id=inner class=a>
    505    </div>
    506  </div>
    507 </template>
    508 <script>
    509 test_scope(document.currentScript, () => {
    510  assert_not_green('.a');
    511  assert_not_green('#inner');
    512 }, ':scope in two different compounds');
    513 </script>
    514 
    515 <template>
    516  <style>
    517    @scope (.a:has(.c)) {
    518      .b { background-color:green; }
    519    }
    520  </style>
    521  <div class=first>
    522    <div class=a>
    523      <div class=b>
    524        <div class=c></div>
    525      </div>
    526    </div>
    527  </div>
    528  <div class=second>
    529    <div class=a>
    530      <div class=b>
    531        <div class=d></div>
    532      </div>
    533    </div>
    534  </div>
    535 </template>
    536 <script>
    537 test_scope(document.currentScript, () => {
    538  assert_not_green('.first .a');
    539  assert_green('.first .b');
    540  assert_not_green('.first .c');
    541 
    542  assert_not_green('.second .a');
    543  assert_not_green('.second .b');
    544  assert_not_green('.second .d');
    545 }, 'Scope root with :has()');
    546 </script>
    547 
    548 <template>
    549  <style>
    550    @scope (.a) to (.b, .c) {
    551      * { background-color:green; }
    552    }
    553  </style>
    554  <div class=a>
    555    <span id="in"></span>
    556    <div class=b>
    557      <span id="out"></span>
    558      <div class=c></div>
    559    </div>
    560  </div>
    561 </template>
    562 <script>
    563 test_scope(document.currentScript, () => {
    564  assert_green('#in');
    565  assert_not_green('#out');
    566 }, 'Any scope limit makes the element out of scope');
    567 </script>