| <!DOCTYPE html> |
| <title>Declarative Shadow DOM</title> |
| <link rel='author' href='mailto:masonf@chromium.org'> |
| <link rel='help' href='https://github.com/whatwg/dom/issues/831'> |
| <script src='/resources/testharness.js'></script> |
| <script src='/resources/testharnessreport.js'></script> |
| |
| <body> |
| <script> |
| let templatesSeen = 0; |
| |
| function myObserver(mutationsList, observer) { |
| document.querySelectorAll('.host').forEach(n => { |
| templatesSeen++; |
| n.className = 'done'; |
| switch (n.id) { |
| case 'openhost': |
| case 'closedhost': |
| assert_equals(n.querySelector('template'),null,'No template ever for streaming declarative Shadow DOM'); |
| assert_equals(n.innerHTML, "", 'Declarative shadow host innerHTML should be empty - all content is inside shadow'); |
| break; |
| case 'noroot': |
| const template = n.querySelector('template'); |
| assert_true(!!template,'Regular template should still be present'); |
| // Make sure adding 'shadowrootmode' attribute doesn't trigger a shadow root, |
| // even if added before parsing completes. |
| template.setAttribute('shadowrootmode','open'); |
| assert_not_equals(template.content, null, 'Regular template should have content, even after adding shadowrootmode attribute'); |
| assert_not_equals(template.innerHTML, "", 'Regular template should have innerHTML, even after adding shadowrootmode attribute'); |
| assert_not_equals(template.getInnerHTML({includeShadowRoots: true}), "", 'Regular template should have getInnerHTML(), even after adding shadowrootmode attribute'); |
| break; |
| default: |
| assert_unreached('Unrecognized template'); |
| } |
| }); |
| } |
| const observer = new MutationObserver(myObserver); |
| observer.observe(document.body, { childList: true, subtree: true }); |
| assert_equals(templatesSeen, 0, 'No mutations yet'); |
| </script> |
| |
| <div id=openhost class=host><template shadowrootmode=open> |
| <slot></slot> |
| <!-- Ensure observer runs at this point (https://github.com/web-platform-tests/wpt/issues/35393) --> |
| <script> // some content, which shouldn't be necessary </script> |
| </template></div> |
| |
| <div id=closedhost class=host><template shadowrootmode=closed> |
| <slot></slot> |
| <!-- Ensure observer runs at this point (https://github.com/web-platform-tests/wpt/issues/35393) --> |
| <script> // some content, which shouldn't be necessary </script> |
| </template></div> |
| |
| <div id=noroot class=host><template> |
| <slot></slot> |
| <!-- Ensure observer runs at this point (https://github.com/web-platform-tests/wpt/issues/35393) --> |
| <script> // some content, which shouldn't be necessary </script> |
| </template></div> |
| |
| <script> |
| test(t => { |
| t.add_cleanup(function() { observer.disconnect(); }); |
| |
| assert_equals(templatesSeen, 3); |
| |
| // Open shadow root |
| let host = document.querySelector('#openhost'); |
| assert_equals(host.querySelector('template'), null, 'No template nodes'); |
| assert_true(!!host.shadowRoot, 'Shadow root should exist'); |
| |
| // Closed shadow root |
| host = document.querySelector('#closedhost'); |
| assert_equals(host.querySelector('template'), null, 'No template nodes'); |
| assert_true(!host.shadowRoot, 'Closed shadow root (can\'t detect)'); |
| |
| // No shadow root |
| host = document.querySelector('#noroot'); |
| assert_true(!!host.querySelector('template'), 'Template node still present for invalid shadowrootmode value'); |
| assert_true(!host.shadowRoot, 'No shadow root'); |
| },'Streaming Declarative Shadow DOM: template .content() should be null'); |
| </script> |
| |
| |
| <script> |
| let synchronous_events_received = new Set(); |
| function synchronousHandler(e) { |
| synchronous_events_received.add(e.type); |
| } |
| const sync_events = ["DOMAttrModified","DOMAttributeNameChanged","DOMCharacterDataModified", |
| "DOMElementNameChanged","DOMNodeInserted","DOMNodeInsertedIntoDocument","DOMNodeRemoved", |
| "DOMNodeRemovedFromDocument","DOMSubtreeModified"]; |
| function addSyncObserver(evt) { |
| window.addEventListener(evt, synchronousHandler, true); |
| } |
| function removeSyncObserver(evt) { |
| window.removeEventListener(evt, synchronousHandler, true); |
| } |
| sync_events.forEach(e => addSyncObserver(e)); |
| </script> |
| |
| <div id=synchost1> |
| <template shadowrootmode=open> |
| <div class=foo>content</div> |
| <slot></slot> |
| </template> |
| </div> |
| |
| <div id=synchost2> |
| <template shadowrootmode=closed> |
| <div class=foo>content</div> |
| <slot></slot> |
| </template> |
| </div> |
| |
| <script> |
| test(t => { |
| t.add_cleanup(function() { sync_events.forEach(e => removeSyncObserver(e)) }); |
| assert_true(!synchronous_events_received.size,`Synchronous mutation events fired: ${Array.from(synchronous_events_received)}`); |
| },'Synchronous mutation events should not be fired during streaming declarative shadow DOM parsing'); |
| </script> |