tor-browser

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

test_xul_custom_element.xhtml (19589B)


      1 <?xml version="1.0"?>
      2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
      3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
      4 
      5 <window title="XUL Custom Elements"
      6        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
      7        onload="runTest();">
      8  <title>XUL Custom Elements</title>
      9 
     10  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
     11 
     12  <script type="application/javascript">
     13  <![CDATA[
     14    SimpleTest.waitForExplicitFinish();
     15 
     16    var gXULDOMParser = new DOMParser();
     17    gXULDOMParser.forceEnableXULXBL();
     18 
     19    function parseXULToFragment(str) {
     20      let doc = gXULDOMParser.parseFromSafeString(`
     21        <box xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">${str}</box>`,
     22        "application/xml");
     23      // We use a range here so that we don't access the inner DOM elements from
     24      // JavaScript before they are imported and inserted into a document.
     25      let range = doc.createRange();
     26      range.selectNodeContents(doc.firstChild);
     27      return range.extractContents();
     28    }
     29 
     30    class TestCustomElement extends XULElement {
     31      constructor() {
     32        super();
     33 
     34        this.attachShadow({mode: "open"});
     35      }
     36 
     37      connectedCallback() {
     38        this.textContent = "foo";
     39      }
     40    }
     41 
     42    customElements.define("test-custom-element", TestCustomElement);
     43 
     44    class TestWithoutDash extends XULElement { }
     45    customElements.define("testwithoutdash", TestWithoutDash);
     46 
     47    class TestWithoutDashExtended extends TestWithoutDash {
     48      constructor() {
     49        super();
     50      }
     51 
     52      connectedCallback() {
     53        this.textContent = "quux";
     54      }
     55    }
     56    customElements.define("testwithoutdash-extended", TestWithoutDashExtended, { extends: "testwithoutdash" });
     57 
     58    class TestCustomBuiltInElement extends XULElement {
     59      constructor() {
     60        super();
     61      }
     62 
     63      connectedCallback() {
     64        this.textContent = "baz";
     65      }
     66    }
     67    customElements.define("test-built-in-element",
     68      TestCustomBuiltInElement, { extends: "axulelement" });
     69 
     70    class TestPopupExtendElement extends XULPopupElement {
     71      constructor() {
     72        super();
     73      }
     74 
     75      connectedCallback() {
     76        this.textContent = "quuz";
     77      }
     78    }
     79    customElements.define("test-popup-extend",
     80      TestPopupExtendElement, { extends: "menupopup" });
     81 
     82    class TestCustomElement3 extends XULElement { }
     83 
     84    customElements.setElementCreationCallback(
     85      "test-custom-element-3", () => customElements.define("test-custom-element-3", TestCustomElement3));
     86 
     87    const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     88 
     89    function basicCustomElementCreate() {
     90      let element = document.createElementNS(XUL_NS, "test-custom-element");
     91      ok(element.shadowRoot, "Shadow DOM works even with pref off");
     92      document.querySelector("#content").appendChild(element);
     93      is(element.textContent, "foo", "Should have set the textContent");
     94      ok(element instanceof TestCustomElement, "Should be an instance of TestCustomElement");
     95 
     96      let element2 = element.cloneNode(false);
     97      is(element2.textContent, "", "Shouldn't have cloned the textContent");
     98      document.querySelector("#content").appendChild(element2);
     99      is(element2.textContent, "foo", "Should have set the textContent");
    100      ok(element2 instanceof TestCustomElement, "Should be an instance of TestCustomElement");
    101 
    102      let element3 = new TestCustomElement();
    103      is(element3.localName, "test-custom-element", "Should see the right tag");
    104      is(element3.textContent, "", "Shouldn't have been inserted yet");
    105      is(element3.namespaceURI, XUL_NS, "Should have set the right namespace");
    106      document.querySelector("#content").appendChild(element3);
    107      is(element3.textContent, "foo", "Should have set the textContent");
    108      ok(element3 instanceof TestCustomElement, "Should be an instance of TestCustomElement");
    109 
    110      document.querySelector("#content").appendChild(parseXULToFragment(`<test-custom-element />`));
    111      let element4 = document.querySelector("#content").lastChild;
    112      is(element4.localName, "test-custom-element", "Should see the right tag");
    113      is(element4.namespaceURI, XUL_NS, "Should have set the right namespace");
    114      is(element4.textContent, "foo", "Should have set the textContent");
    115      ok(element4 instanceof TestCustomElement, "Should be an instance of TestCustomElement");
    116    }
    117 
    118    function parserBasicElementUpgrade() {
    119      let element = document.getElementById("element4");
    120      is(element.textContent, "foo",
    121         "Parser should have instantiated the custom element.");
    122      ok(element instanceof TestCustomElement, "Should be an instance of TestCustomElement");
    123    }
    124 
    125    function tagNameWithoutDash() {
    126      let element = document.getElementById("element5");
    127      ok(element instanceof TestWithoutDash, "Should be an instance of TestWithoutDash");
    128    }
    129 
    130    function upgradeAfterDefine() {
    131      class TestCustomElement1 extends XULElement {
    132        constructor() {
    133          super();
    134        }
    135 
    136        connectedCallback() {
    137          this.textContent = "bar";
    138        }
    139      }
    140 
    141      let element = document.createElementNS(XUL_NS, "test-custom-element-1");
    142      ok(!(element instanceof TestCustomElement1), "Should not be an instance of TestCustomElement1");
    143      customElements.define("test-custom-element-1", TestCustomElement1);
    144      ok(!(element instanceof TestCustomElement1), "Should not be an instance of TestCustomElement1");
    145      document.querySelector("#content").appendChild(element);
    146      ok(element instanceof TestCustomElement1, "Should be upgraded to an instance of TestCustomElement1");
    147      is(element.textContent, "bar", "Should have set the textContent");
    148    }
    149 
    150    function basicElementCreateBuiltIn() {
    151      let element = document.createElementNS(XUL_NS, "axulelement", { is: "test-built-in-element" });
    152      ok(element instanceof TestCustomBuiltInElement, "Should be an instance of TestCustomBuiltInElement");
    153      is(element.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type.");
    154      document.querySelector("#content").appendChild(element);
    155      is(element.textContent, "baz", "Should have set the textContent");
    156 
    157      let element2 = element.cloneNode(false);
    158      is(element2.localName, "axulelement", "Should see the right tag");
    159      is(element2.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type.");
    160      is(element2.textContent, "", "Shouldn't have cloned the textContent");
    161      document.querySelector("#content").appendChild(element2);
    162      is(element2.textContent, "baz", "Should have set the textContent");
    163      ok(element2 instanceof TestCustomBuiltInElement, "Should be an instance of TestCustomBuiltInElement");
    164 
    165      let element3 = new TestCustomBuiltInElement();
    166      is(element3.localName, "axulelement", "Should see the right tag");
    167      is(element3.textContent, "", "Shouldn't have been inserted yet");
    168      is(element3.namespaceURI, XUL_NS, "Should have set the right namespace");
    169      document.querySelector("#content").appendChild(element3);
    170      is(element3.textContent, "baz", "Should have set the textContent");
    171      ok(element3 instanceof TestCustomBuiltInElement, "Should be an instance of TestCustomBuiltInElement");
    172 
    173      document.querySelector("#content").appendChild(parseXULToFragment(`<axulelement is="test-built-in-element" />`))
    174      let element4 = document.querySelector("#content").lastChild;
    175      is(element4.localName, "axulelement", "Should see the right tag");
    176      is(element4.namespaceURI, XUL_NS, "Should have set the right namespace");
    177      is(element4.textContent, "baz", "Should have set the textContent");
    178      ok(element4 instanceof TestCustomBuiltInElement, "Should be an instance of TestCustomBuiltInElement");
    179    }
    180 
    181    function parserBasicElementUpgradeBuiltIn() {
    182      let element = document.getElementById("element6");
    183      is(element.textContent, "baz",
    184         "Parser should have instantiated the custom element.");
    185      ok(element instanceof TestCustomBuiltInElement, "Should be an instance of TestCustomBuiltInElement");
    186    }
    187 
    188    function subclassElementCreateBuiltIn() {
    189      let element = document.createElementNS(XUL_NS, "menupopup", { is: "test-popup-extend" });
    190      ok(element instanceof TestPopupExtendElement, "Should be an instance of TestPopupExtendElement");
    191      is(element.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type.");
    192      document.querySelector("#content").appendChild(element);
    193      is(element.textContent, "quuz", "Should have set the textContent");
    194 
    195      let element2 = element.cloneNode(false);
    196      is(element2.localName, "menupopup", "Should see the right tag");
    197      is(element2.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type.");
    198      is(element2.textContent, "", "Shouldn't have cloned the textContent");
    199      document.querySelector("#content").appendChild(element2);
    200      is(element2.textContent, "quuz", "Should have set the textContent");
    201      ok(element2 instanceof TestPopupExtendElement, "Should be an instance of TestPopupExtendElement");
    202 
    203      let element3 = new TestPopupExtendElement();
    204      is(element3.localName, "menupopup", "Should see the right tag");
    205      is(element3.textContent, "", "Shouldn't have been inserted yet");
    206      is(element3.namespaceURI, XUL_NS, "Should have set the right namespace");
    207      document.querySelector("#content").appendChild(element3);
    208      is(element3.textContent, "quuz", "Should have set the textContent");
    209      ok(element3 instanceof TestPopupExtendElement, "Should be an instance of TestPopupExtendElement");
    210 
    211      document.querySelector("#content").appendChild(parseXULToFragment(`<menupopup is="test-popup-extend" />`))
    212      let element4 = document.querySelector("#content").lastChild;
    213      is(element4.localName, "menupopup", "Should see the right tag");
    214      is(element4.namespaceURI, XUL_NS, "Should have set the right namespace");
    215      is(element4.textContent, "quuz", "Should have set the textContent");
    216      ok(element4 instanceof TestPopupExtendElement, "Should be an instance of TestPopupExtendElement");
    217    }
    218 
    219    function parserSubclassElementUpgradeBuiltIn() {
    220      let element = document.getElementById("element7");
    221      is(element.textContent, "quuz",
    222         "Parser should have instantiated the custom element.");
    223      ok(element instanceof TestPopupExtendElement, "Should be an instance of TestPopupExtendElement");
    224    }
    225 
    226    function upgradeAfterDefineBuiltIn() {
    227      class TestCustomBuiltInElement1 extends XULElement {
    228        constructor() {
    229          super();
    230        }
    231 
    232        connectedCallback() {
    233          this.textContent = "qux";
    234        }
    235      }
    236      let element = document.createElementNS(XUL_NS, "axulelement", { is: "test-built-in-element-1" });
    237      ok(!(element instanceof TestCustomBuiltInElement1), "Should not be an instance of TestCustomBuiltInElement1");
    238      customElements.define("test-built-in-element-1",
    239        TestCustomBuiltInElement1, { extends: "axulelement" });
    240      ok(!(element instanceof TestCustomBuiltInElement1), "Should not be an instance of TestCustomBuiltInElement1");
    241      document.querySelector("#content").appendChild(element);
    242      ok(element instanceof TestCustomBuiltInElement1, "Should be upgraded to an instance of TestCustomBuiltInElement1");
    243      is(element.textContent, "qux", "Should have set the textContent");
    244    }
    245 
    246    function throwForInvalidBuiltInName() {
    247      try {
    248        // <axulelement is="testwithoutdashbuiltin" /> is not allowed;
    249        // built-in type names need dashes.
    250        customElements.define(
    251          "testwithoutdashbuiltin", class extends XULElement {}, { extends: "axulelement" });
    252        ok(false, "Built-in type name without dash should be rejected.");
    253      } catch (e) {
    254        ok(true, "Built-in type name without dash is rejected.");
    255      }
    256      try {
    257        // <test-built-in-element-2 is="test-custom-element-2" /> is not allowed;
    258        // built-in type tag names forbid dashes
    259        customElements.define(
    260          "test-built-in-element-2", class extends XULElement {}, { extends: "test-custom-element-2" });
    261        ok(false, "Extending from a name with dash should be rejected.");
    262      } catch (e) {
    263        ok(true, "Extending from a name with dash is rejected.");
    264      }
    265    }
    266 
    267    function extendingWithoutDashCustomElement() {
    268      let element = document.createElementNS(XUL_NS, "testwithoutdash", { is: "testwithoutdash-extended" });
    269      ok(element instanceof TestWithoutDashExtended, "Should be an instance of TestWithoutDashExtended");
    270      ok(element instanceof TestWithoutDash, "Should be an instance of TestWithoutDash");
    271      is(element.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type.");
    272      document.querySelector("#content").appendChild(element);
    273      is(element.textContent, "quux", "Should have set the textContent");
    274 
    275      let element2 = element.cloneNode(false);
    276      is(element2.localName, "testwithoutdash", "Should see the right tag");
    277      is(element2.getAttribute("is"), null, "The |is| attribute of the created element should not be the extended type.");
    278      is(element2.textContent, "", "Shouldn't have cloned the textContent");
    279      document.querySelector("#content").appendChild(element2);
    280      is(element2.textContent, "quux", "Should have set the textContent");
    281      ok(element2 instanceof TestWithoutDashExtended, "Should be an instance of TestWithoutDashExtended");
    282      ok(element2 instanceof TestWithoutDash, "Should be an instance of TestWithoutDash");
    283 
    284      let element3 = new TestWithoutDashExtended();
    285      is(element3.localName, "testwithoutdash", "Should see the right tag");
    286      is(element3.textContent, "", "Shouldn't have been inserted yet");
    287      is(element3.namespaceURI, XUL_NS, "Should have set the right namespace");
    288      document.querySelector("#content").appendChild(element3);
    289      is(element3.textContent, "quux", "Should have set the textContent");
    290      ok(element3 instanceof TestWithoutDashExtended, "Should be an instance of TestWithoutDashExtended");
    291      ok(element3 instanceof TestWithoutDash, "Should be an instance of TestWithoutDash");
    292 
    293      document.querySelector("#content").appendChild(parseXULToFragment(`<testwithoutdash is="testwithoutdash-extended" />`))
    294      let element4 = document.querySelector("#content").lastChild;
    295      is(element4.localName, "testwithoutdash", "Should see the right tag");
    296      is(element4.namespaceURI, XUL_NS, "Should have set the right namespace");
    297      is(element4.textContent, "quux", "Should have set the textContent");
    298      ok(element4 instanceof TestWithoutDashExtended, "Should be an instance of TestWithoutDashExtended");
    299      ok(element4 instanceof TestWithoutDash, "Should be an instance of TestWithoutDash");
    300    }
    301 
    302    function nonCustomElementCreate() {
    303      // All of these should be created as plain XUL elements without hitting
    304      // any assertions.
    305      let elements = [
    306        document.createElementNS(XUL_NS, "axulelement", { is: "test-custom-element" }),
    307        document.createElementNS(XUL_NS, "axulelement", { is: "testwithoutdash" }),
    308        document.createElementNS(XUL_NS, "axulelement", { is: "test-custom-element-1" }),
    309        document.createElementNS(XUL_NS, "name-with-dash", { is: "name-with-dash" }),
    310        document.createElementNS(XUL_NS, "name-with-dash", { is: "another-name-with-dash" }),
    311        document.createElementNS(XUL_NS, "testwithoutdash-extended"),
    312        document.createElementNS(XUL_NS, "test-built-in-element"),
    313        document.createElementNS(XUL_NS, "test-popup-extend"),
    314        document.createElementNS(XUL_NS, "test-built-in-element-1")];
    315 
    316      for (let element of elements) {
    317        is(Object.getPrototypeOf(element), XULElement.prototype,
    318          `<${element.localName} is="${element.getAttribute("is")}" /> should not be a custom element.`);
    319      }
    320    }
    321 
    322    function testSetElementCreationballbackInDocument() {
    323      let element = document.getElementById("element8");
    324      ok(element instanceof TestCustomElement3, "Should be an instance of TestCustomElement3");
    325    }
    326 
    327    function setElementCreationCallbackCreate() {
    328      class TestCustomElement4 extends XULElement {}
    329      customElements.setElementCreationCallback(
    330        "test-custom-element-4", () => customElements.define("test-custom-element-4", TestCustomElement4));
    331 
    332      let element = document.createElementNS(XUL_NS, "test-custom-element-4");
    333      ok(element instanceof TestCustomElement4, "Should be an instance of TestCustomElement4");
    334 
    335      class TestCustomElement5 extends XULElement {}
    336      customElements.setElementCreationCallback(
    337        "test-custom-element-5", () => {
    338          ok(true, "test-custom-element-5 callback called");
    339          customElements.define("test-custom-element-5", TestCustomElement5);
    340        });
    341 
    342      document.querySelector("#content").appendChild(parseXULToFragment(`<test-custom-element-5 />`));
    343      let element1 = document.querySelector("#content").lastChild;
    344      ok(element1 instanceof TestCustomElement5, "Should be an instance of TestCustomElement5");
    345    }
    346 
    347    function testSetElementCreationCallbackExistsBeforeCall() {
    348      class TestCustomElement6 extends XULElement {}
    349      document.querySelector("#content").appendChild(parseXULToFragment(`<test-custom-element-6 />`));
    350 
    351      let element = document.querySelector("#content").lastChild;
    352      ok(!(element instanceof TestCustomElement6), "Is not a TestCustomElement6 when DOM parsed");
    353 
    354      customElements.setElementCreationCallback(
    355        "test-custom-element-6",
    356        () => customElements.define("test-custom-element-6", TestCustomElement6)
    357      );
    358      ok(element instanceof TestCustomElement6, "setElementCreationCallback called automatically to upgrade candidate component");
    359    }
    360 
    361    function runTest() {
    362      basicCustomElementCreate();
    363      parserBasicElementUpgrade();
    364 
    365      tagNameWithoutDash();
    366      upgradeAfterDefine();
    367 
    368      basicElementCreateBuiltIn();
    369      parserBasicElementUpgradeBuiltIn();
    370 
    371      subclassElementCreateBuiltIn();
    372      parserSubclassElementUpgradeBuiltIn();
    373 
    374      upgradeAfterDefineBuiltIn();
    375 
    376      throwForInvalidBuiltInName();
    377      extendingWithoutDashCustomElement();
    378 
    379      nonCustomElementCreate();
    380 
    381      testSetElementCreationballbackInDocument();
    382      setElementCreationCallbackCreate();
    383 
    384      testSetElementCreationCallbackExistsBeforeCall();
    385 
    386      SimpleTest.finish();
    387    }
    388  ]]>
    389  </script>
    390 
    391  <body xmlns="http://www.w3.org/1999/xhtml">
    392    <p id="display"></p>
    393    <div id="content" style="display: none">
    394      <test-custom-element id="element4" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
    395      <testwithoutdash id="element5" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
    396      <axulelement id="element6" is="test-built-in-element" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
    397      <menupopup id="element7" is="test-popup-extend" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
    398      <test-custom-element-3 id="element8" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"></test-custom-element-3>
    399    </div>
    400    <pre id="test"></pre>
    401  </body>
    402 </window>