tor-browser

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

ParentNode-querySelector-All.js (9081B)


      1 // Require selectors.js to be included before this.
      2 
      3 /*
      4 * Create and append special elements that cannot be created correctly with HTML markup alone.
      5 */
      6 function setupSpecialElements(doc, parent) {
      7  // Setup null and undefined tests
      8  parent.appendChild(doc.createElement("null"));
      9  parent.appendChild(doc.createElement("undefined"));
     10 
     11  // Setup namespace tests
     12  var anyNS = doc.createElement("div");
     13  var noNS = doc.createElement("div");
     14  anyNS.id = "any-namespace";
     15  noNS.id = "no-namespace";
     16 
     17  var divs;
     18  div = [doc.createElement("div"),
     19         doc.createElementNS("http://www.w3.org/1999/xhtml", "div"),
     20         doc.createElementNS("", "div"),
     21         doc.createElementNS("http://www.example.org/ns", "div")];
     22 
     23  div[0].id = "any-namespace-div1";
     24  div[1].id = "any-namespace-div2";
     25  div[2].setAttribute("id", "any-namespace-div3"); // Non-HTML elements can't use .id property
     26  div[3].setAttribute("id", "any-namespace-div4");
     27 
     28  for (var i = 0; i < div.length; i++) {
     29    anyNS.appendChild(div[i])
     30  }
     31 
     32  div = [doc.createElement("div"),
     33         doc.createElementNS("http://www.w3.org/1999/xhtml", "div"),
     34         doc.createElementNS("", "div"),
     35         doc.createElementNS("http://www.example.org/ns", "div")];
     36 
     37  div[0].id = "no-namespace-div1";
     38  div[1].id = "no-namespace-div2";
     39  div[2].setAttribute("id", "no-namespace-div3"); // Non-HTML elements can't use .id property
     40  div[3].setAttribute("id", "no-namespace-div4");
     41 
     42  for (i = 0; i < div.length; i++) {
     43    noNS.appendChild(div[i])
     44  }
     45 
     46  parent.appendChild(anyNS);
     47  parent.appendChild(noNS);
     48 
     49  var span = doc.getElementById("attr-presence-i1");
     50  span.setAttributeNS("http://www.example.org/ns", "title", "");
     51 }
     52 
     53 /*
     54 * Check that the querySelector and querySelectorAll methods exist on the given Node
     55 */
     56 function interfaceCheck(type, obj) {
     57  test(function() {
     58    var q = typeof obj.querySelector === "function";
     59    assert_true(q, type + " supports querySelector.");
     60  }, type + " supports querySelector")
     61 
     62  test(function() {
     63    var qa = typeof obj.querySelectorAll === "function";
     64    assert_true( qa, type + " supports querySelectorAll.");
     65  }, type + " supports querySelectorAll")
     66 
     67  test(function() {
     68    var list = obj.querySelectorAll("div");
     69    if (obj.ownerDocument) { // The object is not a Document
     70      assert_true(list instanceof obj.ownerDocument.defaultView.NodeList, "The result should be an instance of a NodeList")
     71    } else { // The object is a Document
     72      assert_true(list instanceof obj.defaultView.NodeList, "The result should be an instance of a NodeList")
     73    }
     74  }, type + ".querySelectorAll returns NodeList instance")
     75 }
     76 
     77 /*
     78 * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after
     79 * each call. A static list should not be affected by subsequent changes to the DOM.
     80 */
     81 function verifyStaticList(type, doc, root) {
     82  var pre, post, preLength;
     83 
     84  test(function() {
     85    pre = root.querySelectorAll("div");
     86    preLength = pre.length;
     87 
     88    var div = doc.createElement("div");
     89    (root.body || root).appendChild(div);
     90 
     91    assert_equals(pre.length, preLength, "The length of the NodeList should not change.")
     92  }, type + ": static NodeList")
     93 
     94  test(function() {
     95    post = root.querySelectorAll("div"),
     96    assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.")
     97  }, type + ": new NodeList")
     98 }
     99 
    100 /*
    101 * Verify handling of special values for the selector parameter, including stringification of
    102 * null and undefined, and the handling of the empty string.
    103 */
    104 function runSpecialSelectorTests(type, root) {
    105  let global = (root.ownerDocument || root).defaultView;
    106 
    107  test(function() { // 1
    108    assert_equals(root.querySelectorAll(null).length, 1, "This should find one element with the tag name 'NULL'.");
    109  }, type + ".querySelectorAll null")
    110 
    111  test(function() { // 2
    112    assert_equals(root.querySelectorAll(undefined).length, 1, "This should find one element with the tag name 'UNDEFINED'.");
    113  }, type + ".querySelectorAll undefined")
    114 
    115  test(function() { // 3
    116    assert_throws_js(global.TypeError, function() {
    117      root.querySelectorAll();
    118    }, "This should throw a TypeError.")
    119  }, type + ".querySelectorAll no parameter")
    120 
    121  test(function() { // 4
    122    var elm = root.querySelector(null)
    123    assert_not_equals(elm, null, "This should find an element.");
    124    assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.")
    125  }, type + ".querySelector null")
    126 
    127  test(function() { // 5
    128    var elm = root.querySelector(undefined)
    129    assert_not_equals(elm, undefined, "This should find an element.");
    130    assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.")
    131  }, type + ".querySelector undefined")
    132 
    133  test(function() { // 6
    134    assert_throws_js(global.TypeError, function() {
    135      root.querySelector();
    136    }, "This should throw a TypeError.")
    137  }, type + ".querySelector no parameter")
    138 
    139  test(function() { // 7
    140    result = root.querySelectorAll("*");
    141    var i = 0;
    142    traverse(root, function(elem) {
    143      if (elem !== root) {
    144        assert_equals(elem, result[i], "The result in index " + i + " should be in tree order.");
    145        i++;
    146      }
    147    })
    148  }, type + ".querySelectorAll tree order");
    149 }
    150 
    151 /*
    152 * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll()
    153 * Only run these tests when results are expected. Don't run for syntax error tests.
    154 */
    155 function runValidSelectorTest(type, root, selectors, testType, docType) {
    156  var nodeType = "";
    157  switch (root.nodeType) {
    158    case Node.DOCUMENT_NODE:
    159      nodeType = "document";
    160      break;
    161    case Node.ELEMENT_NODE:
    162      nodeType = root.parentNode ? "element" : "detached";
    163      break;
    164    case Node.DOCUMENT_FRAGMENT_NODE:
    165      nodeType = "fragment";
    166      break;
    167    default:
    168      assert_unreached();
    169      nodeType = "unknown"; // This should never happen.
    170  }
    171 
    172  for (var i = 0; i < selectors.length; i++) {
    173    var s = selectors[i];
    174    var n = s["name"];
    175    var q = s["selector"];
    176    var e = s["expect"];
    177 
    178    if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1))
    179     && (s["testType"] & testType) ) {
    180      var foundall, found;
    181 
    182      test(function() {
    183        foundall = root.querySelectorAll(q);
    184        assert_not_equals(foundall, null, "The method should not return null.")
    185        assert_equals(foundall.length, e.length, "The method should return the expected number of matches.")
    186 
    187        for (var i = 0; i < e.length; i++) {
    188          assert_not_equals(foundall[i], null, "The item in index " + i + " should not be null.")
    189          assert_equals(foundall[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID.");
    190          assert_false(foundall[i].hasAttribute("data-clone"), "This should not be a cloned element.");
    191        }
    192      }, type + ".querySelectorAll: " + n + ": " + q);
    193 
    194      test(function() {
    195        found = root.querySelector(q);
    196 
    197        if (e.length > 0) {
    198          assert_not_equals(found, null, "The method should return a match.")
    199          assert_equals(found.getAttribute("id"), e[0], "The method should return the first match.");
    200          assert_equals(found, foundall[0], "The result should match the first item from querySelectorAll.");
    201          assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element.");
    202        } else {
    203          assert_equals(found, null, "The method should not match anything.");
    204        }
    205      }, type + ".querySelector: " + n + ": " + q);
    206    }
    207  }
    208 }
    209 
    210 function windowFor(root) {
    211  return root.defaultView || root.ownerDocument.defaultView;
    212 }
    213 
    214 /*
    215 * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll()
    216 * Only run these tests when errors are expected. Don't run for valid selector tests.
    217 */
    218 function runInvalidSelectorTest(type, root, selectors) {
    219  for (var i = 0; i < selectors.length; i++) {
    220    var s = selectors[i];
    221    var n = s["name"];
    222    var q = s["selector"];
    223 
    224    test(function() {
    225      assert_throws_dom("SyntaxError", windowFor(root).DOMException, function() {
    226        root.querySelector(q)
    227      });
    228    }, type + ".querySelector: " + n + ": " + q);
    229 
    230    test(function() {
    231      assert_throws_dom("SyntaxError", windowFor(root).DOMException, function() {
    232        root.querySelectorAll(q)
    233      });
    234    }, type + ".querySelectorAll: " + n + ": " + q);
    235  }
    236 }
    237 
    238 function traverse(elem, fn) {
    239  if (elem.nodeType === elem.ELEMENT_NODE) {
    240    fn(elem);
    241  }
    242  elem = elem.firstChild;
    243  while (elem) {
    244    traverse(elem, fn);
    245    elem = elem.nextSibling;
    246  }
    247 }
    248 
    249 function getNodeType(node) {
    250  switch (node.nodeType) {
    251    case Node.DOCUMENT_NODE:
    252      return "document";
    253    case Node.ELEMENT_NODE:
    254      return node.parentNode ? "element" : "detached";
    255    case Node.DOCUMENT_FRAGMENT_NODE:
    256      return "fragment";
    257    default:
    258      assert_unreached();
    259      return "unknown"; // This should never happen.
    260  }
    261 }