element-internals-shadowroot.html (5185B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>ElementInternals.shadowRoot</title> 4 <link rel="author" href="mailto:masonf@chromium.org"> 5 <link rel="help" href="https://html.spec.whatwg.org/#dom-elementinternals-shadowroot"> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 9 <script> 10 11 test(() => { 12 let constructed = false; 13 customElements.define('custom-open', class extends HTMLElement { 14 constructor() { 15 super(); 16 const elementInternals = this.attachInternals(); 17 assert_equals(elementInternals.shadowRoot, null); 18 const shadow = this.attachShadow({mode: 'open'}); 19 assert_equals(elementInternals.shadowRoot, shadow); 20 constructed = true; 21 } 22 }); 23 const element = document.createElement('custom-open'); 24 assert_true(constructed); 25 }, 'ElementInternals.shadowRoot allows access to open shadow root'); 26 27 test(() => { 28 let constructed = false; 29 customElements.define('custom-closed', class extends HTMLElement { 30 constructor() { 31 super(); 32 const elementInternals = this.attachInternals(); 33 assert_equals(elementInternals.shadowRoot, null); 34 const shadow = this.attachShadow({mode: 'closed'}); 35 assert_equals(elementInternals.shadowRoot, shadow); 36 assert_equals(this.shadowRoot, null); 37 constructed = true; 38 } 39 }); 40 const element = document.createElement('custom-closed'); 41 assert_true(constructed); 42 }, 'ElementInternals.shadowRoot allows access to closed shadow root'); 43 44 test(() => { 45 let constructed = false; 46 const element = document.createElement('x-1'); 47 assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals cannot be called before definition exists'); 48 customElements.define('x-1', class extends HTMLElement { 49 constructor() { 50 super(); 51 assert_true(!!this.attachInternals()); 52 constructed = true; 53 } 54 }); 55 assert_false(constructed); 56 assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals cannot be called before constructor'); 57 customElements.upgrade(element); 58 assert_true(constructed); 59 assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals already called'); 60 }, 'ElementInternals cannot be called before constructor, upgrade case'); 61 62 test(() => { 63 let constructed = false; 64 const element = document.createElement('x-2'); 65 customElements.define('x-2', class extends HTMLElement { 66 constructor() { 67 super(); 68 // Don't attachInternals() here 69 constructed = true; 70 } 71 }); 72 assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals cannot be called before constructor'); 73 assert_false(constructed); 74 customElements.upgrade(element); 75 assert_true(constructed); 76 assert_true(!!element.attachInternals(),'After the constructor, ok to call from outside'); 77 }, 'ElementInternals *can* be called after constructor, upgrade case'); 78 79 test(() => { 80 let constructed = false; 81 customElements.define('x-3', class extends HTMLElement { 82 constructor() { 83 super(); 84 assert_true(!!this.attachInternals()); 85 constructed = true; 86 } 87 }); 88 const element = document.createElement('x-3'); 89 assert_true(constructed); 90 assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals already called'); 91 }, 'ElementInternals cannot be called after constructor calls it, create case'); 92 93 test(() => { 94 let constructed = false; 95 const element = document.createElement('x-5'); 96 customElements.define('x-5', class extends HTMLElement { 97 static disabledFeatures = [ 'internals' ]; 98 constructor() { 99 super(); 100 assert_throws_dom('NotSupportedError', () => this.attachInternals(), 'attachInternals forbidden by disabledFeatures, constructor'); 101 constructed = true; 102 } 103 }); 104 assert_false(constructed); 105 assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals forbidden by disabledFeatures, pre-upgrade'); 106 customElements.upgrade(element); 107 assert_true(constructed); 108 assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals forbidden by disabledFeatures, post-upgrade'); 109 }, 'ElementInternals disabled by disabledFeatures'); 110 111 test(() => { 112 let constructed = false; 113 const element = document.createElement('x-6'); 114 const sr = element.attachShadow({mode: 'closed'}); 115 assert_true(sr instanceof ShadowRoot); 116 customElements.define('x-6', class extends HTMLElement { 117 constructor() { 118 super(); 119 assert_throws_dom('NotSupportedError', () => this.attachShadow({mode:'open'}), 'attachShadow already called'); 120 const elementInternals = this.attachInternals(); 121 assert_equals(elementInternals.shadowRoot, null, 'ElementInternals.shadowRoot should not be available for pre-attached shadow'); 122 constructed = true; 123 } 124 }); 125 assert_false(constructed); 126 customElements.upgrade(element); 127 assert_true(constructed,'Failed to construct - test failed'); 128 assert_equals(element.shadowRoot, null, 'shadow root is closed'); 129 }, 'ElementInternals.shadowRoot doesn\'t reveal pre-attached closed shadowRoot'); 130 </script>