mirror of
https://github.com/servo/servo.git
synced 2025-07-24 07:40:27 +01:00
Fix dynamic updates when :dir matching changes in stylo.
This is the servo part of https://bugzilla.mozilla.org/show_bug.cgi?id=1364280
This commit is contained in:
parent
f3c8f7e0d0
commit
cd29916c99
2 changed files with 50 additions and 0 deletions
|
@ -115,6 +115,11 @@ bitflags! {
|
||||||
const IN_HANDLER_VULNERABLE_NO_UPDATE_STATE = 1 << 42,
|
const IN_HANDLER_VULNERABLE_NO_UPDATE_STATE = 1 << 42,
|
||||||
/// https://drafts.csswg.org/selectors-4/#the-focus-within-pseudo
|
/// https://drafts.csswg.org/selectors-4/#the-focus-within-pseudo
|
||||||
const IN_FOCUS_WITHIN_STATE = 1 << 43,
|
const IN_FOCUS_WITHIN_STATE = 1 << 43,
|
||||||
|
/// :dir matching; the states are used for dynamic change detection.
|
||||||
|
/// State that elements that match :dir(ltr) are in.
|
||||||
|
const IN_LTR_STATE = 1 << 44,
|
||||||
|
/// State that elements that match :dir(rtl) are in.
|
||||||
|
const IN_RTL_STATE = 1 << 45,
|
||||||
/// Non-standard & undocumented.
|
/// Non-standard & undocumented.
|
||||||
const IN_AUTOFILL_STATE = 1 << 50,
|
const IN_AUTOFILL_STATE = 1 << 50,
|
||||||
/// Non-standard & undocumented.
|
/// Non-standard & undocumented.
|
||||||
|
|
|
@ -314,6 +314,22 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn dir_selector_to_state(s: &[u16]) -> ElementState {
|
||||||
|
// Jump through some hoops to deal with our Box<[u16]> thing.
|
||||||
|
const LTR: [u16; 4] = [b'l' as u16, b't' as u16, b'r' as u16, 0];
|
||||||
|
const RTL: [u16; 4] = [b'r' as u16, b't' as u16, b'l' as u16, 0];
|
||||||
|
if LTR == *s {
|
||||||
|
IN_LTR_STATE
|
||||||
|
} else if RTL == *s {
|
||||||
|
IN_RTL_STATE
|
||||||
|
} else {
|
||||||
|
// :dir(something-random) is a valid selector, but shouldn't
|
||||||
|
// match anything.
|
||||||
|
ElementState::empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, E> Element for ElementWrapper<'a, E>
|
impl<'a, E> Element for ElementWrapper<'a, E>
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
{
|
{
|
||||||
|
@ -336,6 +352,31 @@ impl<'a, E> Element for ElementWrapper<'a, E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// :dir needs special handling. It's implemented in terms of state
|
||||||
|
// flags, but which state flag it maps to depends on the argument to
|
||||||
|
// :dir. That means we can't just add its state flags to the
|
||||||
|
// NonTSPseudoClass, because if we added all of them there, and tested
|
||||||
|
// via intersects() here, we'd get incorrect behavior for :not(:dir())
|
||||||
|
// cases.
|
||||||
|
//
|
||||||
|
// FIXME(bz): How can I set this up so once Servo adds :dir() support we
|
||||||
|
// don't forget to update this code?
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
{
|
||||||
|
if let NonTSPseudoClass::Dir(ref s) = *pseudo_class {
|
||||||
|
let selector_flag = dir_selector_to_state(s);
|
||||||
|
if selector_flag.is_empty() {
|
||||||
|
// :dir() with some random argument; does not match.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let state = match self.snapshot().and_then(|s| s.state()) {
|
||||||
|
Some(snapshot_state) => snapshot_state,
|
||||||
|
None => self.element.get_state(),
|
||||||
|
};
|
||||||
|
return state.contains(selector_flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let flag = pseudo_class.state_flag();
|
let flag = pseudo_class.state_flag();
|
||||||
if flag.is_empty() {
|
if flag.is_empty() {
|
||||||
return self.element.match_non_ts_pseudo_class(pseudo_class,
|
return self.element.match_non_ts_pseudo_class(pseudo_class,
|
||||||
|
@ -425,6 +466,10 @@ impl<'a, E> Element for ElementWrapper<'a, E>
|
||||||
|
|
||||||
fn selector_to_state(sel: &Component<SelectorImpl>) -> ElementState {
|
fn selector_to_state(sel: &Component<SelectorImpl>) -> ElementState {
|
||||||
match *sel {
|
match *sel {
|
||||||
|
// FIXME(bz): How can I set this up so once Servo adds :dir() support we
|
||||||
|
// don't forget to update this code?
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
Component::NonTSPseudoClass(NonTSPseudoClass::Dir(ref s)) => dir_selector_to_state(s),
|
||||||
Component::NonTSPseudoClass(ref pc) => pc.state_flag(),
|
Component::NonTSPseudoClass(ref pc) => pc.state_flag(),
|
||||||
_ => ElementState::empty(),
|
_ => ElementState::empty(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue