tor-browser

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

scoped-registry-define-upgrade-criteria.html (9386B)


      1 <!DOCTYPE html>
      2 <title>Tests which nodes are upgraded after adding a scoped custom element definition</title>
      3 <meta name="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
      4 <link rel="help" href="https://wicg.github.io/webcomponents/proposals/Scoped-Custom-Element-Registries">
      5 <link rel="help" href="https://github.com/WICG/webcomponents/issues/923">
      6 <script src="/resources/testharness.js"></script>
      7 <script src="/resources/testharnessreport.js"></script>
      8 
      9 <body>
     10 
     11 <script>
     12 function attachShadowForTest(t, customElementRegistry) {
     13  const host = document.createElement('div');
     14  const shadow = host.attachShadow({mode: 'open', customElementRegistry});
     15  document.body.appendChild(host);
     16  t.add_cleanup(() => host.remove());
     17  return shadow;
     18 }
     19 
     20 function createIFrameForTest(t) {
     21  const iframe = document.createElement('iframe');
     22  document.body.appendChild(iframe);
     23  if (!iframe.contentDocument.body) {
     24    iframe.contentDocument.body = iframe.contentDocument.createElement('body');
     25  }
     26  t.add_cleanup(() => iframe.remove());
     27  return iframe;
     28 }
     29 
     30 let definitionCount = 0;
     31 function nextCustomElementName() {
     32  return `test-element-${++definitionCount}`;
     33 }
     34 
     35 function insertNewElementIntoShadow(shadow, name) {
     36  shadow.innerHTML = `<${name}></${name}>`;
     37  return shadow.querySelector(name);
     38 }
     39 
     40 test(t => {
     41  const name = nextCustomElementName();
     42  document.body.appendChild(document.createElement(name));
     43 
     44  const registry = new CustomElementRegistry;
     45  const shadow = attachShadowForTest(t, registry);
     46  insertNewElementIntoShadow(shadow, name);
     47 
     48  class TestElement extends HTMLElement {};
     49  customElements.define(name, TestElement);
     50 
     51  assert_true(document.querySelector(name) instanceof TestElement);
     52  assert_false(shadow.querySelector(name) instanceof TestElement);
     53 }, 'Adding definition to global registry should not affect shadow roots using scoped registry');
     54 
     55 test(t => {
     56  const name = nextCustomElementName();
     57 
     58  const shadow1 = attachShadowForTest(t, customElements);
     59  shadow1.appendChild(document.createElement(name));
     60 
     61  const shadow2 = attachShadowForTest(t);
     62  shadow2.appendChild(document.createElement(name));
     63 
     64  class TestElement extends HTMLElement {};
     65  customElements.define(name, TestElement);
     66 
     67  assert_true(shadow1.querySelector(name) instanceof TestElement);
     68  assert_true(shadow2.querySelector(name) instanceof TestElement);
     69 }, 'Adding definition to global registry should affect shadow roots also using global registry');
     70 
     71 test(t => {
     72  const name = nextCustomElementName();
     73 
     74  const registry = new CustomElementRegistry;
     75  const shadow1 = attachShadowForTest(t, registry);
     76  insertNewElementIntoShadow(shadow1, name);
     77 
     78  const shadow2 = attachShadowForTest(t, registry);
     79  insertNewElementIntoShadow(shadow2, name);
     80 
     81  class TestElement extends HTMLElement {};
     82  registry.define(name, TestElement);
     83 
     84  assert_true(shadow1.querySelector(name) instanceof TestElement);
     85  assert_true(shadow2.querySelector(name) instanceof TestElement);
     86 }, 'Adding definition to scoped registry should affect all associated shadow roots');
     87 
     88 test(t => {
     89  const name = nextCustomElementName();
     90  document.body.appendChild(document.createElement(name));
     91 
     92  const registry = new CustomElementRegistry;
     93  const shadow = attachShadowForTest(t, registry);
     94  insertNewElementIntoShadow(shadow, name);
     95 
     96  class TestElement extends HTMLElement {};
     97  registry.define(name, TestElement);
     98 
     99  assert_false(document.querySelector(name) instanceof TestElement);
    100  assert_true(shadow.querySelector(name) instanceof TestElement);
    101 }, 'Adding definition to scoped registry should not affect document tree scope');
    102 
    103 test(t => {
    104  const name = nextCustomElementName();
    105 
    106  const registry = new CustomElementRegistry;
    107  const shadow1 = attachShadowForTest(t, registry);
    108  insertNewElementIntoShadow(shadow1, name);
    109 
    110  const shadow2 = attachShadowForTest(t, new CustomElementRegistry);
    111  insertNewElementIntoShadow(shadow2, name);
    112 
    113  const shadow3 = attachShadowForTest(t);
    114  insertNewElementIntoShadow(shadow3, name);
    115 
    116  class TestElement extends HTMLElement {};
    117  registry.define(name, TestElement);
    118 
    119  assert_true(shadow1.querySelector(name) instanceof TestElement);
    120  assert_false(shadow2.querySelector(name) instanceof TestElement);
    121  assert_false(shadow3.querySelector(name) instanceof TestElement);
    122 }, 'Adding definition to scoped registry should not affect shadow roots using other registries');
    123 
    124 test(t => {
    125  const name = nextCustomElementName();
    126  const registry = new CustomElementRegistry;
    127  const node = document.body.appendChild(document.createElement(name, {customElementRegistry: registry}));
    128  const shadow = attachShadowForTest(t, registry);
    129  shadow.appendChild(node);
    130 
    131  class TestElement extends HTMLElement {};
    132  registry.define(name, TestElement);
    133 
    134  assert_true(node instanceof TestElement);
    135 }, 'Adding definition to scoped registry should upgrade nodes even after the node is moved into a separate shadow tree.');
    136 
    137 test(t => {
    138  const name = nextCustomElementName();
    139 
    140  const registry = new CustomElementRegistry;
    141  const shadow1 = attachShadowForTest(t, registry);
    142  const node = insertNewElementIntoShadow(shadow1, name);
    143 
    144  const shadow2 = attachShadowForTest(t, new CustomElementRegistry);
    145  shadow2.appendChild(node);
    146 
    147  class TestElement extends HTMLElement {};
    148  registry.define(name, TestElement);
    149 
    150  assert_true(node instanceof TestElement);
    151 }, 'Adding definition to scoped registry should upgrade nodes even after the node is moved to a separate shadow tree using a different registry.');
    152 
    153 test(t => {
    154  const name = nextCustomElementName();
    155 
    156  const registry = new CustomElementRegistry;
    157  const shadow1 = attachShadowForTest(t, registry);
    158  const node1 = insertNewElementIntoShadow(shadow1, name);
    159 
    160  const iframe = createIFrameForTest(t);
    161  const host2 = iframe.contentDocument.createElement('div');
    162  const shadow2 = host2.attachShadow({mode: 'open', customElementRegistry: registry});
    163  const node2 = insertNewElementIntoShadow(shadow2, name);
    164  iframe.contentDocument.body.appendChild(host2);
    165 
    166  class TestElement extends HTMLElement {};
    167  registry.define(name, TestElement);
    168 
    169  assert_true(node1 instanceof TestElement);
    170  assert_true(node2 instanceof TestElement);
    171 }, 'Adding definition to scoped registry affects associated shadow roots in all iframes');
    172 
    173 test(t => {
    174  const name = nextCustomElementName();
    175 
    176  const registry = new CustomElementRegistry;
    177 
    178  const newWindow = window.open('about:blank');
    179  t.add_cleanup(() => newWindow.close());
    180 
    181  const host = newWindow.document.createElement('div');
    182  const shadow = host.attachShadow({mode: 'open', customElementRegistry: registry});
    183  const node = insertNewElementIntoShadow(shadow, name);
    184  newWindow.document.body.appendChild(host);
    185 
    186  class TestElement extends HTMLElement {};
    187  registry.define(name, TestElement);
    188 
    189  assert_true(node instanceof TestElement);
    190 }, 'Adding definition to scoped registry affects associated shadow roots in other frame trees');
    191 
    192 test(t => {
    193  const name = nextCustomElementName();
    194 
    195  const registry = new CustomElementRegistry;
    196  const shadow = attachShadowForTest(t, registry);
    197  const node = insertNewElementIntoShadow(shadow, name);
    198  shadow.host.remove();
    199 
    200  class TestElement extends HTMLElement {};
    201  registry.define(name, TestElement);
    202 
    203  assert_false(node instanceof TestElement);
    204 }, 'Adding definition to scoped registry should not upgrade disconnected elements');
    205 
    206 test(t => {
    207  const name = nextCustomElementName();
    208 
    209  const registry = new CustomElementRegistry;
    210  const doc = document.implementation.createHTMLDocument();
    211  const host = doc.createElement('div');
    212  const shadow = host.attachShadow({mode: 'open', registry});
    213  const node = insertNewElementIntoShadow(shadow, name);
    214  doc.body.appendChild(host);
    215 
    216  class TestElement extends HTMLElement {};
    217  registry.define(name, TestElement);
    218 
    219  assert_false(node instanceof TestElement);
    220 }, 'Adding definition to scoped registry should not upgrade nodes in constructed documents');
    221 
    222 test(t => {
    223  const name = nextCustomElementName();
    224 
    225  const iframe = createIFrameForTest(t);
    226  const registry = new CustomElementRegistry;
    227  const host = iframe.contentDocument.createElement('div');
    228  const shadow = host.attachShadow({mode: 'open', registry});
    229  const node = insertNewElementIntoShadow(shadow, name);
    230  iframe.contentDocument.body.appendChild(host);
    231 
    232  iframe.remove();
    233 
    234  class TestElement extends HTMLElement {};
    235  registry.define(name, TestElement);
    236 
    237  assert_false(node instanceof TestElement);
    238 }, 'Adding definition to scoped registry should not upgrade nodes in detached frames');
    239 
    240 promise_test(async t => {
    241  const name = nextCustomElementName();
    242 
    243  const newWindow = window.open('about:blank');
    244  t.add_cleanup(() => newWindow.close());
    245 
    246  const host = newWindow.document.createElement('div');
    247  const shadow = host.attachShadow({mode: 'open', registry: window.customElements});
    248  const node = insertNewElementIntoShadow(shadow, name);
    249  newWindow.document.body.appendChild(host);
    250 
    251  newWindow.close();
    252 
    253  // `window.close()` is async. Wait a while until it's fully closed
    254  await new Promise(resolve => t.step_timeout(resolve, 500));
    255 
    256  class TestElement extends HTMLElement {};
    257  window.customElements.define(name, TestElement);
    258 
    259  assert_false(node instanceof TestElement);
    260 }, 'Adding definition to scoped registry should not upgrade nodes in closed windows');
    261 </script>