Skip to content

Commit 2372aae

Browse files
mfreed7Commit Bot
authored and
Commit Bot
committed
Deny ElementInternals.shadowRoot for pre-created shadow roots
Per the spec issue [1], this change disallows the use of ElementInternals.shadowRoot for shadow roots created prior to the custom element constructor being run. This protects potentially-closed shadow roots, created outside of the custom element, from being revealed to the custom element itself. (Use case unclear, but this was the request.) [1] WICG/webcomponents#871 Bug: 1042130 Change-Id: I25192256e8b1334d09ea587f29d64f35d4f5f949 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412470 Commit-Queue: Kouhei Ueno <[email protected]> Auto-Submit: Mason Freed <[email protected]> Reviewed-by: Kouhei Ueno <[email protected]> Cr-Commit-Position: refs/heads/master@{#807311}
1 parent 6cdec97 commit 2372aae

File tree

4 files changed

+50
-4
lines changed

4 files changed

+50
-4
lines changed

Diff for: third_party/blink/renderer/core/dom/element.cc

+16
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,13 @@ Node* Element::Clone(Document& factory, CloneChildrenFlag flag) const {
656656
// set copy’s shadow root’s "is declarative shadow root" property to true.
657657
cloned_shadow_root.SetIsDeclarativeShadowRoot(
658658
shadow_root->IsDeclarativeShadowRoot());
659+
660+
// 7.NEW If node’s shadow root’s "is available to element internals" is
661+
// true, then set copy’s shadow root’s "is available to element internals"
662+
// property to true.
663+
cloned_shadow_root.SetAvailableToElementInternals(
664+
shadow_root->IsAvailableToElementInternals());
665+
659666
// 7.3 If the clone children flag is set, clone all the children of node’s
660667
// shadow root and append them to copy’s shadow root, with document as
661668
// specified, the clone children flag being set, and the clone shadows
@@ -3591,6 +3598,15 @@ ShadowRoot& Element::AttachShadowRootInternal(
35913598
FocusDelegation::kDelegateFocus);
35923599
// 8. Set shadow’s "is declarative shadow root" property to false.
35933600
shadow_root.SetIsDeclarativeShadowRoot(false);
3601+
3602+
// NEW. If shadow host is a custom element, and if custom element state is
3603+
// not "precustomized" or "custom", set shadow root's
3604+
// IsAvailableToElementInternals flag to false. Otherwise, set it to true.
3605+
shadow_root.SetAvailableToElementInternals(
3606+
!(IsCustomElement() &&
3607+
GetCustomElementState() != CustomElementState::kCustom &&
3608+
GetCustomElementState() != CustomElementState::kPreCustomized));
3609+
35943610
shadow_root.SetSlotAssignmentMode(slot_assignment_mode);
35953611
return shadow_root;
35963612
}

Diff for: third_party/blink/renderer/core/dom/shadow_root.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
163163
}
164164
bool IsDeclarativeShadowRoot() const { return is_declarative_shadow_root_; }
165165

166+
void SetAvailableToElementInternals(bool flag) {
167+
DCHECK(!flag || GetType() == ShadowRootType::kOpen ||
168+
GetType() == ShadowRootType::kClosed);
169+
available_to_element_internals_ = flag;
170+
}
171+
bool IsAvailableToElementInternals() const {
172+
return available_to_element_internals_ || is_declarative_shadow_root_;
173+
}
174+
166175
bool ContainsShadowRoots() const { return child_shadow_root_count_; }
167176

168177
StyleSheetList& StyleSheets();
@@ -195,8 +204,9 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
195204
unsigned delegates_focus_ : 1;
196205
unsigned slot_assignment_mode_ : 1;
197206
unsigned is_declarative_shadow_root_ : 1;
207+
unsigned available_to_element_internals_ : 1;
198208
unsigned needs_distribution_recalc_ : 1;
199-
unsigned unused_ : 9;
209+
unsigned unused_ : 8;
200210
};
201211

202212
inline Element* ShadowRoot::ActiveElement() const {

Diff for: third_party/blink/renderer/core/html/custom/element_internals.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,10 @@ bool ElementInternals::HasState(const AtomicString& state) const {
239239
}
240240

241241
ShadowRoot* ElementInternals::shadowRoot() const {
242-
return Target().AuthorShadowRoot();
242+
if (ShadowRoot* shadow_root = Target().AuthorShadowRoot()) {
243+
return shadow_root->IsAvailableToElementInternals() ? shadow_root : nullptr;
244+
}
245+
return nullptr;
243246
}
244247

245248
const AtomicString& ElementInternals::FastGetAttribute(

Diff for: third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html

+19-2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,23 @@
108108
assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals forbidden by disabledFeatures, post-upgrade');
109109
}, 'ElementInternals disabled by disabledFeatures');
110110

111-
112-
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');
113130
</script>

0 commit comments

Comments
 (0)