tor-browser

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

has-in-ancestor-position.html (11945B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>CSS Selector Invalidation: :has() in ancestor position</title>
      4 <link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <link rel="help" href="https://drafts.csswg.org/selectors/#relational">
      8 <style>
      9 div, main { color: grey }
     10 div:has(.test) #subject { color: red }
     11 div:has([test_attr]) #subject { color: orangered }
     12 div:has(> .test) #subject { color: green }
     13 div:has(> [test_attr]) #subject { color: lightgreen }
     14 div:has(~ .test) #subject { color: yellow }
     15 div:has(~ [test_attr]) #subject { color: ivory }
     16 div:has(+ .test) #subject { color: blue }
     17 div:has(+ [test_attr]) #subject { color: skyblue }
     18 div:has(~ div .test) #subject { color: purple }
     19 div:has(~ div [test_attr]) #subject { color: violet }
     20 div:has(+ div .test) #subject { color: pink }
     21 div:has(+ div [test_attr]) #subject { color: lightpink }
     22 </style>
     23 
     24 <main id=main>
     25    <div id=subject_ancestor>
     26        <div id=subject_parent>
     27            <div id=subject>
     28                <div id=subject_child>
     29                    <div id=subject_descendant></div>
     30                </div>
     31            </div>
     32        </div>
     33    </div>
     34    <div id=next_sibling>
     35        <div id=next_sibling_child>
     36            <div id=next_sibling_descendant></div>
     37        </div>
     38    </div>
     39 </main>
     40 
     41 <script>
     42 const grey = 'rgb(128, 128, 128)';
     43 const red = 'rgb(255, 0, 0)';
     44 const orangered = 'rgb(255, 69, 0)';
     45 const green = 'rgb(0, 128, 0)';
     46 const lightgreen = 'rgb(144, 238, 144)';
     47 const blue = 'rgb(0, 0, 255)';
     48 const skyblue = 'rgb(135, 206, 235)';
     49 const yellow = 'rgb(255, 255, 0)';
     50 const ivory = 'rgb(255, 255, 240)';
     51 const purple = 'rgb(128, 0, 128)';
     52 const violet = 'rgb(238, 130, 238)';
     53 const pink = 'rgb(255, 192, 203)';
     54 const lightpink = 'rgb(255, 182, 193)';
     55 const colors = {
     56  grey: {
     57    classTest: grey,
     58    attributeTest: grey,
     59  },
     60  red: {
     61    classTest: red,
     62    attributeTest: orangered,
     63  },
     64  green: {
     65    classTest: green,
     66    attributeTest: lightgreen,
     67  },
     68  blue: {
     69    classTest: blue,
     70    attributeTest: skyblue,
     71  },
     72  yellow: {
     73    classTest: yellow,
     74    attributeTest: ivory,
     75  },
     76  purple: {
     77    classTest: purple,
     78    attributeTest: violet,
     79  },
     80  pink: {
     81    classTest: pink,
     82    attributeTest: lightpink,
     83  },
     84 };
     85 
     86 function testColor(test_name, color) {
     87    test(function() {
     88        assert_equals(getComputedStyle(subject).color, color);
     89    }, test_name);
     90 }
     91 
     92 function testClassChange(element, expectedColorName)
     93 {
     94    const expectedColorForClassTest = colors[expectedColorName].classTest;
     95    element.classList.add('test');
     96    testColor(`add .test to ${element.id}`, expectedColorForClassTest);
     97    element.classList.remove('test');
     98    testColor(`remove .test from ${element.id}`, grey);
     99 }
    100 
    101 function testElementInsertionBefore(beforeElement, expectedColorName)
    102 {
    103    const expectedColorForClassTest = colors[expectedColorName].classTest;
    104    const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
    105    const newElement = document.createElement('div');
    106    newElement.classList.add('test')
    107 
    108    beforeElement.before(newElement);
    109    testColor(`insert element div.test before ${beforeElement.id}`, expectedColorForClassTest);
    110 
    111    newElement.classList.remove('test');
    112    testColor(`remove the class 'test' from the element inserted before ${beforeElement.id}`, grey);
    113 
    114    newElement.classList.add('test');
    115    testColor(`add the class 'test' again to the element inserted before ${beforeElement.id}`, expectedColorForClassTest);
    116 
    117    newElement.remove();
    118    testColor(`remove element div.test before ${beforeElement.id}`, grey);
    119 
    120    newElement.classList.remove('test');
    121 
    122    beforeElement.before(newElement);
    123    testColor(`insert element div before ${beforeElement.id}`, grey);
    124 
    125    newElement.classList.add('test');
    126    testColor(`add the class 'test' to the element inserted again before ${beforeElement.id}`, expectedColorForClassTest);
    127 
    128    newElement.classList.remove('test');
    129    testColor(`remove the class 'test' from the element inserted again before ${beforeElement.id}`, grey);
    130 
    131    newElement.remove();
    132    testColor(`remove element div before ${beforeElement.id}`, grey);
    133 
    134    newElement.setAttribute('test_attr', '');
    135 
    136    beforeElement.before(newElement);
    137    testColor(`insert element div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
    138 
    139    newElement.remove();
    140    testColor(`remove element div[test_attr] before ${beforeElement.id}`, grey);
    141 }
    142 
    143 function testElementInsertionAfter(afterElement, expectedColorName)
    144 {
    145    const expectedColorForClassTest = colors[expectedColorName].classTest;
    146    const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
    147    const newElement = document.createElement('div');
    148    newElement.classList.add('test')
    149 
    150    afterElement.after(newElement);
    151    testColor(`insert element div.test after ${afterElement.id}`, expectedColorForClassTest);
    152 
    153    newElement.classList.remove('test');
    154    testColor(`remove the class 'test' from the element inserted after ${afterElement.id}`, grey);
    155 
    156    newElement.classList.add('test');
    157    testColor(`add the class 'test' again to the element inserted after ${afterElement.id}`, expectedColorForClassTest);
    158 
    159    newElement.remove();
    160    testColor(`remove element div.test after ${afterElement.id}`, grey);
    161 
    162    newElement.classList.remove('test');
    163 
    164    afterElement.after(newElement);
    165    testColor(`insert element div after ${afterElement.id}`, grey);
    166 
    167    newElement.classList.add('test');
    168    testColor(`add the class 'test' to the element inserted again after ${afterElement.id}`, expectedColorForClassTest);
    169 
    170    newElement.classList.remove('test');
    171    testColor(`remove the class 'test' from the element inserted again after ${afterElement.id}`, grey);
    172 
    173    newElement.remove();
    174    testColor(`remove element div after ${afterElement.id}`, grey);
    175 
    176    newElement.setAttribute('test_attr', '');
    177 
    178    afterElement.after(newElement);
    179    testColor(`insert element div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
    180 
    181    newElement.remove();
    182    testColor(`remove element div[test_attr] after ${afterElement.id}`, grey);
    183 }
    184 
    185 function testTreeInsertionBefore(beforeElement, expectedColorName)
    186 {
    187    const expectedColorForClassTest = colors[expectedColorName].classTest;
    188    const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
    189    const newElement = document.createElement('div');
    190    const newChild = document.createElement('div');
    191    newChild.classList.add('test');
    192    newElement.appendChild(newChild);
    193 
    194    beforeElement.before(newElement);
    195    testColor(`insert tree div>div.test before ${beforeElement.id}`, expectedColorForClassTest);
    196 
    197    newChild.classList.remove('test');
    198    testColor(`remove the class 'test' from the element in the tree inserted before ${beforeElement.id}`, grey);
    199 
    200    newChild.classList.add('test');
    201    testColor(`add the class 'test' again to the element in the tree inserted before ${beforeElement.id}`, expectedColorForClassTest);
    202 
    203    newElement.remove();
    204    testColor(`remove tree div>div.test before ${beforeElement.id}`, grey);
    205 
    206    newChild.classList.remove('test');
    207 
    208    beforeElement.before(newElement);
    209    testColor(`insert tree div>div before ${beforeElement.id}`, grey);
    210 
    211    newChild.classList.add('test');
    212    testColor(`add the class 'test' to the element in the tree inserted again before ${beforeElement.id}`, expectedColorForClassTest);
    213 
    214    newChild.classList.remove('test');
    215    testColor(`remove the class 'test' from the element in the tree inserted again before ${beforeElement.id}`, grey);
    216 
    217    newElement.remove();
    218    testColor(`remove tree div>div before ${beforeElement.id}`, grey);
    219 
    220    newChild.setAttribute('test_attr', '');
    221 
    222    beforeElement.before(newElement);
    223    testColor(`insert element div>div[test_attr] before ${beforeElement.id}`, expectedColorForAttributeTest);
    224 
    225    newElement.remove();
    226    testColor(`remove element div>div[test_attr] before ${beforeElement.id}`, grey);
    227 }
    228 
    229 function testTreeInsertionAfter(afterElement, expectedColorName)
    230 {
    231    const expectedColorForClassTest = colors[expectedColorName].classTest;
    232    const expectedColorForAttributeTest = colors[expectedColorName].attributeTest;
    233    const newElement = document.createElement('div');
    234    const newChild = document.createElement('div');
    235    newChild.classList.add('test');
    236    newElement.appendChild(newChild);
    237 
    238    afterElement.after(newElement);
    239    testColor(`insert tree div>div.test after ${afterElement.id}`, expectedColorForClassTest);
    240 
    241    newChild.classList.remove('test');
    242    testColor(`remove the class 'test' from the element in the tree inserted after ${afterElement.id}`, grey);
    243 
    244    newChild.classList.add('test');
    245    testColor(`add the class 'test' again to the element in the tree inserted after ${afterElement.id}`, expectedColorForClassTest);
    246 
    247    newElement.remove();
    248    testColor(`remove tree div>div.test after ${afterElement.id}`, grey);
    249 
    250    newChild.classList.remove('test');
    251 
    252    afterElement.after(newElement);
    253    testColor(`insert tree div>div after ${afterElement.id}`, grey);
    254 
    255    newChild.classList.add('test');
    256    testColor(`add the class 'test' to the element in the tree inserted again after ${afterElement.id}`, expectedColorForClassTest);
    257 
    258    newChild.classList.remove('test');
    259    testColor(`remove the class 'test' from the element in the tree inserted again after ${afterElement.id}`, grey);
    260 
    261    newElement.remove();
    262    testColor(`remove tree div>div after ${afterElement.id}`, grey);
    263 
    264    newChild.setAttribute('test_attr', '');
    265 
    266    afterElement.after(newElement);
    267    testColor(`insert element div>div[test_attr] after ${afterElement.id}`, expectedColorForAttributeTest);
    268 
    269    newElement.remove();
    270    testColor(`remove element div>div[test_attr] after ${afterElement.id}`, grey);
    271 }
    272 
    273 testColor('Initial color', grey);
    274 
    275 testClassChange(subject_ancestor, "grey");
    276 testClassChange(subject_parent, "green");
    277 testClassChange(subject, "green");
    278 testClassChange(subject_child, "red");
    279 testClassChange(subject_descendant, "red");
    280 testClassChange(next_sibling, "blue");
    281 testClassChange(next_sibling_child, "pink");
    282 testClassChange(next_sibling_descendant, "pink");
    283 
    284 testElementInsertionBefore(subject_ancestor, "grey");
    285 testElementInsertionBefore(subject_parent, "green");
    286 testElementInsertionBefore(subject, "green");
    287 testElementInsertionBefore(subject_child, "red");
    288 testElementInsertionBefore(subject_descendant, "red");
    289 testElementInsertionBefore(next_sibling, "blue");
    290 testElementInsertionBefore(next_sibling_child, "pink");
    291 testElementInsertionBefore(next_sibling_descendant, "pink");
    292 
    293 testElementInsertionAfter(subject_ancestor, "blue");
    294 testElementInsertionAfter(subject_parent, "blue");
    295 testElementInsertionAfter(subject, "green");
    296 testElementInsertionAfter(subject_child, "red");
    297 testElementInsertionAfter(subject_descendant, "red");
    298 testElementInsertionAfter(next_sibling, "yellow");
    299 testElementInsertionAfter(next_sibling_child, "pink");
    300 testElementInsertionAfter(next_sibling_descendant, "pink");
    301 
    302 testTreeInsertionBefore(subject_ancestor, "grey");
    303 testTreeInsertionBefore(subject_parent, "red");
    304 testTreeInsertionBefore(subject, "red");
    305 testTreeInsertionBefore(subject_child, "red");
    306 testTreeInsertionBefore(subject_descendant, "red");
    307 testTreeInsertionBefore(next_sibling, "pink");
    308 testTreeInsertionBefore(next_sibling_child, "pink");
    309 testTreeInsertionBefore(next_sibling_descendant, "pink");
    310 
    311 testTreeInsertionAfter(subject_ancestor, "pink");
    312 testTreeInsertionAfter(subject_parent, "pink");
    313 testTreeInsertionAfter(subject, "red");
    314 testTreeInsertionAfter(subject_child, "red");
    315 testTreeInsertionAfter(subject_descendant, "red");
    316 testTreeInsertionAfter(next_sibling, "purple");
    317 testTreeInsertionAfter(next_sibling_child, "pink");
    318 testTreeInsertionAfter(next_sibling_descendant, "pink");
    319 
    320 </script>