not-pseudo-containing-complex-in-has.html (27355B)
1 <!DOCTYPE html> 2 <meta charset="utf-8" /> 3 <title>CSS Selectors Invalidation: :not(<complex-selector>) in :has() argument (complex selector)</title> 4 <link rel="author" title="Byungwoo Lee" href="blee@igalia.com"> 5 <link rel="help" href="https://drafts.csswg.org/selectors/#relational"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <style> 9 div { color: grey } 10 .red:has(#descendant:not(.a_has_scope .b)) { color: red } 11 .orangered:has(#descendant:not(.a_descendant .b)) #descendant { color: orangered } 12 .darkred:has(#descendant:not(.a_indirect_next .b)) ~ #indirect_next { color: darkred } 13 .pink:has(#descendant:not(.a_indirect_next_child .b)) ~ #indirect_next #indirect_next_child { color: pink } 14 .green:has(#descendant:not(.p + .c_has_scope ~ .d .e)) { color: green } 15 .lightgreen:has(#descendant:not(.p + .c_descendant ~ .d .e)) #descendant { color: lightgreen } 16 .darkgreen:has(#descendant:not(.p + .c_indirect_next ~ .d .e)) ~ #indirect_next { color: darkgreen } 17 .yellowgreen:has(#descendant:not(.p + .c_indirect_next_child ~ .d .e)) ~ #indirect_next #indirect_next_child { color: yellowgreen } 18 .blue:has(~ #indirect_next:not(.p + .f_has_scope ~ .g)) { color: blue } 19 .skyblue:has(~ #indirect_next:not(.p + .f_descendant ~ .g)) #descendant { color: skyblue } 20 .lightblue:has(~ #indirect_next:not(.p + .f_indirect_next ~ .g)) ~ #indirect_next { color: lightblue } 21 .darkblue:has(~ #indirect_next:not(.p + .f_indirect_next_child ~ .g)) ~ #indirect_next #indirect_next_child { color: darkblue } 22 .yellow:has(~ #indirect_next:not(.h_has_scope .i)) { color: yellow } 23 .ivory:has(~ #indirect_next:not(.h_descendant .i)) #descendant { color: ivory } 24 .greenyellow:has(~ #indirect_next:not(.h_indirect_next .i)) ~ #indirect_next { color: greenyellow } 25 .khaki:has(~ #indirect_next:not(.h_indirect_next_child .i)) ~ #indirect_next #indirect_next_child { color: khaki } 26 .purple:has(~ #indirect_next:not(.p + .j_has_scope ~ .k .l)) { color: purple } 27 .violet:has(~ #indirect_next:not(.p + .j_descendant ~ .k .l)) #descendant { color: violet } 28 .orchid:has(~ #indirect_next:not(.p + .j_indirect_next ~ .k .l)) ~ #indirect_next { color: orchid } 29 .plum:has(~ #indirect_next:not(.p + .j_indirect_next_child ~ .k .l)) ~ #indirect_next #indirect_next_child { color: plum } 30 .orange:has(#descendant:not(.m:not(.n) .o)) { color: orange } 31 </style> 32 <div> 33 <div class="p"></div> 34 <div id="parent_previous"></div> 35 <div id="parent" class="d k"> 36 <div class="p"></div> 37 <div id="previous"></div> 38 <div class="p"></div> 39 <div id="has_scope" class="d"> 40 <div class="p"></div> 41 <div id="child_previous"></div> 42 <div id="child" class="d"> 43 <div id="descendant" class="b e o"></div> 44 </div> 45 </div> 46 <div class="p"></div> 47 <div id="direct_next"></div> 48 <div id="indirect_next" class="g i l"> 49 <div id="indirect_next_child"></div> 50 </div> 51 </div> 52 </div> 53 <script> 54 const grey = "rgb(128, 128, 128)"; 55 const red = "rgb(255, 0, 0)"; 56 const orangered = "rgb(255, 69, 0)"; 57 const darkred = "rgb(139, 0, 0)"; 58 const pink = "rgb(255, 192, 203)"; 59 const green = "rgb(0, 128, 0)"; 60 const lightgreen = "rgb(144, 238, 144)"; 61 const darkgreen = "rgb(0, 100, 0)"; 62 const yellowgreen = "rgb(154, 205, 50)"; 63 const blue = "rgb(0, 0, 255)"; 64 const skyblue = "rgb(135, 206, 235)"; 65 const lightblue = "rgb(173, 216, 230)"; 66 const darkblue = "rgb(0, 0, 139)"; 67 const yellow = "rgb(255, 255, 0)"; 68 const ivory = "rgb(255, 255, 240)"; 69 const greenyellow = "rgb(173, 255, 47)"; 70 const khaki = "rgb(240, 230, 140)"; 71 const purple = "rgb(128, 0, 128)"; 72 const violet = "rgb(238, 130, 238)"; 73 const orchid = "rgb(218, 112, 214)"; 74 const plum = "rgb(221, 160, 221)"; 75 const orange = "rgb(255, 165, 0)"; 76 77 function addClass(element, class_name) { 78 element.classList.add(class_name); 79 } 80 81 function removeClass(element, class_name) { 82 element.classList.remove(class_name); 83 } 84 85 function testClassChange(operation, class_name, element_id, 86 selector, matches_result, 87 subject_id, subject_color) { 88 let element = document.getElementById(element_id); 89 assert_equals(element ? element.id : "", element_id); 90 let subject = document.getElementById(subject_id); 91 assert_equals(subject ? subject.id : "", subject_id); 92 let message_prefix = [ 93 "[", selector, "]", 94 ["#", element.id, ".classList.", 95 (operation == addClass ? "add" : "remove"), 96 "('", class_name, "')"].join(""), 97 ": "].join(" "); 98 operation(element, class_name); 99 test(function() { 100 assert_equals(subject.matches(selector), matches_result); 101 }, message_prefix + "check matches (" + matches_result + ")"); 102 test(function() { 103 assert_equals(getComputedStyle(subject).color, subject_color); 104 }, message_prefix + "check #" + subject_id + " color"); 105 } 106 107 function testSiblingInsertionRemoval(class_name, insert_before_id, selector, 108 subject_id, 109 insertion_matches_result, 110 insertion_subject_color, 111 removal_matches_result, 112 removal_subject_color) { 113 let insert_before = document.getElementById(insert_before_id); 114 assert_equals(insert_before ? insert_before.id : "", insert_before_id); 115 let parent = insert_before.parentElement; 116 let subject = document.getElementById(subject_id); 117 assert_equals(subject ? subject.id : "", subject_id); 118 let message_prefix = [ 119 "[", selector, "]", 120 ["insert/remove .", 121 class_name, " before #", insert_before.id, ")"].join(""), 122 ": "].join(" "); 123 124 let div = document.createElement("div"); 125 div.classList.add(class_name); 126 127 parent.insertBefore(div, insert_before); 128 test(function() { 129 assert_equals(subject.matches(selector), insertion_matches_result); 130 }, message_prefix + "(insertion) check matches (" + 131 insertion_matches_result + ")"); 132 test(function() { 133 assert_equals(getComputedStyle(subject).color, insertion_subject_color); 134 }, message_prefix + "(insertion) check #" + subject_id + " color"); 135 136 div.remove(); 137 test(function() { 138 assert_equals(subject.matches(selector), removal_matches_result); 139 }, message_prefix + "(removal) check matches (" + 140 removal_matches_result + ")"); 141 test(function() { 142 assert_equals(getComputedStyle(subject).color, removal_subject_color); 143 }, message_prefix + "(removal) check #" + subject_id + " color"); 144 } 145 146 assert_equals(getComputedStyle(has_scope).color, grey); 147 148 let selector = ".red:has(#descendant:not(.a_has_scope .b))"; 149 testClassChange(addClass, "red", "has_scope", selector, true, "has_scope", red); 150 testClassChange(addClass, "a_has_scope", "parent", selector, false, "has_scope", grey); 151 testClassChange(removeClass, "a_has_scope", "parent", selector, true, "has_scope", red); 152 testClassChange(addClass, "a_has_scope", "has_scope", selector, false, "has_scope", grey); 153 testClassChange(removeClass, "a_has_scope", "has_scope", selector, true, "has_scope", red); 154 testClassChange(addClass, "a_has_scope", "child", selector, false, "has_scope", grey); 155 testClassChange(removeClass, "a_has_scope", "child", selector, true, "has_scope", red); 156 testClassChange(removeClass, "red", "has_scope", selector, false, "has_scope", grey); 157 158 selector = ".orangered:has(#descendant:not(.a_descendant .b)) #descendant"; 159 testClassChange(addClass, "orangered", "has_scope", selector, true, "descendant", orangered); 160 testClassChange(addClass, "a_descendant", "parent", selector, false, "descendant", grey); 161 testClassChange(removeClass, "a_descendant", "parent", selector, true, "descendant", orangered); 162 testClassChange(addClass, "a_descendant", "has_scope", selector, false, "descendant", grey); 163 testClassChange(removeClass, "a_descendant", "has_scope", selector, true, "descendant", orangered); 164 testClassChange(addClass, "a_descendant", "child", selector, false, "descendant", grey); 165 testClassChange(removeClass, "a_descendant", "child", selector, true, "descendant", orangered); 166 testClassChange(removeClass, "orangered", "has_scope", selector, false, "descendant", grey); 167 168 selector = ".darkred:has(#descendant:not(.a_indirect_next .b)) ~ #indirect_next"; 169 testClassChange(addClass, "darkred", "has_scope", selector, true, "indirect_next", darkred); 170 testClassChange(addClass, "a_indirect_next", "parent", selector, false, "indirect_next", grey); 171 testClassChange(removeClass, "a_indirect_next", "parent", selector, true, "indirect_next", darkred); 172 testClassChange(addClass, "a_indirect_next", "has_scope", selector, false, "indirect_next", grey); 173 testClassChange(removeClass, "a_indirect_next", "has_scope", selector, true, "indirect_next", darkred); 174 testClassChange(addClass, "a_indirect_next", "child", selector, false, "indirect_next", grey); 175 testClassChange(removeClass, "a_indirect_next", "child", selector, true, "indirect_next", darkred); 176 testClassChange(removeClass, "darkred", "has_scope", selector, false, "indirect_next", grey); 177 178 selector = ".pink:has(#descendant:not(.a_indirect_next_child .b)) ~ #indirect_next #indirect_next_child"; 179 testClassChange(addClass, "pink", "has_scope", selector, true, "indirect_next_child", pink); 180 testClassChange(addClass, "a_indirect_next_child", "parent", selector, false, "indirect_next_child", grey); 181 testClassChange(removeClass, "a_indirect_next_child", "parent", selector, true, "indirect_next_child", pink); 182 testClassChange(addClass, "a_indirect_next_child", "has_scope", selector, false, "indirect_next_child", grey); 183 testClassChange(removeClass, "a_indirect_next_child", "has_scope", selector, true, "indirect_next_child", pink); 184 testClassChange(addClass, "a_indirect_next_child", "child", selector, false, "indirect_next_child", grey); 185 testClassChange(removeClass, "a_indirect_next_child", "child", selector, true, "indirect_next_child", pink); 186 testClassChange(removeClass, "pink", "has_scope", selector, false, "indirect_next_child", grey); 187 188 selector = ".green:has(#descendant:not(.p + .c_has_scope ~ .d .e))"; 189 testClassChange(addClass, "green", "has_scope", selector, true, "has_scope", green); 190 testClassChange(addClass, "c_has_scope", "parent_previous", selector, false, "has_scope", grey); 191 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "has_scope", true, green, false, grey); 192 testClassChange(removeClass, "c_has_scope", "parent_previous", selector, true, "has_scope", green); 193 testSiblingInsertionRemoval("c_has_scope", "parent_previous", selector, "has_scope", false, grey, true, green); 194 testClassChange(addClass, "c_has_scope", "previous", selector, false, "has_scope", grey); 195 testSiblingInsertionRemoval("invalid", "previous", selector, "has_scope", true, green, false, grey); 196 testClassChange(removeClass, "c_has_scope", "previous", selector, true, "has_scope", green); 197 testSiblingInsertionRemoval("c_has_scope", "previous", selector, "has_scope", false, grey, true, green); 198 testClassChange(addClass, "c_has_scope", "child_previous", selector, false, "has_scope", grey); 199 testSiblingInsertionRemoval("invalid", "child_previous", selector, "has_scope", true, green, false, grey); 200 testClassChange(removeClass, "c_has_scope", "child_previous", selector, true, "has_scope", green); 201 testSiblingInsertionRemoval("c_has_scope", "child_previous", selector, "has_scope", false, grey, true, green); 202 testClassChange(removeClass, "green", "has_scope", selector, false, "has_scope", grey); 203 204 selector = ".lightgreen:has(#descendant:not(.p + .c_descendant ~ .d .e)) #descendant"; 205 testClassChange(addClass, "lightgreen", "has_scope", selector, true, "descendant", lightgreen); 206 testClassChange(addClass, "c_descendant", "parent_previous", selector, false, "descendant", grey); 207 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "descendant", true, lightgreen, false, grey); 208 testClassChange(removeClass, "c_descendant", "parent_previous", selector, true, "descendant", lightgreen); 209 testSiblingInsertionRemoval("c_descendant", "parent_previous", selector, "descendant", false, grey, true, lightgreen); 210 testClassChange(addClass, "c_descendant", "previous", selector, false, "descendant", grey); 211 testSiblingInsertionRemoval("invalid", "previous", selector, "descendant", true, lightgreen, false, grey); 212 testClassChange(removeClass, "c_descendant", "previous", selector, true, "descendant", lightgreen); 213 testSiblingInsertionRemoval("c_descendant", "previous", selector, "descendant", false, grey, true, lightgreen); 214 testClassChange(addClass, "c_descendant", "child_previous", selector, false, "descendant", grey); 215 testSiblingInsertionRemoval("invalid", "child_previous", selector, "descendant", true, lightgreen, false, grey); 216 testClassChange(removeClass, "c_descendant", "child_previous", selector, true, "descendant", lightgreen); 217 testSiblingInsertionRemoval("c_descendant", "child_previous", selector, "descendant", false, grey, true, lightgreen); 218 testClassChange(removeClass, "lightgreen", "has_scope", selector, false, "descendant", grey); 219 220 selector = ".darkgreen:has(#descendant:not(.p + .c_indirect_next ~ .d .e)) ~ #indirect_next"; 221 testClassChange(addClass, "darkgreen", "has_scope", selector, true, "indirect_next", darkgreen); 222 testClassChange(addClass, "c_indirect_next", "parent_previous", selector, false, "indirect_next", grey); 223 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next", true, darkgreen, false, grey); 224 testClassChange(removeClass, "c_indirect_next", "parent_previous", selector, true, "indirect_next", darkgreen); 225 testSiblingInsertionRemoval("c_indirect_next", "parent_previous", selector, "indirect_next", false, grey, true, darkgreen); 226 testClassChange(addClass, "c_indirect_next", "previous", selector, false, "indirect_next", grey); 227 testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next", true, darkgreen, false, grey); 228 testClassChange(removeClass, "c_indirect_next", "previous", selector, true, "indirect_next", darkgreen); 229 testSiblingInsertionRemoval("c_indirect_next", "previous", selector, "indirect_next", false, grey, true, darkgreen); 230 testClassChange(addClass, "c_indirect_next", "child_previous", selector, false, "indirect_next", grey); 231 testSiblingInsertionRemoval("invalid", "child_previous", selector, "indirect_next", true, darkgreen, false, grey); 232 testClassChange(removeClass, "c_indirect_next", "child_previous", selector, true, "indirect_next", darkgreen); 233 testSiblingInsertionRemoval("c_indirect_next", "child_previous", selector, "indirect_next", false, grey, true, darkgreen); 234 testClassChange(removeClass, "darkgreen", "has_scope", selector, false, "indirect_next", grey); 235 236 selector = ".yellowgreen:has(#descendant:not(.p + .c_indirect_next_child ~ .d .e)) ~ #indirect_next #indirect_next_child"; 237 testClassChange(addClass, "yellowgreen", "has_scope", selector, true, "indirect_next_child", yellowgreen); 238 testClassChange(addClass, "c_indirect_next_child", "parent_previous", selector, false, "indirect_next_child", grey); 239 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next_child", true, yellowgreen, false, grey); 240 testClassChange(removeClass, "c_indirect_next_child", "parent_previous", selector, true, "indirect_next_child", yellowgreen); 241 testSiblingInsertionRemoval("c_indirect_next_child", "parent_previous", selector, "indirect_next_child", false, grey, true, yellowgreen); 242 testClassChange(addClass, "c_indirect_next_child", "previous", selector, false, "indirect_next_child", grey); 243 testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next_child", true, yellowgreen, false, grey); 244 testClassChange(removeClass, "c_indirect_next_child", "previous", selector, true, "indirect_next_child", yellowgreen); 245 testSiblingInsertionRemoval("c_indirect_next_child", "previous", selector, "indirect_next_child", false, grey, true, yellowgreen); 246 testClassChange(addClass, "c_indirect_next_child", "child_previous", selector, false, "indirect_next_child", grey); 247 testSiblingInsertionRemoval("invalid", "child_previous", selector, "indirect_next_child", true, yellowgreen, false, grey); 248 testClassChange(removeClass, "c_indirect_next_child", "child_previous", selector, true, "indirect_next_child", yellowgreen); 249 testSiblingInsertionRemoval("c_indirect_next_child", "child_previous", selector, "indirect_next_child", false, grey, true, yellowgreen); 250 testClassChange(removeClass, "yellowgreen", "has_scope", selector, false, "indirect_next_child", grey); 251 252 selector = ".blue:has(~ #indirect_next:not(.p + .f_has_scope ~ .g))"; 253 testClassChange(addClass, "blue", "has_scope", selector, true, "has_scope", blue); 254 testClassChange(addClass, "f_has_scope", "previous", selector, false, "has_scope", grey); 255 testClassChange(removeClass, "f_has_scope", "previous", selector, true, "has_scope", blue); 256 testSiblingInsertionRemoval("f_has_scope", "previous", selector, "has_scope", false, grey, true, blue); 257 testClassChange(addClass, "f_has_scope", "has_scope", selector, false, "has_scope", grey); 258 testClassChange(removeClass, "f_has_scope", "has_scope", selector, true, "has_scope", blue); 259 testClassChange(addClass, "f_has_scope", "direct_next", selector, false, "has_scope", grey); 260 testClassChange(removeClass, "f_has_scope", "direct_next", selector, true, "has_scope", blue); 261 testSiblingInsertionRemoval("f_has_scope", "direct_next", selector, "has_scope", false, grey, true, blue); 262 testClassChange(removeClass, "blue", "has_scope", selector, false, "has_scope", grey); 263 264 selector = ".skyblue:has(~ #indirect_next:not(.p + .f_descendant ~ .g)) #descendant"; 265 testClassChange(addClass, "skyblue", "has_scope", selector, true, "descendant", skyblue); 266 testClassChange(addClass, "f_descendant", "previous", selector, false, "descendant", grey); 267 testClassChange(removeClass, "f_descendant", "previous", selector, true, "descendant", skyblue); 268 testSiblingInsertionRemoval("f_descendant", "previous", selector, "descendant", false, grey, true, skyblue); 269 testClassChange(addClass, "f_descendant", "has_scope", selector, false, "descendant", grey); 270 testClassChange(removeClass, "f_descendant", "has_scope", selector, true, "descendant", skyblue); 271 testClassChange(addClass, "f_descendant", "direct_next", selector, false, "descendant", grey); 272 testClassChange(removeClass, "f_descendant", "direct_next", selector, true, "descendant", skyblue); 273 testSiblingInsertionRemoval("f_descendant", "direct_next", selector, "descendant", false, grey, true, skyblue); 274 testClassChange(removeClass, "skyblue", "has_scope", selector, false, "descendant", grey); 275 276 selector = ".lightblue:has(~ #indirect_next:not(.p + .f_indirect_next ~ .g)) ~ #indirect_next"; 277 testClassChange(addClass, "lightblue", "has_scope", selector, true, "indirect_next", lightblue); 278 testClassChange(addClass, "f_indirect_next", "previous", selector, false, "indirect_next", grey); 279 testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next", true, lightblue, false, grey); 280 testClassChange(removeClass, "f_indirect_next", "previous", selector, true, "indirect_next", lightblue); 281 testSiblingInsertionRemoval("f_indirect_next", "previous", selector, "indirect_next", false, grey, true, lightblue); 282 testClassChange(addClass, "f_indirect_next", "has_scope", selector, false, "indirect_next", grey); 283 testClassChange(removeClass, "f_indirect_next", "has_scope", selector, true, "indirect_next", lightblue); 284 testClassChange(addClass, "f_indirect_next", "direct_next", selector, false, "indirect_next", grey); 285 testSiblingInsertionRemoval("invalid", "direct_next", selector, "indirect_next", true, lightblue, false, grey); 286 testClassChange(removeClass, "f_indirect_next", "direct_next", selector, true, "indirect_next", lightblue); 287 testSiblingInsertionRemoval("f_indirect_next", "direct_next", selector, "indirect_next", false, grey, true, lightblue); 288 testClassChange(removeClass, "lightblue", "has_scope", selector, false, "indirect_next", grey); 289 290 selector = ".darkblue:has(~ #indirect_next:not(.p + .f_indirect_next_child ~ .g)) ~ #indirect_next #indirect_next_child"; 291 testClassChange(addClass, "darkblue", "has_scope", selector, true, "indirect_next_child", darkblue); 292 testClassChange(addClass, "f_indirect_next_child", "previous", selector, false, "indirect_next_child", grey); 293 testSiblingInsertionRemoval("invalid", "previous", selector, "indirect_next_child", true, darkblue, false, grey); 294 testClassChange(removeClass, "f_indirect_next_child", "previous", selector, true, "indirect_next_child", darkblue); 295 testSiblingInsertionRemoval("f_indirect_next_child", "previous", selector, "indirect_next_child", false, grey, true, darkblue); 296 testClassChange(addClass, "f_indirect_next_child", "has_scope", selector, false, "indirect_next_child", grey); 297 testClassChange(removeClass, "f_indirect_next_child", "has_scope", selector, true, "indirect_next_child", darkblue); 298 testClassChange(addClass, "f_indirect_next_child", "direct_next", selector, false, "indirect_next_child", grey); 299 testSiblingInsertionRemoval("invalid", "direct_next", selector, "indirect_next_child", true, darkblue, false, grey); 300 testClassChange(removeClass, "f_indirect_next_child", "direct_next", selector, true, "indirect_next_child", darkblue); 301 testSiblingInsertionRemoval("f_indirect_next_child", "direct_next", selector, "indirect_next_child", false, grey, true, darkblue); 302 testClassChange(removeClass, "darkblue", "has_scope", selector, false, "indirect_next_child", grey); 303 304 selector = ".yellow:has(~ #indirect_next:not(.h_has_scope .i))" 305 testClassChange(addClass, "yellow", "has_scope", selector, true, "has_scope", yellow); 306 testClassChange(addClass, "h_has_scope", "parent", selector, false, "has_scope", grey); 307 testClassChange(removeClass, "h_has_scope", "parent", selector, true, "has_scope", yellow); 308 testClassChange(removeClass, "yellow", "has_scope", selector, false, "has_scope", grey); 309 310 selector = ".ivory:has(~ #indirect_next:not(.h_descendant .i)) #descendant"; 311 testClassChange(addClass, "ivory", "has_scope", selector, true, "descendant", ivory); 312 testClassChange(addClass, "h_descendant", "parent", selector, false, "descendant", grey); 313 testClassChange(removeClass, "h_descendant", "parent", selector, true, "descendant", ivory); 314 testClassChange(removeClass, "ivory", "has_scope", selector, false, "descendant", grey); 315 316 selector = ".greenyellow:has(~ #indirect_next:not(.h_indirect_next .i)) ~ #indirect_next"; 317 testClassChange(addClass, "greenyellow", "has_scope", selector, true, "indirect_next", greenyellow); 318 testClassChange(addClass, "h_indirect_next", "parent", selector, false, "indirect_next", grey); 319 testClassChange(removeClass, "h_indirect_next", "parent", selector, true, "indirect_next", greenyellow); 320 testClassChange(removeClass, "greenyellow", "has_scope", selector, false, "indirect_next", grey); 321 322 selector = ".khaki:has(~ #indirect_next:not(.h_indirect_next_child .i)) ~ #indirect_next #indirect_next_child"; 323 testClassChange(addClass, "khaki", "has_scope", selector, true, "indirect_next_child", khaki); 324 testClassChange(addClass, "h_indirect_next_child", "parent", selector, false, "indirect_next_child", grey); 325 testClassChange(removeClass, "h_indirect_next_child", "parent", selector, true, "indirect_next_child", khaki); 326 testClassChange(removeClass, "khaki", "has_scope", selector, false, "indirect_next_child", grey); 327 328 selector = ".purple:has(~ #indirect_next:not(.p + .j_has_scope ~ .k .l))" 329 testClassChange(addClass, "purple", "has_scope", selector, true, "has_scope", purple); 330 testClassChange(addClass, "j_has_scope", "parent_previous", selector, false, "has_scope", grey); 331 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "has_scope", true, purple, false, grey); 332 testClassChange(removeClass, "j_has_scope", "parent_previous", selector, true, "has_scope", purple); 333 testSiblingInsertionRemoval("j_has_scope", "parent_previous", selector, "has_scope", false, grey, true, purple); 334 testClassChange(removeClass, "purple", "has_scope", selector, false, "has_scope", grey); 335 336 selector = ".violet:has(~ #indirect_next:not(.p + .j_descendant ~ .k .l)) #descendant"; 337 testClassChange(addClass, "violet", "has_scope", selector, true, "descendant", violet); 338 testClassChange(addClass, "j_descendant", "parent_previous", selector, false, "descendant", grey); 339 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "descendant", true, violet, false, grey); 340 testClassChange(removeClass, "j_descendant", "parent_previous", selector, true, "descendant", violet); 341 testSiblingInsertionRemoval("j_descendant", "parent_previous", selector, "descendant", false, grey, true, violet); 342 testClassChange(removeClass, "violet", "has_scope", selector, false, "descendant", grey); 343 344 selector = ".orchid:has(~ #indirect_next:not(.p + .j_indirect_next ~ .k .l)) ~ #indirect_next"; 345 testClassChange(addClass, "orchid", "has_scope", selector, true, "indirect_next", orchid); 346 testClassChange(addClass, "j_indirect_next", "parent_previous", selector, false, "indirect_next", grey); 347 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next", true, orchid, false, grey); 348 testClassChange(removeClass, "j_indirect_next", "parent_previous", selector, true, "indirect_next", orchid); 349 testSiblingInsertionRemoval("j_indirect_next", "parent_previous", selector, "indirect_next", false, grey, true, orchid); 350 testClassChange(removeClass, "orchid", "has_scope", selector, false, "indirect_next", grey); 351 352 selector = ".plum:has(~ #indirect_next:not(.p + .j_indirect_next_child ~ .k .l)) ~ #indirect_next #indirect_next_child"; 353 testClassChange(addClass, "plum", "has_scope", selector, true, "indirect_next_child", plum); 354 testClassChange(addClass, "j_indirect_next_child", "parent_previous", selector, false, "indirect_next_child", grey); 355 testSiblingInsertionRemoval("invalid", "parent_previous", selector, "indirect_next_child", true, plum, false, grey); 356 testClassChange(removeClass, "j_indirect_next_child", "parent_previous", selector, true, "indirect_next_child", plum); 357 testSiblingInsertionRemoval("j_indirect_next_child", "parent_previous", selector, "indirect_next_child", false, grey, true, plum); 358 testClassChange(removeClass, "plum", "has_scope", selector, false, "indirect_next_child", grey); 359 360 selector = ".orange:has(#descendant:not(.m:not(.n) .o))"; 361 testClassChange(addClass, "orange", "has_scope", selector, true, "has_scope", orange); 362 testClassChange(addClass, "m", "parent", selector, false, "has_scope", grey); 363 testClassChange(addClass, "n", "parent", selector, true, "has_scope", orange); 364 testClassChange(removeClass, "n", "parent", selector, false, "has_scope", grey); 365 testClassChange(removeClass, "m", "parent", selector, true, "has_scope", orange); 366 testClassChange(addClass, "m", "has_scope", selector, false, "has_scope", grey); 367 testClassChange(addClass, "n", "has_scope", selector, true, "has_scope", orange); 368 testClassChange(removeClass, "n", "has_scope", selector, false, "has_scope", grey); 369 testClassChange(removeClass, "m", "has_scope", selector, true, "has_scope", orange); 370 testClassChange(addClass, "m", "child", selector, false, "has_scope", grey); 371 testClassChange(addClass, "n", "child", selector, true, "has_scope", orange); 372 testClassChange(removeClass, "n", "child", selector, false, "has_scope", grey); 373 testClassChange(removeClass, "m", "child", selector, true, "has_scope", orange); 374 testClassChange(removeClass, "orange", "has_scope", selector, false, "has_scope", grey); 375 </script>