Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <head> |
michael@0 | 4 | <title>Test for CSS Selectors</title> |
michael@0 | 5 | <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 6 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
michael@0 | 7 | </head> |
michael@0 | 8 | <body onload="run()"> |
michael@0 | 9 | <p id="display"><iframe id="iframe" src="about:blank"></iframe><iframe id="cloneiframe" src="about:blank"></iframe></p> |
michael@0 | 10 | <pre id="test"> |
michael@0 | 11 | <script class="testbody" type="text/javascript"> |
michael@0 | 12 | |
michael@0 | 13 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 14 | |
michael@0 | 15 | var cloneiframe; |
michael@0 | 16 | |
michael@0 | 17 | function run() { |
michael@0 | 18 | |
michael@0 | 19 | var iframe = document.getElementById("iframe"); |
michael@0 | 20 | var ifwin = iframe.contentWindow; |
michael@0 | 21 | var ifdoc = iframe.contentDocument; |
michael@0 | 22 | |
michael@0 | 23 | cloneiframe = document.getElementById("cloneiframe"); |
michael@0 | 24 | |
michael@0 | 25 | var style_elem = ifdoc.createElement("style"); |
michael@0 | 26 | style_elem.setAttribute("type", "text/css"); |
michael@0 | 27 | ifdoc.getElementsByTagName("head")[0].appendChild(style_elem); |
michael@0 | 28 | var style_text = ifdoc.createTextNode(""); |
michael@0 | 29 | style_elem.appendChild(style_text); |
michael@0 | 30 | |
michael@0 | 31 | var gCounter = 0; |
michael@0 | 32 | |
michael@0 | 33 | /* |
michael@0 | 34 | * selector: the selector to test |
michael@0 | 35 | * body_contents: what to set the body's innerHTML to |
michael@0 | 36 | * match_fn: a function that, given the document object into which |
michael@0 | 37 | * body_contents has been inserted, produces an array of nodes that |
michael@0 | 38 | * should match selector |
michael@0 | 39 | * notmatch_fn: likewise, but for nodes that should not match |
michael@0 | 40 | * namespaces (optional): @namespace rules to be included in the sheet |
michael@0 | 41 | */ |
michael@0 | 42 | function test_selector_in_html(selector, body_contents, match_fn, notmatch_fn, namespaces) |
michael@0 | 43 | { |
michael@0 | 44 | var zi = ++gCounter; |
michael@0 | 45 | if (typeof(body_contents) == "string") { |
michael@0 | 46 | ifdoc.body.innerHTML = body_contents; |
michael@0 | 47 | } else { |
michael@0 | 48 | // It's a function. |
michael@0 | 49 | ifdoc.body.innerHTML = ""; |
michael@0 | 50 | body_contents(ifdoc.body); |
michael@0 | 51 | } |
michael@0 | 52 | if (!namespaces) { |
michael@0 | 53 | namespaces = ""; |
michael@0 | 54 | } |
michael@0 | 55 | style_text.data = namespaces + selector + "{ z-index: " + zi + " }"; |
michael@0 | 56 | |
michael@0 | 57 | var idx = style_text.parentNode.sheet.cssRules.length - 1; |
michael@0 | 58 | if (namespaces == "") { |
michael@0 | 59 | is(idx, 0, "unexpected rule index"); |
michael@0 | 60 | } |
michael@0 | 61 | if (idx < 0 || |
michael@0 | 62 | style_text.parentNode.sheet.cssRules[idx].type != |
michael@0 | 63 | CSSRule.STYLE_RULE) |
michael@0 | 64 | { |
michael@0 | 65 | ok(false, "selector " + selector + " could not be parsed"); |
michael@0 | 66 | return; |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | var should_match = match_fn(ifdoc); |
michael@0 | 70 | var should_not_match = notmatch_fn(ifdoc); |
michael@0 | 71 | if (should_match.length + should_not_match.length == 0) { |
michael@0 | 72 | ok(false, "nothing to check"); |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | for (var i = 0; i < should_match.length; ++i) { |
michael@0 | 76 | var e = should_match[i]; |
michael@0 | 77 | is(ifwin.getComputedStyle(e, "").zIndex, zi, |
michael@0 | 78 | "element in " + body_contents + " matched " + selector); |
michael@0 | 79 | } |
michael@0 | 80 | for (var i = 0; i < should_not_match.length; ++i) { |
michael@0 | 81 | var e = should_not_match[i]; |
michael@0 | 82 | is(ifwin.getComputedStyle(e, "").zIndex, "auto", |
michael@0 | 83 | "element in " + body_contents + " did not match " + selector); |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | // Now, since we're here, may as well make sure serialization |
michael@0 | 87 | // works correctly. It need not produce the exact same text, |
michael@0 | 88 | // but it should produce a selector that matches the same |
michael@0 | 89 | // elements. |
michael@0 | 90 | zi = ++gCounter; |
michael@0 | 91 | var ser1 = style_text.parentNode.sheet.cssRules[idx].selectorText; |
michael@0 | 92 | style_text.data = namespaces + ser1 + "{ z-index: " + zi + " }"; |
michael@0 | 93 | for (var i = 0; i < should_match.length; ++i) { |
michael@0 | 94 | var e = should_match[i]; |
michael@0 | 95 | is(ifwin.getComputedStyle(e, "").zIndex, zi, |
michael@0 | 96 | "element in " + body_contents + " matched " + ser1 + |
michael@0 | 97 | " which is the reserialization of " + selector); |
michael@0 | 98 | } |
michael@0 | 99 | for (var i = 0; i < should_not_match.length; ++i) { |
michael@0 | 100 | var e = should_not_match[i]; |
michael@0 | 101 | is(ifwin.getComputedStyle(e, "").zIndex, "auto", |
michael@0 | 102 | "element in " + body_contents + " did not match " + ser1 + |
michael@0 | 103 | " which is the reserialization of " + selector); |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | // But when we serialize the serialized result, we should get |
michael@0 | 107 | // the same text. |
michael@0 | 108 | var ser2 = style_text.parentNode.sheet.cssRules[idx].selectorText; |
michael@0 | 109 | is(ser2, ser1, "parse+serialize of selector \"" + selector + |
michael@0 | 110 | "\" is idempotent"); |
michael@0 | 111 | |
michael@0 | 112 | ifdoc.body.innerHTML = ""; |
michael@0 | 113 | style_text.data = ""; |
michael@0 | 114 | |
michael@0 | 115 | // And now test that when we clone the style sheet, we end up |
michael@0 | 116 | // with the same selector (serializes to same string, and |
michael@0 | 117 | // matches the same things). |
michael@0 | 118 | zi = ++gCounter; |
michael@0 | 119 | var style_sheet = "data:text/css," + |
michael@0 | 120 | escape(namespaces + selector + "{ z-index: " + zi + " }"); |
michael@0 | 121 | var style_sheet_link = |
michael@0 | 122 | "<link rel='stylesheet' href='" + style_sheet + "'>"; |
michael@0 | 123 | var html_doc = "<!DOCTYPE HTML>" + |
michael@0 | 124 | style_sheet_link + style_sheet_link + |
michael@0 | 125 | "<body>"; |
michael@0 | 126 | if (typeof(body_contents) == "string") { |
michael@0 | 127 | html_doc += body_contents; |
michael@0 | 128 | } |
michael@0 | 129 | var docurl = "data:text/html," + escape(html_doc); |
michael@0 | 130 | defer_clonedoc_tests(docurl, function() { |
michael@0 | 131 | var clonedoc = cloneiframe.contentDocument; |
michael@0 | 132 | var clonewin = cloneiframe.contentWindow; |
michael@0 | 133 | |
michael@0 | 134 | if (typeof(body_contents) != "string") { |
michael@0 | 135 | body_contents(clonedoc.body); |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | var links = clonedoc.getElementsByTagName("link"); |
michael@0 | 139 | // cause a clone |
michael@0 | 140 | links[1].sheet.insertRule("#nonexistent { color: purple}", idx + 1); |
michael@0 | 141 | // remove the uncloned sheet |
michael@0 | 142 | links[0].parentNode.removeChild(links[0]); |
michael@0 | 143 | |
michael@0 | 144 | var should_match = match_fn(clonedoc); |
michael@0 | 145 | var should_not_match = notmatch_fn(clonedoc); |
michael@0 | 146 | |
michael@0 | 147 | if (should_match.length + should_not_match.length == 0) { |
michael@0 | 148 | ok(false, "nothing to check"); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | for (var i = 0; i < should_match.length; ++i) { |
michael@0 | 152 | var e = should_match[i]; |
michael@0 | 153 | is(clonewin.getComputedStyle(e, "").zIndex, zi, |
michael@0 | 154 | "element in " + body_contents + " matched clone of " + |
michael@0 | 155 | selector); |
michael@0 | 156 | } |
michael@0 | 157 | for (var i = 0; i < should_not_match.length; ++i) { |
michael@0 | 158 | var e = should_not_match[i]; |
michael@0 | 159 | is(clonewin.getComputedStyle(e, "").zIndex, "auto", |
michael@0 | 160 | "element in " + body_contents + " did not match clone of " + |
michael@0 | 161 | selector); |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | var ser3 = links[0].sheet.cssRules[idx].selectorText; |
michael@0 | 165 | is(ser3, ser1, |
michael@0 | 166 | "selector " + selector + " serializes correctly after cloning"); |
michael@0 | 167 | }); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | function should_serialize_to(selector, serialization) |
michael@0 | 171 | { |
michael@0 | 172 | style_text.data = selector + "{ z-index: 0 }"; |
michael@0 | 173 | is(style_text.parentNode.sheet.cssRules[0].selectorText, |
michael@0 | 174 | serialization, |
michael@0 | 175 | "selector '" + selector + "' should serialize to '" + |
michael@0 | 176 | serialization + "'."); |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | function test_parseable(selector) |
michael@0 | 180 | { |
michael@0 | 181 | ifdoc.body.innerHTML = "<p></p>"; |
michael@0 | 182 | |
michael@0 | 183 | var zi = ++gCounter; |
michael@0 | 184 | style_text.data = "p, " + selector + "{ z-index: " + zi + " }"; |
michael@0 | 185 | var should_match = ifdoc.getElementsByTagName("p")[0]; |
michael@0 | 186 | var parsed = ifwin.getComputedStyle(should_match, "").zIndex == zi; |
michael@0 | 187 | ok(parsed, "selector " + selector + " was parsed"); |
michael@0 | 188 | if (!parsed) { |
michael@0 | 189 | return; |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | // Test that it serializes to something that is also parseable. |
michael@0 | 193 | var ser1 = style_elem.sheet.cssRules[0].selectorText; |
michael@0 | 194 | zi = ++gCounter; |
michael@0 | 195 | style_text.data = ser1 + "{ z-index: " + zi + " }"; |
michael@0 | 196 | is(ifwin.getComputedStyle(should_match, "").zIndex, zi, |
michael@0 | 197 | "serialization " + ser1 + " of selector p, " + selector + |
michael@0 | 198 | " was parsed"); |
michael@0 | 199 | var ser2 = style_elem.sheet.cssRules[0].selectorText; |
michael@0 | 200 | is(ser2, ser1, |
michael@0 | 201 | "parse+serialize of selector " + selector + " is idempotent"); |
michael@0 | 202 | |
michael@0 | 203 | ifdoc.body.innerHTML = ""; |
michael@0 | 204 | style_text.data = ""; |
michael@0 | 205 | |
michael@0 | 206 | // Test that it clones to the same thing it serializes to. |
michael@0 | 207 | zi = ++gCounter; |
michael@0 | 208 | var style_sheet = "data:text/css," + |
michael@0 | 209 | escape("p, " + selector + "{ z-index: " + zi + " }"); |
michael@0 | 210 | var style_sheet_link = |
michael@0 | 211 | "<link rel='stylesheet' href='" + style_sheet + "'>"; |
michael@0 | 212 | var html_doc = "<!DOCTYPE HTML>" + |
michael@0 | 213 | style_sheet_link + style_sheet_link + |
michael@0 | 214 | "<p></p>"; |
michael@0 | 215 | var docurl = "data:text/html," + escape(html_doc); |
michael@0 | 216 | |
michael@0 | 217 | defer_clonedoc_tests(docurl, function() { |
michael@0 | 218 | var clonedoc = cloneiframe.contentDocument; |
michael@0 | 219 | var clonewin = cloneiframe.contentWindow; |
michael@0 | 220 | var links = clonedoc.getElementsByTagName("link"); |
michael@0 | 221 | // cause a clone |
michael@0 | 222 | links[1].sheet.insertRule("#nonexistent { color: purple}", 0); |
michael@0 | 223 | // remove the uncloned sheet |
michael@0 | 224 | links[0].parentNode.removeChild(links[0]); |
michael@0 | 225 | |
michael@0 | 226 | should_match = clonedoc.getElementsByTagName("p")[0]; |
michael@0 | 227 | is(clonewin.getComputedStyle(should_match, "").zIndex, zi, |
michael@0 | 228 | "selector " + selector + " was cloned correctly"); |
michael@0 | 229 | var ser3 = links[0].sheet.cssRules[1].selectorText; |
michael@0 | 230 | is(ser3, ser1, |
michael@0 | 231 | "selector " + selector + " serializes correctly after cloning"); |
michael@0 | 232 | }); |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | function test_unparseable_via_api(selector) |
michael@0 | 236 | { |
michael@0 | 237 | try { |
michael@0 | 238 | // Test that it is also unparseable when followed by EOF. |
michael@0 | 239 | ifdoc.body.mozMatchesSelector(selector); |
michael@0 | 240 | ok(false, "selector '" + selector + "' plus EOF is parse error"); |
michael@0 | 241 | } catch(ex) { |
michael@0 | 242 | is(ex.name, "SyntaxError", |
michael@0 | 243 | "selector '" + selector + "' plus EOF is parse error"); |
michael@0 | 244 | is(ex.code, DOMException.SYNTAX_ERR, |
michael@0 | 245 | "selector '" + selector + "' plus EOF is parse error"); |
michael@0 | 246 | } |
michael@0 | 247 | } |
michael@0 | 248 | |
michael@0 | 249 | function test_parseable_via_api(selector) |
michael@0 | 250 | { |
michael@0 | 251 | var threw = false; |
michael@0 | 252 | try { |
michael@0 | 253 | // Test that a selector is parseable when followed by EOF. |
michael@0 | 254 | ifdoc.body.mozMatchesSelector(selector); |
michael@0 | 255 | } catch(ex) { |
michael@0 | 256 | threw = true; |
michael@0 | 257 | } |
michael@0 | 258 | ok(!threw, "selector '" + selector + "' was parsed"); |
michael@0 | 259 | } |
michael@0 | 260 | |
michael@0 | 261 | function test_balanced_unparseable(selector) |
michael@0 | 262 | { |
michael@0 | 263 | var zi1 = ++gCounter; |
michael@0 | 264 | var zi2 = ++gCounter; |
michael@0 | 265 | ifdoc.body.innerHTML = "<p></p><div></div>"; |
michael@0 | 266 | style_text.data = "p, " + selector + "{ z-index: " + zi1 + " }" + |
michael@0 | 267 | "div { z-index: " + zi2 + " }"; |
michael@0 | 268 | var should_not_match = ifdoc.getElementsByTagName("p")[0]; |
michael@0 | 269 | var should_match = ifdoc.getElementsByTagName("div")[0]; |
michael@0 | 270 | is(ifwin.getComputedStyle(should_not_match, "").zIndex, "auto", |
michael@0 | 271 | "selector " + selector + " was a parser error"); |
michael@0 | 272 | is(ifwin.getComputedStyle(should_match, "").zIndex, zi2, |
michael@0 | 273 | "selector " + selector + " error was recovered from"); |
michael@0 | 274 | ifdoc.body.innerHTML = ""; |
michael@0 | 275 | style_text.data = ""; |
michael@0 | 276 | test_unparseable_via_api(selector); |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | function test_unbalanced_unparseable(selector) |
michael@0 | 280 | { |
michael@0 | 281 | var zi1 = ++gCounter; |
michael@0 | 282 | var zi2 = ++gCounter; |
michael@0 | 283 | ifdoc.body.innerHTML = "<p></p>"; |
michael@0 | 284 | style_text.data = "p, " + selector + "{ z-index: " + zi1 + " }"; |
michael@0 | 285 | var should_not_match = ifdoc.getElementsByTagName("p")[0]; |
michael@0 | 286 | is(ifwin.getComputedStyle(should_not_match, "").zIndex, "auto", |
michael@0 | 287 | "selector " + selector + " was a parser error"); |
michael@0 | 288 | is(style_text.parentNode.sheet.cssRules.length, 0, |
michael@0 | 289 | "sheet should have no rules since " + selector + " is parse error"); |
michael@0 | 290 | ifdoc.body.innerHTML = ""; |
michael@0 | 291 | style_text.data = ""; |
michael@0 | 292 | test_unparseable_via_api(selector); |
michael@0 | 293 | } |
michael@0 | 294 | |
michael@0 | 295 | |
michael@0 | 296 | // [attr= ] selector |
michael@0 | 297 | test_parseable("[attr=\"x\"]"); |
michael@0 | 298 | test_parseable("[attr='x']"); |
michael@0 | 299 | test_parseable("[attr=x]"); |
michael@0 | 300 | test_parseable("[attr=\"\"]"); |
michael@0 | 301 | test_parseable("[attr='']"); |
michael@0 | 302 | test_parseable("[attr=\"foo bar\"]"); |
michael@0 | 303 | |
michael@0 | 304 | test_balanced_unparseable("[attr=]"); |
michael@0 | 305 | test_balanced_unparseable("[attr=foo bar]"); |
michael@0 | 306 | |
michael@0 | 307 | test_selector_in_html( |
michael@0 | 308 | '[title=""]', |
michael@0 | 309 | '<p title=""></p>' |
michael@0 | 310 | + '<div lang=" "></div><div lang="\t"></div><div lang="\n"></div>', |
michael@0 | 311 | function(doc) { return doc.getElementsByTagName("p"); }, |
michael@0 | 312 | function(doc) { return doc.getElementsByTagName("div"); } |
michael@0 | 313 | ); |
michael@0 | 314 | |
michael@0 | 315 | // [attr~= ] selector |
michael@0 | 316 | test_parseable("[attr~=\"x\"]"); |
michael@0 | 317 | test_parseable("[attr~='x']"); |
michael@0 | 318 | test_parseable("[attr~=x]"); |
michael@0 | 319 | test_parseable("[attr~=\"\"]"); |
michael@0 | 320 | test_parseable("[attr~='']"); |
michael@0 | 321 | test_parseable("[attr~=\"foo bar\"]"); |
michael@0 | 322 | |
michael@0 | 323 | test_balanced_unparseable("[attr~=]"); |
michael@0 | 324 | test_balanced_unparseable("[attr~=foo bar]"); |
michael@0 | 325 | |
michael@0 | 326 | test_selector_in_html( |
michael@0 | 327 | '[class~="x x"]', |
michael@0 | 328 | '<div class="x x"></div><div class="x"></div><div class="x\tx"></div>div class="x\nx"></div>', |
michael@0 | 329 | function(doc) { return []; }, |
michael@0 | 330 | function(doc) { return doc.getElementsByTagName("div"); } |
michael@0 | 331 | ); |
michael@0 | 332 | |
michael@0 | 333 | // [attr|="x"] |
michael@0 | 334 | test_parseable('[attr|="x"]'); |
michael@0 | 335 | test_parseable("[attr|='x']"); |
michael@0 | 336 | test_parseable('[attr|=x]'); |
michael@0 | 337 | |
michael@0 | 338 | test_parseable('[attr|=""]'); |
michael@0 | 339 | test_parseable("[attr|='']"); |
michael@0 | 340 | test_balanced_unparseable('[attr|=]'); |
michael@0 | 341 | |
michael@0 | 342 | test_selector_in_html( |
michael@0 | 343 | '[lang|=""]', |
michael@0 | 344 | '<p lang=""></p><p lang="-"></p><p lang="-GB"></p>' |
michael@0 | 345 | + '<div lang="en-GB"></div><div lang="en-"></div>', |
michael@0 | 346 | function(doc) { return doc.getElementsByTagName("p"); }, |
michael@0 | 347 | function(doc) { return doc.getElementsByTagName("div"); } |
michael@0 | 348 | ); |
michael@0 | 349 | |
michael@0 | 350 | // [attr$= ] selector |
michael@0 | 351 | test_parseable("[attr$=\"x\"]"); |
michael@0 | 352 | test_parseable("[attr$='x']"); |
michael@0 | 353 | test_parseable("[attr$=x]"); |
michael@0 | 354 | test_parseable("[attr$=\"\"]"); |
michael@0 | 355 | test_parseable("[attr$='']"); |
michael@0 | 356 | test_parseable("[attr$=\"foo bar\"]"); |
michael@0 | 357 | |
michael@0 | 358 | test_balanced_unparseable("[attr$=]"); |
michael@0 | 359 | test_balanced_unparseable("[attr$=foo bar]"); |
michael@0 | 360 | |
michael@0 | 361 | // [attr^= ] selector |
michael@0 | 362 | test_parseable("[attr^=\"x\"]"); |
michael@0 | 363 | test_parseable("[attr^='x']"); |
michael@0 | 364 | test_parseable("[attr^=x]"); |
michael@0 | 365 | test_parseable("[attr^=\"\"]"); |
michael@0 | 366 | test_parseable("[attr^='']"); |
michael@0 | 367 | test_parseable("[attr^=\"foo bar\"]"); |
michael@0 | 368 | |
michael@0 | 369 | test_balanced_unparseable("[attr^=]"); |
michael@0 | 370 | test_balanced_unparseable("[attr^=foo bar]"); |
michael@0 | 371 | |
michael@0 | 372 | // attr[*= ] selector |
michael@0 | 373 | test_parseable("[attr*=\"x\"]"); |
michael@0 | 374 | test_parseable("[attr*='x']"); |
michael@0 | 375 | test_parseable("[attr*=x]"); |
michael@0 | 376 | test_parseable("[attr*=\"\"]"); |
michael@0 | 377 | test_parseable("[attr*='']"); |
michael@0 | 378 | test_parseable("[attr*=\"foo bar\"]"); |
michael@0 | 379 | |
michael@0 | 380 | test_balanced_unparseable("[attr*=]"); |
michael@0 | 381 | test_balanced_unparseable("[attr*=foo bar]"); |
michael@0 | 382 | |
michael@0 | 383 | |
michael@0 | 384 | // Bug 420814 |
michael@0 | 385 | test_selector_in_html( |
michael@0 | 386 | "div ~ div p", |
michael@0 | 387 | "<div></div><div><div><p>match</p></div></div>", |
michael@0 | 388 | function(doc) { return doc.getElementsByTagName("p"); }, |
michael@0 | 389 | function(doc) { return []; } |
michael@0 | 390 | ); |
michael@0 | 391 | |
michael@0 | 392 | // Bug 420245 |
michael@0 | 393 | test_selector_in_html( |
michael@0 | 394 | "p[attr$=\"\"]", |
michael@0 | 395 | "<p attr=\"foo\">This should not match</p>", |
michael@0 | 396 | function(doc) { return []; }, |
michael@0 | 397 | function(doc) { return doc.getElementsByTagName("p"); } |
michael@0 | 398 | ); |
michael@0 | 399 | test_selector_in_html( |
michael@0 | 400 | "div + p[attr~=\"\"]", |
michael@0 | 401 | "<div>Dummy</div><p attr=\"foo\">This should not match</p>", |
michael@0 | 402 | function(doc) { return []; }, |
michael@0 | 403 | function(doc) { return doc.getElementsByTagName("p"); } |
michael@0 | 404 | ); |
michael@0 | 405 | test_selector_in_html( |
michael@0 | 406 | "div[attr^=\"\"]", |
michael@0 | 407 | "<div attr=\"dummy1\">Dummy</div><div attr=\"dummy2\">Dummy</div>", |
michael@0 | 408 | function(doc) { return []; }, |
michael@0 | 409 | function(doc) { return doc.getElementsByTagName("div"); } |
michael@0 | 410 | ); |
michael@0 | 411 | test_selector_in_html( |
michael@0 | 412 | "div[attr*=\"\"]", |
michael@0 | 413 | "<div attr=\"dummy1\">Dummy</div><div attr=\"dummy2\">Dummy</div>", |
michael@0 | 414 | function(doc) { return []; }, |
michael@0 | 415 | function(doc) { return doc.getElementsByTagName("div"); } |
michael@0 | 416 | ); |
michael@0 | 417 | |
michael@0 | 418 | // :nth-child(), etc. |
michael@0 | 419 | // Follow the whitespace rules as proposed in |
michael@0 | 420 | // http://lists.w3.org/Archives/Public/www-style/2008Mar/0121.html |
michael@0 | 421 | test_balanced_unparseable(":nth-child()"); |
michael@0 | 422 | test_balanced_unparseable(":nth-of-type( )"); |
michael@0 | 423 | test_parseable(":nth-last-child( odd)"); |
michael@0 | 424 | test_parseable(":nth-last-of-type(even )"); |
michael@0 | 425 | test_parseable(":nth-child(n )"); |
michael@0 | 426 | test_parseable(":nth-of-type( 2n)"); |
michael@0 | 427 | test_parseable(":nth-last-child( -n)"); |
michael@0 | 428 | test_parseable(":nth-last-of-type(-2n )"); |
michael@0 | 429 | test_balanced_unparseable(":nth-child(- n)"); |
michael@0 | 430 | test_balanced_unparseable(":nth-of-type(-2 n)"); |
michael@0 | 431 | test_balanced_unparseable(":nth-last-of-type(2n1)"); |
michael@0 | 432 | test_balanced_unparseable(":nth-child(2n++1)"); |
michael@0 | 433 | test_balanced_unparseable(":nth-of-type(2n-+1)"); |
michael@0 | 434 | test_balanced_unparseable(":nth-last-child(2n+-1)"); |
michael@0 | 435 | test_balanced_unparseable(":nth-last-of-type(2n--1)"); |
michael@0 | 436 | test_parseable(":nth-child( 3n + 1 )"); |
michael@0 | 437 | test_parseable(":nth-child( +3n - 2 )"); |
michael@0 | 438 | test_parseable(":nth-child( -n+ 6)"); |
michael@0 | 439 | test_parseable(":nth-child( +6 )"); |
michael@0 | 440 | test_balanced_unparseable(":nth-child(3 n)"); |
michael@0 | 441 | test_balanced_unparseable(":nth-child(+ 2n)"); |
michael@0 | 442 | test_balanced_unparseable(":nth-child(+ 2)"); |
michael@0 | 443 | test_parseable(":nth-child(3)"); |
michael@0 | 444 | test_parseable(":nth-of-type(-3)"); |
michael@0 | 445 | test_parseable(":nth-last-child(+3)"); |
michael@0 | 446 | test_parseable(":nth-last-of-type(0)"); |
michael@0 | 447 | test_parseable(":nth-child(-0)"); |
michael@0 | 448 | test_parseable(":nth-of-type(3n)"); |
michael@0 | 449 | test_parseable(":nth-last-child(-3n)"); |
michael@0 | 450 | test_parseable(":nth-last-of-type(+3n)"); |
michael@0 | 451 | test_parseable(":nth-last-of-type(0n)"); |
michael@0 | 452 | test_parseable(":nth-child(-0n)"); |
michael@0 | 453 | test_parseable(":nth-of-type(n)"); |
michael@0 | 454 | test_parseable(":nth-last-child(-n)"); |
michael@0 | 455 | test_parseable(":nth-last-of-type(2n+1)"); |
michael@0 | 456 | test_parseable(":nth-child(2n-1)"); |
michael@0 | 457 | test_parseable(":nth-of-type(2n+0)"); |
michael@0 | 458 | test_parseable(":nth-last-child(2n-0)"); |
michael@0 | 459 | test_parseable(":nth-child(-0n+0)"); |
michael@0 | 460 | test_parseable(":nth-of-type(n+1)"); |
michael@0 | 461 | test_parseable(":nth-last-child(n-1)"); |
michael@0 | 462 | test_parseable(":nth-last-of-type(-n+1)"); |
michael@0 | 463 | test_parseable(":nth-child(-n-1)"); |
michael@0 | 464 | test_balanced_unparseable(":nth-child(2-n)"); |
michael@0 | 465 | test_balanced_unparseable(":nth-child(2-n-1)"); |
michael@0 | 466 | test_balanced_unparseable(":nth-child(n-2-1)"); |
michael@0 | 467 | // Bug 750388 |
michael@0 | 468 | test_parseable(":nth-child(+n)"); |
michael@0 | 469 | test_balanced_unparseable(":nth-child(+ n)"); |
michael@0 | 470 | test_parseable(":nth-child(+n+2)"); |
michael@0 | 471 | test_parseable(":nth-child(+n-2)"); |
michael@0 | 472 | test_parseable(":nth-child(+n + 2)"); |
michael@0 | 473 | test_parseable(":nth-child(+n - 2)"); |
michael@0 | 474 | test_balanced_unparseable(":nth-child(+ n+2)"); |
michael@0 | 475 | test_balanced_unparseable(":nth-child(+ n-2)"); |
michael@0 | 476 | test_balanced_unparseable(":nth-child(+ n + 2)"); |
michael@0 | 477 | test_balanced_unparseable(":nth-child(+ n - 2)"); |
michael@0 | 478 | test_parseable(":nth-child(+n-100)"); |
michael@0 | 479 | test_parseable(":nth-child(+n - 100)"); |
michael@0 | 480 | test_balanced_unparseable(":nth-child(+ n-100)"); |
michael@0 | 481 | test_balanced_unparseable(":nth-child(+-n+2)"); |
michael@0 | 482 | test_balanced_unparseable(":nth-child(+ -n+2)"); |
michael@0 | 483 | test_balanced_unparseable(":nth-child(+-n-100)"); |
michael@0 | 484 | test_balanced_unparseable(":nth-child(+ -n-100)"); |
michael@0 | 485 | test_balanced_unparseable(":nth-child(++n-100)"); |
michael@0 | 486 | test_balanced_unparseable(":nth-child(-+n-100)"); |
michael@0 | 487 | test_balanced_unparseable(":nth-child(++2n - 100)"); |
michael@0 | 488 | test_balanced_unparseable(":nth-child(+-2n - 100)"); |
michael@0 | 489 | test_balanced_unparseable(":nth-child(-+2n - 100)"); |
michael@0 | 490 | test_balanced_unparseable(":nth-child(--2n - 100)"); |
michael@0 | 491 | test_balanced_unparseable(":nth-child(+/**/+2n - 100)"); |
michael@0 | 492 | test_balanced_unparseable(":nth-child(+/**/-2n - 100)"); |
michael@0 | 493 | test_balanced_unparseable(":nth-child(-/**/+2n - 100)"); |
michael@0 | 494 | test_balanced_unparseable(":nth-child(-/**/-2n - 100)"); |
michael@0 | 495 | test_balanced_unparseable(":nth-child(+/**/+/**/2n - 100)"); |
michael@0 | 496 | test_balanced_unparseable(":nth-child(+/**/-/**/2n - 100)"); |
michael@0 | 497 | test_balanced_unparseable(":nth-child(-/**/+/**/2n - 100)"); |
michael@0 | 498 | test_balanced_unparseable(":nth-child(-/**/-/**/2n - 100)"); |
michael@0 | 499 | test_balanced_unparseable(":nth-child(++/**/2n - 100)"); |
michael@0 | 500 | test_balanced_unparseable(":nth-child(+-/**/2n - 100)"); |
michael@0 | 501 | test_balanced_unparseable(":nth-child(-+/**/2n - 100)"); |
michael@0 | 502 | test_balanced_unparseable(":nth-child(--/**/2n - 100)"); |
michael@0 | 503 | test_balanced_unparseable(":nth-child(-even)"); |
michael@0 | 504 | test_balanced_unparseable(":nth-child(-odd)"); |
michael@0 | 505 | test_balanced_unparseable(":nth-child(+even)"); |
michael@0 | 506 | test_balanced_unparseable(":nth-child(+odd)"); |
michael@0 | 507 | test_balanced_unparseable(":nth-child(+ even)"); |
michael@0 | 508 | test_balanced_unparseable(":nth-child(+ odd)"); |
michael@0 | 509 | test_balanced_unparseable(":nth-child(+-n)"); |
michael@0 | 510 | test_balanced_unparseable(":nth-child(+-n-)"); |
michael@0 | 511 | test_balanced_unparseable(":nth-child(-+n)"); |
michael@0 | 512 | test_balanced_unparseable(":nth-child(+n--)"); |
michael@0 | 513 | test_parseable(":nth-child(n+2)"); |
michael@0 | 514 | test_parseable(":nth-child(n/**/+/**/2)"); |
michael@0 | 515 | test_parseable(":nth-child(n-2)"); |
michael@0 | 516 | test_parseable(":nth-child(n/**/-/**/2)"); |
michael@0 | 517 | test_balanced_unparseable(":nth-child(n++2)"); |
michael@0 | 518 | test_balanced_unparseable(":nth-child(n+-2)"); |
michael@0 | 519 | test_balanced_unparseable(":nth-child(n-+2)"); |
michael@0 | 520 | test_balanced_unparseable(":nth-child(n--2)"); |
michael@0 | 521 | test_balanced_unparseable(":nth-child(n/**/++2)"); |
michael@0 | 522 | test_balanced_unparseable(":nth-child(n/**/+-2)"); |
michael@0 | 523 | test_balanced_unparseable(":nth-child(n/**/-+2)"); |
michael@0 | 524 | test_balanced_unparseable(":nth-child(n/**/--2)"); |
michael@0 | 525 | test_balanced_unparseable(":nth-child(n/**/+/**/+2)"); |
michael@0 | 526 | test_balanced_unparseable(":nth-child(n/**/+/**/-2)"); |
michael@0 | 527 | test_balanced_unparseable(":nth-child(n/**/-/**/+2)"); |
michael@0 | 528 | test_balanced_unparseable(":nth-child(n/**/-/**/-2)"); |
michael@0 | 529 | test_balanced_unparseable(":nth-child(n+/**/+2)"); |
michael@0 | 530 | test_balanced_unparseable(":nth-child(n+/**/-2)"); |
michael@0 | 531 | test_balanced_unparseable(":nth-child(n-/**/+2)"); |
michael@0 | 532 | test_balanced_unparseable(":nth-child(n-/**/-2)"); |
michael@0 | 533 | test_balanced_unparseable(":nth-child(n++/**/2)"); |
michael@0 | 534 | test_balanced_unparseable(":nth-child(n+-/**/2)"); |
michael@0 | 535 | test_balanced_unparseable(":nth-child(n-+/**/2)"); |
michael@0 | 536 | test_balanced_unparseable(":nth-child(n--/**/2)"); |
michael@0 | 537 | test_balanced_unparseable(":nth-child(n/**/++/**/2)"); |
michael@0 | 538 | test_balanced_unparseable(":nth-child(n/**/+-/**/2)"); |
michael@0 | 539 | test_balanced_unparseable(":nth-child(n/**/-+/**/2)"); |
michael@0 | 540 | test_balanced_unparseable(":nth-child(n/**/--/**/2)"); |
michael@0 | 541 | test_balanced_unparseable(":nth-child(n/**/+/**/+/**/2)"); |
michael@0 | 542 | test_balanced_unparseable(":nth-child(n/**/+/**/-/**/2)"); |
michael@0 | 543 | test_balanced_unparseable(":nth-child(n/**/-/**/+/**/2)"); |
michael@0 | 544 | test_balanced_unparseable(":nth-child(n/**/-/**/-/**/2)"); |
michael@0 | 545 | test_balanced_unparseable(":nth-child(n+/**/+/**/2)"); |
michael@0 | 546 | test_balanced_unparseable(":nth-child(n+/**/-/**/2)"); |
michael@0 | 547 | test_balanced_unparseable(":nth-child(n-/**/+/**/2)"); |
michael@0 | 548 | test_balanced_unparseable(":nth-child(n-/**/-/**/2)"); |
michael@0 | 549 | test_parseable(":nth-child(2n+2)"); |
michael@0 | 550 | test_parseable(":nth-child(2n/**/+/**/2)"); |
michael@0 | 551 | test_parseable(":nth-child(2n-2)"); |
michael@0 | 552 | test_parseable(":nth-child(2n/**/-/**/2)"); |
michael@0 | 553 | test_balanced_unparseable(":nth-child(2n++2)"); |
michael@0 | 554 | test_balanced_unparseable(":nth-child(2n+-2)"); |
michael@0 | 555 | test_balanced_unparseable(":nth-child(2n-+2)"); |
michael@0 | 556 | test_balanced_unparseable(":nth-child(2n--2)"); |
michael@0 | 557 | test_balanced_unparseable(":nth-child(2n/**/++2)"); |
michael@0 | 558 | test_balanced_unparseable(":nth-child(2n/**/+-2)"); |
michael@0 | 559 | test_balanced_unparseable(":nth-child(2n/**/-+2)"); |
michael@0 | 560 | test_balanced_unparseable(":nth-child(2n/**/--2)"); |
michael@0 | 561 | test_balanced_unparseable(":nth-child(2n/**/+/**/+2)"); |
michael@0 | 562 | test_balanced_unparseable(":nth-child(2n/**/+/**/-2)"); |
michael@0 | 563 | test_balanced_unparseable(":nth-child(2n/**/-/**/+2)"); |
michael@0 | 564 | test_balanced_unparseable(":nth-child(2n/**/-/**/-2)"); |
michael@0 | 565 | test_balanced_unparseable(":nth-child(2n+/**/+2)"); |
michael@0 | 566 | test_balanced_unparseable(":nth-child(2n+/**/-2)"); |
michael@0 | 567 | test_balanced_unparseable(":nth-child(2n-/**/+2)"); |
michael@0 | 568 | test_balanced_unparseable(":nth-child(2n-/**/-2)"); |
michael@0 | 569 | test_balanced_unparseable(":nth-child(2n++/**/2)"); |
michael@0 | 570 | test_balanced_unparseable(":nth-child(2n+-/**/2)"); |
michael@0 | 571 | test_balanced_unparseable(":nth-child(2n-+/**/2)"); |
michael@0 | 572 | test_balanced_unparseable(":nth-child(2n--/**/2)"); |
michael@0 | 573 | test_balanced_unparseable(":nth-child(2n/**/++/**/2)"); |
michael@0 | 574 | test_balanced_unparseable(":nth-child(2n/**/+-/**/2)"); |
michael@0 | 575 | test_balanced_unparseable(":nth-child(2n/**/-+/**/2)"); |
michael@0 | 576 | test_balanced_unparseable(":nth-child(2n/**/--/**/2)"); |
michael@0 | 577 | test_balanced_unparseable(":nth-child(2n/**/+/**/+/**/2)"); |
michael@0 | 578 | test_balanced_unparseable(":nth-child(2n/**/+/**/-/**/2)"); |
michael@0 | 579 | test_balanced_unparseable(":nth-child(2n/**/-/**/+/**/2)"); |
michael@0 | 580 | test_balanced_unparseable(":nth-child(2n/**/-/**/-/**/2)"); |
michael@0 | 581 | test_balanced_unparseable(":nth-child(2n+/**/+/**/2)"); |
michael@0 | 582 | test_balanced_unparseable(":nth-child(2n+/**/-/**/2)"); |
michael@0 | 583 | test_balanced_unparseable(":nth-child(2n-/**/+/**/2)"); |
michael@0 | 584 | test_balanced_unparseable(":nth-child(2n-/**/-/**/2)"); |
michael@0 | 585 | test_parseable(":nth-child(+/**/n+2)"); |
michael@0 | 586 | test_parseable(":nth-child(+n/**/+2)"); |
michael@0 | 587 | test_parseable(":nth-child(+n/**/+2)"); |
michael@0 | 588 | test_parseable(":nth-child(+n+/**/2)"); |
michael@0 | 589 | test_parseable(":nth-child(+n+2/**/)"); |
michael@0 | 590 | test_parseable(":nth-child(+1/**/n+2)"); |
michael@0 | 591 | test_parseable(":nth-child(+1n/**/+2)"); |
michael@0 | 592 | test_parseable(":nth-child(+1n/**/+2)"); |
michael@0 | 593 | test_parseable(":nth-child(+1n+/**/2)"); |
michael@0 | 594 | test_parseable(":nth-child(+1n+2/**/)"); |
michael@0 | 595 | test_parseable(":nth-child(-/**/n+2)"); |
michael@0 | 596 | test_parseable(":nth-child(-n/**/+2)"); |
michael@0 | 597 | test_parseable(":nth-child(-n/**/+2)"); |
michael@0 | 598 | test_parseable(":nth-child(-n+/**/2)"); |
michael@0 | 599 | test_parseable(":nth-child(-n+2/**/)"); |
michael@0 | 600 | test_parseable(":nth-child(-1/**/n+2)"); |
michael@0 | 601 | test_parseable(":nth-child(-1n/**/+2)"); |
michael@0 | 602 | test_parseable(":nth-child(-1n/**/+2)"); |
michael@0 | 603 | test_parseable(":nth-child(-1n+/**/2)"); |
michael@0 | 604 | test_parseable(":nth-child(-1n+2/**/)"); |
michael@0 | 605 | test_balanced_unparseable(":nth-child(-/**/ n+2)"); |
michael@0 | 606 | test_balanced_unparseable(":nth-child(- /**/n+2)"); |
michael@0 | 607 | test_balanced_unparseable(":nth-child(+/**/ n+2)"); |
michael@0 | 608 | test_balanced_unparseable(":nth-child(+ /**/n+2)"); |
michael@0 | 609 | test_parseable(":nth-child(+/**/n-2)"); |
michael@0 | 610 | test_parseable(":nth-child(+n/**/-2)"); |
michael@0 | 611 | test_parseable(":nth-child(+n/**/-2)"); |
michael@0 | 612 | test_parseable(":nth-child(+n-/**/2)"); |
michael@0 | 613 | test_parseable(":nth-child(+n-2/**/)"); |
michael@0 | 614 | test_parseable(":nth-child(+1/**/n-2)"); |
michael@0 | 615 | test_parseable(":nth-child(+1n/**/-2)"); |
michael@0 | 616 | test_parseable(":nth-child(+1n/**/-2)"); |
michael@0 | 617 | test_parseable(":nth-child(+1n-/**/2)"); |
michael@0 | 618 | test_parseable(":nth-child(+1n-2/**/)"); |
michael@0 | 619 | test_parseable(":nth-child(-/**/n-2)"); |
michael@0 | 620 | test_parseable(":nth-child(-n/**/-2)"); |
michael@0 | 621 | test_parseable(":nth-child(-n/**/-2)"); |
michael@0 | 622 | test_parseable(":nth-child(-n-/**/2)"); |
michael@0 | 623 | test_parseable(":nth-child(-n-2/**/)"); |
michael@0 | 624 | test_parseable(":nth-child(-1/**/n-2)"); |
michael@0 | 625 | test_parseable(":nth-child(-1n/**/-2)"); |
michael@0 | 626 | test_parseable(":nth-child(-1n/**/-2)"); |
michael@0 | 627 | test_parseable(":nth-child(-1n-/**/2)"); |
michael@0 | 628 | test_parseable(":nth-child(-1n-2/**/)"); |
michael@0 | 629 | test_balanced_unparseable(":nth-child(-/**/ n-2)"); |
michael@0 | 630 | test_balanced_unparseable(":nth-child(- /**/n-2)"); |
michael@0 | 631 | test_balanced_unparseable(":nth-child(+/**/ n-2)"); |
michael@0 | 632 | test_balanced_unparseable(":nth-child(+ /**/n-2)"); |
michael@0 | 633 | test_parseable(":nth-child( +n + 1 )"); |
michael@0 | 634 | test_parseable(":nth-child( +/**/n + 1 )"); |
michael@0 | 635 | test_parseable(":nth-child( -/**/2/**/n/**/+/**/4 )"); |
michael@0 | 636 | test_balanced_unparseable(":nth-child( -/**/ 2/**/n/**/+/**/4 )"); |
michael@0 | 637 | test_balanced_unparseable(":nth-child( -/**/2 /**/n/**/+/**/4 )"); |
michael@0 | 638 | test_balanced_unparseable(":nth-child( -/**/2/**/ n/**/+/**/4 )"); |
michael@0 | 639 | test_parseable(":nth-child( -/**/2/**/n /**/+/**/4 )"); |
michael@0 | 640 | test_parseable(":nth-child( -/**/2/**/n/**/ +/**/4 )"); |
michael@0 | 641 | test_parseable(":nth-child(+1/**/n-1)"); |
michael@0 | 642 | test_parseable(":nth-child(1/**/n-1)"); |
michael@0 | 643 | // bug 876570 |
michael@0 | 644 | test_balanced_unparseable(":nth-child(+2n-)"); |
michael@0 | 645 | test_balanced_unparseable(":nth-child(+n-)"); |
michael@0 | 646 | test_balanced_unparseable(":nth-child(-2n-)"); |
michael@0 | 647 | test_balanced_unparseable(":nth-child(-n-)"); |
michael@0 | 648 | test_balanced_unparseable(":nth-child(2n-)"); |
michael@0 | 649 | test_balanced_unparseable(":nth-child(n-)"); |
michael@0 | 650 | test_balanced_unparseable(":nth-child(+2n+)"); |
michael@0 | 651 | test_balanced_unparseable(":nth-child(+n+)"); |
michael@0 | 652 | test_balanced_unparseable(":nth-child(-2n+)"); |
michael@0 | 653 | test_balanced_unparseable(":nth-child(-n+)"); |
michael@0 | 654 | test_balanced_unparseable(":nth-child(2n+)"); |
michael@0 | 655 | test_balanced_unparseable(":nth-child(n+)"); |
michael@0 | 656 | |
michael@0 | 657 | // exercise the an+b matching logic particularly hard for |
michael@0 | 658 | // :nth-child() (since we know we use the same code for all 4) |
michael@0 | 659 | var seven_ps = "<p></p><p></p><p></p><p></p><p></p><p></p><p></p>"; |
michael@0 | 660 | function pset(indices) { // takes an array of 1-based indices |
michael@0 | 661 | return function pset_filter(doc) { |
michael@0 | 662 | var a = doc.getElementsByTagName("p"); |
michael@0 | 663 | var result = []; |
michael@0 | 664 | for (var i in indices) |
michael@0 | 665 | result.push(a[indices[i] - 1]); |
michael@0 | 666 | return result; |
michael@0 | 667 | } |
michael@0 | 668 | } |
michael@0 | 669 | test_selector_in_html(":nth-child(0)", seven_ps, |
michael@0 | 670 | pset([]), pset([1, 2, 3, 4, 5, 6, 7])); |
michael@0 | 671 | test_selector_in_html(":nth-child(-3)", seven_ps, |
michael@0 | 672 | pset([]), pset([1, 2, 3, 4, 5, 6, 7])); |
michael@0 | 673 | test_selector_in_html(":nth-child(3)", seven_ps, |
michael@0 | 674 | pset([3]), pset([1, 2, 4, 5, 6, 7])); |
michael@0 | 675 | test_selector_in_html(":nth-child(0n+3)", seven_ps, |
michael@0 | 676 | pset([3]), pset([1, 2, 4, 5, 6, 7])); |
michael@0 | 677 | test_selector_in_html(":nth-child(-0n+3)", seven_ps, |
michael@0 | 678 | pset([3]), pset([1, 2, 4, 5, 6, 7])); |
michael@0 | 679 | test_selector_in_html(":nth-child(8)", seven_ps, |
michael@0 | 680 | pset([]), pset([1, 2, 3, 4, 5, 6, 7])); |
michael@0 | 681 | test_selector_in_html(":nth-child(odd)", seven_ps, |
michael@0 | 682 | pset([1, 3, 5, 7]), pset([2, 4, 6])); |
michael@0 | 683 | test_selector_in_html(":nth-child(even)", seven_ps, |
michael@0 | 684 | pset([2, 4, 6]), pset([1, 3, 5, 7])); |
michael@0 | 685 | test_selector_in_html(":nth-child(2n-1)", seven_ps, |
michael@0 | 686 | pset([1, 3, 5, 7]), pset([2, 4, 6])); |
michael@0 | 687 | test_selector_in_html(":nth-child( 2n - 1 )", seven_ps, |
michael@0 | 688 | pset([1, 3, 5, 7]), pset([2, 4, 6])); |
michael@0 | 689 | test_selector_in_html(":nth-child(2n+1)", seven_ps, |
michael@0 | 690 | pset([1, 3, 5, 7]), pset([2, 4, 6])); |
michael@0 | 691 | test_selector_in_html(":nth-child( 2n + 1 )", seven_ps, |
michael@0 | 692 | pset([1, 3, 5, 7]), pset([2, 4, 6])); |
michael@0 | 693 | test_selector_in_html(":nth-child(2n+0)", seven_ps, |
michael@0 | 694 | pset([2, 4, 6]), pset([1, 3, 5, 7])); |
michael@0 | 695 | test_selector_in_html(":nth-child(2n-0)", seven_ps, |
michael@0 | 696 | pset([2, 4, 6]), pset([1, 3, 5, 7])); |
michael@0 | 697 | test_selector_in_html(":nth-child(-n+3)", seven_ps, |
michael@0 | 698 | pset([1, 2, 3]), pset([4, 5, 6, 7])); |
michael@0 | 699 | test_selector_in_html(":nth-child(-n-3)", seven_ps, |
michael@0 | 700 | pset([]), pset([1, 2, 3, 4, 5, 6, 7])); |
michael@0 | 701 | test_selector_in_html(":nth-child(n)", seven_ps, |
michael@0 | 702 | pset([1, 2, 3, 4, 5, 6, 7]), pset([])); |
michael@0 | 703 | test_selector_in_html(":nth-child(n-3)", seven_ps, |
michael@0 | 704 | pset([1, 2, 3, 4, 5, 6, 7]), pset([])); |
michael@0 | 705 | test_selector_in_html(":nth-child(n+3)", seven_ps, |
michael@0 | 706 | pset([3, 4, 5, 6, 7]), pset([1, 2])); |
michael@0 | 707 | test_selector_in_html(":nth-child(2n+3)", seven_ps, |
michael@0 | 708 | pset([3, 5, 7]), pset([1, 2, 4, 6])); |
michael@0 | 709 | test_selector_in_html(":nth-child(2n)", seven_ps, |
michael@0 | 710 | pset([2, 4, 6]), pset([1, 3, 5, 7])); |
michael@0 | 711 | test_selector_in_html(":nth-child(2n-3)", seven_ps, |
michael@0 | 712 | pset([1, 3, 5, 7]), pset([2, 4, 6])); |
michael@0 | 713 | test_selector_in_html(":nth-child(-1n+3)", seven_ps, |
michael@0 | 714 | pset([1, 2, 3]), pset([4, 5, 6, 7])); |
michael@0 | 715 | test_selector_in_html(":nth-child(-2n+3)", seven_ps, |
michael@0 | 716 | pset([1, 3]), pset([2, 4, 5, 6, 7])); |
michael@0 | 717 | // And a few spot-checks for the other :nth-* selectors |
michael@0 | 718 | test_selector_in_html(":nth-child(4n+1)", seven_ps, |
michael@0 | 719 | pset([1, 5]), pset([2, 3, 4, 6, 7])); |
michael@0 | 720 | test_selector_in_html(":nth-last-child(4n+1)", seven_ps, |
michael@0 | 721 | pset([3, 7]), pset([1, 2, 4, 5, 6])); |
michael@0 | 722 | test_selector_in_html(":nth-of-type(4n+1)", seven_ps, |
michael@0 | 723 | pset([1, 5]), pset([2, 3, 4, 6, 7])); |
michael@0 | 724 | test_selector_in_html(":nth-last-of-type(4n+1)", seven_ps, |
michael@0 | 725 | pset([3, 7]), pset([1, 2, 4, 5, 6])); |
michael@0 | 726 | test_selector_in_html(":nth-child(6)", seven_ps, |
michael@0 | 727 | pset([6]), pset([1, 2, 3, 4, 5, 7])); |
michael@0 | 728 | test_selector_in_html(":nth-last-child(6)", seven_ps, |
michael@0 | 729 | pset([2]), pset([1, 3, 4, 5, 6, 7])); |
michael@0 | 730 | test_selector_in_html(":nth-of-type(6)", seven_ps, |
michael@0 | 731 | pset([6]), pset([1, 2, 3, 4, 5, 7])); |
michael@0 | 732 | test_selector_in_html(":nth-last-of-type(6)", seven_ps, |
michael@0 | 733 | pset([2]), pset([1, 3, 4, 5, 6, 7])); |
michael@0 | 734 | |
michael@0 | 735 | // Test [first|last|only]-[child|node|of-type] |
michael@0 | 736 | var interesting_doc = "<!----> <div id='p1'> <!---->x<p id='s1'></p> <!----><p id='s2'></p> <!----></div> <!----><p id='p2'> <!----><span id='s3'></span> <!----><span id='s4'></span> <!---->x</p> <!----><div id='p3'> <!----><p id='s5'></p> <!----></div> <!---->"; |
michael@0 | 737 | function idset(ids) { // takes an array of ids |
michael@0 | 738 | return function idset_filter(doc) { |
michael@0 | 739 | var result = []; |
michael@0 | 740 | for (var id of ids) |
michael@0 | 741 | result.push(doc.getElementById(id)); |
michael@0 | 742 | return result; |
michael@0 | 743 | } |
michael@0 | 744 | } |
michael@0 | 745 | function classset(classes) { // takes an array of classes |
michael@0 | 746 | return function classset_filter(doc) { |
michael@0 | 747 | var i, j, els; |
michael@0 | 748 | var result = []; |
michael@0 | 749 | for (i = 0; i < classes.length; i++) { |
michael@0 | 750 | els = doc.getElementsByClassName(classes[i]); |
michael@0 | 751 | for (j = 0; j < els.length; j++) { |
michael@0 | 752 | result.push(els[j]); |
michael@0 | 753 | } |
michael@0 | 754 | } |
michael@0 | 755 | return result; |
michael@0 | 756 | } |
michael@0 | 757 | } |
michael@0 | 758 | function emptyset(doc) { return []; } |
michael@0 | 759 | test_parseable(":first-child"); |
michael@0 | 760 | test_parseable(":last-child"); |
michael@0 | 761 | test_parseable(":only-child"); |
michael@0 | 762 | test_parseable(":-moz-first-node"); |
michael@0 | 763 | test_parseable(":-moz-last-node"); |
michael@0 | 764 | test_parseable(":first-of-type"); |
michael@0 | 765 | test_parseable(":last-of-type"); |
michael@0 | 766 | test_parseable(":only-of-type"); |
michael@0 | 767 | test_selector_in_html(":first-child", seven_ps, |
michael@0 | 768 | pset([1]), pset([2, 3, 4, 5, 6, 7])); |
michael@0 | 769 | test_selector_in_html(":first-child", interesting_doc, |
michael@0 | 770 | idset(["p1", "s1", "s3", "s5"]), |
michael@0 | 771 | idset(["s2", "p2", "s4", "p3"])); |
michael@0 | 772 | test_selector_in_html(":-moz-first-node", interesting_doc, |
michael@0 | 773 | idset(["p1", "s3", "s5"]), |
michael@0 | 774 | idset(["s1", "s2", "p2", "s4", "p3"])); |
michael@0 | 775 | test_selector_in_html(":last-child", seven_ps, |
michael@0 | 776 | pset([7]), pset([1, 2, 3, 4, 5, 6])); |
michael@0 | 777 | test_selector_in_html(":last-child", interesting_doc, |
michael@0 | 778 | idset(["s2", "s4", "p3", "s5"]), |
michael@0 | 779 | idset(["p1", "s1", "p2", "s3"])); |
michael@0 | 780 | test_selector_in_html(":-moz-last-node", interesting_doc, |
michael@0 | 781 | idset(["s2", "p3", "s5"]), |
michael@0 | 782 | idset(["p1", "s1", "p2", "s3", "s4"])); |
michael@0 | 783 | test_selector_in_html(":only-child", seven_ps, |
michael@0 | 784 | pset([]), pset([1, 2, 3, 4, 5, 6, 7])); |
michael@0 | 785 | test_selector_in_html(":only-child", interesting_doc, |
michael@0 | 786 | idset(["s5"]), |
michael@0 | 787 | idset(["p1", "s1", "s2", "p2", "s3", "s4", "p3"])); |
michael@0 | 788 | test_selector_in_html(":first-of-type", seven_ps, |
michael@0 | 789 | pset([1]), pset([2, 3, 4, 5, 6, 7])); |
michael@0 | 790 | test_selector_in_html(":first-of-type", interesting_doc, |
michael@0 | 791 | idset(["p1", "s1", "p2", "s3", "s5"]), |
michael@0 | 792 | idset(["s2", "s4", "p3"])); |
michael@0 | 793 | test_selector_in_html(":last-of-type", seven_ps, |
michael@0 | 794 | pset([7]), pset([1, 2, 3, 4, 5, 6])); |
michael@0 | 795 | test_selector_in_html(":last-of-type", interesting_doc, |
michael@0 | 796 | idset(["s2", "p2", "s4", "p3", "s5"]), |
michael@0 | 797 | idset(["p1", "s1", "s3"])); |
michael@0 | 798 | test_selector_in_html(":only-of-type", seven_ps, |
michael@0 | 799 | pset([]), pset([1, 2, 3, 4, 5, 6, 7])); |
michael@0 | 800 | test_selector_in_html(":only-of-type", interesting_doc, |
michael@0 | 801 | idset(["p2", "s5"]), |
michael@0 | 802 | idset(["p1", "s1", "s2", "s3", "s4", "p3"])); |
michael@0 | 803 | |
michael@0 | 804 | // And a bunch of tests for the of-type aspect of :nth-of-type() and |
michael@0 | 805 | // :nth-last-of-type(). Note that the last div here contains two |
michael@0 | 806 | // children. |
michael@0 | 807 | var mixed_elements="<p></p><p></p><div></div><p></p><div><p></p><address></address></div><address></address>"; |
michael@0 | 808 | function pdaset(ps, divs, addresses) { // takes an array of 1-based indices |
michael@0 | 809 | var l = { p: ps, div: divs, address: addresses }; |
michael@0 | 810 | return function pdaset_filter(doc) { |
michael@0 | 811 | var result = []; |
michael@0 | 812 | for (var tag in l) { |
michael@0 | 813 | var a = doc.getElementsByTagName(tag); |
michael@0 | 814 | var indices = l[tag]; |
michael@0 | 815 | for (var i in indices) |
michael@0 | 816 | result.push(a[indices[i] - 1]); |
michael@0 | 817 | } |
michael@0 | 818 | return result; |
michael@0 | 819 | } |
michael@0 | 820 | } |
michael@0 | 821 | test_selector_in_html(":nth-of-type(odd)", mixed_elements, |
michael@0 | 822 | pdaset([1, 3, 4], [1], [1, 2]), |
michael@0 | 823 | pdaset([2], [2], [])); |
michael@0 | 824 | test_selector_in_html(":nth-of-type(2n-0)", mixed_elements, |
michael@0 | 825 | pdaset([2], [2], []), |
michael@0 | 826 | pdaset([1, 3, 4], [1], [1, 2])); |
michael@0 | 827 | test_selector_in_html(":nth-last-of-type(even)", mixed_elements, |
michael@0 | 828 | pdaset([2], [1], []), |
michael@0 | 829 | pdaset([1, 3, 4], [2], [1, 2])); |
michael@0 | 830 | |
michael@0 | 831 | // Test greediness of descendant combinators. |
michael@0 | 832 | var four_children="<div id='a'><div id='b'><div id='c'><div id='d'><\/div><\/div><\/div><\/div>"; |
michael@0 | 833 | test_selector_in_html("#a > div div", four_children, |
michael@0 | 834 | idset(["c", "d"]), idset(["a", "b"])); |
michael@0 | 835 | test_selector_in_html("#a > #b div", four_children, |
michael@0 | 836 | idset(["c", "d"]), idset(["a", "b"])); |
michael@0 | 837 | test_selector_in_html("#a div > div", four_children, |
michael@0 | 838 | idset(["c", "d"]), idset(["a", "b"])); |
michael@0 | 839 | test_selector_in_html("#a #b > div", four_children, |
michael@0 | 840 | idset(["c"]), idset(["a", "b", "d"])); |
michael@0 | 841 | test_selector_in_html("#a > #b div", four_children, |
michael@0 | 842 | idset(["c", "d"]), idset(["a", "b"])); |
michael@0 | 843 | test_selector_in_html("#a #c > div", four_children, |
michael@0 | 844 | idset(["d"]), idset(["a", "b", "c"])); |
michael@0 | 845 | test_selector_in_html("#a > #c div", four_children, |
michael@0 | 846 | idset([]), idset(["a", "b", "c", "d"])); |
michael@0 | 847 | |
michael@0 | 848 | // More descendant combinator greediness (bug 511147) |
michael@0 | 849 | test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"></div><div class="match"></div></div>', |
michael@0 | 850 | classset(["match"]), classset(["a", "b"])); |
michael@0 | 851 | test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"></div><div class="x"></div><div class="match"></div></div>', |
michael@0 | 852 | classset(["match"]), classset(["a", "b", "x"])); |
michael@0 | 853 | test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"><p>filler filler <i>filler</i> filler</p></div><div class="match"></div></div>', |
michael@0 | 854 | classset(["match"]), classset(["a", "b", "x"])); |
michael@0 | 855 | test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="x"><p>filler filler <i>filler</i> filler</p></div><div></div><div class="b"></div><div></div><div class="x"><p>filler filler <i>filler</i> filler</p></div><div class="match"></div></div>', |
michael@0 | 856 | classset(["match"]), classset(["a", "b", "x"])); |
michael@0 | 857 | test_selector_in_html(".a > .b ~ .match", '<div class="a"><div class="b"></div><div class="match"></div><div class="match"></div></div>', |
michael@0 | 858 | classset(["match"]), classset(["a", "b"])); |
michael@0 | 859 | |
michael@0 | 860 | test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div><div class="b"></div><div class="nomatch"></div></div></div>', |
michael@0 | 861 | emptyset, classset(["a", "b", "nomatch"])); |
michael@0 | 862 | test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div><div class="b"></div><div class="nomatch"></div></div><div class="nomatch"></div></div>', |
michael@0 | 863 | emptyset, classset(["a", "b", "nomatch"])); |
michael@0 | 864 | test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div class="b"></div><div><div class="nomatch"></div></div><div></div></div>', |
michael@0 | 865 | emptyset, classset(["a", "b", "nomatch"])); |
michael@0 | 866 | test_selector_in_html(".a > .b ~ .nomatch", '<div class="a"><div class="b"></div></div><div class="nomatch"></div>', |
michael@0 | 867 | emptyset, classset(["a", "b", "nomatch"])); |
michael@0 | 868 | |
michael@0 | 869 | // Test serialization of pseudo-elements. |
michael@0 | 870 | should_serialize_to("p:first-letter", "p:first-letter"); |
michael@0 | 871 | should_serialize_to("div>p:first-letter", "div > p:first-letter"); |
michael@0 | 872 | should_serialize_to("span +div:first-line", "span + div:first-line"); |
michael@0 | 873 | |
michael@0 | 874 | // Test default namespaces, including inside :not(). |
michael@0 | 875 | var html_default_ns = "@namespace url(http://www.w3.org/1999/xhtml);"; |
michael@0 | 876 | var html_ns = "@namespace html url(http://www.w3.org/1999/xhtml);"; |
michael@0 | 877 | var xul_default_ns = "@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);"; |
michael@0 | 878 | var single_a = "<a id='a' href='data:text/plain,this_better_be_unvisited'></a>"; |
michael@0 | 879 | var set_single = idset(['a']); |
michael@0 | 880 | var empty_set = idset([]); |
michael@0 | 881 | test_selector_in_html("a", single_a, set_single, empty_set, |
michael@0 | 882 | html_default_ns); |
michael@0 | 883 | test_selector_in_html("a", single_a, empty_set, set_single, |
michael@0 | 884 | xul_default_ns); |
michael@0 | 885 | test_selector_in_html("*|a", single_a, set_single, empty_set, |
michael@0 | 886 | xul_default_ns); |
michael@0 | 887 | test_selector_in_html("html|a", single_a, set_single, empty_set, |
michael@0 | 888 | xul_default_ns + html_ns); |
michael@0 | 889 | // Type selectors inside :not() bring in default namespaces, but |
michael@0 | 890 | // non-type selectors don't. |
michael@0 | 891 | test_selector_in_html("*|a:not(*)", single_a, set_single, empty_set, |
michael@0 | 892 | xul_default_ns); |
michael@0 | 893 | test_selector_in_html("*|a:not(a)", single_a, set_single, empty_set, |
michael@0 | 894 | xul_default_ns); |
michael@0 | 895 | test_selector_in_html("*|a:not(*|*)", single_a, empty_set, set_single, |
michael@0 | 896 | xul_default_ns); |
michael@0 | 897 | test_selector_in_html("*|a:not(*|a)", single_a, empty_set, set_single, |
michael@0 | 898 | xul_default_ns); |
michael@0 | 899 | test_selector_in_html("*|a:not(:link)", single_a + "<a id='b'></a>", |
michael@0 | 900 | idset(["b"]), set_single, |
michael@0 | 901 | xul_default_ns); |
michael@0 | 902 | test_selector_in_html("*|a:not(:visited)", single_a + "<a id='b'></a>", |
michael@0 | 903 | idset(["a", "b"]), empty_set, |
michael@0 | 904 | xul_default_ns); |
michael@0 | 905 | test_selector_in_html("*|a:not(html|*)", single_a, empty_set, set_single, |
michael@0 | 906 | xul_default_ns + html_ns); |
michael@0 | 907 | test_selector_in_html("*|a:not(html|a)", single_a, empty_set, set_single, |
michael@0 | 908 | xul_default_ns + html_ns); |
michael@0 | 909 | test_selector_in_html("*|a:not(|*)", single_a, set_single, empty_set, |
michael@0 | 910 | xul_default_ns + html_ns); |
michael@0 | 911 | test_selector_in_html("*|a:not(|a)", single_a, set_single, empty_set, |
michael@0 | 912 | xul_default_ns + html_ns); |
michael@0 | 913 | test_selector_in_html("html|a:not(|*)", single_a, set_single, empty_set, |
michael@0 | 914 | xul_default_ns + html_ns); |
michael@0 | 915 | test_selector_in_html("html|a:not(|a)", single_a, set_single, empty_set, |
michael@0 | 916 | xul_default_ns + html_ns); |
michael@0 | 917 | test_selector_in_html("html|a:not(*|*)", single_a, empty_set, set_single, |
michael@0 | 918 | xul_default_ns + html_ns); |
michael@0 | 919 | test_selector_in_html("html|a:not(*|a)", single_a, empty_set, set_single, |
michael@0 | 920 | xul_default_ns + html_ns); |
michael@0 | 921 | |
michael@0 | 922 | // Test -moz-locale-dir |
michael@0 | 923 | test_parseable(":-moz-locale-dir(ltr)"); |
michael@0 | 924 | test_parseable(":-moz-locale-dir(rtl)"); |
michael@0 | 925 | test_parseable(":-moz-locale-dir(rTl)"); |
michael@0 | 926 | test_parseable(":-moz-locale-dir(LTR)"); |
michael@0 | 927 | if (document.body.mozMatchesSelector(":-moz-locale-dir(ltr)")) { |
michael@0 | 928 | test_selector_in_html("a:-moz-locale-dir(LTr)", single_a, |
michael@0 | 929 | set_single, empty_set); |
michael@0 | 930 | test_selector_in_html("a:-moz-locale-dir(ltR)", single_a, |
michael@0 | 931 | set_single, empty_set); |
michael@0 | 932 | test_selector_in_html("a:-moz-locale-dir(LTR)", single_a, |
michael@0 | 933 | set_single, empty_set); |
michael@0 | 934 | test_selector_in_html("a:-moz-locale-dir(RTl)", single_a, |
michael@0 | 935 | empty_set, set_single); |
michael@0 | 936 | } else { |
michael@0 | 937 | test_selector_in_html("a:-moz-locale-dir(RTl)", single_a, |
michael@0 | 938 | set_single, empty_set); |
michael@0 | 939 | test_selector_in_html("a:-moz-locale-dir(rtL)", single_a, |
michael@0 | 940 | set_single, empty_set); |
michael@0 | 941 | test_selector_in_html("a:-moz-locale-dir(RTL)", single_a, |
michael@0 | 942 | set_single, empty_set); |
michael@0 | 943 | test_selector_in_html("a:-moz-locale-dir(LTr)", single_a, |
michael@0 | 944 | empty_set, set_single); |
michael@0 | 945 | } |
michael@0 | 946 | |
michael@0 | 947 | test_balanced_unparseable(":-moz-locale-dir(other)"); |
michael@0 | 948 | test_balanced_unparseable(":-moz-locale-dir()"); |
michael@0 | 949 | test_balanced_unparseable(":-moz-locale-dir(())"); |
michael@0 | 950 | test_balanced_unparseable(":-moz-locale-dir(3())"); |
michael@0 | 951 | test_balanced_unparseable(":-moz-locale-dir(f{})"); |
michael@0 | 952 | test_balanced_unparseable(":-moz-locale-dir('ltr')"); |
michael@0 | 953 | test_balanced_unparseable(":-moz-locale-dir(ltr, other)"); |
michael@0 | 954 | test_balanced_unparseable(":-moz-locale-dir"); |
michael@0 | 955 | |
michael@0 | 956 | // Test :-moz-dir() |
michael@0 | 957 | test_parseable(":-moz-dir(ltr)"); |
michael@0 | 958 | test_parseable(":-moz-dir(rtl)"); |
michael@0 | 959 | test_parseable(":-moz-dir(rTl)"); |
michael@0 | 960 | test_parseable(":-moz-dir(LTR)"); |
michael@0 | 961 | if (document.body.mozMatchesSelector(":-moz-dir(ltr)")) { |
michael@0 | 962 | test_selector_in_html("a:-moz-dir(LTr)", single_a, |
michael@0 | 963 | set_single, empty_set); |
michael@0 | 964 | test_selector_in_html("a:-moz-dir(ltR)", single_a, |
michael@0 | 965 | set_single, empty_set); |
michael@0 | 966 | test_selector_in_html("a:-moz-dir(LTR)", single_a, |
michael@0 | 967 | set_single, empty_set); |
michael@0 | 968 | test_selector_in_html("a:-moz-dir(RTl)", single_a, |
michael@0 | 969 | empty_set, set_single); |
michael@0 | 970 | } else { |
michael@0 | 971 | test_selector_in_html("a:-moz-dir(RTl)", single_a, |
michael@0 | 972 | set_single, empty_set); |
michael@0 | 973 | test_selector_in_html("a:-moz-dir(rtL)", single_a, |
michael@0 | 974 | set_single, empty_set); |
michael@0 | 975 | test_selector_in_html("a:-moz-dir(RTL)", single_a, |
michael@0 | 976 | set_single, empty_set); |
michael@0 | 977 | test_selector_in_html("a:-moz-dir(LTr)", single_a, |
michael@0 | 978 | empty_set, set_single); |
michael@0 | 979 | } |
michael@0 | 980 | |
michael@0 | 981 | test_balanced_unparseable(":-moz-dir(other)"); |
michael@0 | 982 | test_balanced_unparseable(":-moz-dir()"); |
michael@0 | 983 | test_balanced_unparseable(":-moz-dir(())"); |
michael@0 | 984 | test_balanced_unparseable(":-moz-dir(3())"); |
michael@0 | 985 | test_balanced_unparseable(":-moz-dir(f{})"); |
michael@0 | 986 | test_balanced_unparseable(":-moz-dir('ltr')"); |
michael@0 | 987 | test_balanced_unparseable(":-moz-dir(ltr, other)"); |
michael@0 | 988 | test_balanced_unparseable(":-moz-dir"); |
michael@0 | 989 | |
michael@0 | 990 | // Test -moz-lwtheme and -moz-lwtheme-[darktext|brighttext] |
michael@0 | 991 | test_parseable(":-moz-lwtheme"); |
michael@0 | 992 | test_parseable(":-moz-lwtheme-brighttext"); |
michael@0 | 993 | test_parseable(":-moz-lwtheme-darktext"); |
michael@0 | 994 | |
michael@0 | 995 | test_parseable(":-moz-tree-row(selected)"); |
michael@0 | 996 | test_parseable("::-moz-tree-row(selected)"); |
michael@0 | 997 | test_parseable(":-moz-tree-row(selected focus)"); |
michael@0 | 998 | test_parseable(":-moz-tree-row(selected , focus)"); |
michael@0 | 999 | test_parseable("::-moz-tree-row(selected ,focus)"); |
michael@0 | 1000 | test_parseable(":-moz-tree-row(selected, focus)"); |
michael@0 | 1001 | test_parseable("::-moz-tree-row(selected,focus)"); |
michael@0 | 1002 | test_parseable(":-moz-tree-row(selected focus)"); |
michael@0 | 1003 | test_parseable("::-moz-tree-row(selected , focus)"); |
michael@0 | 1004 | test_parseable("::-moz-tree-twisty( hover open )"); |
michael@0 | 1005 | test_balanced_unparseable("::-moz-tree-row(selected {[]} )"); |
michael@0 | 1006 | test_balanced_unparseable(":-moz-tree-twisty(open())"); |
michael@0 | 1007 | test_balanced_unparseable("::-moz-tree-twisty(hover ())"); |
michael@0 | 1008 | |
michael@0 | 1009 | test_parseable(":-moz-window-inactive"); |
michael@0 | 1010 | test_parseable("div p:-moz-window-inactive:hover span"); |
michael@0 | 1011 | |
michael@0 | 1012 | // Plugin pseudoclasses |
michael@0 | 1013 | test_parseable(":-moz-type-unsupported"); |
michael@0 | 1014 | test_parseable(":-moz-handler-disabled"); |
michael@0 | 1015 | test_parseable(":-moz-handler-blocked"); |
michael@0 | 1016 | test_parseable(":-moz-handler-crashed"); |
michael@0 | 1017 | |
michael@0 | 1018 | // Case sensitivity of tag selectors |
michael@0 | 1019 | function setup_cased_spans(body) { |
michael@0 | 1020 | var data = [ |
michael@0 | 1021 | { tag: "span" }, |
michael@0 | 1022 | { tag: "sPaN" }, |
michael@0 | 1023 | { tag: "Span" }, |
michael@0 | 1024 | { tag: "SPAN" }, |
michael@0 | 1025 | { ns: "http://www.w3.org/1999/xhtml", tag: "span" }, |
michael@0 | 1026 | { ns: "http://www.w3.org/1999/xhtml", tag: "sPaN" }, |
michael@0 | 1027 | { ns: "http://www.w3.org/1999/xhtml", tag: "Span" }, |
michael@0 | 1028 | { ns: "http://www.w3.org/1999/xhtml", tag: "SPAN" }, |
michael@0 | 1029 | { ns: "http://example.com/useless", tag: "span" }, |
michael@0 | 1030 | { ns: "http://example.com/useless", tag: "sPaN" }, |
michael@0 | 1031 | { ns: "http://example.com/useless", tag: "Span" }, |
michael@0 | 1032 | { ns: "http://example.com/useless", tag: "SPAN" }, |
michael@0 | 1033 | ] |
michael@0 | 1034 | for (var i in data) { |
michael@0 | 1035 | var ent = data[i]; |
michael@0 | 1036 | var elem; |
michael@0 | 1037 | if ("ns" in ent) { |
michael@0 | 1038 | elem = body.ownerDocument.createElementNS(ent.ns, ent.tag); |
michael@0 | 1039 | } else { |
michael@0 | 1040 | elem = body.ownerDocument.createElement(ent.tag); |
michael@0 | 1041 | } |
michael@0 | 1042 | body.appendChild(elem); |
michael@0 | 1043 | } |
michael@0 | 1044 | } |
michael@0 | 1045 | function bodychildset(indices) { |
michael@0 | 1046 | return function bodychildset_filter(doc) { |
michael@0 | 1047 | var body = doc.body; |
michael@0 | 1048 | var result = []; |
michael@0 | 1049 | for (var i in indices) { |
michael@0 | 1050 | result.push(body.childNodes[indices[i]]); |
michael@0 | 1051 | } |
michael@0 | 1052 | return result; |
michael@0 | 1053 | } |
michael@0 | 1054 | } |
michael@0 | 1055 | test_selector_in_html("span", setup_cased_spans, |
michael@0 | 1056 | bodychildset([0, 1, 2, 3, 4, 8]), |
michael@0 | 1057 | bodychildset([5, 6, 7, 9, 10, 11])); |
michael@0 | 1058 | test_selector_in_html("sPaN", setup_cased_spans, |
michael@0 | 1059 | bodychildset([0, 1, 2, 3, 4, 9]), |
michael@0 | 1060 | bodychildset([5, 6, 7, 8, 10, 11])); |
michael@0 | 1061 | test_selector_in_html("Span", setup_cased_spans, |
michael@0 | 1062 | bodychildset([0, 1, 2, 3, 4, 10]), |
michael@0 | 1063 | bodychildset([5, 6, 7, 8, 9, 11])); |
michael@0 | 1064 | test_selector_in_html("SPAN", setup_cased_spans, |
michael@0 | 1065 | bodychildset([0, 1, 2, 3, 4, 11]), |
michael@0 | 1066 | bodychildset([5, 6, 7, 8, 9, 10])); |
michael@0 | 1067 | |
michael@0 | 1068 | // bug 528096 (tree pseudos) |
michael@0 | 1069 | test_unbalanced_unparseable(":-moz-tree-column((){} a"); |
michael@0 | 1070 | test_unbalanced_unparseable(":-moz-tree-column(x(){} a"); |
michael@0 | 1071 | test_unbalanced_unparseable(":-moz-tree-column(a b (){} a"); |
michael@0 | 1072 | test_unbalanced_unparseable(":-moz-tree-column(a, b (){} a"); |
michael@0 | 1073 | |
michael@0 | 1074 | // Bug 543428 (escaping) |
michael@0 | 1075 | test_selector_in_html("\\32|a", single_a, set_single, empty_set, |
michael@0 | 1076 | "@namespace \\32 url(http://www.w3.org/1999/xhtml);"); |
michael@0 | 1077 | test_selector_in_html("-\\32|a", single_a, set_single, empty_set, |
michael@0 | 1078 | "@namespace -\\32 url(http://www.w3.org/1999/xhtml);"); |
michael@0 | 1079 | test_selector_in_html("\\2|a", single_a, set_single, empty_set, |
michael@0 | 1080 | "@namespace \\0002 url(http://www.w3.org/1999/xhtml);"); |
michael@0 | 1081 | test_selector_in_html("-\\2|a", single_a, set_single, empty_set, |
michael@0 | 1082 | "@namespace -\\000002 url(http://www.w3.org/1999/xhtml);"); |
michael@0 | 1083 | var spans = "<span class='2'></span><span class=''></span>" + |
michael@0 | 1084 | "<span id='2'></span><span id=''></span>" |
michael@0 | 1085 | test_selector_in_html(".\\32", spans, |
michael@0 | 1086 | bodychildset([0]), bodychildset([1, 2, 3])); |
michael@0 | 1087 | test_selector_in_html("[class=\\32]", spans, |
michael@0 | 1088 | bodychildset([0]), bodychildset([1, 2, 3])); |
michael@0 | 1089 | test_selector_in_html(".\\2", spans, |
michael@0 | 1090 | bodychildset([1]), bodychildset([0, 2, 3])); |
michael@0 | 1091 | test_selector_in_html("[class=\\2]", spans, |
michael@0 | 1092 | bodychildset([1]), bodychildset([0, 2, 3])); |
michael@0 | 1093 | test_selector_in_html("#\\32", spans, |
michael@0 | 1094 | bodychildset([2]), bodychildset([0, 1, 3])); |
michael@0 | 1095 | test_selector_in_html("[id=\\32]", spans, |
michael@0 | 1096 | bodychildset([2]), bodychildset([0, 1, 3])); |
michael@0 | 1097 | test_selector_in_html("#\\2", spans, |
michael@0 | 1098 | bodychildset([3]), bodychildset([0, 1, 2])); |
michael@0 | 1099 | test_selector_in_html("[id=\\2]", spans, |
michael@0 | 1100 | bodychildset([3]), bodychildset([0, 1, 2])); |
michael@0 | 1101 | test_balanced_unparseable("#2"); |
michael@0 | 1102 | |
michael@0 | 1103 | // Bug 553805: :not() containing nothing is forbidden |
michael@0 | 1104 | test_balanced_unparseable(":not()"); |
michael@0 | 1105 | test_balanced_unparseable(":not( )"); |
michael@0 | 1106 | test_balanced_unparseable(":not( \t\n )"); |
michael@0 | 1107 | test_balanced_unparseable(":not(/*comment*/)"); |
michael@0 | 1108 | test_balanced_unparseable(":not( /*comment*/ /* comment */ )"); |
michael@0 | 1109 | test_balanced_unparseable("p :not()"); |
michael@0 | 1110 | test_balanced_unparseable("p :not( )"); |
michael@0 | 1111 | test_balanced_unparseable("p :not( \t\n )"); |
michael@0 | 1112 | test_balanced_unparseable("p :not(/*comment*/)"); |
michael@0 | 1113 | test_balanced_unparseable("p :not( /*comment*/ /* comment */ )"); |
michael@0 | 1114 | test_balanced_unparseable("p:not()"); |
michael@0 | 1115 | test_balanced_unparseable("p:not( )"); |
michael@0 | 1116 | test_balanced_unparseable("p:not( \t\n )"); |
michael@0 | 1117 | test_balanced_unparseable("p:not(/*comment*/)"); |
michael@0 | 1118 | test_balanced_unparseable("p:not( /*comment*/ /* comment */ )"); |
michael@0 | 1119 | |
michael@0 | 1120 | test_balanced_unparseable(":not(:nth-child(2k))"); |
michael@0 | 1121 | test_balanced_unparseable(":not(:nth-child(()))"); |
michael@0 | 1122 | |
michael@0 | 1123 | // :-moz-any() |
michael@0 | 1124 | test_balanced_unparseable(":-moz-any()"); |
michael@0 | 1125 | test_balanced_unparseable(":-moz-any(div p)"); |
michael@0 | 1126 | test_balanced_unparseable(":-moz-any(div ~ p)"); |
michael@0 | 1127 | test_balanced_unparseable(":-moz-any(div~p)"); |
michael@0 | 1128 | test_balanced_unparseable(":-moz-any(div + p)"); |
michael@0 | 1129 | test_balanced_unparseable(":-moz-any(div+p)"); |
michael@0 | 1130 | test_balanced_unparseable(":-moz-any(div > p)"); |
michael@0 | 1131 | test_balanced_unparseable(":-moz-any(div>p)"); |
michael@0 | 1132 | test_parseable(":-moz-any(div, p)"); |
michael@0 | 1133 | test_parseable(":-moz-any( div , p )"); |
michael@0 | 1134 | test_parseable(":-moz-any(div,p)"); |
michael@0 | 1135 | test_parseable(":-moz-any(div)"); |
michael@0 | 1136 | test_parseable(":-moz-any(div,p,:link,span:focus)"); |
michael@0 | 1137 | test_parseable(":-moz-any(:active,:focus)"); |
michael@0 | 1138 | test_parseable(":-moz-any(:active,:link:focus)"); |
michael@0 | 1139 | test_balanced_unparseable(":-moz-any(div,:nonexistentpseudo)"); |
michael@0 | 1140 | var any_elts = "<input type='text'><a href='http://www.example.com/'></a><div></div><a name='foo'>"; |
michael@0 | 1141 | test_selector_in_html(":-moz-any(a,input)", any_elts, |
michael@0 | 1142 | bodychildset([0, 1, 3]), bodychildset([2])); |
michael@0 | 1143 | test_selector_in_html(":-moz-any(:link,:not(a))", any_elts, |
michael@0 | 1144 | bodychildset([0, 1, 2]), bodychildset([3])); |
michael@0 | 1145 | test_selector_in_html(":-moz-any([href],input[type],input[name])", any_elts, |
michael@0 | 1146 | bodychildset([0, 1]), bodychildset([2, 3])); |
michael@0 | 1147 | test_selector_in_html(":-moz-any(div,a):-moz-any([type],[href],[name])", |
michael@0 | 1148 | any_elts, |
michael@0 | 1149 | bodychildset([1, 3]), bodychildset([0, 2])); |
michael@0 | 1150 | |
michael@0 | 1151 | test_selector_in_html(":-moz-table-border-nonzero", |
michael@0 | 1152 | "<p></p>" + |
michael@0 | 1153 | "<p border='2'></p>" + |
michael@0 | 1154 | "<table border='2'></table>" + |
michael@0 | 1155 | "<table border></table>" + |
michael@0 | 1156 | "<table></table>" + |
michael@0 | 1157 | "<table frame='border'></table>" + |
michael@0 | 1158 | "<table border='0'></table>" + |
michael@0 | 1159 | "<table border='0pt'></table>" + |
michael@0 | 1160 | "<table border='3pt'></table>", |
michael@0 | 1161 | bodychildset([2, 3, 8]), |
michael@0 | 1162 | bodychildset([0, 1, 4, 5, 6, 7])); |
michael@0 | 1163 | |
michael@0 | 1164 | // Test that we don't tokenize an empty HASH. |
michael@0 | 1165 | test_balanced_unparseable("#"); |
michael@0 | 1166 | test_balanced_unparseable("# "); |
michael@0 | 1167 | test_balanced_unparseable("#, p"); |
michael@0 | 1168 | test_balanced_unparseable("# , p"); |
michael@0 | 1169 | test_balanced_unparseable("p #"); |
michael@0 | 1170 | test_balanced_unparseable("p # "); |
michael@0 | 1171 | test_balanced_unparseable("p #, p"); |
michael@0 | 1172 | test_balanced_unparseable("p # , p"); |
michael@0 | 1173 | |
michael@0 | 1174 | // Test that a backslash alone at EOF outside of a string is treated |
michael@0 | 1175 | // as U+FFFD. |
michael@0 | 1176 | test_parseable_via_api("#a\\"); |
michael@0 | 1177 | test_parseable_via_api("#\\"); |
michael@0 | 1178 | test_parseable_via_api("\\"); |
michael@0 | 1179 | |
michael@0 | 1180 | // Test that newline escapes are only supported in strings. |
michael@0 | 1181 | test_balanced_unparseable("di\\\nv"); |
michael@0 | 1182 | test_balanced_unparseable("div \\\n p"); |
michael@0 | 1183 | test_balanced_unparseable("div\\\n p"); |
michael@0 | 1184 | test_balanced_unparseable("div \\\np"); |
michael@0 | 1185 | test_balanced_unparseable("div\\\np"); |
michael@0 | 1186 | |
michael@0 | 1187 | // Test that :-moz-placeholder is parsable. |
michael@0 | 1188 | test_parseable(":-moz-placeholder"); |
michael@0 | 1189 | |
michael@0 | 1190 | run_deferred_tests(); |
michael@0 | 1191 | } |
michael@0 | 1192 | |
michael@0 | 1193 | var deferred_tests = []; |
michael@0 | 1194 | |
michael@0 | 1195 | function defer_clonedoc_tests(docurl, onloadfunc) |
michael@0 | 1196 | { |
michael@0 | 1197 | deferred_tests.push( { docurl: docurl, onloadfunc: onloadfunc } ); |
michael@0 | 1198 | } |
michael@0 | 1199 | |
michael@0 | 1200 | function run_deferred_tests() |
michael@0 | 1201 | { |
michael@0 | 1202 | if (deferred_tests.length == 0) { |
michael@0 | 1203 | SimpleTest.finish(); |
michael@0 | 1204 | return; |
michael@0 | 1205 | } |
michael@0 | 1206 | |
michael@0 | 1207 | cloneiframe.onload = deferred_tests_onload; |
michael@0 | 1208 | cloneiframe.src = deferred_tests[0].docurl; |
michael@0 | 1209 | } |
michael@0 | 1210 | |
michael@0 | 1211 | function deferred_tests_onload(event) |
michael@0 | 1212 | { |
michael@0 | 1213 | if (event.target != cloneiframe) |
michael@0 | 1214 | return; |
michael@0 | 1215 | |
michael@0 | 1216 | deferred_tests[0].onloadfunc(); |
michael@0 | 1217 | deferred_tests.shift(); |
michael@0 | 1218 | |
michael@0 | 1219 | run_deferred_tests(); |
michael@0 | 1220 | } |
michael@0 | 1221 | |
michael@0 | 1222 | </script> |
michael@0 | 1223 | </pre> |
michael@0 | 1224 | </body> |
michael@0 | 1225 | </html> |