0

Remove non-streaming (deprecated) declarative shadow dom

The deprecation was completed on January 8, 2024, fully disabled
for M120 stable users. And the flag was disabled in code as of
121.0.6143.0, in November, 2023.

This CL removes all of the code supporting the deprecated/removed
version of the `shadowroot` attribute.

Bug: 1396384
Change-Id: Icbe4b264c2cb4b4425898310fca7c5f804cb930c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5187471
Auto-Submit: Mason Freed <masonf@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: David Baron <dbaron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1247640}
This commit is contained in:
Mason Freed
2024-01-16 19:00:53 +00:00
committed by Chromium LUCI CQ
parent b49dd8fd6c
commit 5f4c1fc06a
23 changed files with 106 additions and 325 deletions

@ -5241,21 +5241,17 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
return &shadow_root;
}
bool Element::AttachStreamingDeclarativeShadowRoot(
HTMLTemplateElement& template_element,
ShadowRootType type,
FocusDelegation focus_delegation,
SlotAssignmentMode slot_assignment) {
bool Element::AttachDeclarativeShadowRoot(HTMLTemplateElement& template_element,
ShadowRootType type,
FocusDelegation focus_delegation,
SlotAssignmentMode slot_assignment) {
CHECK(type == ShadowRootType::kOpen || type == ShadowRootType::kClosed);
CHECK(!template_element.IsNonStreamingDeclarativeShadowRoot());
// 12. Run attach a shadow root with shadow host equal to declarative shadow
// host element, mode equal to declarative shadow mode, and delegates focus
// equal to declarative shadow delegates focus. If an exception was thrown by
// attach a shadow root, catch it, and ignore the exception.
if (const char* error_message = ErrorMessageForAttachShadow()) {
template_element.SetDeclarativeShadowRootType(
DeclarativeShadowRootType::kNone);
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kError, error_message));
@ -5273,55 +5269,6 @@ bool Element::AttachStreamingDeclarativeShadowRoot(
return true;
}
// TODO(crbug.com/1396384) Remove this entire function when the older version
// of declarative shadow DOM is removed.
bool Element::AttachDeprecatedNonStreamingDeclarativeShadowRoot(
HTMLTemplateElement& template_element,
ShadowRootType type,
FocusDelegation focus_delegation,
SlotAssignmentMode slot_assignment) {
CHECK(type == ShadowRootType::kOpen || type == ShadowRootType::kClosed);
CHECK(template_element.IsNonStreamingDeclarativeShadowRoot());
CHECK(RuntimeEnabledFeatures::
DeprecatedNonStreamingDeclarativeShadowDOMEnabled());
Deprecation::CountDeprecation(
GetDocument().GetExecutionContext(),
mojom::blink::WebFeature::kDeclarativeShadowRoot);
// 12. Run attach a shadow root with shadow host equal to declarative shadow
// host element, mode equal to declarative shadow mode, and delegates focus
// equal to declarative shadow delegates focus. If an exception was thrown by
// attach a shadow root, catch it, and ignore the exception.
if (const char* error_message = ErrorMessageForAttachShadow()) {
template_element.SetDeclarativeShadowRootType(
DeclarativeShadowRootType::kNone);
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kError, error_message));
return false;
}
ShadowRoot& shadow_root =
AttachShadowRootInternal(type, focus_delegation, slot_assignment);
// 13.1. Set declarative shadow host element's shadow host's "is declarative
// shadow root" property to true.
shadow_root.SetIsDeclarativeShadowRoot(true);
// 13.NEW. Set declarative shadow host element's shadow host's "available
// to element internals" to true.
shadow_root.SetAvailableToElementInternals(true);
// 13.2. Append the declarative template element's DocumentFragment to the
// newly-created shadow root.
shadow_root.ParserTakeAllChildrenFrom(
*template_element.DeclarativeShadowContent());
// 13.3. Remove the declarative template element from the document.
if (template_element.parentNode()) {
template_element.parentNode()->ParserRemoveChild(template_element);
}
return true;
}
ShadowRoot& Element::CreateUserAgentShadowRoot() {
DCHECK(!GetShadowRoot());
GetDocument().SetContainsShadowRoot();
@ -6648,11 +6595,7 @@ void Element::SetInnerHTMLInternal(const String& html,
ContainerNode* container = this;
bool swap_dom_parts{false};
if (auto* template_element = DynamicTo<HTMLTemplateElement>(*this)) {
// Allow replacing innerHTML on declarative shadow templates, prior to
// their closing tag being parsed.
container = template_element->IsDeclarativeShadowRoot()
? template_element->DeclarativeShadowContent()
: template_element->content();
container = template_element->content();
swap_dom_parts =
template_element->hasAttribute(html_names::kParsepartsAttr);
}

@ -713,16 +713,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
ShadowRoot* attachShadow(const ShadowRootInit*, ExceptionState&);
// Returns true if the attachment was successful.
bool AttachStreamingDeclarativeShadowRoot(HTMLTemplateElement&,
ShadowRootType,
FocusDelegation,
SlotAssignmentMode);
// TODO(crbug.com/1396384) Remove this entire function when the older version
// of declarative shadow DOM is removed.
bool AttachDeprecatedNonStreamingDeclarativeShadowRoot(HTMLTemplateElement&,
ShadowRootType,
FocusDelegation,
SlotAssignmentMode);
bool AttachDeclarativeShadowRoot(HTMLTemplateElement&,
ShadowRootType,
FocusDelegation,
SlotAssignmentMode);
ShadowRoot& CreateUserAgentShadowRoot();
ShadowRoot& AttachShadowRootInternal(

@ -322,6 +322,7 @@
],
chrome_status_feature: 6239658726391808,
milestone: 119,
obsolete_to_be_removed_after_milestone: 132,
},
{
name: "NoSysexWebMIDIWithoutPermission",

@ -46,7 +46,7 @@ HTMLTemplateElement::HTMLTemplateElement(Document& document)
HTMLTemplateElement::~HTMLTemplateElement() = default;
DocumentFragment* HTMLTemplateElement::ContentInternal() const {
DocumentFragment* HTMLTemplateElement::content() const {
CHECK(!declarative_shadow_root_);
if (!content_ && GetExecutionContext())
content_ = MakeGarbageCollected<TemplateContentDocumentFragment>(
@ -56,18 +56,6 @@ DocumentFragment* HTMLTemplateElement::ContentInternal() const {
return content_.Get();
}
DocumentFragment* HTMLTemplateElement::content() const {
CHECK(!declarative_shadow_root_);
return IsDeclarativeShadowRoot() ? nullptr : ContentInternal();
}
DocumentFragment* HTMLTemplateElement::DeclarativeShadowContent() const {
CHECK(RuntimeEnabledFeatures::
DeprecatedNonStreamingDeclarativeShadowDOMEnabled());
CHECK(IsNonStreamingDeclarativeShadowRoot());
return IsDeclarativeShadowRoot() ? ContentInternal() : nullptr;
}
// https://html.spec.whatwg.org/C/#the-template-element:concept-node-clone-ext
void HTMLTemplateElement::CloneNonAttributePropertiesFrom(
const Element& source,

@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/template_content_document_fragment.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@ -41,17 +42,10 @@ namespace blink {
class DocumentFragment;
class TemplateContentDocumentFragment;
// TODO(crbug.com/1379513, crbug.com/1396384) Only three of these should be
// needed at a time, depending on the state of the StreamingDeclarativeShadowDOM
// feature and whether the `shadowroot` or `shadowrootmode` attribute is used.
// For a given template, either kNone/kOpen/kClosed or
// kNone/kStreamingOpen/kStreamingClosed are used.
enum class DeclarativeShadowRootType {
kNone,
kOpen,
kStreamingOpen,
kClosed,
kStreamingClosed,
};
class CORE_EXPORT HTMLTemplateElement final : public HTMLElement {
@ -67,35 +61,22 @@ class CORE_EXPORT HTMLTemplateElement final : public HTMLElement {
DocumentFragment* content() const;
// This gives direct access to ContentInternal, and should *only*
// This just retrieves existing content, and will not construct a content
// DocumentFragment if one does not exist.
DocumentFragment* getContent() const {
CHECK(!declarative_shadow_root_ || !content_);
return content_;
}
// This retrieves either a currently-being-parsed declarative shadow root,
// or the content fragment for a "regular" template element. This should only
// be used by HTMLConstructionSite.
DocumentFragment* TemplateContentForHTMLConstructionSite() const {
if (declarative_shadow_root_) {
return declarative_shadow_root_.Get();
}
return ContentInternal();
}
// TODO(crbug.com/1396384) Eventually remove this.
bool IsNonStreamingDeclarativeShadowRoot() const;
// TODO(crbug.com/1396384) Eventually remove this.
DocumentFragment* DeclarativeShadowContent() const;
void SetDeclarativeShadowRootType(DeclarativeShadowRootType val) {
declarative_shadow_root_type_ = val;
}
DeclarativeShadowRootType GetDeclarativeShadowRootType() const {
return declarative_shadow_root_type_;
}
bool IsDeclarativeShadowRoot() const {
return declarative_shadow_root_type_ != DeclarativeShadowRootType::kNone;
DocumentFragment* TemplateContentOrDeclarativeShadowRoot() const {
return declarative_shadow_root_ ? declarative_shadow_root_.Get()
: content();
}
void SetDeclarativeShadowRoot(ShadowRoot& shadow) {
DCHECK(declarative_shadow_root_type_ ==
DeclarativeShadowRootType::kStreamingOpen ||
declarative_shadow_root_type_ ==
DeclarativeShadowRootType::kStreamingClosed);
declarative_shadow_root_ = &shadow;
}
@ -104,33 +85,11 @@ class CORE_EXPORT HTMLTemplateElement final : public HTMLElement {
NodeCloningData&) override;
void DidMoveToNewDocument(Document& old_document) override;
DocumentFragment* ContentInternal() const;
mutable Member<TemplateContentDocumentFragment> content_;
Member<ShadowRoot> declarative_shadow_root_;
DeclarativeShadowRootType declarative_shadow_root_type_;
};
// TODO(crbug.com/1396384) Remove this entire function when the older version
// of declarative shadow DOM is removed.
ALWAYS_INLINE bool HTMLTemplateElement::IsNonStreamingDeclarativeShadowRoot()
const {
switch (declarative_shadow_root_type_) {
case DeclarativeShadowRootType::kNone:
return false;
case DeclarativeShadowRootType::kOpen:
case DeclarativeShadowRootType::kClosed:
DCHECK(!declarative_shadow_root_);
CHECK(RuntimeEnabledFeatures::
DeprecatedNonStreamingDeclarativeShadowDOMEnabled());
return true;
case DeclarativeShadowRootType::kStreamingOpen:
case DeclarativeShadowRootType::kStreamingClosed:
return false;
}
}
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_TEMPLATE_ELEMENT_H_

@ -35,20 +35,14 @@
] interface HTMLTemplateElement : HTMLElement {
readonly attribute DocumentFragment content;
// This is the shipped version of declarative shadow DOM - using the
// 'shadowRoot' IDL attribute. However, discussions on the HTML spec PR
// (https://github.com/whatwg/html/pull/5465) has changed this behavior.
// This IDL will remain during the period during which we deprecate it.
// This 'shadowRoot' attribute shadows Element.prototype.shadowRoot
// without changing any behavior. The existence of this attribute
// indicates support of Declarative Shadow DOM, so that this works:
// function supportsDeclarativeShadowDOM() {
// return HTMLTemplateElement.prototype.hasOwnProperty("shadowRoot");
// }
// See https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md#feature-detection-and-polyfilling
// for more detail.
// This is the deprecated and removed IDL for `shadowRoot`, which was used
// by the old declarative shadow DOM proposal. Note that it was only used
// for feature detection - this override of `shadowRoot` returns the same
// thing as HTMLElement's `shadowRoot` attribute. For safety, it is here,
// guarded by a runtime flag, in case of compat problems.
// TODO(crbug.com/1396384) Eventually remove this.
[ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
[ImplementedAs=OpenShadowRoot, RuntimeEnabled=DeprecatedTemplateShadowRoot]
readonly attribute ShadowRoot? shadowRoot;
// This is the declarative Shadow DOM IDL attribute, which reflects the
// 'shadowrootmode' content attribute.

@ -211,7 +211,7 @@ static inline void Insert(HTMLConstructionSiteTask& task) {
// instead be inside the template element's template contents, after its last
// child (if any).
if (auto* template_element = DynamicTo<HTMLTemplateElement>(*task.parent)) {
task.parent = template_element->TemplateContentForHTMLConstructionSite();
task.parent = template_element->TemplateContentOrDeclarativeShadowRoot();
// If the Document was detached in the middle of parsing, The template
// element won't be able to initialize its contents, so bail out.
if (!task.parent)
@ -917,22 +917,20 @@ void HTMLConstructionSite::InsertHTMLFormElement(AtomicHTMLToken* token,
void HTMLConstructionSite::InsertHTMLTemplateElement(
AtomicHTMLToken* token,
DeclarativeShadowRootType declarative_shadow_root_type) {
// Regardless of the state of the StreamingDeclarativeShadowDOM feature, the
// template element is always created. If the feature is enabled, and if the
// template is a valid declarative Shadow Root (has a valid attribute value
// and parent element), then the template is only added to the stack of open
// elements, but is not attached to the DOM tree.
// Regardless of whether a declarative shadow root is being attached, the
// template element is always created. If the template is a valid declarative
// Shadow Root (has a valid attribute value and parent element), then the
// template is only added to the stack of open elements, but is not attached
// to the DOM tree.
auto* template_element = To<HTMLTemplateElement>(
CreateElement(token, html_names::xhtmlNamespaceURI));
template_element->SetDeclarativeShadowRootType(declarative_shadow_root_type);
HTMLStackItem* template_stack_item =
HTMLStackItem::Create(template_element, token);
bool should_attach_template = true;
if ((declarative_shadow_root_type ==
DeclarativeShadowRootType::kStreamingOpen ||
declarative_shadow_root_type ==
DeclarativeShadowRootType::kStreamingClosed) &&
if (declarative_shadow_root_type != DeclarativeShadowRootType::kNone &&
IsA<Element>(open_elements_.TopStackItem()->GetNode())) {
CHECK(declarative_shadow_root_type == DeclarativeShadowRootType::kOpen ||
declarative_shadow_root_type == DeclarativeShadowRootType::kClosed);
// Attach the shadow root now
auto focus_delegation = template_stack_item->GetAttributeItem(
html_names::kShadowrootdelegatesfocusAttr)
@ -944,41 +942,27 @@ void HTMLConstructionSite::InsertHTMLTemplateElement(
HTMLStackItem* shadow_host_stack_item = open_elements_.TopStackItem();
Element* host = shadow_host_stack_item->GetElement();
ShadowRootType type = declarative_shadow_root_type ==
DeclarativeShadowRootType::kStreamingOpen
? ShadowRootType::kOpen
: ShadowRootType::kClosed;
bool success = host->AttachStreamingDeclarativeShadowRoot(
ShadowRootType type =
declarative_shadow_root_type == DeclarativeShadowRootType::kOpen
? ShadowRootType::kOpen
: ShadowRootType::kClosed;
bool success = host->AttachDeclarativeShadowRoot(
*template_element, type, focus_delegation, slot_assignment_mode);
// If the shadow root attachment fails, e.g. if the host element isn't a
// valid shadow host, then we leave should_attach_template true, so that
// a "normal" template element gets attached to the DOM tree.
if (success) {
DCHECK(host->AuthorShadowRoot());
UseCounter::Count(host->GetDocument(),
WebFeature::kStreamingDeclarativeShadowDOM);
should_attach_template = false;
template_element->SetDeclarativeShadowRoot(*host->AuthorShadowRoot());
} else {
// If the shadow root attachment fails, e.g. if the host element isn't a
// valid shadow host, then we leave should_attach_template true, so that
// a "normal" template element gets attached to the DOM tree.
template_element->SetDeclarativeShadowRootType(
DeclarativeShadowRootType::kNone);
}
}
if (should_attach_template) {
// Attach a normal template element, or the opening tag of a non-streaming
// declarative shadow root.
// Attach a normal template element.
AttachLater(CurrentNode(), template_element, token->GetDOMPartsNeeded());
// cant_attach_shadow can happen if we are being asked to attach a
// declarative shadowroot to another declarative shadowroot or another
// existing shadowroot.
bool cant_attach_shadow =
!IsA<Element>(open_elements_.TopStackItem()->GetNode());
DocumentFragment* template_content =
cant_attach_shadow ||
template_element->GetDeclarativeShadowRootType() ==
DeclarativeShadowRootType::kNone
? template_element->content()
: template_element->DeclarativeShadowContent();
DocumentFragment* template_content = template_element->content();
if (pending_dom_parts_ && template_content) {
pending_dom_parts_->PushPartRoot(&template_content->getPartRoot());
}
@ -1073,7 +1057,7 @@ void HTMLConstructionSite::InsertTextNode(const StringView& string,
// If the Document was detached in the middle of parsing, the template
// element won't be able to initialize its contents.
if (auto* content =
template_element->TemplateContentForHTMLConstructionSite()) {
template_element->TemplateContentOrDeclarativeShadowRoot()) {
dummy_task.parent = content;
}
}
@ -1136,7 +1120,7 @@ Document& HTMLConstructionSite::OwnerDocumentForCurrentNode() {
// element won't be able to initialize its contents. Fallback to the
// current node's document in that case..
if (auto* content =
template_element->TemplateContentForHTMLConstructionSite()) {
template_element->TemplateContentOrDeclarativeShadowRoot()) {
return content->GetDocument();
}
}

@ -1011,70 +1011,32 @@ DeclarativeShadowRootType DeclarativeShadowRootTypeFromToken(
AtomicHTMLToken* token,
const Document& document,
bool include_shadow_roots) {
// Declarative shadow DOM, as initially shipped:
// 1. used the 'shadowroot' attribute, and
// 2. attached the shadow root at the *closing* </template> tag.
// In 2022, discussions of the spec resumed, and two changes were made:
// 1. the attribute is called 'shadowrootmode', and
// 2. the shadow root is attached at the *opening* <template> tag.
// During the transition between these two behaviors, *both* behaviors can
// be used, and are controlled by the developer:
// <template shadowroot=open> ==> old behavior
// <template shadowrootmode=open> ==> new behavior
// <template shadowroot=open shadowrootmode=open> ==> new behavior
// crbug.com/1379513 tracks the new behavior.
// crbug.com/1396384 tracks the eventual removal of the old behavior.
Attribute* type_attribute_streaming =
Attribute* type_attribute =
token->GetAttributeItem(html_names::kShadowrootmodeAttr);
String shadow_mode;
if (type_attribute_streaming) {
shadow_mode = type_attribute_streaming->Value();
} else {
Attribute* type_attribute_non_streaming =
token->GetAttributeItem(html_names::kShadowrootAttr);
if (!type_attribute_non_streaming) {
return DeclarativeShadowRootType::kNone;
}
if (!RuntimeEnabledFeatures::
DeprecatedNonStreamingDeclarativeShadowDOMEnabled()) {
document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kDeprecation,
mojom::blink::ConsoleMessageLevel::kError,
"Found an old-style declarative `shadowroot` attribute on a "
"template, but that style was deprecated and has been removed. "
"Please use the `shadowrootmode` attribute instead. Please see "
"https://chromestatus.com/feature/6239658726391808."));
return DeclarativeShadowRootType::kNone;
}
shadow_mode = type_attribute_non_streaming->Value();
if (!type_attribute) {
return DeclarativeShadowRootType::kNone;
}
String shadow_mode = type_attribute->Value();
if (include_shadow_roots) {
if (EqualIgnoringASCIICase(shadow_mode, "open")) {
return type_attribute_streaming
? DeclarativeShadowRootType::kStreamingOpen
: DeclarativeShadowRootType::kOpen;
return DeclarativeShadowRootType::kOpen;
} else if (EqualIgnoringASCIICase(shadow_mode, "closed")) {
return type_attribute_streaming
? DeclarativeShadowRootType::kStreamingClosed
: DeclarativeShadowRootType::kClosed;
return DeclarativeShadowRootType::kClosed;
}
}
String attribute_in_use =
type_attribute_streaming ? "shadowrootmode" : "shadowroot";
if (!include_shadow_roots) {
document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kWarning,
"Found declarative " + attribute_in_use +
" attribute on a template, but declarative "
"Shadow DOM has not been enabled by includeShadowRoots."));
"Found declarative shadowrootmode attribute on a template, but "
"declarative Shadow DOM has not been enabled by includeShadowRoots."));
} else {
document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::blink::ConsoleMessageSource::kOther,
mojom::blink::ConsoleMessageLevel::kWarning,
"Invalid declarative " + attribute_in_use + " attribute value \"" +
shadow_mode + "\". Valid values include \"open\" and \"closed\"."));
"Invalid declarative shadowrootmode attribute value \"" + shadow_mode +
"\". Valid values include \"open\" and \"closed\"."));
}
return DeclarativeShadowRootType::kNone;
}
@ -1106,7 +1068,6 @@ bool HTMLTreeBuilder::ProcessTemplateEndTag(AtomicHTMLToken* token) {
tree_.OpenElements()->PopUntil(HTMLTag::kTemplate);
HTMLStackItem* template_stack_item = tree_.OpenElements()->TopStackItem();
tree_.OpenElements()->Pop();
HTMLStackItem* shadow_host_stack_item = tree_.OpenElements()->TopStackItem();
tree_.ActiveFormattingElements()->ClearToLastMarker();
template_insertion_modes_.pop_back();
ResetInsertionModeAppropriately();
@ -1114,44 +1075,7 @@ bool HTMLTreeBuilder::ProcessTemplateEndTag(AtomicHTMLToken* token) {
DCHECK(template_stack_item->IsElementNode());
HTMLTemplateElement* template_element =
DynamicTo<HTMLTemplateElement>(template_stack_item->GetElement());
DocumentFragment* template_content = nullptr;
if (template_element->IsDeclarativeShadowRoot()) {
if (RuntimeEnabledFeatures::
DeprecatedNonStreamingDeclarativeShadowDOMEnabled()) {
if (shadow_host_stack_item->GetNode() ==
tree_.OpenElements()->RootNode()) {
// 10. If the adjusted current node is the topmost element in the
// stack of open elements, then stop this algorithm.
template_element->SetDeclarativeShadowRootType(
DeclarativeShadowRootType::kNone);
} else {
DCHECK(shadow_host_stack_item);
DCHECK(shadow_host_stack_item->IsElementNode());
if (template_element->IsNonStreamingDeclarativeShadowRoot()) {
template_content = template_element->DeclarativeShadowContent();
auto focus_delegation =
template_stack_item->GetAttributeItem(
html_names::kShadowrootdelegatesfocusAttr)
? FocusDelegation::kDelegateFocus
: FocusDelegation::kNone;
// TODO(crbug.com/1063157): Add an attribute for imperative slot
// assignment.
auto slot_assignment_mode = SlotAssignmentMode::kNamed;
shadow_host_stack_item->GetElement()
->AttachDeprecatedNonStreamingDeclarativeShadowRoot(
*template_element,
template_element->GetDeclarativeShadowRootType() ==
DeclarativeShadowRootType::kOpen
? ShadowRootType::kOpen
: ShadowRootType::kClosed,
focus_delegation, slot_assignment_mode);
}
}
}
} else {
template_content = template_element->content();
}
if (template_content) {
if (DocumentFragment* template_content = template_element->getContent()) {
tree_.FinishedTemplateElement(template_content);
}
}

@ -1870,12 +1870,9 @@ std::unique_ptr<protocol::DOM::Node> InspectorDOMAgent::BuildObjectForNode(
}
if (auto* template_element = DynamicTo<HTMLTemplateElement>(*element)) {
// The inspector should not try to access the .content() property of
// declarative Shadow DOM <template> elements, because it will be null.
if (!template_element->IsDeclarativeShadowRoot() &&
template_element->content()) {
value->setTemplateContent(BuildObjectForNode(
template_element->content(), 0, pierce, nodes_map, flatten_result));
if (DocumentFragment* content = template_element->content()) {
value->setTemplateContent(
BuildObjectForNode(content, 0, pierce, nodes_map, flatten_result));
force_push_children = true;
}
}

@ -1250,10 +1250,9 @@
status: "test",
},
{
// TODO(crbug.com/1396384) This is being disabled, very slowly, via
// Finch over 119 and 120. For now, it is enabled in code, and will be
// removed from code starting in M121, assuming things go well.
name: "DeprecatedNonStreamingDeclarativeShadowDOM",
// This is a killswitch (enabled by *enabling* the feature) for the
// removal of the IDL reflection of the old 'shadowroot' attribute.
name: "DeprecatedTemplateShadowRoot",
},
{
name: "DesktopCaptureDisableLocalEchoControl",

@ -1067,7 +1067,7 @@
},
{
"prefix": "dom-parts-disabled",
"owners": ["masonf@chromium.org", "dom-dev@chromium.org"],
"owners": ["masonf@chromium.org"],
"platforms": ["Linux"],
"bases": [
"external/wpt/dom/parts",
@ -1077,6 +1077,17 @@
"--disable-threaded-compositing", "--disable-threaded-animation"],
"expires": "Jul 1, 2024"
},
{
"prefix": "template-shadowroot-enabled",
"owners": ["masonf@chromium.org"],
"platforms": ["Linux"],
"bases": [
"external/wpt/shadow-dom/declarative",
"shadow-dom/template-shadowroot-reflection.html"
],
"args": ["--enable-blink-features=DeprecatedTemplateShadowRoot"],
"expires": "Jul 1, 2024"
},
{
"prefix": "details-styling-disabled",
"owners": ["dbaron@chromium.org", "dom-dev@chromium.org"],

@ -74,10 +74,8 @@ testPaste("<span>foo</span><div><template>Hello</template></div><span>bar</span>
// Contained shadow DOM is stripped, but content is retained (streaming DSD API, shadowrootmode attribute):
testPaste("<span>foo</span><div><template shadowrootmode='open'>Hello</template></div><span>bar</span>", "foo<div>Hello</div>bar");
testPaste("<span>foo</span><div><template shadowrootmode='open'><slot></slot>DEF</template>ABC</div><span>bar</span>", "foo<div><slot>ABC</slot>DEF</div>bar");
// Make sure non-declarative <template shadowroot> doesn't form a shadow root on paste:
// Make sure non-declarative <template shadowrootmode> doesn't form a shadow root on paste:
const nodeWithTemplate = createEditable("<span>foo</span><div>ABC<template>Hello</template></div><span>bar</span>");
nodeWithTemplate.querySelector('template').setAttribute('shadowroot','open');
testPaste(nodeWithTemplate, "foo<div>ABC</div>bar", "non-streaming DSD 3");
nodeWithTemplate.querySelector('template').setAttribute('shadowrootmode','open');
testPaste(nodeWithTemplate, "foo<div>ABC</div>bar");
</script>

@ -60,7 +60,7 @@ function testElementType(allowed, nochildren, elementType, mode, delegatesFocus)
}, 'Calling attachShadow a second time on an element with a declarative shadow fails (opposite mode)');
} else {
if (!nochildren) {
// Invalid elements should retain a <template> element child with a shadowroot attribute.
// Invalid elements should retain a <template> element child with a shadowrootmode attribute.
const template = nodes.wrapper.querySelector('template[shadowrootmode]');
assert_true(!!template);
assert_equals(template.getAttribute('shadowrootmode'), mode, `Template with shadowrootmode=${mode} should be left over`);

@ -46,6 +46,6 @@ test(t => {
assert_true(!!shadowroot, 'Shadow root should be present');
assert_true(!!shadowroot.querySelector('#newcontent'),'The innerHTML replacement content should be present');
assert_true(!shadowroot.querySelector('#oldcontent'),'The old replaced content should not be present');
}, 'Declarative Shadow DOM: innerHTML should work while parsing STREAMING declarative shadow root <template>');
}, 'Declarative Shadow DOM: innerHTML should work while parsing streaming declarative shadow root <template>');
</script>
</body>

@ -1,3 +0,0 @@
Verifies that Streaming declarative shadow DOM (<template shadowrootmode>) does not trigger a deprecation issue.
Success - no issues reported

@ -1,22 +0,0 @@
(async function (testRunner) {
const { session, dp } = await testRunner.startBlank(
'Verifies that Streaming declarative shadow DOM (<template shadowrootmode>) does not trigger a deprecation issue.');
await dp.Audits.enable();
const issueAdded = dp.Audits.onceIssueAdded();
await session.navigate('../resources/streaming-declarative-shadow-dom.html');
// This is a test that issues are NOT reported. So we need to just wait
// for a period of time.
let timedOut = false;
const timeout = new Promise(resolve => setTimeout(() => {
timedOut = true;
resolve();
}, 100));
await Promise.race([
timeout,
issueAdded,
]);
testRunner.log(timedOut ? "Success - no issues reported" : "FAIL: issues reported.");
testRunner.completeTest();
})

@ -1,3 +0,0 @@
<!DOCTYPE html>
<div><template shadowroot=open>Deprecated Shadow Root</template></div>

@ -1,3 +0,0 @@
<!DOCTYPE html>
<div><template shadowrootmode=open>NON-Deprecated Shadow Root</template></div>

@ -0,0 +1,15 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Template shadowRoot reflection</title>
<script src='../resources/testharness.js'></script>
<script src='../resources/testharnessreport.js'></script>
<!-- This simply tests whether HTMLTemplateElement has a `shadowRoot` attribute.
It should not, since that was deprecated and removed as part of the original
declarative Shadow DOM. -->
<script>
test(() => {
assert_false(HTMLTemplateElement.prototype.hasOwnProperty("shadowRoot"));
}, "HTMLTemplateElement should not have a shadowRoot own property");
</script>

@ -4354,7 +4354,6 @@ interface HTMLTableSectionElement : HTMLElement
interface HTMLTemplateElement : HTMLElement
attribute @@toStringTag
getter content
getter shadowRoot
getter shadowRootMode
method constructor
setter shadowRootMode

@ -0,0 +1,2 @@
# This suite runs tests with --enable-blink-features=DeprecatedTemplateShadowRoot.
This is to ensure the killswitch works.

@ -0,0 +1,5 @@
This is a testharness.js-based test.
[FAIL] HTMLTemplateElement should not have a shadowRoot own property
assert_false: expected false got true
Harness: the test ran to completion.

@ -4930,7 +4930,6 @@ interface HTMLTemplateElement : HTMLElement
attribute @@toStringTag
getter content
getter parseparts
getter shadowRoot
getter shadowRootMode
method constructor
setter parseparts