tor-browser

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

enqueue-custom-element-callback-reactions-inside-another-callback.html (9502B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Custom Elements: must enqueue an element on the appropriate element queue after checking callback is null and the attribute name</title>
      5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
      6 <meta name="assert" content="To enqueue a custom element callback reaction, the callback must be checked of being null and whether the attribute name is observed or not">
      7 <link rel="help" content="https://html.spec.whatwg.org/multipage/custom-elements.html#enqueue-a-custom-element-callback-reaction">
      8 <link rel="help" content="https://github.com/w3c/webcomponents/issues/760">
      9 <script src="/resources/testharness.js"></script>
     10 <script src="/resources/testharnessreport.js"></script>
     11 <script src="resources/custom-elements-helpers.js"></script>
     12 </head>
     13 <body>
     14 <script>
     15 
     16 test_with_window((contentWindow, contentDocument) => {
     17    class ParentElement extends contentWindow.HTMLElement {
     18        connectedCallback()
     19        {
     20            logs.push('begin');
     21            const child = this.firstChild;
     22            child.remove();
     23            logs.push('end');
     24        }
     25    }
     26    contentWindow.customElements.define('parent-element', ParentElement);
     27 
     28    const logs = [];
     29    class ChildElement extends contentWindow.HTMLElement {
     30        connectedCallback() { logs.push('connected'); }
     31        disconnectedCallback() { logs.push('disconnected'); }
     32    }
     33    contentWindow.customElements.define('child-element', ChildElement);
     34 
     35    const parent = new ParentElement;
     36    const child = new ChildElement;
     37    parent.appendChild(child);
     38 
     39    contentDocument.body.appendChild(parent);
     40    assert_array_equals(logs, ['begin', 'connected', 'disconnected', 'end']);
     41 }, 'Disconnecting an element with disconnectedCallback while it has a connectedCallback in its custom element reaction queue must result in connectedCallback getting invoked before the removal completes');
     42 
     43 test_with_window((contentWindow, contentDocument) => {
     44    class ParentElement extends contentWindow.HTMLElement {
     45        connectedCallback()
     46        {
     47            logs.push('begin');
     48            const child = this.firstChild;
     49            child.remove();
     50            logs.push('end');
     51        }
     52    }
     53    contentWindow.customElements.define('parent-element', ParentElement);
     54 
     55    const logs = [];
     56    class ChildElement extends contentWindow.HTMLElement {
     57        connectedCallback() { logs.push('connected'); }
     58    }
     59    contentWindow.customElements.define('child-element', ChildElement);
     60 
     61    const parent = new ParentElement;
     62    const child = new ChildElement;
     63    parent.appendChild(child);
     64 
     65    contentDocument.body.appendChild(parent);
     66    assert_array_equals(logs, ['begin', 'end', 'connected']);
     67 }, 'Disconnecting an element without disconnectedCallback while it has a connectedCallback in its custom element reaction queue must not result in connectedCallback getting invoked before the removal completes');
     68 
     69 test_with_window((contentWindow, contentDocument) => {
     70    class ParentElement extends contentWindow.HTMLElement {
     71        disconnectedCallback()
     72        {
     73            logs.push('begin');
     74            contentDocument.body.appendChild(this.firstChild);
     75            logs.push('end');
     76        }
     77    }
     78    contentWindow.customElements.define('parent-element', ParentElement);
     79 
     80    const logs = [];
     81    class ChildElement extends contentWindow.HTMLElement {
     82        connectedCallback() { logs.push('connected'); }
     83        disconnectedCallback() { logs.push('disconnected'); }
     84    }
     85    contentWindow.customElements.define('child-element', ChildElement);
     86 
     87    const parent = new ParentElement;
     88    const child = new ChildElement;
     89    parent.appendChild(child);
     90    contentDocument.body.appendChild(parent);
     91    parent.remove();
     92    assert_array_equals(logs, ['connected', 'begin', 'disconnected', 'connected', 'end']);
     93 }, 'Connecting a element with connectedCallback while it has a disconnectedCallback in its custom element reaction queue must result in disconnectedCallback getting invoked before the insertion completes');
     94 
     95 test_with_window((contentWindow, contentDocument) => {
     96    class ParentElement extends contentWindow.HTMLElement {
     97        disconnectedCallback()
     98        {
     99            logs.push('begin');
    100            contentDocument.body.appendChild(this.firstChild);
    101            logs.push('end');
    102        }
    103    }
    104    contentWindow.customElements.define('parent-element', ParentElement);
    105 
    106    const logs = [];
    107    class ChildElement extends contentWindow.HTMLElement {
    108        disconnectedCallback() { logs.push('disconnected'); }
    109    }
    110    contentWindow.customElements.define('child-element', ChildElement);
    111 
    112    const parent = new ParentElement;
    113    const child = new ChildElement;
    114    parent.appendChild(child);
    115    contentDocument.body.appendChild(parent);
    116    parent.remove();
    117    assert_array_equals(logs, ['begin', 'end', 'disconnected']);
    118 }, 'Connecting an element without connectedCallback while it has a disconnectedCallback in its custom element reaction queue must not result in disconnectedCallback getting invoked before the insertion completes');
    119 
    120 test_with_window((contentWindow, contentDocument) => {
    121    class ParentElement extends contentWindow.HTMLElement {
    122        connectedCallback()
    123        {
    124            logs.push('begin');
    125            document.adoptNode(this.firstChild);
    126            logs.push('end');
    127        }
    128    }
    129    contentWindow.customElements.define('parent-element', ParentElement);
    130 
    131    const logs = [];
    132    class ChildElement extends contentWindow.HTMLElement {
    133        adoptedCallback() { logs.push('adopted'); }
    134        connectedCallback() { logs.push('connected'); }
    135    }
    136    contentWindow.customElements.define('child-element', ChildElement);
    137 
    138    const parent = new ParentElement;
    139    const child = new ChildElement;
    140    parent.appendChild(child);
    141    contentDocument.body.appendChild(parent);
    142    assert_array_equals(logs, ['begin', 'connected', 'adopted', 'end']);
    143 }, 'Adopting an element with adoptingCallback while it has a connectedCallback in its custom element reaction queue must result in connectedCallback getting invoked before the adoption completes');
    144 
    145 test_with_window((contentWindow, contentDocument) => {
    146    class ParentElement extends contentWindow.HTMLElement {
    147        connectedCallback()
    148        {
    149            logs.push('begin');
    150            document.adoptNode(this.firstChild);
    151            logs.push('end');
    152        }
    153    }
    154    contentWindow.customElements.define('parent-element', ParentElement);
    155 
    156    const logs = [];
    157    class ChildElement extends contentWindow.HTMLElement {
    158        connectedCallback() { logs.push('connected'); }
    159    }
    160    contentWindow.customElements.define('child-element', ChildElement);
    161 
    162    const parent = new ParentElement;
    163    const child = new ChildElement;
    164    parent.appendChild(child);
    165    contentDocument.body.appendChild(parent);
    166    assert_array_equals(logs, ['begin', 'end', 'connected']);
    167 }, 'Adopting an element without adoptingCallback while it has a connectedCallback in its custom element reaction queue must not result in connectedCallback getting invoked before the adoption completes');
    168 
    169 test_with_window((contentWindow, contentDocument) => {
    170    class ParentElement extends contentWindow.HTMLElement {
    171        connectedCallback()
    172        {
    173            logs.push('begin');
    174            this.firstChild.setAttribute('title', 'foo');
    175            logs.push('end');
    176        }
    177    }
    178    contentWindow.customElements.define('parent-element', ParentElement);
    179 
    180    const logs = [];
    181    class ChildElement extends contentWindow.HTMLElement {
    182        attributeChangedCallback() { logs.push('attributeChanged'); }
    183        connectedCallback() { logs.push('connected'); }
    184        static get observedAttributes() { return ['title']; }
    185    }
    186    contentWindow.customElements.define('child-element', ChildElement);
    187 
    188    const parent = new ParentElement;
    189    const child = new ChildElement;
    190    parent.appendChild(child);
    191    contentDocument.body.appendChild(parent);
    192    assert_array_equals(logs, ['begin', 'connected', 'attributeChanged', 'end']);
    193 }, 'Setting an observed attribute on an element with attributeChangedCallback while it has a connectedCallback in its custom element reaction queue must result in connectedCallback getting invoked before the attribute change completes');
    194 
    195 test_with_window((contentWindow, contentDocument) => {
    196    class ParentElement extends contentWindow.HTMLElement {
    197        connectedCallback()
    198        {
    199            logs.push('begin');
    200            this.firstChild.setAttribute('lang', 'en');
    201            logs.push('end');
    202        }
    203    }
    204    contentWindow.customElements.define('parent-element', ParentElement);
    205 
    206    const logs = [];
    207    class ChildElement extends contentWindow.HTMLElement {
    208        attributeChangedCallback() { logs.push('attributeChanged'); }
    209        connectedCallback() { logs.push('connected'); }
    210        static get observedAttributes() { return ['title']; }
    211    }
    212    contentWindow.customElements.define('child-element', ChildElement);
    213 
    214    const parent = new ParentElement;
    215    const child = new ChildElement;
    216    parent.appendChild(child);
    217    contentDocument.body.appendChild(parent);
    218    assert_array_equals(logs, ['begin', 'end', 'connected']);
    219 }, 'Setting an observed attribute on an element with attributeChangedCallback while it has a connectedCallback in its custom element reaction queue must not result in connectedCallback getting invoked before the attribute change completes');
    220 
    221 </script>
    222 </body>
    223 </html>