@@ -3513,29 +3513,6 @@ ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) {
35133513 return *shadow_root;
35143514}
35153515
3516- void Element::AttachDeclarativeShadowRoot (HTMLTemplateElement* template_element,
3517- ShadowRootType type,
3518- FocusDelegation focus_delegation,
3519- SlotAssignmentMode slot_assignment) {
3520- DCHECK (template_element);
3521- DCHECK (type == ShadowRootType::kOpen || type == ShadowRootType::kClosed );
3522- if (!CanAttachShadowRoot ()) {
3523- // TODO(1067488): Eventually, this should be a DOMException.
3524- LOG (ERROR) << " Invalid shadow root host element" ;
3525- return ;
3526- }
3527- if (GetShadowRoot ()) {
3528- // TODO(1067488): Eventually, this should be a DOMException.
3529- LOG (ERROR) << " Shadow root already present!" ;
3530- return ;
3531- }
3532- ShadowRoot* shadow_root = &AttachShadowRootInternal (
3533- type, focus_delegation == FocusDelegation::kDelegateFocus ,
3534- slot_assignment == SlotAssignmentMode::kManual );
3535- shadow_root->appendChild (template_element->DeclarativeShadowContent ());
3536- template_element->remove ();
3537- }
3538-
35393516ShadowRoot* Element::GetShadowRoot () const {
35403517 return HasRareData () ? GetElementRareData ()->GetShadowRoot () : nullptr ;
35413518}
@@ -3644,6 +3621,7 @@ ElementInternals& Element::EnsureElementInternals() {
36443621}
36453622
36463623ShadowRoot* Element::createShadowRoot (ExceptionState& exception_state) {
3624+ DCHECK (RuntimeEnabledFeatures::ShadowDOMV0Enabled (&GetDocument ()));
36473625 if (ShadowRoot* root = GetShadowRoot ()) {
36483626 if (root->IsUserAgent ()) {
36493627 exception_state.ThrowDOMException (
@@ -3677,6 +3655,15 @@ ShadowRoot* Element::createShadowRoot(ExceptionState& exception_state) {
36773655 return &CreateShadowRootInternal ();
36783656}
36793657
3658+ ShadowRoot& Element::CreateShadowRootInternal () {
3659+ DCHECK (RuntimeEnabledFeatures::ShadowDOMV0Enabled (&GetDocument ()));
3660+ DCHECK (!ClosedShadowRoot ());
3661+ DCHECK (AreAuthorShadowsAllowed ());
3662+ DCHECK (!AlwaysCreateUserAgentShadowRoot ());
3663+ GetDocument ().SetShadowCascadeOrder (ShadowCascadeOrder::kShadowCascadeV0 );
3664+ return CreateAndAttachShadowRoot (ShadowRootType::V0);
3665+ }
3666+
36803667bool Element::CanAttachShadowRoot () const {
36813668 const AtomicString& tag_name = localName ();
36823669 // Checking Is{V0}CustomElement() here is just an optimization
@@ -3696,17 +3683,26 @@ bool Element::CanAttachShadowRoot() const {
36963683 tag_name == html_names::kSpanTag ;
36973684}
36983685
3699- ShadowRoot* Element::attachShadow (const ShadowRootInit* shadow_root_init_dict,
3700- ExceptionState& exception_state) {
3701- DCHECK (shadow_root_init_dict->hasMode ());
3686+ const char * Element::ErrorMessageForAttachShadow () const {
3687+ // https://dom.spec.whatwg.org/#concept-attach-a-shadow-root
3688+ // 1. If shadow host’s namespace is not the HTML namespace, then throw a
3689+ // "NotSupportedError" DOMException.
3690+ // 2. If shadow host’s local name is not a valid custom element name,
3691+ // "article", "aside", "blockquote", "body", "div", "footer", "h1", "h2",
3692+ // "h3", "h4", "h5", "h6", "header", "main", "nav", "p", "section", or "span",
3693+ // then throw a "NotSupportedError" DOMException.
37023694 if (!CanAttachShadowRoot ()) {
3703- exception_state.ThrowDOMException (
3704- DOMExceptionCode::kNotSupportedError ,
3705- " This element does not support attachShadow" );
3706- return nullptr ;
3695+ return " This element does not support attachShadow" ;
37073696 }
37083697
3709- // Checking IsCustomElement() here is just an optimization because
3698+ // 3. If shadow host’s local name is a valid custom element name, or shadow
3699+ // host’s is value is not null, then:
3700+ // 3.1 Let definition be the result of looking up a custom element
3701+ // definition given shadow host’s node document, its namespace, its local
3702+ // name, and its is value.
3703+ // 3.2 If definition is not null and definition’s
3704+ // disable shadow is true, then throw a "NotSupportedError" DOMException.
3705+ // Note: Checking IsCustomElement() is just an optimization because
37103706 // IsValidName() is not cheap.
37113707 if (IsCustomElement () &&
37123708 (CustomElement::IsValidName (localName ()) || !IsValue ().IsNull ())) {
@@ -3716,55 +3712,86 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
37163712 : IsValue ())
37173713 : nullptr ;
37183714 if (definition && definition->DisableShadow ()) {
3719- exception_state.ThrowDOMException (
3720- DOMExceptionCode::kNotSupportedError ,
3721- " attachShadow() is disabled by disabledFeatures static field." );
3722- return nullptr ;
3715+ return " attachShadow() is disabled by disabledFeatures static field." ;
37233716 }
37243717 }
37253718
3719+ // 4. If shadow host has a non-null shadow root whose is declarative shadow
3720+ // root property is false, then throw an "NotSupportedError" DOMException.
3721+ // 5. TODO(masonfreed): If shadow host has a non-null shadow root whose is
3722+ // declarative shadow root property is true, then remove all of shadow root’s
3723+ // children, in tree order. Return shadow host’s shadow root.
37263724 if (GetShadowRoot ()) {
3727- exception_state.ThrowDOMException (DOMExceptionCode::kNotSupportedError ,
3728- " Shadow root cannot be created on a host "
3729- " which already hosts a shadow tree." );
3730- return nullptr ;
3725+ return " Shadow root cannot be created on a host "
3726+ " which already hosts a shadow tree." ;
37313727 }
3728+ return nullptr ;
3729+ }
37323730
3731+ ShadowRoot* Element::attachShadow (const ShadowRootInit* shadow_root_init_dict,
3732+ ExceptionState& exception_state) {
3733+ DCHECK (shadow_root_init_dict->hasMode ());
37333734 ShadowRootType type = shadow_root_init_dict->mode () == " open"
37343735 ? ShadowRootType::kOpen
37353736 : ShadowRootType::kClosed ;
3736-
37373737 if (type == ShadowRootType::kOpen )
37383738 UseCounter::Count (GetDocument (), WebFeature::kElementAttachShadowOpen );
37393739 else
37403740 UseCounter::Count (GetDocument (), WebFeature::kElementAttachShadowClosed );
37413741
3742- DCHECK (!shadow_root_init_dict->hasMode () || !GetShadowRoot ());
3743- bool delegates_focus = shadow_root_init_dict->hasDelegatesFocus () &&
3744- shadow_root_init_dict->delegatesFocus ();
3745- bool manual_slotting = false ;
3746- if (shadow_root_init_dict->hasSlotAssignment ()) {
3747- manual_slotting = (shadow_root_init_dict->slotAssignment () == " manual" );
3742+ auto focus_delegation = (shadow_root_init_dict->hasDelegatesFocus () &&
3743+ shadow_root_init_dict->delegatesFocus ())
3744+ ? FocusDelegation::kDelegateFocus
3745+ : FocusDelegation::kNone ;
3746+ auto slot_assignment = (shadow_root_init_dict->hasSlotAssignment () &&
3747+ shadow_root_init_dict->slotAssignment () == " manual" )
3748+ ? SlotAssignmentMode::kManual
3749+ : SlotAssignmentMode::kAuto ;
3750+
3751+ if (const char * error_message = ErrorMessageForAttachShadow ()) {
3752+ exception_state.ThrowDOMException (DOMExceptionCode::kNotSupportedError ,
3753+ error_message);
3754+ return nullptr ;
37483755 }
3749- return &AttachShadowRootInternal (type, delegates_focus, manual_slotting );
3756+ return &AttachShadowRootInternal (type, focus_delegation, slot_assignment );
37503757}
37513758
3752- ShadowRoot& Element::CreateShadowRootInternal () {
3753- DCHECK (!ClosedShadowRoot ());
3754- DCHECK (AreAuthorShadowsAllowed ());
3755- DCHECK (!AlwaysCreateUserAgentShadowRoot ());
3756- GetDocument ().SetShadowCascadeOrder (ShadowCascadeOrder::kShadowCascadeV0 );
3757- return CreateAndAttachShadowRoot (ShadowRootType::V0);
3759+ void Element::AttachDeclarativeShadowRoot (HTMLTemplateElement* template_element,
3760+ ShadowRootType type,
3761+ FocusDelegation focus_delegation,
3762+ SlotAssignmentMode slot_assignment) {
3763+ DCHECK (template_element);
3764+ DCHECK (type == ShadowRootType::kOpen || type == ShadowRootType::kClosed );
3765+
3766+ // 12. Run attach a shadow root with shadow host equal to declarative shadow
3767+ // host element, mode equal to declarative shadow mode, and delegates focus
3768+ // equal to declarative shadow delegates focus. If an exception was thrown by
3769+ // attach a shadow root, catch it, and report the exception.
3770+ if (const char * error_message = ErrorMessageForAttachShadow ()) {
3771+ // TODO(1067488): Fire this exception at Window.
3772+ LOG (ERROR) << error_message;
3773+ return ;
3774+ }
3775+ ShadowRoot& shadow_root =
3776+ AttachShadowRootInternal (type, focus_delegation, slot_assignment);
3777+ // 13.1. TODO(masonfreed): Set declarative shadow host element's shadow host's
3778+ // is declarative shadow root property to true.
3779+ // 13.2. Append the declarative template element's DocumentFragment to the
3780+ // newly-created shadow root.
3781+ shadow_root.appendChild (template_element->DeclarativeShadowContent ());
3782+ // 13.3. Remove the declarative template element from the document.
3783+ template_element->remove ();
37583784}
37593785
37603786ShadowRoot& Element::CreateUserAgentShadowRoot () {
37613787 DCHECK (!GetShadowRoot ());
37623788 return CreateAndAttachShadowRoot (ShadowRootType::kUserAgent );
37633789}
37643790
3765- ShadowRoot& Element::AttachShadowRootInternal (ShadowRootType type,
3766- bool delegates_focus,
3767- bool manual_slotting) {
3791+ ShadowRoot& Element::AttachShadowRootInternal (
3792+ ShadowRootType type,
3793+ FocusDelegation focus_delegation,
3794+ SlotAssignmentMode slot_assignment_mode) {
37683795 // SVG <use> is a special case for using this API to create a closed shadow
37693796 // root.
37703797 DCHECK (CanAttachShadowRoot () || IsA<SVGUseElement>(*this ));
@@ -3773,11 +3800,17 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
37733800 DCHECK (!AlwaysCreateUserAgentShadowRoot ());
37743801
37753802 GetDocument ().SetShadowCascadeOrder (ShadowCascadeOrder::kShadowCascadeV1 );
3803+
3804+ // 6. Let shadow be a new shadow root whose node document is shadow host’s
3805+ // node document, host is shadow host, and mode is mode.
3806+ // 9. Set shadow host’s shadow root to shadow.
37763807 ShadowRoot& shadow_root = CreateAndAttachShadowRoot (type);
3777- shadow_root.SetDelegatesFocus (delegates_focus);
3778- shadow_root.SetSlotAssignmentMode (manual_slotting
3779- ? SlotAssignmentMode::kManual
3780- : SlotAssignmentMode::kAuto );
3808+ // 7. Set shadow’s delegates focus to delegates focus.
3809+ // 8. TODO(masonfreed): Set shadow’s is declarative shadow root property to
3810+ // false.
3811+ shadow_root.SetDelegatesFocus (focus_delegation ==
3812+ FocusDelegation::kDelegateFocus );
3813+ shadow_root.SetSlotAssignmentMode (slot_assignment_mode);
37813814 return shadow_root;
37823815}
37833816
0 commit comments