mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Auto merge of #20456 - upsuper:remove-nscsspseudoclasses, r=emilio
Remove nsCSSPseudoClasses and friends This is the Servo side change of [bug 1449097](https://bugzilla.mozilla.org/show_bug.cgi?id=1449097) and [bug 1449089](https://bugzilla.mozilla.org/show_bug.cgi?id=1449089).
This commit is contained in:
commit
97c12bd392
6 changed files with 70 additions and 161 deletions
|
@ -54,7 +54,6 @@ use gecko_bindings::structs::RawServoSelectorList;
|
||||||
use gecko_bindings::structs::RawServoSourceSizeList;
|
use gecko_bindings::structs::RawServoSourceSizeList;
|
||||||
use gecko_bindings::structs::RefPtr;
|
use gecko_bindings::structs::RefPtr;
|
||||||
use gecko_bindings::structs::RustString;
|
use gecko_bindings::structs::RustString;
|
||||||
use gecko_bindings::structs::CSSPseudoClassType;
|
|
||||||
use gecko_bindings::structs::CSSPseudoElementType;
|
use gecko_bindings::structs::CSSPseudoElementType;
|
||||||
use gecko_bindings::structs::ServoTraversalFlags;
|
use gecko_bindings::structs::ServoTraversalFlags;
|
||||||
use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;
|
use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;
|
||||||
|
@ -627,12 +626,6 @@ extern "C" {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_IsRootElement(element: RawGeckoElementBorrowed) -> bool;
|
pub fn Gecko_IsRootElement(element: RawGeckoElementBorrowed) -> bool;
|
||||||
}
|
}
|
||||||
extern "C" {
|
|
||||||
pub fn Gecko_MatchesElement(
|
|
||||||
type_: CSSPseudoClassType,
|
|
||||||
element: RawGeckoElementBorrowed,
|
|
||||||
) -> bool;
|
|
||||||
}
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_MatchLang(
|
pub fn Gecko_MatchLang(
|
||||||
element: RawGeckoElementBorrowed,
|
element: RawGeckoElementBorrowed,
|
||||||
|
@ -647,6 +640,12 @@ extern "C" {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_GetDocumentLWTheme(aDocument: *const nsIDocument) -> nsIDocument_DocumentTheme;
|
pub fn Gecko_GetDocumentLWTheme(aDocument: *const nsIDocument) -> nsIDocument_DocumentTheme;
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_IsTableBorderNonzero(element: RawGeckoElementBorrowed) -> bool;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_IsBrowserFrame(element: RawGeckoElementBorrowed) -> bool;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_AtomAttrValue(
|
pub fn Gecko_AtomAttrValue(
|
||||||
element: RawGeckoElementBorrowed,
|
element: RawGeckoElementBorrowed,
|
||||||
|
|
|
@ -12267,97 +12267,6 @@ pub mod root {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pub type CSSPseudoClassTypeBase = u8;
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub enum CSSPseudoClassType {
|
|
||||||
empty = 0,
|
|
||||||
mozOnlyWhitespace = 1,
|
|
||||||
lang = 2,
|
|
||||||
root = 3,
|
|
||||||
any = 4,
|
|
||||||
firstChild = 5,
|
|
||||||
firstNode = 6,
|
|
||||||
lastChild = 7,
|
|
||||||
lastNode = 8,
|
|
||||||
onlyChild = 9,
|
|
||||||
firstOfType = 10,
|
|
||||||
lastOfType = 11,
|
|
||||||
onlyOfType = 12,
|
|
||||||
nthChild = 13,
|
|
||||||
nthLastChild = 14,
|
|
||||||
nthOfType = 15,
|
|
||||||
nthLastOfType = 16,
|
|
||||||
mozIsHTML = 17,
|
|
||||||
mozNativeAnonymous = 18,
|
|
||||||
mozUseShadowTreeRoot = 19,
|
|
||||||
mozLocaleDir = 20,
|
|
||||||
mozLWTheme = 21,
|
|
||||||
mozLWThemeBrightText = 22,
|
|
||||||
mozLWThemeDarkText = 23,
|
|
||||||
mozWindowInactive = 24,
|
|
||||||
mozTableBorderNonzero = 25,
|
|
||||||
mozBrowserFrame = 26,
|
|
||||||
scope = 27,
|
|
||||||
negation = 28,
|
|
||||||
dir = 29,
|
|
||||||
link = 30,
|
|
||||||
mozAnyLink = 31,
|
|
||||||
anyLink = 32,
|
|
||||||
visited = 33,
|
|
||||||
active = 34,
|
|
||||||
checked = 35,
|
|
||||||
disabled = 36,
|
|
||||||
enabled = 37,
|
|
||||||
focus = 38,
|
|
||||||
focusWithin = 39,
|
|
||||||
hover = 40,
|
|
||||||
mozDragOver = 41,
|
|
||||||
target = 42,
|
|
||||||
indeterminate = 43,
|
|
||||||
mozDevtoolsHighlighted = 44,
|
|
||||||
mozStyleeditorTransitioning = 45,
|
|
||||||
fullscreen = 46,
|
|
||||||
mozFullScreen = 47,
|
|
||||||
mozFocusRing = 48,
|
|
||||||
mozBroken = 49,
|
|
||||||
mozLoading = 50,
|
|
||||||
mozUserDisabled = 51,
|
|
||||||
mozSuppressed = 52,
|
|
||||||
mozHandlerClickToPlay = 53,
|
|
||||||
mozHandlerVulnerableUpdatable = 54,
|
|
||||||
mozHandlerVulnerableNoUpdate = 55,
|
|
||||||
mozHandlerDisabled = 56,
|
|
||||||
mozHandlerBlocked = 57,
|
|
||||||
mozHandlerCrashed = 58,
|
|
||||||
mozMathIncrementScriptLevel = 59,
|
|
||||||
mozHasDirAttr = 60,
|
|
||||||
mozDirAttrLTR = 61,
|
|
||||||
mozDirAttrRTL = 62,
|
|
||||||
mozDirAttrLikeAuto = 63,
|
|
||||||
mozAutofill = 64,
|
|
||||||
mozAutofillPreview = 65,
|
|
||||||
required = 66,
|
|
||||||
optional = 67,
|
|
||||||
valid = 68,
|
|
||||||
invalid = 69,
|
|
||||||
inRange = 70,
|
|
||||||
outOfRange = 71,
|
|
||||||
defaultPseudo = 72,
|
|
||||||
placeholderShown = 73,
|
|
||||||
mozReadOnly = 74,
|
|
||||||
mozReadWrite = 75,
|
|
||||||
mozSubmitInvalid = 76,
|
|
||||||
mozUIInvalid = 77,
|
|
||||||
mozUIValid = 78,
|
|
||||||
mozMeterOptimum = 79,
|
|
||||||
mozMeterSubOptimum = 80,
|
|
||||||
mozMeterSubSubOptimum = 81,
|
|
||||||
mozPlaceholder = 82,
|
|
||||||
Count = 83,
|
|
||||||
NotPseudo = 84,
|
|
||||||
MAX = 85,
|
|
||||||
}
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct GeckoFont {
|
pub struct GeckoFont {
|
||||||
pub gecko: root::nsStyleFont,
|
pub gecko: root::nsStyleFont,
|
||||||
|
|
|
@ -28,9 +28,6 @@
|
||||||
*
|
*
|
||||||
* :scope -> <style scoped>, pending discussion.
|
* :scope -> <style scoped>, pending discussion.
|
||||||
*
|
*
|
||||||
* This follows the order defined in layout/style/nsCSSPseudoClassList.h when
|
|
||||||
* possible.
|
|
||||||
*
|
|
||||||
* $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType.
|
* $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType.
|
||||||
* $state can be either "_" or an expression of type ElementState. If present,
|
* $state can be either "_" or an expression of type ElementState. If present,
|
||||||
* the semantics are that the pseudo-class matches if any of the bits in
|
* the semantics are that the pseudo-class matches if any of the bits in
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use cssparser::{BasicParseError, BasicParseErrorKind, Parser, ToCss, Token, CowRcStr, SourceLocation};
|
use cssparser::{BasicParseError, BasicParseErrorKind, Parser, ToCss, Token, CowRcStr, SourceLocation};
|
||||||
use element_state::{DocumentState, ElementState};
|
use element_state::{DocumentState, ElementState};
|
||||||
use gecko_bindings::structs::{self, CSSPseudoClassType};
|
use gecko_bindings::structs;
|
||||||
use gecko_bindings::structs::RawServoSelectorList;
|
use gecko_bindings::structs::RawServoSelectorList;
|
||||||
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use invalidation::element::document_state::InvalidationMatchingData;
|
use invalidation::element::document_state::InvalidationMatchingData;
|
||||||
|
@ -133,6 +133,22 @@ impl Visit for NonTSPseudoClass {
|
||||||
|
|
||||||
|
|
||||||
impl NonTSPseudoClass {
|
impl NonTSPseudoClass {
|
||||||
|
/// Parses the name and returns a non-ts-pseudo-class if succeeds.
|
||||||
|
/// None otherwise. It doesn't check whether the pseudo-class is enabled
|
||||||
|
/// in a particular state.
|
||||||
|
pub fn parse_non_functional(name: &str) -> Option<Self> {
|
||||||
|
macro_rules! pseudo_class_parse {
|
||||||
|
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||||
|
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
|
||||||
|
match_ignore_ascii_case! { &name,
|
||||||
|
$($css => Some(NonTSPseudoClass::$name),)*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apply_non_ts_list!(pseudo_class_parse)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if this pseudo-class has any of the given flags set.
|
/// Returns true if this pseudo-class has any of the given flags set.
|
||||||
fn has_any_flag(&self, flags: NonTSPseudoClassFlag) -> bool {
|
fn has_any_flag(&self, flags: NonTSPseudoClassFlag) -> bool {
|
||||||
macro_rules! check_flag {
|
macro_rules! check_flag {
|
||||||
|
@ -242,28 +258,6 @@ impl NonTSPseudoClass {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert NonTSPseudoClass to Gecko's CSSPseudoClassType.
|
|
||||||
pub fn to_gecko_pseudoclasstype(&self) -> Option<CSSPseudoClassType> {
|
|
||||||
macro_rules! gecko_type {
|
|
||||||
(_) => (None);
|
|
||||||
($gecko_type:ident) =>
|
|
||||||
(Some(::gecko_bindings::structs::CSSPseudoClassType::$gecko_type));
|
|
||||||
}
|
|
||||||
macro_rules! pseudo_class_geckotype {
|
|
||||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
|
||||||
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
|
|
||||||
match *self {
|
|
||||||
$(NonTSPseudoClass::$name => gecko_type!($gecko_type),)*
|
|
||||||
$(NonTSPseudoClass::$s_name(..) => gecko_type!($s_gecko_type),)*
|
|
||||||
NonTSPseudoClass::MozLocaleDir(_) => gecko_type!(mozLocaleDir),
|
|
||||||
NonTSPseudoClass::Dir(_) => gecko_type!(dir),
|
|
||||||
NonTSPseudoClass::MozAny(_) => gecko_type!(any),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
apply_non_ts_list!(pseudo_class_geckotype)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the evaluation of the pseudo-class depends on the
|
/// Returns true if the evaluation of the pseudo-class depends on the
|
||||||
/// element's attributes.
|
/// element's attributes.
|
||||||
pub fn is_attr_based(&self) -> bool {
|
pub fn is_attr_based(&self) -> bool {
|
||||||
|
@ -373,24 +367,13 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
location: SourceLocation,
|
location: SourceLocation,
|
||||||
name: CowRcStr<'i>,
|
name: CowRcStr<'i>,
|
||||||
) -> Result<NonTSPseudoClass, ParseError<'i>> {
|
) -> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||||
macro_rules! pseudo_class_parse {
|
if let Some(pseudo_class) = NonTSPseudoClass::parse_non_functional(&name) {
|
||||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
|
||||||
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
|
|
||||||
match_ignore_ascii_case! { &name,
|
|
||||||
$($css => NonTSPseudoClass::$name,)*
|
|
||||||
_ => return Err(location.new_custom_error(
|
|
||||||
SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let pseudo_class = apply_non_ts_list!(pseudo_class_parse);
|
|
||||||
if self.is_pseudo_class_enabled(&pseudo_class) {
|
if self.is_pseudo_class_enabled(&pseudo_class) {
|
||||||
Ok(pseudo_class)
|
return Ok(pseudo_class);
|
||||||
} else {
|
|
||||||
Err(location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name)))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_non_ts_functional_pseudo_class<'t>(
|
fn parse_non_ts_functional_pseudo_class<'t>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -32,7 +32,6 @@ use gecko_bindings::bindings;
|
||||||
use gecko_bindings::bindings::{Gecko_ConstructStyleChildrenIterator, Gecko_DestroyStyleChildrenIterator};
|
use gecko_bindings::bindings::{Gecko_ConstructStyleChildrenIterator, Gecko_DestroyStyleChildrenIterator};
|
||||||
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme};
|
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme};
|
||||||
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetNextStyleChild};
|
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetNextStyleChild};
|
||||||
use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement};
|
|
||||||
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
|
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
|
||||||
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
||||||
use gecko_bindings::bindings::Gecko_ElementHasAnimations;
|
use gecko_bindings::bindings::Gecko_ElementHasAnimations;
|
||||||
|
@ -814,6 +813,21 @@ impl<'le> GeckoElement<'le> {
|
||||||
(!self.as_node().is_in_shadow_tree() && self.has_xbl_binding_parent())
|
(!self.as_node().is_in_shadow_tree() && self.has_xbl_binding_parent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if this node is the shadow root of an use-element shadow tree.
|
||||||
|
#[inline]
|
||||||
|
fn is_root_of_use_element_shadow_tree(&self) -> bool {
|
||||||
|
if !self.is_root_of_anonymous_subtree() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
match self.parent_element() {
|
||||||
|
Some(e) => {
|
||||||
|
e.local_name() == &*local_name!("use") &&
|
||||||
|
e.namespace() == &*ns!("http://www.w3.org/2000/svg")
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn css_transitions_info(&self) -> FnvHashMap<LonghandId, Arc<AnimationValue>> {
|
fn css_transitions_info(&self) -> FnvHashMap<LonghandId, Arc<AnimationValue>> {
|
||||||
use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
|
use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
|
||||||
use gecko_bindings::bindings::Gecko_ElementTransitions_Length;
|
use gecko_bindings::bindings::Gecko_ElementTransitions_Length;
|
||||||
|
@ -1981,7 +1995,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_IsRootElement(self.0)
|
bindings::Gecko_IsRootElement(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2103,11 +2117,17 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::MozTableBorderNonzero |
|
NonTSPseudoClass::MozNativeAnonymous => {
|
||||||
NonTSPseudoClass::MozBrowserFrame |
|
self.is_in_native_anonymous_subtree()
|
||||||
NonTSPseudoClass::MozNativeAnonymous |
|
}
|
||||||
NonTSPseudoClass::MozUseShadowTreeRoot => unsafe {
|
NonTSPseudoClass::MozUseShadowTreeRoot => {
|
||||||
Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0)
|
self.is_root_of_use_element_shadow_tree()
|
||||||
|
}
|
||||||
|
NonTSPseudoClass::MozTableBorderNonzero => unsafe {
|
||||||
|
bindings::Gecko_IsTableBorderNonzero(self.0)
|
||||||
|
}
|
||||||
|
NonTSPseudoClass::MozBrowserFrame => unsafe {
|
||||||
|
bindings::Gecko_IsBrowserFrame(self.0)
|
||||||
},
|
},
|
||||||
NonTSPseudoClass::MozIsHTML => {
|
NonTSPseudoClass::MozIsHTML => {
|
||||||
self.is_html_element_in_html_document()
|
self.is_html_element_in_html_document()
|
||||||
|
@ -2235,20 +2255,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn blocks_ancestor_combinators(&self) -> bool {
|
fn blocks_ancestor_combinators(&self) -> bool {
|
||||||
if !self.is_root_of_anonymous_subtree() {
|
// If this element is the shadow root of an use-element shadow tree,
|
||||||
return false
|
// according to the spec, we should not match rules cross the shadow
|
||||||
}
|
// DOM boundary.
|
||||||
|
self.is_root_of_use_element_shadow_tree()
|
||||||
match self.parent_element() {
|
|
||||||
Some(e) => {
|
|
||||||
// If this element is the shadow root of an use-element shadow
|
|
||||||
// tree, according to the spec, we should not match rules
|
|
||||||
// cross the shadow DOM boundary.
|
|
||||||
e.local_name() == &*local_name!("use") &&
|
|
||||||
e.namespace() == &*ns!("http://www.w3.org/2000/svg")
|
|
||||||
},
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use style::font_metrics::{FontMetricsProvider, get_metrics_provider_for_product}
|
||||||
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||||
use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_THREAD_POOL};
|
use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_THREAD_POOL};
|
||||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||||
use style::gecko::selector_parser::PseudoElement;
|
use style::gecko::selector_parser::{NonTSPseudoClass, PseudoElement};
|
||||||
use style::gecko::traversal::RecalcStyleOnly;
|
use style::gecko::traversal::RecalcStyleOnly;
|
||||||
use style::gecko::wrapper::{GeckoElement, GeckoNode};
|
use style::gecko::wrapper::{GeckoElement, GeckoNode};
|
||||||
use style::gecko_bindings::bindings;
|
use style::gecko_bindings::bindings;
|
||||||
|
@ -5115,3 +5115,14 @@ pub extern "C" fn Servo_ParseCounterStyleDescriptor(
|
||||||
result,
|
result,
|
||||||
).is_ok()
|
).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Servo_PseudoClass_GetStates(name: *const nsACString) -> u64 {
|
||||||
|
let name = name.as_ref().unwrap().as_str_unchecked();
|
||||||
|
match NonTSPseudoClass::parse_non_functional(name) {
|
||||||
|
None => 0,
|
||||||
|
// Ignore :any-link since it contains both visited and unvisited state.
|
||||||
|
Some(NonTSPseudoClass::AnyLink) => 0,
|
||||||
|
Some(pseudo_class) => pseudo_class.state_flag().bits(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue