scoped-registry-define-upgrade-order.html (6784B)
1 <!DOCTYPE html> 2 <title>Tests element upgrade order 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 let definitionCount = 0; 13 function nextCustomElementDefinition() { 14 const log = []; 15 const name = `test-element-${++definitionCount}`; 16 const constructor = class extends HTMLElement { 17 constructor() { 18 super(); 19 log.push(this.id); 20 } 21 }; 22 return {name, constructor, log}; 23 } 24 25 function attachShadowForTest(t, {parent, registry}) { 26 parent = parent || document.body; 27 const host = parent.ownerDocument.createElement('div'); 28 const shadow = host.attachShadow({mode: 'open', customElementRegistry: registry}); 29 parent.appendChild(host); 30 t.add_cleanup(() => host.remove()); 31 return shadow; 32 } 33 34 function createIFrameForTest(t, {parent, nextSibling}) { 35 parent = parent || document.body; 36 const iframe = parent.ownerDocument.createElement('iframe'); 37 parent.insertBefore(iframe, nextSibling); 38 if (!iframe.contentDocument.body) { 39 iframe.contentDocument.body = iframe.contentDocument.createElement('body'); 40 } 41 t.add_cleanup(() => iframe.remove()); 42 return iframe; 43 } 44 45 test(t => { 46 const {name, constructor, log} = nextCustomElementDefinition(); 47 48 const registry = new CustomElementRegistry; 49 const shadow = attachShadowForTest(t, {registry}); 50 shadow.innerHTML = ` 51 <${name} id="a"></${name}> 52 <${name} id="b"></${name}> 53 <${name} id="c"></${name}> 54 `; 55 56 registry.define(name, constructor); 57 assert_array_equals(log, ['a', 'b', 'c']); 58 }, 'Upgrade in tree order in the same tree scope'); 59 60 test(t => { 61 // document 62 // +- shadow1 63 // | +- a 64 // | +- shadow2 65 // | +- b 66 // +- shadow3 67 // +- c 68 69 const {name, constructor, log} = nextCustomElementDefinition(); 70 const registry = new CustomElementRegistry; 71 72 const shadow1 = attachShadowForTest(t, {registry}); 73 shadow1.innerHTML = `<${name} id="a"></${name}>`; 74 75 const shadow2 = attachShadowForTest(t, {registry, parent: shadow1}); 76 shadow2.innerHTML = `<${name} id="b"></${name}>`; 77 78 const shadow3 = attachShadowForTest(t, {registry}); 79 shadow3.innerHTML = `<${name} id="c"></${name}>`; 80 81 registry.define(name, constructor); 82 assert_array_equals(log, ['a', 'b', 'c']); 83 }, 'Upgrade in shadow-including tree order across tree scopes'); 84 85 test(t => { 86 // document 87 // +- shadow1 88 // | +- a 89 // | +- shadow3 90 // | +- c 91 // +- shadow2 92 // +- b 93 94 const {name, constructor, log} = nextCustomElementDefinition(); 95 const registry = new CustomElementRegistry; 96 97 const shadow1 = attachShadowForTest(t, {registry}); 98 shadow1.innerHTML = `<${name} id="a"></${name}>`; 99 100 const shadow2 = attachShadowForTest(t, {registry}); 101 shadow2.innerHTML = `<${name} id="b"></${name}>`; 102 103 const shadow3 = attachShadowForTest(t, {registry, parent: shadow1}); 104 shadow3.innerHTML = `<${name} id="c"></${name}>`; 105 106 registry.define(name, constructor); 107 assert_array_equals(log, ['a', 'c', 'b']); 108 }, 'Upgrade order does not depend on shadow root attach order'); 109 110 test(t => { 111 // document 112 // +- iframe1 113 // | +- shadow1 114 // | | +- a 115 // | +- iframe2 116 // | +- shadow2 117 // | +- b 118 // +- shadow3 119 // +- c 120 121 const {name, constructor, log} = nextCustomElementDefinition(); 122 const registry = new CustomElementRegistry; 123 124 const iframe1 = createIFrameForTest(t, {}); 125 const shadow1 = attachShadowForTest(t, {registry, parent: iframe1.contentDocument.body}); 126 shadow1.innerHTML = `<${name} id="a"></${name}>`; 127 128 const iframe2 = createIFrameForTest(t, {parent: iframe1.contentDocument.body}); 129 const shadow2 = attachShadowForTest(t, {registry, parent: iframe2.contentDocument.body}); 130 shadow2.innerHTML = `<${name} id="b"></${name}>`; 131 132 const shadow3 = attachShadowForTest(t, {registry}); 133 shadow3.innerHTML = `<${name} id="c"></${name}>`; 134 135 registry.define(name, constructor); 136 assert_array_equals(log, ['a', 'b', 'c']); 137 }, 'Upgrade in association order across documents, then tree order in each document'); 138 139 test(t => { 140 // document 141 // +- iframe2 142 // | +- shadow2 143 // | +- b 144 // +- iframe1 145 // | +- shadow1 146 // | +- a 147 148 const {name, constructor, log} = nextCustomElementDefinition(); 149 const registry = new CustomElementRegistry; 150 151 const iframe1 = createIFrameForTest(t, {}); 152 const shadow1 = attachShadowForTest(t, {registry, parent: iframe1.contentDocument.body}); 153 shadow1.innerHTML = `<${name} id="a"></${name}>`; 154 155 const iframe2 = createIFrameForTest(t, {nextSibling: iframe1}); 156 const shadow2 = attachShadowForTest(t, {registry, parent: iframe2.contentDocument.body}); 157 shadow2.innerHTML = `<${name} id="b"></${name}>`; 158 159 registry.define(name, constructor); 160 assert_array_equals(log, ['a', 'b']); 161 }, 'Upgrade order is not affected by DOM order between child frames'); 162 163 test(t => { 164 // document 165 // +- iframe1 166 // | +- shadow2 167 // | +- b 168 // +- iframe2 169 // | +- shadow1 170 // | +- a 171 172 const {name, constructor, log} = nextCustomElementDefinition(); 173 const registry = new CustomElementRegistry; 174 175 const iframe1 = createIFrameForTest(t, {}); 176 const iframe2 = createIFrameForTest(t, {}); 177 178 const shadow1 = attachShadowForTest(t, {registry}); 179 const host1 = shadow1.host; 180 shadow1.innerHTML = `<${name} id="a"></${name}>`; 181 182 const shadow2 = attachShadowForTest(t, {registry}); 183 const host2 = shadow2.host; 184 shadow2.innerHTML = `<${name} id="b"></${name}>`; 185 186 iframe1.contentDocument.body.appendChild(host2); 187 iframe2.contentDocument.body.appendChild(host1); 188 189 registry.define(name, constructor); 190 assert_array_equals(log, ['b', 'a']); 191 }, 'Upgrade order is affected by shadow tree adoption across documents'); 192 193 test(t => { 194 // Create a registry in one window, but associate it with another document first 195 // document 196 // +- iframe1 197 // | +- shadow1 198 // | +- a 199 // +- shadowr2 200 // +- b 201 202 const {name, constructor, log} = nextCustomElementDefinition(); 203 const registry = new CustomElementRegistry; 204 205 const iframe1 = createIFrameForTest(t, {}); 206 const shadow1 = attachShadowForTest(t, {registry, parent: iframe1.contentDocument.body}); 207 shadow1.innerHTML = `<${name} id="a"></${name}>`; 208 209 const shadow2 = attachShadowForTest(t, {registry}); 210 shadow2.innerHTML = `<${name} id="b"></${name}>`; 211 212 registry.define(name, constructor); 213 assert_array_equals(log, ['a', 'b']); 214 }, 'Elements in the "owner" window of a scoped registry are not always upgraded first'); 215 216 </script>