mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Use "slot" attribute for slottable name (#35191)
* Implement Element::slot attribute Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Simplify slottable name update Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Update WPT expectations Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
c633ca1cde
commit
f6d1b30e97
9 changed files with 18 additions and 98 deletions
|
@ -2241,6 +2241,12 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
||||||
.or_init(|| DOMTokenList::new(self, &local_name!("class"), None))
|
.or_init(|| DOMTokenList::new(self, &local_name!("class"), None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#dom-element-slot
|
||||||
|
make_getter!(Slot, "slot");
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#dom-element-slot
|
||||||
|
make_setter!(SetSlot, "slot");
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-element-attributes
|
// https://dom.spec.whatwg.org/#dom-element-attributes
|
||||||
fn Attributes(&self) -> DomRoot<NamedNodeMap> {
|
fn Attributes(&self) -> DomRoot<NamedNodeMap> {
|
||||||
self.attr_list
|
self.attr_list
|
||||||
|
@ -3666,7 +3672,12 @@ impl VirtualMethods for Element {
|
||||||
// Update slottable data
|
// Update slottable data
|
||||||
let cx = GlobalScope::get_cx();
|
let cx = GlobalScope::get_cx();
|
||||||
rooted!(in(*cx) let slottable = Slottable::Element(Dom::from_ref(self)));
|
rooted!(in(*cx) let slottable = Slottable::Element(Dom::from_ref(self)));
|
||||||
slottable.update_slot_name(attr, mutation, CanGc::note())
|
|
||||||
|
// Slottable name change steps from https://dom.spec.whatwg.org/#light-tree-slotables
|
||||||
|
if let Some(assigned_slot) = slottable.assigned_slot() {
|
||||||
|
assigned_slot.assign_slottables();
|
||||||
|
}
|
||||||
|
slottable.assign_a_slot();
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// FIXME(emilio): This is pretty dubious, and should be done in
|
// FIXME(emilio): This is pretty dubious, and should be done in
|
||||||
|
|
|
@ -8,8 +8,6 @@ use dom_struct::dom_struct;
|
||||||
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
|
||||||
use js::gc::{RootedGuard, RootedVec};
|
use js::gc::{RootedGuard, RootedVec};
|
||||||
use js::rust::HandleObject;
|
use js::rust::HandleObject;
|
||||||
use servo_atoms::Atom;
|
|
||||||
use style::attr::AttrValue;
|
|
||||||
|
|
||||||
use crate::dom::attr::Attr;
|
use crate::dom::attr::Attr;
|
||||||
use crate::dom::bindings::codegen::Bindings::HTMLSlotElementBinding::{
|
use crate::dom::bindings::codegen::Bindings::HTMLSlotElementBinding::{
|
||||||
|
@ -382,58 +380,6 @@ impl Slottable {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Slottable name change steps from <https://dom.spec.whatwg.org/#light-tree-slotables>
|
|
||||||
pub(crate) fn update_slot_name(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
|
|
||||||
debug_assert!(matches!(self, Self::Element(_)));
|
|
||||||
|
|
||||||
// Step 1. If localName is slot and namespace is null:
|
|
||||||
// NOTE: This is done by the caller
|
|
||||||
let old_value = if let AttributeMutation::Set(old_name) = mutation {
|
|
||||||
old_name.and_then(|attr| match attr {
|
|
||||||
AttrValue::String(s) => Some(s.clone()),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let value = mutation.new_value(attr).and_then(|attr| match &*attr {
|
|
||||||
AttrValue::String(s) => Some(s.clone()),
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Step 1.1 If value is oldValue, then return.
|
|
||||||
if value == old_value {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1.2 If value is null and oldValue is the empty string, then return.
|
|
||||||
if value.is_none() && old_value.as_ref().is_some_and(|s| s.is_empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1.3 If value is the empty string and oldValue is null, then return.
|
|
||||||
if old_value.is_none() && value.as_ref().is_some_and(|s| s.is_empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1.4 If value is null or the empty string, then set element’s name to the empty string.
|
|
||||||
if value.as_ref().is_none_or(|s| s.is_empty()) {
|
|
||||||
self.set_name(DOMString::new(), can_gc);
|
|
||||||
}
|
|
||||||
// Step 1.5 Otherwise, set element’s name to value.
|
|
||||||
else {
|
|
||||||
self.set_name(DOMString::from(value.unwrap_or_default()), can_gc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1.6 If element is assigned, then run assign slottables for element’s assigned slot.
|
|
||||||
if let Some(assigned_slot) = self.assigned_slot() {
|
|
||||||
assigned_slot.assign_slottables();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1.7 Run assign a slot for element.
|
|
||||||
self.assign_a_slot();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <https://dom.spec.whatwg.org/#assign-a-slot>
|
/// <https://dom.spec.whatwg.org/#assign-a-slot>
|
||||||
pub(crate) fn assign_a_slot(&self) {
|
pub(crate) fn assign_a_slot(&self) {
|
||||||
// Step 1. Let slot be the result of finding a slot with slottable.
|
// Step 1. Let slot be the result of finding a slot with slottable.
|
||||||
|
@ -452,7 +398,7 @@ impl Slottable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assigned_slot(&self) -> Option<DomRoot<HTMLSlotElement>> {
|
pub(crate) fn assigned_slot(&self) -> Option<DomRoot<HTMLSlotElement>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Element(element) => element.assigned_slot(),
|
Self::Element(element) => element.assigned_slot(),
|
||||||
Self::Text(text) => {
|
Self::Text(text) => {
|
||||||
|
@ -501,30 +447,13 @@ impl Slottable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_name(&self, name: DOMString, can_gc: CanGc) {
|
|
||||||
// NOTE: Only elements have non-empty names
|
|
||||||
let Self::Element(element) = self else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let element = element.as_rooted();
|
|
||||||
element.set_attribute(
|
|
||||||
&local_name!("name"),
|
|
||||||
AttrValue::Atom(Atom::from(name)),
|
|
||||||
can_gc,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> DOMString {
|
fn name(&self) -> DOMString {
|
||||||
// NOTE: Only elements have non-empty names
|
// NOTE: Only elements have non-empty names
|
||||||
let Self::Element(element) = self else {
|
let Self::Element(element) = self else {
|
||||||
return DOMString::new();
|
return DOMString::new();
|
||||||
};
|
};
|
||||||
|
|
||||||
element
|
element.get_string_attribute(&local_name!("slot"))
|
||||||
.name_attribute()
|
|
||||||
.map(|a| DOMString::from(a.as_ref()))
|
|
||||||
.unwrap_or_default()
|
|
||||||
.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ interface Element : Node {
|
||||||
attribute DOMString className;
|
attribute DOMString className;
|
||||||
[SameObject, PutForwards=value]
|
[SameObject, PutForwards=value]
|
||||||
readonly attribute DOMTokenList classList;
|
readonly attribute DOMTokenList classList;
|
||||||
|
[CEReactions, Unscopable] attribute DOMString slot;
|
||||||
|
|
||||||
[Pure]
|
[Pure]
|
||||||
boolean hasAttributes();
|
boolean hasAttributes();
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[Element.html]
|
|
||||||
[slot on Element must enqueue an attributeChanged reaction when adding slot content attribute]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[slot on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
|
|
||||||
expected: FAIL
|
|
3
tests/wpt/meta/dom/idlharness.window.js.ini
vendored
3
tests/wpt/meta/dom/idlharness.window.js.ini
vendored
|
@ -56,9 +56,6 @@
|
||||||
[CharacterData interface: operation remove()]
|
[CharacterData interface: operation remove()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Element interface: element must inherit property "slot" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[AbortController interface: new AbortController() must inherit property "signal" with the proper type]
|
[AbortController interface: new AbortController() must inherit property "signal" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,6 @@
|
||||||
[assignedNodes({"flattened":true}) must return the list of assigned nodes when none of the assigned nodes themselves are slots]
|
[assignedNodes({"flattened":true}) must return the list of assigned nodes when none of the assigned nodes themselves are slots]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[assignedNodes() must update when slot and name attributes are modified]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[assignedNodes({"flattened":false}) must update when slot and name attributes are modified]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[assignedNodes({"flattened":true}) must update when slot and name attributes are modified]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[assignedNodes() must update when slot elements are inserted or removed]
|
[assignedNodes() must update when slot elements are inserted or removed]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[Slottable-mixin.html]
|
|
||||||
[assignedSlot must return the assigned slot]
|
|
||||||
expected: FAIL
|
|
|
@ -3,8 +3,5 @@
|
||||||
[slotchange event: Append a child to a host.]
|
[slotchange event: Append a child to a host.]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
||||||
[slotchange event: A slot is assigned to another slot.]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
||||||
[slotchange event: Child content is added to nested slots.]
|
[slotchange event: Child content is added to nested slots.]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
3
tests/wpt/meta/shadow-dom/slots.html.ini
vendored
3
tests/wpt/meta/shadow-dom/slots.html.ini
vendored
|
@ -31,3 +31,6 @@
|
||||||
|
|
||||||
[Slots: Mutation: Change slot slot= attribute.]
|
[Slots: Mutation: Change slot slot= attribute.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[Slots: Mutation: Remove a slot.]
|
||||||
|
expected: FAIL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue