tor-browser

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

event-inside-shadow-tree.html (7601B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Shadow DOM: Firing an event inside a shadow tree</title>
      5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
      6 <meta name="assert" content="The event path calculation algorithm must be used to determine event path">
      7 <link rel="help" href="https://w3c.github.io/webcomponents/spec/shadow/#event-paths">
      8 <script src="/resources/testharness.js"></script>
      9 <script src="/resources/testharnessreport.js"></script>
     10 </head>
     11 <body>
     12 <div id="log"></div>
     13 <script>
     14 
     15 function dispatchEventWithLog(target, event) {
     16    var log = [];
     17 
     18    for (var node = target; node; node = node.parentNode || node.host) {
     19        node.addEventListener(event.type, (function (event) {
     20            log.push([this, event.target]);
     21        }).bind(node));
     22    }
     23 
     24    target.dispatchEvent(event);
     25 
     26    return log;
     27 }
     28 
     29 function createShadowRootWithGrandChild(mode) {
     30    var host = document.createElement('div');
     31    var root = host.attachShadow({mode: mode});
     32 
     33    var parent = document.createElement('span');
     34    root.appendChild(parent);
     35 
     36    var target = document.createElement('b');
     37    parent.appendChild(target);
     38    return {target: target, parent: parent, root: root, host: host};
     39 }
     40 
     41 function testEventInDetachedShadowTree(mode) {
     42    test(function () {
     43        var shadow = createShadowRootWithGrandChild(mode);
     44 
     45        log = dispatchEventWithLog(shadow.target, new Event('foo', {composed: true, bubbles: true}));
     46 
     47        assert_equals(log.length, 4, 'EventPath must contain [target, parent, shadow root, shadow host]');
     48        assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
     49        assert_array_equals(log[1], [shadow.parent, shadow.target], 'EventPath[1] must be the parent of the target');
     50        assert_array_equals(log[2], [shadow.root, shadow.target], 'EventPath[2] must be the shadow root');
     51        assert_array_equals(log[3], [shadow.host, shadow.host], 'EventPath[3] must be the shadow host');
     52 
     53    }, 'Firing an event inside a grand child of a detached ' + mode + ' mode shadow tree');
     54 }
     55 
     56 testEventInDetachedShadowTree('open');
     57 testEventInDetachedShadowTree('closed');
     58 
     59 function testEventInShadowTreeInsideDocument(mode) {
     60    test(function () {
     61        var shadow = createShadowRootWithGrandChild(mode);
     62        document.body.appendChild(shadow.host);
     63 
     64        log = dispatchEventWithLog(shadow.target, new Event('foo', {composed: true, bubbles: true}));
     65 
     66        assert_equals(log.length, 7, 'EventPath must contain [target, parent, shadow root, shadow host, body, html, document]');
     67        assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
     68        assert_array_equals(log[1], [shadow.parent, shadow.target], 'EventPath[1] must be the parent of the target');
     69        assert_array_equals(log[2], [shadow.root, shadow.target], 'EventPath[2] must be the shadow root');
     70        assert_array_equals(log[3], [shadow.host, shadow.host], 'EventPath[3] must be the shadow host');
     71        assert_array_equals(log[4], [document.body, shadow.host], 'EventPath[4] must be the body element (parent of shadow host)');
     72        assert_array_equals(log[5], [document.documentElement, shadow.host], 'EventPath[5] must be the html element');
     73        assert_array_equals(log[6], [document, shadow.host], 'EventPath[6] must be the document node');
     74 
     75    }, 'Firing an event inside a grand child of an in-document ' + mode + ' mode shadow tree');
     76 }
     77 
     78 testEventInShadowTreeInsideDocument('open');
     79 testEventInShadowTreeInsideDocument('closed');
     80 
     81 function createNestedShadowRoot(innerMode, outerMode) {
     82    var outerHost = document.createElement('div');
     83    var outerRoot = outerHost.attachShadow({mode: outerMode});
     84 
     85    var outerChild = document.createElement('p');
     86    outerRoot.appendChild(outerChild);
     87 
     88    var innerHost = document.createElement('span');
     89    outerChild.appendChild(innerHost);
     90 
     91    var innerRoot = innerHost.attachShadow({mode: innerMode});
     92    var innerChild = document.createElement('span');
     93    innerRoot.appendChild(innerChild);
     94 
     95    return {target: innerChild, innerRoot: innerRoot, innerHost: innerHost, outerChild: outerChild, outerRoot: outerRoot, outerHost: outerHost};
     96 }
     97 
     98 function testEventInDetachedNestedShadowTree(innerMode, outerMode) {
     99    test(function () {
    100        var shadow = createNestedShadowRoot(innerMode, outerMode);
    101 
    102        log = dispatchEventWithLog(shadow.target, new Event('bar', {composed: true, bubbles: true}));
    103 
    104        assert_equals(log.length, 6, 'EventPath must contain [target, inner root, inner host, parent, outer root, outer host]');
    105        assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
    106        assert_array_equals(log[1], [shadow.innerRoot, shadow.target], 'EventPath[1] must be the inner shadow root');
    107        assert_array_equals(log[2], [shadow.innerHost, shadow.innerHost], 'EventPath[2] must be the inner shadow host');
    108        assert_array_equals(log[3], [shadow.outerChild, shadow.innerHost], 'EventPath[3] must be the parent of the inner shadow host');
    109        assert_array_equals(log[4], [shadow.outerRoot, shadow.innerHost], 'EventPath[4] must be the outer shadow root');
    110        assert_array_equals(log[5], [shadow.outerHost, shadow.outerHost], 'EventPath[5] must be the outer shadow host');
    111 
    112    }, 'Firing an event inside a detached ' + innerMode + ' mode shadow tree inside ' + outerMode + ' mode shadow tree');
    113 }
    114 
    115 testEventInDetachedNestedShadowTree('open',  'open');
    116 testEventInDetachedNestedShadowTree('open',  'closed');
    117 testEventInDetachedNestedShadowTree('closed', 'open');
    118 testEventInDetachedNestedShadowTree('closed', 'closed');
    119 
    120 function testEventInNestedShadowTreeInsideDocument(innerMode, outerMode) {
    121    test(function () {
    122        var shadow = createNestedShadowRoot(innerMode, outerMode);
    123        document.body.appendChild(shadow.outerHost);
    124 
    125        log = dispatchEventWithLog(shadow.target, new Event('bar', {composed: true, bubbles: true}));
    126 
    127        assert_equals(log.length, 9, 'EventPath must contain [target, inner root, inner host, parent, outer root, outer host]');
    128        assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
    129        assert_array_equals(log[1], [shadow.innerRoot, shadow.target], 'EventPath[1] must be the inner shadow root');
    130        assert_array_equals(log[2], [shadow.innerHost, shadow.innerHost], 'EventPath[2] must be the inner shadow host');
    131        assert_array_equals(log[3], [shadow.outerChild, shadow.innerHost], 'EventPath[3] must be the parent of the inner shadow host');
    132        assert_array_equals(log[4], [shadow.outerRoot, shadow.innerHost], 'EventPath[4] must be the outer shadow root');
    133        assert_array_equals(log[5], [shadow.outerHost, shadow.outerHost], 'EventPath[5] must be the outer shadow host');
    134        assert_array_equals(log[6], [document.body, shadow.outerHost], 'EventPath[6] must be the body element');
    135        assert_array_equals(log[7], [document.documentElement, shadow.outerHost], 'EventPath[7] must be the html element');
    136        assert_array_equals(log[8], [document, shadow.outerHost], 'EventPath[8] must be the document node');
    137 
    138    }, 'Firing an event inside an in-document ' + innerMode + ' mode shadow tree inside ' + outerMode + ' mode shadow tree');
    139 }
    140 
    141 testEventInNestedShadowTreeInsideDocument('open',  'open');
    142 testEventInNestedShadowTreeInsideDocument('open',  'closed');
    143 testEventInNestedShadowTreeInsideDocument('closed', 'open');
    144 testEventInNestedShadowTreeInsideDocument('closed', 'closed');
    145 
    146 </script>
    147 </body>
    148 </html>