tor-browser

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

custom-element-reaction-queue.html (10619B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Custom Elements: Each element must have its own custom element reaction queue</title>
      5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
      6 <meta name="assert" content="Each element must have its own custom element reaction queue">
      7 <meta name="help" content="https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reaction-queue">
      8 <script src="/resources/testharness.js"></script>
      9 <script src="/resources/testharnessreport.js"></script>
     10 <script src="./resources/custom-elements-helpers.js"></script>
     11 </head>
     12 <body>
     13 <div id="log"></div>
     14 <script>
     15 
     16 test_with_window(function (contentWindow) {
     17    const contentDocument = contentWindow.document;
     18    contentDocument.write('<test-element id="first-element">');
     19    contentDocument.write('<test-element id="second-element">');
     20 
     21    const element1 = contentDocument.getElementById('first-element');
     22    const element2 = contentDocument.getElementById('second-element');
     23    assert_equals(Object.getPrototypeOf(element1), contentWindow.HTMLElement.prototype);
     24    assert_equals(Object.getPrototypeOf(element2), contentWindow.HTMLElement.prototype);
     25 
     26    let log = [];
     27    class TestElement extends contentWindow.HTMLElement {
     28        constructor() {
     29            super();
     30            log.push(create_constructor_log(this));
     31        }
     32        connectedCallback(...args) {
     33            log.push(create_connected_callback_log(this, ...args));
     34        }
     35        attributeChangedCallback(...args) {
     36            log.push(create_attribute_changed_callback_log(this, ...args));
     37        }
     38        static get observedAttributes() { return ['id']; }
     39    }
     40    contentWindow.customElements.define('test-element', TestElement);
     41    assert_equals(Object.getPrototypeOf(element1), TestElement.prototype);
     42    assert_equals(Object.getPrototypeOf(element2), TestElement.prototype);
     43 
     44    assert_equals(log.length, 6);
     45    assert_constructor_log_entry(log[0], element1);
     46    assert_attribute_log_entry(log[1], {name: 'id', oldValue: null, newValue: 'first-element', namespace: null});
     47    assert_connected_log_entry(log[2], element1);
     48    assert_constructor_log_entry(log[3], element2);
     49    assert_attribute_log_entry(log[4], {name: 'id', oldValue: null, newValue: 'second-element', namespace: null});
     50    assert_connected_log_entry(log[5], element2);
     51 }, 'Upgrading a custom element must invoke attributeChangedCallback and connectedCallback before start upgrading another element');
     52 
     53 test_with_window(function (contentWindow) {
     54    const contentDocument = contentWindow.document;
     55    contentDocument.write('<test-element>');
     56 
     57    const element = contentDocument.querySelector('test-element');
     58    assert_equals(Object.getPrototypeOf(element), contentWindow.HTMLElement.prototype);
     59 
     60    let log = [];
     61    class TestElement extends contentWindow.HTMLElement {
     62        constructor() {
     63            super();
     64            this.id = "foo";
     65            this.setAttribute('id', 'foo');
     66            this.removeAttribute('id');
     67            this.style.fontSize = '10px';
     68            log.push(create_constructor_log(this));
     69        }
     70        connectedCallback(...args) {
     71            log.push(create_connected_callback_log(this, ...args));
     72        }
     73        attributeChangedCallback(...args) {
     74            log.push(create_attribute_changed_callback_log(this, ...args));
     75        }
     76        static get observedAttributes() { return ['id', 'style']; }
     77    }
     78    contentWindow.customElements.define('test-element', TestElement);
     79    assert_equals(Object.getPrototypeOf(element), TestElement.prototype);
     80 
     81    assert_equals(log.length, 2);
     82    assert_constructor_log_entry(log[0], element);
     83    assert_connected_log_entry(log[1], element);
     84 }, 'Upgrading a custom element must not invoke attributeChangedCallback for the attribute that is changed during upgrading');
     85 
     86 test_with_window(function (contentWindow) {
     87    const contentDocument = contentWindow.document;
     88    contentDocument.write('<test-element>');
     89 
     90    const element = contentDocument.querySelector('test-element');
     91    assert_equals(Object.getPrototypeOf(element), contentWindow.HTMLElement.prototype);
     92 
     93    let log = [];
     94    class TestElement extends contentWindow.HTMLElement {
     95        constructor() {
     96            super();
     97            this.remove();
     98            log.push(create_constructor_log(this));
     99        }
    100        connectedCallback(...args) {
    101            log.push(create_connected_callback_log(this, ...args));
    102        }
    103        disconnectedCallback(...args) {
    104            log.push(create_disconnected_callback_log(this, ...args));
    105        }
    106    }
    107    contentWindow.customElements.define('test-element', TestElement);
    108    assert_equals(Object.getPrototypeOf(element), TestElement.prototype);
    109 
    110    assert_equals(log.length, 2);
    111    assert_constructor_log_entry(log[0], element);
    112    assert_connected_log_entry(log[1], element);
    113 }, 'Upgrading a custom element must not invoke disconnectedCallback if the element is disconnected during upgrading');
    114 
    115 test_with_window(function (contentWindow) {
    116    const contentDocument = contentWindow.document;
    117    const element = contentDocument.createElement('test-element');
    118    assert_equals(Object.getPrototypeOf(element), contentWindow.HTMLElement.prototype);
    119 
    120    let log = [];
    121    class TestElement extends contentWindow.HTMLElement {
    122        constructor() {
    123            super();
    124            contentDocument.documentElement.appendChild(this);
    125            log.push(create_constructor_log(this));
    126        }
    127        connectedCallback(...args) {
    128            log.push(create_connected_callback_log(this, ...args));
    129        }
    130    }
    131    contentWindow.customElements.define('test-element', TestElement);
    132    contentWindow.customElements.upgrade(element);
    133 
    134    assert_equals(Object.getPrototypeOf(element), TestElement.prototype);
    135 
    136    assert_equals(log.length, 1);
    137    assert_constructor_log_entry(log[0], element);
    138 }, 'Upgrading a disconnected custom element must not invoke connectedCallback if the element is connected during upgrading');
    139 
    140 test_with_window(function (contentWindow) {
    141    const contentDocument = contentWindow.document;
    142    contentDocument.write('<test-element id="first-element">');
    143    contentDocument.write('<test-element id="second-element">');
    144 
    145    const element1 = contentDocument.getElementById('first-element');
    146    const element2 = contentDocument.getElementById('second-element');
    147    assert_equals(Object.getPrototypeOf(element1), contentWindow.HTMLElement.prototype);
    148    assert_equals(Object.getPrototypeOf(element2), contentWindow.HTMLElement.prototype);
    149 
    150    let log = [];
    151    class TestElement extends contentWindow.HTMLElement {
    152        constructor() {
    153            super();
    154            log.push(create_constructor_log(this));
    155            if (this == element1) {
    156                element2.setAttribute('title', 'hi');
    157                element2.removeAttribute('title');
    158                element2.setAttribute('class', 'foo');
    159            }
    160        }
    161        connectedCallback(...args) {
    162            log.push(create_connected_callback_log(this, ...args));
    163        }
    164        attributeChangedCallback(...args) {
    165            log.push(create_attribute_changed_callback_log(this, ...args));
    166        }
    167        static get observedAttributes() { return ['id', 'class', 'title']; }
    168    }
    169    contentWindow.customElements.define('test-element', TestElement);
    170    assert_equals(Object.getPrototypeOf(element1), TestElement.prototype);
    171    assert_equals(Object.getPrototypeOf(element2), TestElement.prototype);
    172 
    173    assert_equals(log.length, 7);
    174    assert_constructor_log_entry(log[0], element1);
    175    assert_attribute_log_entry(log[1], {name: 'id', oldValue: null, newValue: 'first-element', namespace: null});
    176    assert_connected_log_entry(log[2], element1);
    177    assert_constructor_log_entry(log[3], element2);
    178    assert_attribute_log_entry(log[4], {name: 'id', oldValue: null, newValue: 'second-element', namespace: null});
    179    assert_attribute_log_entry(log[5], {name: 'class', oldValue: null, newValue: 'foo', namespace: null});
    180    assert_connected_log_entry(log[6], element2);
    181 }, 'Mutating a undefined custom element while upgrading a custom element must not enqueue or invoke reactions on the mutated element');
    182 
    183 test_with_window(function (contentWindow) {
    184    let log = [];
    185    let element1;
    186    let element2;
    187    class TestElement extends contentWindow.HTMLElement {
    188        constructor() {
    189            super();
    190            log.push(create_constructor_log(this));
    191        }
    192        adoptedCallback(...args) {
    193            log.push(create_adopted_callback_log(this, ...args));
    194            if (this == element1)
    195                element3.setAttribute('id', 'foo');
    196        }
    197        connectedCallback(...args) {
    198            log.push(create_connected_callback_log(this, ...args));
    199        }
    200        attributeChangedCallback(...args) {
    201            log.push(create_attribute_changed_callback_log(this, ...args));
    202        }
    203        static get observedAttributes() { return ['id', 'class']; }
    204    }
    205 
    206    contentWindow.customElements.define('test-element', TestElement);
    207 
    208    let contentDocument = contentWindow.document;
    209    element1 = contentDocument.createElement('test-element');
    210    element2 = contentDocument.createElement('test-element');
    211    element3 = contentDocument.createElement('test-element');
    212    assert_equals(Object.getPrototypeOf(element1), TestElement.prototype);
    213    assert_equals(Object.getPrototypeOf(element2), TestElement.prototype);
    214    assert_equals(Object.getPrototypeOf(element3), TestElement.prototype);
    215 
    216    assert_equals(log.length, 3);
    217    assert_constructor_log_entry(log[0], element1);
    218    assert_constructor_log_entry(log[1], element2);
    219    assert_constructor_log_entry(log[2], element3);
    220    log = [];
    221 
    222    const container = contentDocument.createElement('div');
    223    container.appendChild(element1);
    224    container.appendChild(element2);
    225    container.appendChild(element3);
    226 
    227    const anotherDocument = document.implementation.createHTMLDocument();
    228    anotherDocument.documentElement.appendChild(container);
    229 
    230    assert_equals(log.length, 7);
    231    assert_adopted_log_entry(log[0], element1);
    232    assert_adopted_log_entry(log[1], element3);
    233    assert_connected_log_entry(log[2], element3);
    234    assert_attribute_log_entry(log[3], {name: 'id', oldValue: null, newValue: 'foo', namespace: null});
    235    assert_connected_log_entry(log[4], element1);
    236    assert_adopted_log_entry(log[5], element2);
    237    assert_connected_log_entry(log[6], element2);
    238 
    239 }, 'Mutating another custom element inside adopted callback must invoke all pending callbacks on the mutated element');
    240 
    241 
    242 </script>
    243 </body>
    244 </html>