mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
stylo: Use namespace ids for content: attr(..)
MozReview-Commit-ID: FZ9YEpHQCBh
This commit is contained in:
parent
7deeccf4cb
commit
25d193ba34
7 changed files with 57 additions and 16 deletions
|
@ -1399,6 +1399,9 @@ extern "C" {
|
||||||
pub fn Gecko_AddPropertyToSet(arg1: nsCSSPropertyIDSetBorrowedMut,
|
pub fn Gecko_AddPropertyToSet(arg1: nsCSSPropertyIDSetBorrowedMut,
|
||||||
arg2: nsCSSPropertyID);
|
arg2: nsCSSPropertyID);
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_RegisterNamespace(ns: *mut nsIAtom) -> i32;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_Construct_Default_nsStyleFont(ptr: *mut nsStyleFont,
|
pub fn Gecko_Construct_Default_nsStyleFont(ptr: *mut nsStyleFont,
|
||||||
pres_context:
|
pres_context:
|
||||||
|
|
|
@ -273,11 +273,11 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_namespace(&self) -> Option<Namespace> {
|
fn default_namespace(&self) -> Option<Namespace> {
|
||||||
self.namespaces.default.clone()
|
self.namespaces.default.clone().as_ref().map(|&(ref ns, _)| ns.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn namespace_for_prefix(&self, prefix: &Atom) -> Option<Namespace> {
|
fn namespace_for_prefix(&self, prefix: &Atom) -> Option<Namespace> {
|
||||||
self.namespaces.prefixes.get(prefix).cloned()
|
self.namespaces.prefixes.get(prefix).map(|&(ref ns, _)| ns.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{Parser, SourcePosition, UnicodeRange};
|
use cssparser::{Parser, SourcePosition, UnicodeRange};
|
||||||
use error_reporting::ParseErrorReporter;
|
use error_reporting::ParseErrorReporter;
|
||||||
|
use parking_lot::RwLock;
|
||||||
use style_traits::OneOrMoreCommaSeparated;
|
use style_traits::OneOrMoreCommaSeparated;
|
||||||
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
|
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
|
||||||
use parking_lot::RwLock;
|
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// The mode to use when parsing values.
|
/// The mode to use when parsing values.
|
||||||
|
|
|
@ -4403,10 +4403,10 @@ clip-path
|
||||||
}
|
}
|
||||||
ContentItem::Attr(ns, val) => {
|
ContentItem::Attr(ns, val) => {
|
||||||
self.gecko.mContents[i].mType = eStyleContentType_Attr;
|
self.gecko.mContents[i].mType = eStyleContentType_Attr;
|
||||||
let s = if let Some(ns) = ns {
|
let s = if let Some((_, ns)) = ns {
|
||||||
format!("{}|{}", ns, val)
|
format!("{}|{}", ns, val)
|
||||||
} else {
|
} else {
|
||||||
val
|
val.into()
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
// NB: we share allocators, so doing this is fine.
|
// NB: we share allocators, so doing this is fine.
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
use values::generics::CounterStyleOrNone;
|
use values::generics::CounterStyleOrNone;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
use gecko_string_cache::namespace::Namespace;
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use super::list_style_type;
|
use super::list_style_type;
|
||||||
|
@ -35,6 +37,8 @@
|
||||||
type CounterStyleType = super::super::list_style_type::computed_value::T;
|
type CounterStyleType = super::super::list_style_type::computed_value::T;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
type CounterStyleType = ::values::generics::CounterStyleOrNone;
|
type CounterStyleType = ::values::generics::CounterStyleOrNone;
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
use gecko_string_cache::namespace::Namespace;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
@ -56,7 +60,7 @@
|
||||||
|
|
||||||
% if product == "gecko":
|
% if product == "gecko":
|
||||||
/// `attr([namespace? `|`]? ident)`
|
/// `attr([namespace? `|`]? ident)`
|
||||||
Attr(Option<String>, String),
|
Attr(Option<(Namespace, u32)>, String),
|
||||||
/// `url(url)`
|
/// `url(url)`
|
||||||
Url(SpecifiedUrl),
|
Url(SpecifiedUrl),
|
||||||
% endif
|
% endif
|
||||||
|
@ -93,7 +97,7 @@
|
||||||
ContentItem::Attr(ref ns, ref attr) => {
|
ContentItem::Attr(ref ns, ref attr) => {
|
||||||
dest.write_str("attr(")?;
|
dest.write_str("attr(")?;
|
||||||
if let Some(ref ns) = *ns {
|
if let Some(ref ns) = *ns {
|
||||||
cssparser::Token::Ident((&**ns).into()).to_css(dest)?;
|
cssparser::Token::Ident(ns.0.to_string().into()).to_css(dest)?;
|
||||||
dest.write_str("|")?;
|
dest.write_str("|")?;
|
||||||
}
|
}
|
||||||
cssparser::Token::Ident((&**attr).into()).to_css(dest)?;
|
cssparser::Token::Ident((&**attr).into()).to_css(dest)?;
|
||||||
|
@ -208,14 +212,29 @@
|
||||||
// FIXME (bug 1346693) we should be checking that
|
// FIXME (bug 1346693) we should be checking that
|
||||||
// this is a valid namespace and encoding it as a namespace
|
// this is a valid namespace and encoding it as a namespace
|
||||||
// number from the map
|
// number from the map
|
||||||
let first = input.try(|i| i.expect_ident()).ok().map(|i| i.into_owned());
|
let first = input.try(|i| i.expect_ident()).ok();
|
||||||
if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
|
if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
|
||||||
match token {
|
match token {
|
||||||
Token::Delim('|') => {
|
Token::Delim('|') => {
|
||||||
// must be followed by an ident
|
// must be followed by an ident
|
||||||
let tok2 = input.next_including_whitespace()?;
|
let tok2 = input.next_including_whitespace()?;
|
||||||
if let Token::Ident(second) = tok2 {
|
if let Token::Ident(second) = tok2 {
|
||||||
return Ok(ContentItem::Attr(first, second.into_owned()))
|
let first: Option<Namespace> = first.map(|i| i.into());
|
||||||
|
let first_with_id = match (first, context.namespaces) {
|
||||||
|
(Some(prefix), Some(map)) => {
|
||||||
|
let map = map.read();
|
||||||
|
if let Some(ref entry) = map.prefixes.get(&prefix.0) {
|
||||||
|
Some((prefix, entry.1))
|
||||||
|
} else {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if we don't have a namespace map (e.g. in CSSOM)
|
||||||
|
// we can't parse namespaces
|
||||||
|
(Some(_), None) => return Err(()),
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
return Ok(ContentItem::Attr(first_with_id, second.into_owned()))
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
|
@ -224,7 +243,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(first) = first {
|
if let Some(first) = first {
|
||||||
Ok(ContentItem::Attr(None, first))
|
Ok(ContentItem::Attr(None, first.into_owned()))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,11 +430,11 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_namespace(&self) -> Option<Namespace> {
|
fn default_namespace(&self) -> Option<Namespace> {
|
||||||
self.namespaces.default.clone()
|
self.namespaces.default.as_ref().map(|&(ref ns, _)| ns.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn namespace_for_prefix(&self, prefix: &Prefix) -> Option<Namespace> {
|
fn namespace_for_prefix(&self, prefix: &Prefix) -> Option<Namespace> {
|
||||||
self.namespaces.prefixes.get(prefix).cloned()
|
self.namespaces.prefixes.get(prefix).map(|&(ref ns, _)| ns.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,11 +96,13 @@ pub enum Origin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of namespaces applying to a given stylesheet.
|
/// A set of namespaces applying to a given stylesheet.
|
||||||
|
///
|
||||||
|
/// The u32 is the namespace id, used in gecko
|
||||||
#[derive(Clone, Default, Debug)]
|
#[derive(Clone, Default, Debug)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub struct Namespaces {
|
pub struct Namespaces {
|
||||||
pub default: Option<Namespace>,
|
pub default: Option<(Namespace, u32)>,
|
||||||
pub prefixes: FnvHashMap<Prefix , Namespace>,
|
pub prefixes: FnvHashMap<Prefix, (Namespace, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like gecko_bindings::structs::MallocSizeOf, but without the Option<> wrapper. Note that
|
/// Like gecko_bindings::structs::MallocSizeOf, but without the Option<> wrapper. Note that
|
||||||
|
@ -1526,6 +1528,21 @@ enum AtRulePrelude {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn register_namespace(ns: &Namespace) -> Result<u32, ()> {
|
||||||
|
let id = unsafe { ::gecko_bindings::bindings::Gecko_RegisterNamespace(ns.0.as_ptr()) };
|
||||||
|
if id == -1 {
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
Ok(id as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
fn register_namespace(ns: &Namespace) -> Result<u32, ()> {
|
||||||
|
Ok(1) // servo doesn't use namespace ids
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||||
type Prelude = AtRulePrelude;
|
type Prelude = AtRulePrelude;
|
||||||
type AtRule = CssRule;
|
type AtRule = CssRule;
|
||||||
|
@ -1584,14 +1601,16 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||||
let prefix_result = input.try(|input| input.expect_ident());
|
let prefix_result = input.try(|input| input.expect_ident());
|
||||||
let url = Namespace::from(try!(input.expect_url_or_string()));
|
let url = Namespace::from(try!(input.expect_url_or_string()));
|
||||||
|
|
||||||
|
let id = register_namespace(&url)?;
|
||||||
|
|
||||||
let opt_prefix = if let Ok(prefix) = prefix_result {
|
let opt_prefix = if let Ok(prefix) = prefix_result {
|
||||||
let prefix = Prefix::from(prefix);
|
let prefix = Prefix::from(prefix);
|
||||||
self.context.namespaces.expect("namespaces must be set whilst parsing rules")
|
self.context.namespaces.expect("namespaces must be set whilst parsing rules")
|
||||||
.write().prefixes.insert(prefix.clone(), url.clone());
|
.write().prefixes.insert(prefix.clone(), (url.clone(), id));
|
||||||
Some(prefix)
|
Some(prefix)
|
||||||
} else {
|
} else {
|
||||||
self.context.namespaces.expect("namespaces must be set whilst parsing rules")
|
self.context.namespaces.expect("namespaces must be set whilst parsing rules")
|
||||||
.write().default = Some(url.clone());
|
.write().default = Some((url.clone(), id));
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue