diff --git a/servo/components/style/gecko/generated/bindings.rs b/servo/components/style/gecko/generated/bindings.rs index 115f83f5151f..90853e851790 100644 --- a/servo/components/style/gecko/generated/bindings.rs +++ b/servo/components/style/gecko/generated/bindings.rs @@ -1596,9 +1596,6 @@ extern "C" { extern "C" { pub fn Gecko_AddPropertyToSet(arg1: nsCSSPropertyIDSetBorrowedMut, arg2: nsCSSPropertyID); } -extern "C" { - pub fn Gecko_RegisterNamespace(ns: *mut nsAtom) -> i32; -} extern "C" { pub fn Gecko_Construct_Default_nsStyleFont( ptr: *mut nsStyleFont, diff --git a/servo/components/style/gecko/generated/structs.rs b/servo/components/style/gecko/generated/structs.rs index ae4c3bb1bbda..6562ae4c1125 100644 --- a/servo/components/style/gecko/generated/structs.rs +++ b/servo/components/style/gecko/generated/structs.rs @@ -26311,6 +26311,47 @@ pub mod root { } #[repr(C)] #[derive(Debug)] + pub struct nsStyleContentAttr { + pub mName: root::RefPtr, + pub mNamespaceURL: root::RefPtr, + } + #[test] + fn bindgen_test_layout_nsStyleContentAttr() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(nsStyleContentAttr)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(nsStyleContentAttr)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).mName as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nsStyleContentAttr), + "::", + stringify!(mName) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).mNamespaceURL as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(nsStyleContentAttr), + "::", + stringify!(mNamespaceURL) + ) + ); + } + #[repr(C)] + #[derive(Debug)] pub struct nsStyleContentData { pub mType: root::nsStyleContentType, pub mContent: root::nsStyleContentData__bindgen_ty_1, @@ -26395,6 +26436,7 @@ pub mod root { #[derive(Debug, Copy)] pub struct nsStyleContentData__bindgen_ty_1 { pub mString: root::__BindgenUnionField<*mut u16>, + pub mAttr: root::__BindgenUnionField<*mut root::nsStyleContentAttr>, pub mImage: root::__BindgenUnionField<*mut root::nsStyleImageRequest>, pub mCounters: root::__BindgenUnionField<*mut root::nsStyleContentData_CounterFunction>, pub bindgen_union_field: u64, @@ -26427,6 +26469,19 @@ pub mod root { stringify!(mString) ) ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).mAttr as *const _ + as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(nsStyleContentData__bindgen_ty_1), + "::", + stringify!(mAttr) + ) + ); assert_eq!( unsafe { &(*(::std::ptr::null::())).mImage as *const _ @@ -41719,6 +41774,44 @@ pub mod root { ); } #[test] + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_4() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify!(root::RefPtr) + ) + ); + assert_eq!( + ::std::mem::align_of::>(), + 8usize, + concat!( + "Alignment of template specialization: ", + stringify!(root::RefPtr) + ) + ); + } + #[test] + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_5() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify!(root::RefPtr) + ) + ); + assert_eq!( + ::std::mem::align_of::>(), + 8usize, + concat!( + "Alignment of template specialization: ", + stringify!(root::RefPtr) + ) + ); + } + #[test] fn __bindgen_test_layout_nsTArray_open0_nsStyleContentData_close0_instantiation() { assert_eq!( ::std::mem::size_of::>(), @@ -41928,7 +42021,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_4() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_6() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -43679,7 +43772,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_5() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_7() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -44126,7 +44219,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_6() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_8() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -44255,7 +44348,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_7() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_9() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -46639,7 +46732,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_8() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_10() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -46658,7 +46751,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_9() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_11() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -46905,7 +46998,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_10() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_12() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -46943,7 +47036,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_11() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_13() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -47518,7 +47611,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_12() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_14() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -48017,7 +48110,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_13() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_15() { assert_eq!( ::std::mem::size_of::>(), 8usize, @@ -48093,7 +48186,7 @@ pub mod root { ); } #[test] - fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_14() { + fn __bindgen_test_layout_RefPtr_open0_nsAtom_close0_instantiation_16() { assert_eq!( ::std::mem::size_of::>(), 8usize, diff --git a/servo/components/style/gecko/selector_parser.rs b/servo/components/style/gecko/selector_parser.rs index 89514d2c1d17..d7a9e0af4259 100644 --- a/servo/components/style/gecko/selector_parser.rs +++ b/servo/components/style/gecko/selector_parser.rs @@ -470,11 +470,11 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } fn default_namespace(&self) -> Option { - self.namespaces.default.clone().as_ref().map(|&(ref ns, _)| ns.clone()) + self.namespaces.default.as_ref().map(|ns| ns.clone()) } fn namespace_for_prefix(&self, prefix: &Atom) -> Option { - self.namespaces.prefixes.get(prefix).map(|&(ref ns, _)| ns.clone()) + self.namespaces.prefixes.get(prefix).cloned() } } diff --git a/servo/components/style/properties/gecko.mako.rs b/servo/components/style/properties/gecko.mako.rs index 9139b2387bf5..16c75025f41f 100644 --- a/servo/components/style/properties/gecko.mako.rs +++ b/servo/components/style/properties/gecko.mako.rs @@ -55,6 +55,7 @@ use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarat use rule_tree::StrongRuleNode; use selector_parser::PseudoElement; use servo_arc::{Arc, RawOffsetArc}; +use std::marker::PhantomData; use std::mem::{forget, uninitialized, transmute, zeroed}; use std::{cmp, ops, ptr}; use values::{self, CustomIdent, Either, KeyframesName, None_}; @@ -5429,6 +5430,7 @@ clip-path use values::computed::counters::{Content, ContentItem}; use values::generics::CounterStyleOrNone; use gecko_bindings::structs::nsStyleContentData; + use gecko_bindings::structs::nsStyleContentAttr; use gecko_bindings::structs::nsStyleContentType; use gecko_bindings::structs::nsStyleContentType::*; use gecko_bindings::bindings::Gecko_ClearAndResizeStyleContents; @@ -5505,14 +5507,19 @@ clip-path self.gecko.mContents[i].mType = eStyleContentType_Attr; unsafe { // NB: we share allocators, so doing this is fine. - *self.gecko.mContents[i].mContent.mString.as_mut() = match attr.namespace { - Some((_, ns)) => { - as_utf16_and_forget(&format!("{}|{}", ns, attr.attribute)) + let maybe_ns = attr.namespace.clone(); + let attr_struct = Box::new(nsStyleContentAttr { + mName: structs::RefPtr { + mRawPtr: attr.attribute.clone().into_addrefed(), + _phantom_0: PhantomData, }, - None => { - as_utf16_and_forget(&attr.attribute) - } - }; + mNamespaceURL: structs::RefPtr { + mRawPtr: maybe_ns.map_or(ptr::null_mut(), |x| (x.1).0.into_addrefed()), + _phantom_0: PhantomData, + }, + }); + *self.gecko.mContents[i].mContent.mAttr.as_mut() = + Box::into_raw(attr_struct); } } ContentItem::OpenQuote @@ -5569,7 +5576,7 @@ clip-path } pub fn clone_content(&self) -> longhands::content::computed_value::T { - use Atom; + use {Atom, Namespace}; use gecko::conversions::string_from_chars_pointer; use gecko_bindings::structs::nsStyleContentType::*; use values::computed::counters::{Content, ContentItem}; @@ -5600,19 +5607,17 @@ clip-path ContentItem::String(string.into_boxed_str()) }, eStyleContentType_Attr => { - let gecko_chars = unsafe { gecko_content.mContent.mString.as_ref() }; - let string = unsafe { string_from_chars_pointer(*gecko_chars) }; - let (namespace, attribute) = - match string.find('|') { - None => (None, string), - Some(index) => { - let (_, val) = string.split_at(index); - // FIXME: We should give NamespaceId as well to make Attr - // struct. However, there is no field for it in Gecko. - debug_assert!(false, "Attr with namespace does not support yet"); - (None, val.to_string()) - } + let (namespace, attribute) = unsafe { + let s = &**gecko_content.mContent.mAttr.as_ref(); + let ns = if s.mNamespaceURL.mRawPtr.is_null() { + None + } else { + // FIXME(bholley): We don't have any way to get the prefix here. :-( + let prefix = atom!(""); + Some((prefix, Namespace(Atom::from_raw(s.mNamespaceURL.mRawPtr)))) }; + (ns, Atom::from_raw(s.mName.mRawPtr)) + }; ContentItem::Attr(Attr { namespace, attribute }) }, eStyleContentType_Counter | eStyleContentType_Counters => { diff --git a/servo/components/style/servo/selector_parser.rs b/servo/components/style/servo/selector_parser.rs index dd2e4f20c9f8..91dce27a7d3b 100644 --- a/servo/components/style/servo/selector_parser.rs +++ b/servo/components/style/servo/selector_parser.rs @@ -591,11 +591,11 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } fn default_namespace(&self) -> Option { - self.namespaces.default.as_ref().map(|&(ref ns, _)| ns.clone()) + self.namespaces.default.as_ref().map(|ns| ns.clone()) } fn namespace_for_prefix(&self, prefix: &Prefix) -> Option { - self.namespaces.prefixes.get(prefix).map(|&(ref ns, _)| ns.clone()) + self.namespaces.prefixes.get(prefix).cloned() } } diff --git a/servo/components/style/stylesheets/rule_parser.rs b/servo/components/style/stylesheets/rule_parser.rs index ff4a609ed6dd..ad8002317488 100644 --- a/servo/components/style/stylesheets/rule_parser.rs +++ b/servo/components/style/stylesheets/rule_parser.rs @@ -137,20 +137,6 @@ pub enum AtRuleNonBlockPrelude { Namespace(Option, Namespace, SourceLocation), } - -#[cfg(feature = "gecko")] -fn register_namespace(ns: &Namespace) -> i32 { - use gecko_bindings::bindings; - let id = unsafe { bindings::Gecko_RegisterNamespace(ns.0.as_ptr()) }; - debug_assert!(id >= 0); - id -} - -#[cfg(feature = "servo")] -fn register_namespace(_: &Namespace) { - // servo doesn't use namespace ids -} - impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a, R> { type PreludeNoBlock = AtRuleNonBlockPrelude; type PreludeBlock = AtRuleBlockPrelude; @@ -242,15 +228,13 @@ impl<'a, 'i, R: ParseErrorReporter> AtRuleParser<'i> for TopLevelRuleParser<'a, CssRule::Import(import_rule) } AtRuleNonBlockPrelude::Namespace(prefix, url, location) => { - let id = register_namespace(&url); - let opt_prefix = if let Some(prefix) = prefix { self.namespaces .prefixes - .insert(prefix.clone(), (url.clone(), id)); + .insert(prefix.clone(), url.clone()); Some(prefix) } else { - self.namespaces.default = Some((url.clone(), id)); + self.namespaces.default = Some(url.clone()); None }; diff --git a/servo/components/style/stylesheets/stylesheet.rs b/servo/components/style/stylesheets/stylesheet.rs index 038df8a2279e..f54a8a3b1832 100644 --- a/servo/components/style/stylesheets/stylesheet.rs +++ b/servo/components/style/stylesheets/stylesheet.rs @@ -23,7 +23,6 @@ use stylesheets::{CssRule, CssRules, Origin, UrlExtraData}; use stylesheets::loader::StylesheetLoader; use stylesheets::rule_parser::{State, TopLevelRuleParser}; use stylesheets::rules_iterator::{EffectiveRules, EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator}; -use values::specified::NamespaceId; /// This structure holds the user-agent and user stylesheets. pub struct UserAgentStylesheets { @@ -41,8 +40,8 @@ pub struct UserAgentStylesheets { #[derive(Clone, Debug, Default, MallocSizeOf)] #[allow(missing_docs)] pub struct Namespaces { - pub default: Option<(Namespace, NamespaceId)>, - pub prefixes: FnvHashMap, + pub default: Option, + pub prefixes: FnvHashMap, } /// The contents of a given stylesheet. This effectively maps to a diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index 728f88f23e7f..85a25fa6e046 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -6,9 +6,9 @@ //! //! TODO(emilio): Enhance docs. -use Prefix; +use {Atom, Namespace, Prefix}; use context::QuirksMode; -use cssparser::{Parser, Token, serialize_identifier}; +use cssparser::{Parser, Token}; use num_traits::One; use parser::{ParserContext, Parse}; use std::f32; @@ -685,24 +685,15 @@ impl AllowQuirks { } } -#[cfg(feature = "gecko")] -/// A namespace ID -pub type NamespaceId = i32; - - -#[cfg(feature = "servo")] -/// A namespace ID (used by gecko only) -pub type NamespaceId = (); - /// An attr(...) rule /// /// `[namespace? `|`]? ident` #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] pub struct Attr { - /// Optional namespace prefix, with the actual namespace id. - pub namespace: Option<(Prefix, NamespaceId)>, + /// Optional namespace prefix and URL. + pub namespace: Option<(Prefix, Namespace)>, /// Attribute name - pub attribute: String, + pub attribute: Atom, } impl Parse for Attr { @@ -712,9 +703,9 @@ impl Parse for Attr { } } -/// Get the Namespace id from the namespace map. -fn get_id_for_namespace(prefix: &Prefix, context: &ParserContext) -> Option { - Some(context.namespaces.as_ref()?.prefixes.get(prefix)?.1) +/// Get the Namespace for a given prefix from the namespace map. +fn get_namespace_for_prefix(prefix: &Prefix, context: &ParserContext) -> Option { + context.namespaces.as_ref()?.prefixes.get(prefix).map(|x| x.clone()) } impl Attr { @@ -737,21 +728,21 @@ impl Attr { ref t => return Err(location.new_unexpected_token_error(t.clone())), }; - let ns_with_id = if let Some(ns) = first { - let ns = Prefix::from(ns.as_ref()); - let id = match get_id_for_namespace(&ns, context) { - Some(id) => id, + let prefix_and_ns = if let Some(ns) = first { + let prefix = Prefix::from(ns.as_ref()); + let ns = match get_namespace_for_prefix(&prefix, context) { + Some(ns) => ns, None => return Err(location.new_custom_error( StyleParseErrorKind::UnspecifiedError )), }; - Some((ns, id)) + Some((prefix, ns)) } else { None }; return Ok(Attr { - namespace: ns_with_id, - attribute: second_token.as_ref().to_owned(), + namespace: prefix_and_ns, + attribute: Atom::from(second_token.as_ref()), }) } // In the case of attr(foobar ) we don't want to error out @@ -764,7 +755,7 @@ impl Attr { if let Some(first) = first { Ok(Attr { namespace: None, - attribute: first.as_ref().to_owned(), + attribute: Atom::from(first.as_ref()), }) } else { Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) @@ -778,11 +769,11 @@ impl ToCss for Attr { W: Write, { dest.write_str("attr(")?; - if let Some((ref prefix, _id)) = self.namespace { + if let Some((ref prefix, ref _url)) = self.namespace { serialize_atom_identifier(prefix, dest)?; dest.write_str("|")?; } - serialize_identifier(&self.attribute, dest)?; + serialize_atom_identifier(&self.attribute, dest)?; dest.write_str(")") } } diff --git a/servo/support/gecko/nsstring/src/lib.rs b/servo/support/gecko/nsstring/src/lib.rs index 8cb8d11ce7e3..023522129388 100644 --- a/servo/support/gecko/nsstring/src/lib.rs +++ b/servo/support/gecko/nsstring/src/lib.rs @@ -559,6 +559,12 @@ macro_rules! define_string_types { hdr: $StringRepr::new(ClassFlags::NULL_TERMINATED), } } + + /// Converts this String into a StringRepr, which will leak if the + /// repr is not passed to something that knows how to free it. + pub fn into_repr(mut self) -> $StringRepr { + mem::replace(&mut self.hdr, $StringRepr::new(ClassFlags::NULL_TERMINATED)) + } } impl Drop for $String { diff --git a/servo/tests/unit/style/parsing/selectors.rs b/servo/tests/unit/style/parsing/selectors.rs index 9efe7f1d2e37..5ace20370d47 100644 --- a/servo/tests/unit/style/parsing/selectors.rs +++ b/servo/tests/unit/style/parsing/selectors.rs @@ -10,7 +10,7 @@ use style_traits::ParseError; fn parse_selector<'i, 't>(input: &mut Parser<'i, 't>) -> Result, ParseError<'i>> { let mut ns = Namespaces::default(); - ns.prefixes.insert("svg".into(), (ns!(svg), ())); + ns.prefixes.insert("svg".into(), ns!(svg)); let parser = SelectorParser { stylesheet_origin: Origin::UserAgent, namespaces: &ns, diff --git a/servo/tests/unit/style/stylesheets.rs b/servo/tests/unit/style/stylesheets.rs index de12d6c763db..be4e2d9cbc19 100644 --- a/servo/tests/unit/style/stylesheets.rs +++ b/servo/tests/unit/style/stylesheets.rs @@ -73,7 +73,7 @@ fn test_parse_stylesheet() { let stylesheet = Stylesheet::from_str(css, url.clone(), Origin::UserAgent, media, lock, None, &CSSErrorReporterTest, QuirksMode::NoQuirks, 0); let mut namespaces = Namespaces::default(); - namespaces.default = Some((ns!(html), ())); + namespaces.default = Some(ns!(html)); let expected = Stylesheet { contents: StylesheetContents { origin: Origin::UserAgent,