tor-browser

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

shadow-dom.js (5341B)


      1 function removeWhiteSpaceOnlyTextNodes(node)
      2 {
      3  for (var i = 0; i < node.childNodes.length; i++) {
      4    var child = node.childNodes[i];
      5    if (child.nodeType === Node.TEXT_NODE && child.nodeValue.trim().length == 0) {
      6      node.removeChild(child);
      7      i--;
      8    } else if (child.nodeType === Node.ELEMENT_NODE || child.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      9      removeWhiteSpaceOnlyTextNodes(child);
     10    }
     11  }
     12  if (node.shadowRoot) {
     13    removeWhiteSpaceOnlyTextNodes(node.shadowRoot);
     14  }
     15 }
     16 
     17 function createTestTree(node) {
     18 
     19  let ids = {};
     20 
     21  function attachShadowFromTemplate(template) {
     22    let parent = template.parentNode;
     23    parent.removeChild(template);
     24    let shadowRoot;
     25    if (template.getAttribute('data-slot-assignment') === 'manual') {
     26       shadowRoot =
     27          parent.attachShadow({mode: template.getAttribute('data-mode'),
     28                               slotAssignment: 'manual'});
     29    } else {
     30      shadowRoot = parent.attachShadow(
     31          {mode: template.getAttribute('data-mode')});
     32    }
     33    let id = template.id;
     34    if (id) {
     35      shadowRoot.id = id;
     36      ids[id] = shadowRoot;
     37    }
     38    shadowRoot.appendChild(document.importNode(template.content, true));
     39    return shadowRoot;
     40  }
     41 
     42  function walk(root) {
     43    if (root.id) {
     44      ids[root.id] = root;
     45    }
     46    for (let e of Array.from(root.querySelectorAll('[id]'))) {
     47      ids[e.id] = e;
     48    }
     49    for (let e of Array.from(root.querySelectorAll('template'))) {
     50      walk(attachShadowFromTemplate(e));
     51    }
     52  }
     53 
     54  walk(node.cloneNode(true));
     55  return ids;
     56 }
     57 
     58 // TODO: Refactor this so that only interested results are recorded.
     59 // Callers of this function would not be interested in every results.
     60 function dispatchEventWithLog(nodes, target, event, options) {
     61 
     62  function labelFor(e) {
     63    return e.id || e.tagName;
     64  }
     65 
     66  let log = [];
     67  let attachedNodes = [];
     68  for (let label in nodes) {
     69    let startingNode = nodes[label];
     70    for (let node = startingNode; node; node = node.parentNode) {
     71      if (attachedNodes.indexOf(node) >= 0)
     72        continue;
     73      let id = node.id;
     74      if (!id)
     75        continue;
     76      attachedNodes.push(node);
     77      if (options && options.capture) {
     78        // Record [currentTarget, target, relatedTarget, composedPath(), 'capture' | 'non-capture']
     79        // TODO: Support registering listeners in different orders.
     80        // e.g. Register a non-capture listener at first, then register a capture listener.
     81        node.addEventListener(event.type, (e) => {
     82          log.push([id,
     83                    labelFor(e.target),
     84                    e.relatedTarget ? labelFor(e.relatedTarget) : null,
     85                    e.composedPath().map((n) => {
     86                      return labelFor(n);
     87                    }),
     88                    'capture']);
     89        }, true);
     90        node.addEventListener(event.type, (e) => {
     91          log.push([id,
     92                    labelFor(e.target),
     93                    e.relatedTarget ? labelFor(e.relatedTarget) : null,
     94                    e.composedPath().map((n) => {
     95                      return labelFor(n);
     96                    }),
     97                    'non-capture']);
     98        });
     99      } else {
    100        // Record [currentTarget, target, relatedTarget, composedPath()]
    101        node.addEventListener(event.type, (e) => {
    102          log.push([id,
    103                    labelFor(e.target),
    104                    e.relatedTarget ? labelFor(e.relatedTarget) : null,
    105                    e.composedPath().map((n) => {
    106                      return labelFor(n);
    107                    })]
    108                  );
    109        });
    110      }
    111    }
    112  }
    113  target.dispatchEvent(event);
    114  return log;
    115 }
    116 
    117 // TODO(hayato): Merge this into dispatchEventWithLog
    118 function dispatchUAEventWithLog(nodes, target, eventType, callback) {
    119 
    120  function labelFor(e) {
    121    return e.id || e.tagName;
    122  }
    123 
    124  let log = [];
    125  let attachedNodes = [];
    126  for (let label in nodes) {
    127    let startingNode = nodes[label];
    128    for (let node = startingNode; node; node = node.parentNode) {
    129      if (attachedNodes.indexOf(node) >= 0)
    130        continue;
    131      let id = node.id;
    132      if (!id)
    133        continue;
    134      attachedNodes.push(node);
    135      node.addEventListener(eventType, (e) => {
    136        // Record [currentTarget, target, relatedTarget, composedPath()]
    137        log.push([id,
    138                  labelFor(e.target),
    139                  e.relatedTarget ? labelFor(e.relatedTarget) : null,
    140                  e.composedPath().map((n) => {
    141                    return labelFor(n);
    142                  })]);
    143      });
    144    }
    145  }
    146  callback(target);
    147  return log;
    148 }
    149 
    150 // This function assumes that testharness.js is available.
    151 function assert_event_path_equals(actual, expected) {
    152  assert_equals(actual.length, expected.length);
    153  for (let i = 0; i < actual.length; ++i) {
    154    assert_equals(actual[i].length, expected[i].length);
    155    assert_equals(actual[i][0], expected[i][0], 'currentTarget at ' + i + ' should be same');
    156    assert_equals(actual[i][1], expected[i][1], 'target at ' + i + ' should be same');
    157    assert_equals(actual[i][2], expected[i][2], 'relatedTarget at ' + i + ' should be same');
    158    assert_array_equals(actual[i][3], expected[i][3], 'composedPath at ' + i + ' should be same');
    159    if (actual[i][4]) {
    160      assert_equals(actual[i][4], expected[i][4], 'listener type should be same at ' + i);
    161    }
    162  }
    163 }