tor-browser

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

Node-cloneNode.html (9126B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Custom Elements: Upgrading</title>
      5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
      6 <meta name="assert" content="Node.prototype.cloneNode should upgrade a custom element">
      7 <link rel="help" href="https://html.spec.whatwg.org/#upgrades">
      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 setup({allow_uncaught_exception:true});
     16 
     17 test(function () {
     18    class MyCustomElement extends HTMLElement {}
     19    customElements.define('my-custom-element', MyCustomElement);
     20 
     21    var instance = document.createElement('my-custom-element');
     22    assert_true(instance instanceof HTMLElement);
     23    assert_true(instance instanceof MyCustomElement);
     24 
     25    var clone = instance.cloneNode(false);
     26    assert_not_equals(instance, clone);
     27    assert_true(clone instanceof HTMLElement,
     28        'A cloned custom element must be an instance of HTMLElement');
     29    assert_true(clone instanceof MyCustomElement,
     30        'A cloned custom element must be an instance of the custom element');
     31 }, 'Node.prototype.cloneNode(false) must be able to clone a custom element');
     32 
     33 test(function () {
     34    class AutonomousCustomElement extends HTMLElement {};
     35    class IsCustomElement extends HTMLElement {};
     36 
     37    customElements.define('autonomous-custom-element', AutonomousCustomElement);
     38    customElements.define('is-custom-element', IsCustomElement);
     39 
     40    var instance = document.createElement('autonomous-custom-element', { is: "is-custom-element"});
     41    assert_true(instance instanceof HTMLElement);
     42    assert_true(instance instanceof AutonomousCustomElement);
     43 
     44    var clone = instance.cloneNode(false);
     45    assert_not_equals(instance, clone);
     46    assert_true(clone instanceof HTMLElement,
     47        'A cloned custom element must be an instance of HTMLElement');
     48    assert_true(clone instanceof AutonomousCustomElement,
     49        'A cloned custom element must be an instance of the custom element');
     50 }, 'Node.prototype.cloneNode(false) must be able to clone as a autonomous custom element when it contains is attribute');
     51 
     52 test_with_window(function (contentWindow) {
     53    var contentDocument = contentWindow.document;
     54    class MyCustomElement extends contentWindow.HTMLElement {}
     55    contentWindow.customElements.define('my-custom-element', MyCustomElement);
     56 
     57    var instance = contentDocument.createElement('my-custom-element');
     58    assert_true(instance instanceof contentWindow.HTMLElement);
     59    assert_true(instance instanceof MyCustomElement);
     60 
     61    var clone = instance.cloneNode(false);
     62    assert_not_equals(instance, clone);
     63    assert_true(clone instanceof contentWindow.HTMLElement,
     64        'A cloned custom element must be an instance of HTMLElement');
     65    assert_true(clone instanceof MyCustomElement,
     66        'A cloned custom element must be an instance of the custom element');
     67 }, 'Node.prototype.cloneNode(false) must be able to clone a custom element inside an iframe');
     68 
     69 test_with_window(function (contentWindow) {
     70    var contentDocument = contentWindow.document;
     71    class MyCustomElement extends contentWindow.HTMLElement { }
     72    contentWindow.customElements.define('my-custom-element', MyCustomElement);
     73 
     74    var instance = contentDocument.createElement('my-custom-element');
     75    var container = contentDocument.createElement('div');
     76    container.appendChild(instance);
     77 
     78    var containerClone = container.cloneNode(true);
     79    assert_true(containerClone instanceof contentWindow.HTMLDivElement);
     80 
     81    var clone = containerClone.firstChild;
     82    assert_not_equals(instance, clone);
     83    assert_true(clone instanceof contentWindow.HTMLElement,
     84        'A cloned custom element must be an instance of HTMLElement');
     85    assert_true(clone instanceof MyCustomElement,
     86        'A cloned custom element must be an instance of the custom element');
     87 }, 'Node.prototype.cloneNode(true) must be able to clone a descendent custom element');
     88 
     89 test_with_window(function (contentWindow) {
     90    var parentNodeInConstructor;
     91    var previousSiblingInConstructor;
     92    var nextSiblingInConstructor;
     93    class MyCustomElement extends contentWindow.HTMLElement {
     94        constructor() {
     95            super();
     96            parentNodeInConstructor = this.parentNode;
     97            previousSiblingInConstructor = this.previousSibling;
     98            nextSiblingInConstructor = this.nextSibling;
     99        }
    100    }
    101    contentWindow.customElements.define('my-custom-element', MyCustomElement);
    102 
    103    var contentDocument = contentWindow.document;
    104    var instance = contentDocument.createElement('my-custom-element');
    105    var siblingBeforeInstance = contentDocument.createElement('b');
    106    var siblingAfterInstance = contentDocument.createElement('a');
    107    var container = contentDocument.createElement('div');
    108    container.appendChild(siblingBeforeInstance);
    109    container.appendChild(instance);
    110    container.appendChild(siblingAfterInstance);
    111 
    112    var containerClone = container.cloneNode(true);
    113 
    114    assert_equals(parentNodeInConstructor, containerClone,
    115        'An upgraded element must have its parentNode set before the custom element constructor is called');
    116    assert_equals(previousSiblingInConstructor, containerClone.firstChild,
    117        'An upgraded element must have its previousSibling set before the custom element constructor is called');
    118    assert_equals(nextSiblingInConstructor, containerClone.lastChild,
    119        'An upgraded element must have its nextSibling set before the custom element constructor is called');
    120 }, 'Node.prototype.cloneNode(true) must set parentNode, previousSibling, and nextSibling before upgrading custom elements');
    121 
    122 // The error reporting isn't clear yet when multiple globals involved in custom
    123 // element, see w3c/webcomponents#635, so using test_with_window is not a good
    124 // idea here.
    125 test(function () {
    126    class MyCustomElement extends HTMLElement {
    127        constructor(doNotCreateItself) {
    128            super();
    129            if (!doNotCreateItself)
    130                new MyCustomElement(true);
    131        }
    132    }
    133    customElements.define('my-custom-element-constructed-after-super', MyCustomElement);
    134 
    135    var instance = new MyCustomElement(false);
    136    var uncaughtError;
    137    window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
    138    instance.cloneNode(false);
    139    assert_equals(uncaughtError.name, 'TypeError');
    140 }, 'HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed'
    141    + ' due to a custom element constructor constructing itself after super() call');
    142 
    143 test(function () {
    144    class MyCustomElement extends HTMLElement {
    145        constructor(doNotCreateItself) {
    146            if (!doNotCreateItself)
    147                new MyCustomElement(true);
    148            super();
    149        }
    150    }
    151    customElements.define('my-custom-element-constructed-before-super', MyCustomElement);
    152 
    153    var instance = new MyCustomElement(false);
    154    var uncaughtError;
    155    window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
    156    instance.cloneNode(false);
    157    assert_equals(uncaughtError.name, 'TypeError');
    158 }, 'HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed'
    159    + ' due to a custom element constructor constructing itself before super() call');
    160 
    161 test(function () {
    162    var returnSpan = false;
    163    class MyCustomElement extends HTMLElement {
    164        constructor() {
    165            super();
    166            if (returnSpan)
    167                return document.createElement('span');
    168        }
    169    }
    170    customElements.define('my-custom-element-return-another', MyCustomElement);
    171 
    172    var instance = new MyCustomElement(false);
    173    returnSpan = true;
    174    var uncaughtError;
    175    window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
    176    instance.cloneNode(false);
    177    assert_equals(uncaughtError.name, 'TypeError');
    178 }, 'Upgrading a custom element must throw TypeError when the custom element\'s constructor returns another element');
    179 
    180 test(function () {
    181    var instance = document.createElement('my-custom-element-throw-exception');
    182    document.body.appendChild(instance);
    183 
    184    var calls = [];
    185    class MyCustomElement extends HTMLElement {
    186        constructor() {
    187            super();
    188            calls.push(this);
    189            throw 'bad';
    190        }
    191    }
    192 
    193    var uncaughtError;
    194    window.onerror = function (message, url, lineNumber, columnNumber, error) { uncaughtError = error; return true; }
    195    customElements.define('my-custom-element-throw-exception', MyCustomElement);
    196    assert_equals(uncaughtError, 'bad');
    197 
    198    assert_array_equals(calls, [instance]);
    199    document.body.removeChild(instance);
    200    document.body.appendChild(instance);
    201    assert_array_equals(calls, [instance]);
    202 }, 'Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once');
    203 
    204 </script>
    205 </body>
    206 </html>