mirror of
https://github.com/servo/servo.git
synced 2025-09-04 03:58:23 +01:00
script: Support custom element states (#38564)
Also adds support for `:state`. Testing: Covered by existing tests --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
dcd25072d3
commit
04dd74dddb
20 changed files with 209 additions and 152 deletions
42
Cargo.lock
generated
42
Cargo.lock
generated
|
@ -384,7 +384,7 @@ dependencies = [
|
|||
"objc2-foundation 0.3.1",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
|
@ -2529,7 +2529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3153,7 +3153,7 @@ dependencies = [
|
|||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps 7.0.5",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4658,7 +4658,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
|||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4963,7 +4963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -7192,7 +7192,7 @@ dependencies = [
|
|||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -7205,7 +7205,7 @@ dependencies = [
|
|||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -7553,7 +7553,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "selectors"
|
||||
version = "0.31.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"cssparser",
|
||||
|
@ -7872,7 +7872,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "servo_arc"
|
||||
version = "0.4.1"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
|
@ -8351,7 +8351,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "stylo"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"app_units",
|
||||
"arrayvec",
|
||||
|
@ -8408,7 +8408,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "stylo_atoms"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
|
@ -8417,12 +8417,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "stylo_config"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
|
||||
[[package]]
|
||||
name = "stylo_derive"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
@ -8434,7 +8434,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "stylo_dom"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"stylo_malloc_size_of",
|
||||
|
@ -8443,7 +8443,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "stylo_malloc_size_of"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"app_units",
|
||||
"cssparser",
|
||||
|
@ -8460,12 +8460,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "stylo_static_prefs"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
|
||||
[[package]]
|
||||
name = "stylo_traits"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"app_units",
|
||||
"bitflags 2.9.3",
|
||||
|
@ -8654,7 +8654,7 @@ dependencies = [
|
|||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.8",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -8880,7 +8880,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
[[package]]
|
||||
name = "to_shmem"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"cssparser",
|
||||
"servo_arc",
|
||||
|
@ -8893,7 +8893,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "to_shmem_derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#8a6763eb2a66d3c93860313fba37fc3f09c7f70f"
|
||||
source = "git+https://github.com/servo/stylo?branch=2025-08-01#35cd8025bb3d5c4cc50db80cb65f9b1840e5ac5a"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
@ -10182,7 +10182,7 @@ version = "0.1.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -343,7 +343,7 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
|
|||
rooted!(in(*cx) let constructor = constructor_.callback());
|
||||
let name = LocalName::from(&*name);
|
||||
|
||||
// Step 1
|
||||
// Step 1. If IsConstructor(constructor) is false, then throw a TypeError.
|
||||
// We must unwrap the constructor as all wrappers are constructable if they are callable.
|
||||
rooted!(in(*cx) let unwrapped_constructor = unsafe { UnwrapObjectStatic(constructor.get()) });
|
||||
|
||||
|
@ -358,17 +358,19 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
|
|||
));
|
||||
}
|
||||
|
||||
// Step 2
|
||||
// Step 2. If name is not a valid custom element name, then throw a "SyntaxError" DOMException.
|
||||
if !is_valid_custom_element_name(&name) {
|
||||
return Err(Error::Syntax);
|
||||
}
|
||||
|
||||
// Step 3
|
||||
// Step 3. If this's custom element definition set contains an item with name name,
|
||||
// then throw a "NotSupportedError" DOMException.
|
||||
if self.definitions.borrow().contains_key(&name) {
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
|
||||
// Step 4
|
||||
// Step 4. If this's custom element definition set contains an
|
||||
// item with constructor constructor, then throw a "NotSupportedError" DOMException.
|
||||
if self
|
||||
.definitions
|
||||
.borrow()
|
||||
|
@ -378,24 +380,29 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
|
|||
return Err(Error::NotSupported);
|
||||
}
|
||||
|
||||
// Step 6
|
||||
// Step 6. Let extends be options["extends"] if it exists; otherwise null.
|
||||
let extends = &options.extends;
|
||||
|
||||
// Steps 5, 7
|
||||
let local_name = if let Some(ref extended_name) = *extends {
|
||||
// Step 7.1
|
||||
// TODO Step 7.1 If this's is scoped is true, then throw a "NotSupportedError" DOMException.
|
||||
|
||||
// Step 7.2 If extends is a valid custom element name, then throw a "NotSupportedError" DOMException.
|
||||
if is_valid_custom_element_name(extended_name) {
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
|
||||
// Step 7.2
|
||||
// Step 7.3 If the element interface for extends and the HTML namespace is HTMLUnknownElement
|
||||
// (e.g., if extends does not indicate an element definition in this specification)
|
||||
// then throw a "NotSupportedError" DOMException.
|
||||
if !is_extendable_element_interface(extended_name) {
|
||||
return Err(Error::NotSupported);
|
||||
}
|
||||
|
||||
// Step 7.4 Set localName to extends.
|
||||
LocalName::from(&**extended_name)
|
||||
} else {
|
||||
// Step 7.3
|
||||
// Step 5. Let localName be name.
|
||||
name.clone()
|
||||
};
|
||||
|
||||
|
|
107
components/script/dom/customstateset.rs
Normal file
107
components/script/dom/customstateset.rs
Normal file
|
@ -0,0 +1,107 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use indexmap::IndexSet;
|
||||
use script_bindings::codegen::GenericBindings::ElementInternalsBinding::CustomStateSetMethods;
|
||||
use script_bindings::like::Setlike;
|
||||
use script_bindings::root::{Dom, DomRoot};
|
||||
use script_bindings::script_runtime::CanGc;
|
||||
use script_bindings::str::DOMString;
|
||||
use script_bindings::trace::CustomTraceable;
|
||||
use style::values::AtomIdent;
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::node::{Node, NodeDamage};
|
||||
use crate::dom::window::Window;
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#customstateset>
|
||||
#[dom_struct]
|
||||
pub(crate) struct CustomStateSet {
|
||||
reflector: Reflector,
|
||||
internal: DomRefCell<IndexSet<DOMString>>,
|
||||
owner_element: Dom<HTMLElement>,
|
||||
}
|
||||
|
||||
impl CustomStateSet {
|
||||
fn new_inherited(element: &HTMLElement) -> Self {
|
||||
Self {
|
||||
reflector: Reflector::new(),
|
||||
internal: DomRefCell::new(Default::default()),
|
||||
owner_element: Dom::from_ref(element),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(window: &Window, element: &HTMLElement, can_gc: CanGc) -> DomRoot<Self> {
|
||||
reflect_dom_object(Box::new(Self::new_inherited(element)), window, can_gc)
|
||||
}
|
||||
|
||||
pub(crate) fn for_each_state<F>(&self, mut callback: F)
|
||||
where
|
||||
F: FnMut(&AtomIdent),
|
||||
{
|
||||
// FIXME: This creates new atoms whenever it is called, which is not optimal.
|
||||
for state in self.internal.borrow().iter() {
|
||||
callback(&AtomIdent::from(state.str()));
|
||||
}
|
||||
}
|
||||
|
||||
fn states_did_change(&self) {
|
||||
self.owner_element.upcast::<Node>().dirty(NodeDamage::Other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Setlike for CustomStateSet {
|
||||
type Key = DOMString;
|
||||
|
||||
#[inline(always)]
|
||||
fn get_index(&self, index: u32) -> Option<Self::Key> {
|
||||
self.internal.get_index(index)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn size(&self) -> u32 {
|
||||
self.internal.size()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn add(&self, key: Self::Key) {
|
||||
self.internal.add(key);
|
||||
self.states_did_change();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn has(&self, key: Self::Key) -> bool {
|
||||
self.internal.has(key)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn clear(&self) {
|
||||
let old_size = self.internal.size();
|
||||
self.internal.clear();
|
||||
if old_size != 0 {
|
||||
self.states_did_change();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn delete(&self, key: Self::Key) -> bool {
|
||||
if self.internal.delete(key) {
|
||||
self.states_did_change();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CustomStateSetMethods<crate::DomTypeHolder> for CustomStateSet {
|
||||
/// <https://html.spec.whatwg.org/multipage/#customstateset>
|
||||
fn Size(&self) -> u32 {
|
||||
self.internal.size()
|
||||
}
|
||||
}
|
|
@ -1325,6 +1325,9 @@ pub(crate) trait LayoutElementHelpers<'dom> {
|
|||
) -> Option<&'dom AttrValue>;
|
||||
fn get_attr_val_for_layout(self, namespace: &Namespace, name: &LocalName) -> Option<&'dom str>;
|
||||
fn get_attr_vals_for_layout(self, name: &LocalName) -> Vec<&'dom AttrValue>;
|
||||
fn each_custom_state<F>(self, callback: F)
|
||||
where
|
||||
F: FnMut(&AtomIdent);
|
||||
}
|
||||
|
||||
impl LayoutDom<'_, Element> {
|
||||
|
@ -1819,6 +1822,13 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
|
|||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn each_custom_state<F>(self, callback: F)
|
||||
where
|
||||
F: FnMut(&AtomIdent),
|
||||
{
|
||||
self.unsafe_get().each_custom_state(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl Element {
|
||||
|
@ -5196,12 +5206,24 @@ impl SelectorsElement for SelectorWrapper<'_> {
|
|||
true
|
||||
}
|
||||
|
||||
fn has_custom_state(&self, _name: &AtomIdent) -> bool {
|
||||
false
|
||||
fn has_custom_state(&self, name: &AtomIdent) -> bool {
|
||||
let mut has_state = false;
|
||||
self.each_custom_state(|state| has_state |= state == name);
|
||||
|
||||
has_state
|
||||
}
|
||||
}
|
||||
|
||||
impl Element {
|
||||
fn each_custom_state<F>(&self, callback: F)
|
||||
where
|
||||
F: FnMut(&AtomIdent),
|
||||
{
|
||||
self.get_element_internals()
|
||||
.and_then(|internals| internals.custom_states())
|
||||
.inspect(|states| states.for_each_state(callback));
|
||||
}
|
||||
|
||||
fn client_rect(&self) -> Rect<i32> {
|
||||
let doc = self.node.owner_doc();
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::dom::bindings::inheritance::Castable;
|
|||
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||
use crate::dom::bindings::str::{DOMString, USVString};
|
||||
use crate::dom::customstateset::CustomStateSet;
|
||||
use crate::dom::element::Element;
|
||||
use crate::dom::file::File;
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
|
@ -69,6 +70,9 @@ pub(crate) struct ElementInternals {
|
|||
state: DomRefCell<SubmissionValue>,
|
||||
form_owner: MutNullableDom<HTMLFormElement>,
|
||||
labels_node_list: MutNullableDom<NodeList>,
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-elementinternals-states>
|
||||
states: MutNullableDom<CustomStateSet>,
|
||||
}
|
||||
|
||||
impl ElementInternals {
|
||||
|
@ -85,6 +89,7 @@ impl ElementInternals {
|
|||
state: DomRefCell::new(SubmissionValue::None),
|
||||
form_owner: MutNullableDom::new(None),
|
||||
labels_node_list: MutNullableDom::new(None),
|
||||
states: MutNullableDom::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,6 +191,10 @@ impl ElementInternals {
|
|||
self.is_instance_validatable() &&
|
||||
!self.satisfies_constraints()
|
||||
}
|
||||
|
||||
pub(crate) fn custom_states(&self) -> Option<DomRoot<CustomStateSet>> {
|
||||
self.states.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl ElementInternalsMethods<crate::DomTypeHolder> for ElementInternals {
|
||||
|
@ -354,6 +363,17 @@ impl ElementInternalsMethods<crate::DomTypeHolder> for ElementInternals {
|
|||
}
|
||||
Ok(self.report_validity(can_gc))
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-elementinternals-states>
|
||||
fn States(&self, can_gc: CanGc) -> DomRoot<CustomStateSet> {
|
||||
self.states.or_init(|| {
|
||||
CustomStateSet::new(
|
||||
&self.target_element.owner_window(),
|
||||
&self.target_element,
|
||||
can_gc,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Form-associated custom elements also need the Validatable trait.
|
||||
|
|
|
@ -604,6 +604,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
// TODO: https://github.com/servo/servo/issues/12776
|
||||
false
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage#dom-attachinternals>
|
||||
fn AttachInternals(&self, can_gc: CanGc) -> Fallible<DomRoot<ElementInternals>> {
|
||||
let element = self.as_element();
|
||||
|
|
|
@ -273,6 +273,7 @@ pub(crate) mod cssstylevalue;
|
|||
pub(crate) mod csssupportsrule;
|
||||
pub(crate) mod customelementregistry;
|
||||
pub(crate) mod customevent;
|
||||
pub(crate) mod customstateset;
|
||||
pub(crate) mod datatransfer;
|
||||
pub(crate) mod datatransferitem;
|
||||
pub(crate) mod datatransferitemlist;
|
||||
|
|
|
@ -560,10 +560,11 @@ impl<'dom> style::dom::TElement for ServoLayoutElement<'dom> {
|
|||
.intersection(ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING)
|
||||
}
|
||||
|
||||
fn each_custom_state<F>(&self, _callback: F)
|
||||
fn each_custom_state<F>(&self, callback: F)
|
||||
where
|
||||
F: FnMut(&AtomIdent),
|
||||
{
|
||||
self.element.each_custom_state(callback);
|
||||
}
|
||||
|
||||
/// Returns the implicit scope root for given sheet index and host.
|
||||
|
@ -960,8 +961,12 @@ impl<'dom> ::selectors::Element for ServoLayoutElement<'dom> {
|
|||
true
|
||||
}
|
||||
|
||||
fn has_custom_state(&self, _name: &AtomIdent) -> bool {
|
||||
false
|
||||
fn has_custom_state(&self, name: &AtomIdent) -> bool {
|
||||
let mut has_state = false;
|
||||
self.element
|
||||
.each_custom_state(|state| has_state |= state == name);
|
||||
|
||||
has_state
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'ElementInternals': {
|
||||
'canGc': ['CheckValidity', 'GetLabels', 'SetValidity', 'ReportValidity'],
|
||||
'canGc': ['CheckValidity', 'GetLabels', 'SetValidity', 'ReportValidity', 'States'],
|
||||
},
|
||||
|
||||
'EventSource': {
|
||||
|
|
|
@ -26,6 +26,9 @@ interface ElementInternals {
|
|||
[Throws] boolean reportValidity();
|
||||
|
||||
[Throws] readonly attribute NodeList labels;
|
||||
|
||||
// Custom state pseudo-class
|
||||
[SameObject] readonly attribute CustomStateSet states;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#elementinternals
|
||||
|
@ -42,3 +45,8 @@ dictionary ValidityStateFlags {
|
|||
boolean customError = false;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#customstateset
|
||||
[Exposed=Window]
|
||||
interface CustomStateSet {
|
||||
setlike<DOMString>;
|
||||
};
|
||||
|
|
|
@ -35,8 +35,5 @@
|
|||
["::part(mypart):playing" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["::part(mypart):state(mystate)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["::part(mypart):xr-overlay" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
[parse-state.html]
|
||||
[":state(--foo)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
[":state(bar)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
[":state(--)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
[":state(--0)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
[":host(:state(--foo))" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["my-input[type=\\"foo\\"\]:state(checked)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["my-input[type=\\"foo\\"\]:state(--0)::before" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["my-input[type=\\"foo\\"\]:state(--0)::part(inner)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["my-input[type=\\"foo\\"\]:state(--0)::part(inner):state(bar)" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["::part(inner):state(bar)::before" should be a valid selector]
|
||||
expected: FAIL
|
||||
|
||||
["::part(inner):state(bar)::after" should be a valid selector]
|
||||
expected: FAIL
|
|
@ -1,12 +1,3 @@
|
|||
[ElementInternals-states.html]
|
||||
[CustomStateSet behavior of ElementInternals.states: Initial state]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet behavior of ElementInternals.states: Exceptions]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet behavior of ElementInternals.states: Modifications]
|
||||
expected: FAIL
|
||||
|
||||
[Updating a CustomStateSet while iterating it should work]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[custom-state-set-strong-ref.html]
|
||||
[customstateset doesn't crash after GC on detached node]
|
||||
expected: FAIL
|
|
@ -1,10 +1,6 @@
|
|||
[state-css-selector-nth-of.html]
|
||||
expected: ERROR
|
||||
[state selector has influence on nth-of when state is applied]
|
||||
expected: FAIL
|
||||
|
||||
[state selector only applies on given ident]
|
||||
expected: NOTRUN
|
||||
|
||||
[style is invalided on clear()]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,30 +1,6 @@
|
|||
[state-css-selector.html]
|
||||
[state selector has no influence when state is not applied]
|
||||
expected: FAIL
|
||||
|
||||
[state selector has no influence on sibling selectors when not applied]
|
||||
expected: FAIL
|
||||
|
||||
[state selector has influence when state is applied]
|
||||
expected: FAIL
|
||||
|
||||
[state selector influences siblings when state is applied]
|
||||
expected: FAIL
|
||||
|
||||
[state selector influences has() when state is applied]
|
||||
expected: FAIL
|
||||
|
||||
[state selector only applies on given ident]
|
||||
expected: FAIL
|
||||
|
||||
[state selector only applies to siblings on given ident]
|
||||
expected: FAIL
|
||||
|
||||
[state selector only applies to has() on given ident]
|
||||
expected: FAIL
|
||||
|
||||
[states added multiple times counts as one]
|
||||
expected: FAIL
|
||||
|
||||
[style is invalided on clear()]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,18 +1,3 @@
|
|||
[state-pseudo-class.html]
|
||||
[:state() parsing passes]
|
||||
expected: FAIL
|
||||
|
||||
[:state(foo) serialization]
|
||||
expected: FAIL
|
||||
|
||||
[:state(foo) in simple cases]
|
||||
expected: FAIL
|
||||
|
||||
[:state(foo) and other pseudo classes]
|
||||
expected: FAIL
|
||||
|
||||
[:state(foo) and ::part()]
|
||||
expected: FAIL
|
||||
|
||||
[:state(foo) and :host()]
|
||||
expected: FAIL
|
||||
|
|
|
@ -4394,30 +4394,6 @@
|
|||
[OffscreenCanvasRenderingContext2D interface: operation roundRect(unrestricted double, unrestricted double, unrestricted double, unrestricted double, optional (unrestricted double or DOMPointInit or sequence<(unrestricted double or DOMPointInit)>))]
|
||||
expected: FAIL
|
||||
|
||||
[ElementInternals interface: attribute states]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[CustomStateSet interface: setlike<DOMString>]
|
||||
expected: FAIL
|
||||
|
||||
[UserActivation interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
|
|
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
2
tests/wpt/mozilla/meta/MANIFEST.json
vendored
|
@ -13749,7 +13749,7 @@
|
|||
]
|
||||
],
|
||||
"interfaces.https.html": [
|
||||
"a9447edae08028bd992e3aa7c9e7a2a483baa446",
|
||||
"1397b723a1cb001521ac1b2032c380f1e02cf1f0",
|
||||
[
|
||||
null,
|
||||
{}
|
||||
|
|
|
@ -62,6 +62,7 @@ test_interfaces([
|
|||
"CSSStyleRule",
|
||||
"CSSStyleSheet",
|
||||
"CSSSupportsRule",
|
||||
"CustomStateSet",
|
||||
"DataTransfer",
|
||||
"DataTransferItem",
|
||||
"DataTransferItemList",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue