tor-browser

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

HTMLSlotElement-interface.html (16485B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Shadow DOM: HTMLSlotElement interface</title>
      5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
      6 <meta name="assert" content="HTMLSlotElement must exist on window with name attribute and getAssignedNode() method">
      7 <link rel="help" href="https://w3c.github.io/webcomponents/spec/shadow/#the-slot-element">
      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 test(function () {
     16    assert_true('HTMLSlotElement' in window, 'HTMLSlotElement must be defined on window');
     17    assert_equals(Object.getPrototypeOf(HTMLSlotElement.prototype), HTMLElement.prototype, 'HTMLSlotElement should inherit from HTMLElement');
     18    assert_true(document.createElement('slot') instanceof HTMLSlotElement, 'slot element should be an instance of HTMLSlotElement');
     19    assert_true(document.createElement('slot') instanceof HTMLElement, 'slot element should be an instance of HTMLElement');
     20 }, 'HTMLSlotElement must be defined on window');
     21 
     22 test(function () {
     23    assert_true('name' in HTMLSlotElement.prototype, '"name" attribute must be defined on HTMLSlotElement.prototype');
     24 
     25    var slotElement = document.createElement('slot');
     26    assert_equals(slotElement.name, '', '"name" attribute must return the empty string when "name" content attribute is not set');
     27 
     28    slotElement.setAttribute('name', 'foo');
     29    assert_equals(slotElement.name, 'foo', '"name" attribute must return the value of the "name" content attribute');
     30 
     31    slotElement.name = 'bar';
     32    assert_equals(slotElement.name, 'bar', '"name" attribute must return the assigned value');
     33    assert_equals(slotElement.getAttribute('name'), 'bar', '"name" attribute must update the "name" content attribute');
     34 }, '"name" attribute on HTMLSlotElement must reflect "name" attribute');
     35 
     36 function testSlotOutsideShadowTree(options)
     37 {
     38    test(function () {
     39        assert_true('assignedNodes' in HTMLSlotElement.prototype, '"assignedNodes" method must be defined on HTMLSlotElement.prototype');
     40 
     41        var slotElement = document.createElement('slot');
     42        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() must return an empty array when the slot element is not in any tree');
     43 
     44        document.body.appendChild(slotElement);
     45        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() must return an empty array when the slot element is in a document tree');
     46 
     47    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '')
     48        + ') on a HTMLSlotElement must return an empty array when the slot element is not in a tree or in a document tree');
     49 }
     50 
     51 testSlotOutsideShadowTree(null);
     52 testSlotOutsideShadowTree({flattened: false});
     53 testSlotOutsideShadowTree({flattened: true});
     54 
     55 function testSingleLevelOfSlotting(options)
     56 {
     57    test(function () {
     58        assert_true('assignedNodes' in HTMLSlotElement.prototype, '"assignedNodes" method must be defined on HTMLSlotElement.prototype');
     59 
     60        var shadowHost = document.createElement('div');
     61        var child = document.createElement('p');
     62 
     63        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
     64        var slotElement = document.createElement('slot');
     65        shadowRoot.appendChild(slotElement);
     66 
     67        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() must return an empty array when there are no nodes in the shadow tree');
     68 
     69        shadowHost.appendChild(child);
     70        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes() on a default slot must return an element without slot element');
     71 
     72        child.setAttribute('slot', 'foo');
     73        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() on a default slot must not return an element with non-empty slot attribute');
     74 
     75        child.setAttribute('slot', '');
     76        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes() on a default slot must return an element with empty slot attribute');
     77 
     78        slotElement.setAttribute('name', 'bar');
     79        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes() on a named slot must not return an element with empty slot attribute');
     80 
     81        slotElement.setAttribute('name', '');
     82        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes() on an empty name slot must return an element with empty slot attribute');
     83 
     84    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '') + ') must return the list of assigned nodes when none of the assigned nodes themselves are slots');
     85 }
     86 
     87 testSingleLevelOfSlotting(null);
     88 testSingleLevelOfSlotting({flattened: false});
     89 testSingleLevelOfSlotting({flattened: true});
     90 
     91 function testMutatingSlottedContents(options)
     92 {
     93    test(function () {
     94        var shadowHost = document.createElement('div');
     95        var p = document.createElement('p');
     96        var b = document.createElement('b');
     97        shadowHost.appendChild(p);
     98        shadowHost.appendChild(b);
     99 
    100        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
    101        var slotElement = document.createElement('slot');
    102        shadowRoot.appendChild(slotElement);
    103 
    104        assert_array_equals(slotElement.assignedNodes(options), [p, b], 'assignedNodes must return the distributed nodes');
    105 
    106        slotElement.name = 'foo';
    107        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes must be empty when there are no matching elements for the slot name');
    108 
    109        b.slot = 'foo';
    110        assert_array_equals(slotElement.assignedNodes(options), [b], 'assignedNodes must return the nodes with the matching slot name');
    111 
    112        p.slot = 'foo';
    113        assert_array_equals(slotElement.assignedNodes(options), [p, b], 'assignedNodes must return the nodes with the matching slot name in the tree order');
    114 
    115        slotElement.removeAttribute('name');
    116        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes must be empty for a default slot when all elements have "slot" attributes specified');
    117 
    118    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '') + ') must update when slot and name attributes are modified');
    119 }
    120 
    121 testMutatingSlottedContents(null);
    122 testMutatingSlottedContents({flattened: false});
    123 testMutatingSlottedContents({flattened: true});
    124 
    125 function testMutatingSlotName(options)
    126 {
    127    test(function () {
    128        var shadowHost = document.createElement('div');
    129        var child = document.createElement('span');
    130        shadowHost.appendChild(child);
    131 
    132        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
    133        var slotElement = document.createElement('slot');
    134        slotElement.name = 'foo';
    135        shadowRoot.appendChild(slotElement);
    136 
    137        assert_array_equals(slotElement.assignedNodes(options), [], 'assignedNodes must be empty when there are no matching elements for the slot name');
    138 
    139        slotElement.removeAttribute('name');
    140        assert_array_equals(slotElement.assignedNodes(options), [child], 'assignedNodes must be empty when there are no matching elements for the slot name');
    141 
    142    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '') + ') must update when a default slot is introduced dynamically by a slot rename');
    143 }
    144 
    145 testMutatingSlotName(null);
    146 testMutatingSlotName({flattened: false});
    147 testMutatingSlotName({flattened: true});
    148 
    149 function testInsertingAndRemovingSlots(options)
    150 {
    151    test(function () {
    152        var shadowHost = document.createElement('div');
    153        var p = document.createElement('p');
    154        var text = document.createTextNode('');
    155        var comment = document.createComment('');
    156        var processingInstruction = document.createProcessingInstruction('target', 'data');
    157        var b = document.createElement('b');
    158        shadowHost.appendChild(p);
    159        shadowHost.appendChild(text);
    160        shadowHost.appendChild(comment);
    161        shadowHost.appendChild(processingInstruction);
    162        shadowHost.appendChild(b);
    163 
    164        var shadowRoot = shadowHost.attachShadow({mode: 'open'});
    165 
    166        var firstSlotElement = document.createElement('slot');
    167        shadowRoot.appendChild(firstSlotElement);
    168 
    169        var secondSlotElement = document.createElement('slot');
    170        shadowRoot.appendChild(secondSlotElement);
    171 
    172        assert_array_equals(firstSlotElement.assignedNodes(options), [p, text, b],
    173            'assignedNodes on a default slot must return the elements without slot attributes and text nodes');
    174        assert_array_equals(secondSlotElement.assignedNodes(options), [],
    175            'assignedNodes on the second unnamed slot element must return an empty array');
    176 
    177        shadowRoot.removeChild(firstSlotElement);
    178        assert_array_equals(firstSlotElement.assignedNodes(options), [],
    179            'assignedNodes on a detached formerly-default slot must return an empty array');
    180        assert_array_equals(secondSlotElement.assignedNodes(options), [p, text, b],
    181            'assignedNodes on the second unnamed slot element after removing the first must return the elements without slot attributes and text nodes');
    182 
    183        shadowRoot.removeChild(secondSlotElement);
    184        shadowRoot.appendChild(secondSlotElement);
    185        assert_array_equals(firstSlotElement.assignedNodes(options), [],
    186            'Removing and re-inserting a default slot must not change the result of assignedNodes on a detached slot');
    187        assert_array_equals(secondSlotElement.assignedNodes(options), [p, text, b],
    188            'Removing and re-inserting a default slot must not change the result of assignedNodes');
    189 
    190        shadowRoot.insertBefore(firstSlotElement, secondSlotElement);
    191        assert_array_equals(firstSlotElement.assignedNodes(options), [p, text, b],
    192            'assignedNodes on a newly inserted unnamed slot element must return the elements without slot attributes and text nodes');
    193        assert_array_equals(secondSlotElement.assignedNodes(options), [],
    194            'assignedNodes on formerly-first but now second unnamed slot element must return an empty array');
    195 
    196    }, 'assignedNodes(' + (options ? JSON.stringify(options) : '') + ') must update when slot elements are inserted or removed');
    197 }
    198 
    199 testInsertingAndRemovingSlots(null);
    200 testInsertingAndRemovingSlots({flattened: false});
    201 testInsertingAndRemovingSlots({flattened: true});
    202 
    203 test(function () {
    204    var outerHost = document.createElement('div');
    205    var outerChild = document.createElement('span');
    206    outerHost.appendChild(outerChild);
    207 
    208    var outerShadow = outerHost.attachShadow({mode: 'closed'});
    209    var innerHost = document.createElement('div');
    210    var outerSlot = document.createElement('slot');
    211    var innerChild = document.createElement('b');
    212    outerShadow.appendChild(innerHost);
    213    innerHost.appendChild(outerSlot);
    214    innerHost.appendChild(innerChild);
    215 
    216    var innerShadow = innerHost.attachShadow({mode: 'closed'});
    217    var innerSlot = document.createElement('slot');
    218    innerShadow.appendChild(innerSlot);
    219 
    220    assert_array_equals(outerSlot.assignedNodes(), [outerChild], 'assignedNodes() on a default slot must return the assigned nodes');
    221    assert_array_equals(outerSlot.assignedNodes({flatten: false}), [outerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
    222    assert_array_equals(outerSlot.assignedNodes({flatten: true}), [outerChild], 'assignedNodes({flatten: true}) on a default slot must return the assigned nodes if they are not themselves slots');
    223 
    224    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
    225    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
    226    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
    227 
    228    outerSlot.name = 'foo';
    229    assert_array_equals(outerSlot.assignedNodes(), [], 'assignedNodes() on a named slot must return an empty array if there are no matching elements');
    230    assert_array_equals(outerSlot.assignedNodes({flatten: false}), [], 'assignedNodes({flatten: false}) on a named slot must return an empty array if there are no matching elements');
    231    assert_array_equals(outerSlot.assignedNodes({flatten: true}), [], 'assignedNodes({flatten: true}) on a named slot must return an empty array if there are no matching elements');
    232 
    233    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
    234    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
    235    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
    236 
    237    outerChild.slot = 'foo';
    238    assert_array_equals(outerSlot.assignedNodes(), [outerChild], 'assignedNodes() on a named slot must return matching elements');
    239    assert_array_equals(outerSlot.assignedNodes({flatten: false}), [outerChild], 'assignedNodes({flatten: false}) on a named slot must return matching elements');
    240    assert_array_equals(outerSlot.assignedNodes({flatten: true}), [outerChild], 'assignedNodes({flatten: true}) on a named slot must return matching elements');
    241 
    242    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
    243    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
    244    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
    245 
    246    var newInnerSlot = document.createElement('slot');
    247    innerShadow.insertBefore(newInnerSlot, innerSlot);
    248    assert_array_equals(newInnerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
    249    assert_array_equals(newInnerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
    250    assert_array_equals(newInnerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
    251 
    252    assert_array_equals(innerSlot.assignedNodes(), [], 'assignedNodes() on a nameless slot element which appears after a default slot must return an empty array');
    253    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [], 'assignedNodes({flatten: false}) on a nameless slot element which appears after a default slot must return an empty array');
    254    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [], 'assignedNodes({flatten: true}) on a nameless slot element which appears after a default slot must return an empty array');
    255 
    256    innerShadow.removeChild(newInnerSlot);
    257    assert_array_equals(newInnerSlot.assignedNodes(), [], 'assignedNodes() must return an empty array when the slot element is not in any tree');
    258    assert_array_equals(newInnerSlot.assignedNodes({flatten: false}), [], 'assignedNodes({flatten: false}) must return an empty array when the slot element is not in any tree');
    259    assert_array_equals(newInnerSlot.assignedNodes({flatten: true}), [], 'assignedNodes({flatten: true}) must return an empty array when the slot element is not in any tree');
    260 
    261    assert_array_equals(innerSlot.assignedNodes(), [outerSlot, innerChild], 'assignedNodes() on a default slot must return the assigned nodes');
    262    assert_array_equals(innerSlot.assignedNodes({flatten: false}), [outerSlot, innerChild], 'assignedNodes({flatten: false}) on a default slot must return the assigned nodes');
    263    assert_array_equals(innerSlot.assignedNodes({flatten: true}), [outerChild, innerChild], 'assignedNodes({flatten: true}) on a default slot must return the distributed nodes');
    264 
    265 }, 'assignedNodes({flatten: true}) must return the distributed nodes, and assignedNodes() and assignedNodes({flatten: false}) must returned the assigned nodes');
    266 
    267 </script>
    268 </body>
    269 </html>