Skip to content

Commit

Permalink
Disallow multiple declarative roots and mismatched imperative ones
Browse files Browse the repository at this point in the history
Two changes:
 1. If two declarative shadow roots are included within a single
    host element, only the *first* one will remain. This is a
    change in behavior from before, but reached consensus [1]
    and hopefully won't be a breaking change for anyone.
 2. If attachShadow() is used on an existing declarative shadow
    root, and the parameters (e.g. shadow root type, etc.) do
    not match, an exception is thrown. This, also, is a breaking
    change, but hopefully not one that gets hit. See also [1].

See [2] and [3] for the corresponding spec PRs.

[1] whatwg/dom#1235
[2] whatwg/html#10069
[3] whatwg/dom#1246

Bug: 1379513,1042130
Change-Id: Ia81088227797013f9f62f5ac90f76898663b0bc4
  • Loading branch information
mfreed7 authored and chromium-wpt-export-bot committed Jan 18, 2024
1 parent d0011b1 commit e97ff92
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
4 changes: 2 additions & 2 deletions shadow-dom/declarative/declarative-shadow-dom-attachment.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
}

// Now, call attachShadow() and make sure we get back the same (original) shadowRoot, but empty.
const oppositeMode = (mode === 'open') ? 'closed' : 'open';
const newShadow = element.attachShadow({mode: oppositeMode}); // Should be no exception here
const newShadow = element.attachShadow({mode: mode, delegatesFocus: delegatesFocus});
if (mode === 'open') {
assert_equals(element.shadowRoot, originalShadowRoot, 'The same shadow root should be returned');
assert_equals(element.shadowRoot.innerHTML, '', 'Empty shadow content');
Expand All @@ -55,6 +54,7 @@
element.attachShadow({mode: mode});
}, 'Calling attachShadow a second time on an element with a declarative shadow fails (same mode)');

const oppositeMode = (mode === 'open') ? 'closed' : 'open';
assert_throws_dom('NotSupportedError', () => {
element.attachShadow({mode: oppositeMode});
}, 'Calling attachShadow a second time on an element with a declarative shadow fails (opposite mode)');
Expand Down
8 changes: 6 additions & 2 deletions shadow-dom/declarative/declarative-shadow-dom-basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,14 @@
<script>
test(() => {
const host = document.querySelector('#multi-host');
assert_equals(host.querySelector('template'), null, "No leftover template nodes from either root");
const leftover = host.querySelector('template');
assert_true(!!leftover, "The second (duplicate) template should be left in the DOM");
assert_true(leftover instanceof HTMLTemplateElement);
assert_equals(leftover.getAttribute('shadowrootmode'),"closed");
assert_equals(leftover.shadowRootMode,"closed");
assert_true(!!host.shadowRoot,"No open shadow root found - first root should remain");
const innerSpan = host.shadowRoot.querySelector('span');
assert_equals(innerSpan.textContent, 'root 2', "Content should come from last declarative shadow root");
assert_equals(innerSpan.textContent, 'root 1', "Content should come from first declarative shadow root");
}, 'Declarative Shadow DOM: Multiple roots');

</script>
Expand Down
70 changes: 70 additions & 0 deletions shadow-dom/declarative/declarative-shadow-dom-repeats.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<title>Declarative Shadow DOM Element Attachment</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>
<script src='../../html/resources/common.js'></script>
<script src="support/helpers.js"></script>

<div id=multiple1>
<template shadowrootmode=open>Open</template>
<template shadowrootmode=closed>Closed</template>
</div>

<div id=multiple2>
<template shadowrootmode=closed>Closed</template>
<template shadowrootmode=open>Open</template>
</div>

<script>
test((t) => {
let shadow = multiple1.shadowRoot;
assert_true(!!shadow,'Remaining shadow root should be open');
assert_equals(shadow.textContent,"Open");
shadow = multiple2.shadowRoot;
assert_false(!!shadow,'Remaining shadow root should be closed');
multiple1.remove(); // Cleanup
multiple2.remove();
},'Repeated declarative shadow roots keep only the first');
</script>

<div id=open1>
<template shadowrootmode=open>Open</template>
</div>

<script>
test((t) => {
assert_throws_dom("NotSupportedError",() => {
open1.attachShadow({mode: "closed"});
},'Mismatched shadow root type should throw');
const initialShadow = open1.shadowRoot;
const shadow = open1.attachShadow({mode: "open"}); // Shouldn't throw
assert_equals(shadow,initialShadow,'Same shadow should be returned');
assert_equals(shadow.textContent,'','Shadow should be empty');
},'Calling attachShadow() on declarative shadow root must match type');
</script>

<div id=open2>
<template shadowrootmode=open shadowrootdelegatesfocus>
Open, delegates focus (not the default), named slot assignment (the default)
</template>
</div>

<script>
test((t) => {
assert_throws_dom("NotSupportedError",() => {
open2.attachShadow({mode: "closed", delegatesFocus: true, slotAssignment: "named"});
},'Mismatched shadow root type should throw');
assert_throws_dom("NotSupportedError",() => {
open2.attachShadow({mode: "open", delegatesFocus: false, slotAssignment: "named"});
},'Mismatched shadow root delegatesFocus should throw');
assert_throws_dom("NotSupportedError",() => {
open2.attachShadow({mode: "open", delegatesFocus: true, slotAssignment: "manual"});
},'Mismatched shadow root slotAssignment should throw');
const initialShadow = open2.shadowRoot;
const shadow = open2.attachShadow({mode: "open", delegatesFocus: true, slotAssignment: "named"}); // Shouldn't throw
assert_equals(shadow,initialShadow,'Same shadow should be returned');
assert_equals(shadow.textContent,'','Shadow should be empty');
},'Calling attachShadow() on declarative shadow root must match all parameters');
</script>

0 comments on commit e97ff92

Please sign in to comment.