@@ -3513,29 +3513,6 @@ ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) {
3513
3513
return *shadow_root;
3514
3514
}
3515
3515
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
-
3539
3516
ShadowRoot* Element::GetShadowRoot () const {
3540
3517
return HasRareData () ? GetElementRareData ()->GetShadowRoot () : nullptr ;
3541
3518
}
@@ -3644,6 +3621,7 @@ ElementInternals& Element::EnsureElementInternals() {
3644
3621
}
3645
3622
3646
3623
ShadowRoot* Element::createShadowRoot (ExceptionState& exception_state) {
3624
+ DCHECK (RuntimeEnabledFeatures::ShadowDOMV0Enabled (&GetDocument ()));
3647
3625
if (ShadowRoot* root = GetShadowRoot ()) {
3648
3626
if (root->IsUserAgent ()) {
3649
3627
exception_state.ThrowDOMException (
@@ -3677,6 +3655,15 @@ ShadowRoot* Element::createShadowRoot(ExceptionState& exception_state) {
3677
3655
return &CreateShadowRootInternal ();
3678
3656
}
3679
3657
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
+
3680
3667
bool Element::CanAttachShadowRoot () const {
3681
3668
const AtomicString& tag_name = localName ();
3682
3669
// Checking Is{V0}CustomElement() here is just an optimization
@@ -3696,17 +3683,26 @@ bool Element::CanAttachShadowRoot() const {
3696
3683
tag_name == html_names::kSpanTag ;
3697
3684
}
3698
3685
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.
3702
3694
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" ;
3707
3696
}
3708
3697
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
3710
3706
// IsValidName() is not cheap.
3711
3707
if (IsCustomElement () &&
3712
3708
(CustomElement::IsValidName (localName ()) || !IsValue ().IsNull ())) {
@@ -3716,55 +3712,86 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict,
3716
3712
: IsValue ())
3717
3713
: nullptr ;
3718
3714
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." ;
3723
3716
}
3724
3717
}
3725
3718
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.
3726
3724
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." ;
3731
3727
}
3728
+ return nullptr ;
3729
+ }
3732
3730
3731
+ ShadowRoot* Element::attachShadow (const ShadowRootInit* shadow_root_init_dict,
3732
+ ExceptionState& exception_state) {
3733
+ DCHECK (shadow_root_init_dict->hasMode ());
3733
3734
ShadowRootType type = shadow_root_init_dict->mode () == " open"
3734
3735
? ShadowRootType::kOpen
3735
3736
: ShadowRootType::kClosed ;
3736
-
3737
3737
if (type == ShadowRootType::kOpen )
3738
3738
UseCounter::Count (GetDocument (), WebFeature::kElementAttachShadowOpen );
3739
3739
else
3740
3740
UseCounter::Count (GetDocument (), WebFeature::kElementAttachShadowClosed );
3741
3741
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 ;
3748
3755
}
3749
- return &AttachShadowRootInternal (type, delegates_focus, manual_slotting );
3756
+ return &AttachShadowRootInternal (type, focus_delegation, slot_assignment );
3750
3757
}
3751
3758
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 ();
3758
3784
}
3759
3785
3760
3786
ShadowRoot& Element::CreateUserAgentShadowRoot () {
3761
3787
DCHECK (!GetShadowRoot ());
3762
3788
return CreateAndAttachShadowRoot (ShadowRootType::kUserAgent );
3763
3789
}
3764
3790
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) {
3768
3795
// SVG <use> is a special case for using this API to create a closed shadow
3769
3796
// root.
3770
3797
DCHECK (CanAttachShadowRoot () || IsA<SVGUseElement>(*this ));
@@ -3773,11 +3800,17 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type,
3773
3800
DCHECK (!AlwaysCreateUserAgentShadowRoot ());
3774
3801
3775
3802
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.
3776
3807
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);
3781
3814
return shadow_root;
3782
3815
}
3783
3816
0 commit comments