tor-browser

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

gethtml.html (6627B)


      1 <!DOCTYPE html>
      2 <title>getHTML behavior</title>
      3 <meta name="timeout" content="long">
      4 <link rel='author' href='mailto:masonf@chromium.org'>
      5 <link rel='help' href='https://github.com/whatwg/html/issues/8867'>
      6 <script src='/resources/testharness.js'></script>
      7 <script src='/resources/testharnessreport.js'></script>
      8 <script src='../../html/resources/common.js'></script>
      9 
     10 <body>
     11 
     12 <script>
     13 function testElementType(allowsShadowDom, elementType, runGetHTMLOnShadowRoot,
     14      lightDOMContent, declarativeShadowDom, mode, delegatesFocus,
     15      serializable, clonable, emptyShadowTree) {
     16  const t = test(t => {
     17    // Create and attach element
     18    let wrapper;
     19    if (runGetHTMLOnShadowRoot) {
     20      // This ensures we're testing both Element.getHTML() and ShadowRoot.getHTML().
     21      const host = document.createElement('div');
     22      t.add_cleanup(function() { host.remove(); });
     23      document.body.appendChild(host);
     24      wrapper = host.attachShadow({mode: 'open'});
     25    } else {
     26      wrapper = document.createElement('div');
     27      t.add_cleanup(function() { wrapper.remove(); });
     28      document.body.appendChild(wrapper);
     29    }
     30 
     31    let shadowRoot;
     32    let initDict = {mode: mode, delegatesFocus: delegatesFocus, clonable};
     33    let expectedSerializable = null;
     34    switch (serializable) {
     35      case undefined: expectedSerializable = false; break;
     36      case "true": initDict.serializable = expectedSerializable = true; break;
     37      case "false": initDict.serializable = expectedSerializable = false; break;
     38      default: throw new Error(`Invalid serializable ${serializable}`);
     39    }
     40    const delegatesAttr = delegatesFocus ? ' shadowrootdelegatesfocus=""' : '';
     41    const serializableAttr = expectedSerializable ? ' shadowrootserializable=""' : '';
     42    const clonableAttr = clonable ? ' shadowrootclonable=""' : '';
     43 
     44    if (allowsShadowDom && declarativeShadowDom) {
     45      const html = `<${elementType}>${lightDOMContent}<template ` +
     46          `shadowrootmode=${mode}${delegatesAttr}${serializableAttr}` +
     47          `${clonableAttr}>`;
     48      wrapper.setHTMLUnsafe(html);
     49      // Get hold of the declarative shadow root in a way that works when its mode is "closed"
     50      shadowRoot = wrapper.firstElementChild.attachShadow(initDict);
     51    } else {
     52      // Imperative shadow dom
     53      const element = document.createElement(elementType);
     54      wrapper.appendChild(element);
     55      const temp = document.createElement('div');
     56      temp.innerHTML = lightDOMContent;
     57      element.append(...temp.childNodes);
     58      if (allowsShadowDom) {
     59        shadowRoot = element.attachShadow(initDict);
     60      }
     61    }
     62    assert_true(!allowsShadowDom || !!shadowRoot);
     63 
     64    if (allowsShadowDom) {
     65      const correctShadowHtml = `<template shadowrootmode="${mode}"` +
     66          `${delegatesAttr}${serializableAttr}${clonableAttr}>` +
     67          (emptyShadowTree ? `` : `<slot></slot>`) + `</template>`;
     68      const correctHtml = `<${elementType}>${correctShadowHtml}` +
     69          `${lightDOMContent}</${elementType}>`;
     70      assert_equals(shadowRoot.mode,mode);
     71      assert_equals(shadowRoot.delegatesFocus,delegatesFocus);
     72      assert_equals(shadowRoot.serializable,expectedSerializable);
     73      assert_equals(shadowRoot.clonable,clonable);
     74      if (!emptyShadowTree) {
     75        shadowRoot.appendChild(document.createElement('slot'));
     76      }
     77      const emptyElement = `<${elementType}>${lightDOMContent}</${elementType}>`;
     78      if (expectedSerializable) {
     79        assert_equals(wrapper.getHTML({serializableShadowRoots: true}),
     80            correctHtml);
     81        assert_equals(wrapper.firstElementChild.getHTML({
     82            serializableShadowRoots: true}),
     83            `${correctShadowHtml}${lightDOMContent}`);
     84      } else {
     85        assert_equals(wrapper.getHTML({serializableShadowRoots: true}), emptyElement);
     86      }
     87      // If we provide the shadow root, serialize it, regardless of serializableShadowRoots.
     88      assert_equals(wrapper.getHTML({serializableShadowRoots: true, shadowRoots:
     89          [shadowRoot]}),correctHtml);
     90      assert_equals(wrapper.getHTML({serializableShadowRoots: false, shadowRoots:
     91          [shadowRoot]}),correctHtml);
     92      assert_equals(wrapper.getHTML({shadowRoots: [shadowRoot]}),correctHtml);
     93    } else {
     94      // For non-shadow hosts, getHTML() should also match .innerHTML
     95      assert_equals(wrapper.getHTML({serializableShadowRoots: true}),wrapper.innerHTML);
     96    }
     97 
     98    // Either way, make sure getHTML({serializableShadowRoots: false}) matches .innerHTML
     99    assert_equals(wrapper.getHTML({serializableShadowRoots: false}),wrapper.innerHTML,
    100        'getHTML() with serializableShadowRoots false should return the same as .innerHTML');
    101    // ...and that the default for serializableShadowRoots is false.
    102    assert_equals(wrapper.getHTML(),wrapper.innerHTML,
    103        'The default for serializableShadowRoots should be false');
    104 
    105  }, `${runGetHTMLOnShadowRoot ? 'ShadowRoot' : 'Element'}.getHTML() on ` +
    106      `<${elementType}>${lightDOMContent}${allowsShadowDom ?
    107      `, with ${declarativeShadowDom ? 'declarative' : 'imperative'} shadow, ` +
    108      `mode=${mode}, delegatesFocus=${delegatesFocus}, ` +
    109      `serializable=${serializable}, clonable=${clonable},` : ''}` +
    110      ` with${emptyShadowTree ? `out` : ``} shadow tree contents.`);
    111 }
    112 
    113 function runAllTests() {
    114  const allElements = [...HTML5_ELEMENTS, 'htmlunknown'];
    115  const safelisted = HTML5_SHADOW_ALLOWED_ELEMENTS.filter(el => el != 'body');
    116  for (const elementName of allElements) {
    117    const allowsShadowDom = safelisted.includes(elementName);
    118    for (const runGetHTMLOnShadowRoot of [false, true]) {
    119      for (const lightDOMContent of ['','<span>light</span>']) {
    120        if (allowsShadowDom) {
    121          for (const declarativeShadowDom of [false, true]) {
    122            for (const delegatesFocus of [false, true]) {
    123              for (const clonable of [false, true]) {
    124                for (const mode of ['open', 'closed']) {
    125                  for (const serializable of [undefined, 'false', 'true']) {
    126                    for (const emptyShadowTree of [false, true]) {
    127                      testElementType(true, elementName, runGetHTMLOnShadowRoot,
    128                          lightDOMContent, declarativeShadowDom, mode,
    129                          delegatesFocus, serializable, clonable,
    130                          emptyShadowTree);
    131                    }
    132                  }
    133                }
    134              }
    135            }
    136          }
    137        } else {
    138          testElementType(false, elementName, runGetHTMLOnShadowRoot,
    139              lightDOMContent);
    140        }
    141      }
    142    }
    143  }
    144 }
    145 
    146 runAllTests();
    147 
    148 </script>