layout/style/test/test_selectors.html

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

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='&#x2;'></span>" +
michael@0 1084 "<span id='2'></span><span id='&#x2;'></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>

mercurial