has-complexity.html (2406B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>CSS Selector Invalidation: :has() invalidation should not be O(n^2)</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 main:has(span) .subject { color: red } 11 main:has(span + span) .subject { color: green } 12 main:has(span + final) .subject { color: blue } 13 main:has(nonexistent + span) .subject { color: black } 14 main:has(span) span { color: black } 15 main:has(nonexistent) span { color: black } 16 main:has(div div span) .subject { color: purple } 17 </style> 18 <main> 19 <div id=container> 20 <span></span> 21 </div> 22 <div id=subject class=subject></div> 23 </main> 24 <script> 25 const grey = 'rgb(128, 128, 128)'; 26 const red = 'rgb(255, 0, 0)'; 27 const green = 'rgb(0, 128, 0)'; 28 const blue = 'rgb(0, 0, 255)'; 29 const purple = 'rgb(128, 0, 128)'; 30 31 function testColor(test_name, color) { 32 test(function() { 33 assert_equals(getComputedStyle(subject).color, color); 34 }, test_name); 35 } 36 37 const count = 25000; 38 39 testColor(`Before appending ${count} elements`, red); 40 41 for (let i = 0; i < count; ++i) { 42 const span = document.createElement("span"); 43 container.appendChild(span); 44 } 45 46 testColor(`After appending ${count} elements. This should not time out.`, green); 47 48 for (let i = 0; i < count - 1; ++i) { 49 const span = document.createElement("span"); 50 container.appendChild(span); 51 } 52 53 const final = document.createElement("final"); 54 container.appendChild(final); 55 56 testColor(`After appending another ${count} elements. This should not time out.`, blue); 57 58 const div = document.createElement("div"); 59 for (let i = 0; i < count; ++i) { 60 const span = document.createElement("span"); 61 div.appendChild(span); 62 } 63 container.appendChild(div); 64 65 testColor(`After appending div with ${count} elements. This should not time out.`, purple); 66 67 div.remove(); 68 69 testColor(`After removing div with ${count} elements. This should not time out.`, blue); 70 71 for (let i = 0; i < count; ++i) 72 container.lastChild.remove(); 73 74 testColor(`After removing ${count} elements one-by-one. This should not time out.`, green); 75 76 container.replaceChildren(); 77 78 testColor(`After removing the remaining elements. This should not time out.`, grey); 79 80 </script>