author | Xidorn Quan <me@upsuper.org> |
Fri, 24 Aug 2018 22:17:37 +1000 | |
changeset 433294 | 988b2e838fd1c3c335169808b563ee6c07feeac9 |
parent 433293 | d4cb5a2697e5298202436b0a29f7240a5b8d5149 |
child 433295 | 2102f887e46bf3cb2b6a7fb00ed33640c9cb330e |
push id | 68253 |
push user | xquan@mozilla.com |
push date | Fri, 24 Aug 2018 12:18:25 +0000 |
treeherder | autoland@988b2e838fd1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | emilio |
bugs | 1424106 |
milestone | 63.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -436,16 +436,23 @@ VARCACHE_PREF( // Does overflow-break: break-word affect intrinsic size? VARCACHE_PREF( "layout.css.overflow-break.intrinsic-size", layout_css_overflow_break_intrinsic_size, bool, false ) +// Does arbitrary ::-webkit-* pseudo-element parsed? +VARCACHE_PREF( + "layout.css.unknown-webkit-pseudo-element", + layout_css_unknown_webkit_pseudo_element, + bool, false +) + //--------------------------------------------------------------------------- // JavaScript prefs //--------------------------------------------------------------------------- // nsJSEnvironmentObserver observes the memory-pressure notifications and // forces a garbage collection and cycle collection when it happens, if the // appropriate pref is set. #ifdef ANDROID
--- a/servo/components/style/gecko/pseudo_element.rs +++ b/servo/components/style/gecko/pseudo_element.rs @@ -9,17 +9,17 @@ //! need to update the checked-in files for Servo. use cssparser::ToCss; use gecko_bindings::structs::{self, CSSPseudoElementType}; use properties::{ComputedValues, PropertyFlags}; use properties::longhands::display::computed_value::T as Display; use selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl}; use std::fmt; -use str::starts_with_ignore_ascii_case; +use str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; use string_cache::Atom; use thin_slice::ThinBoxedSlice; use values::serialize_atom_identifier; include!(concat!( env!("OUT_DIR"), "/gecko/pseudo_element_definition.rs" ));
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs +++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs @@ -8,16 +8,19 @@ pub enum PseudoElement { % for pseudo in PSEUDOS: /// ${pseudo.value} % if pseudo.is_tree_pseudo_element(): ${pseudo.capitalized_pseudo()}(ThinBoxedSlice<Atom>), % else: ${pseudo.capitalized_pseudo()}, % endif % endfor + /// ::-webkit-* that we don't recognize + /// https://github.com/whatwg/compat/issues/103 + UnknownWebkit(Atom), } /// Important: If you change this, you should also update Gecko's /// nsCSSPseudoElements::IsEagerlyCascadedInServo. <% EAGER_PSEUDOS = ["Before", "After", "FirstLine", "FirstLetter"] %> <% TREE_PSEUDOS = [pseudo for pseudo in PSEUDOS if pseudo.is_tree_pseudo_element()] %> <% SIMPLE_PSEUDOS = [pseudo for pseudo in PSEUDOS if not pseudo.is_tree_pseudo_element()] %> @@ -42,31 +45,33 @@ pub const EAGER_PSEUDOS: [PseudoElement; <%def name="pseudo_element_variant(pseudo, tree_arg='..')">\ PseudoElement::${pseudo.capitalized_pseudo()}${"({})".format(tree_arg) if pseudo.is_tree_pseudo_element() else ""}\ </%def> impl PseudoElement { /// Get the pseudo-element as an atom. #[inline] - pub fn atom(&self) -> Atom { + fn atom(&self) -> Atom { match *self { % for pseudo in PSEUDOS: ${pseudo_element_variant(pseudo)} => atom!("${pseudo.value}"), % endfor + PseudoElement::UnknownWebkit(..) => unreachable!(), } } /// Returns an index of the pseudo-element. #[inline] pub fn index(&self) -> usize { match *self { % for i, pseudo in enumerate(PSEUDOS): ${pseudo_element_variant(pseudo)} => ${i}, % endfor + PseudoElement::UnknownWebkit(..) => unreachable!(), } } /// Returns an array of `None` values. /// /// FIXME(emilio): Integer generics can't come soon enough. pub fn pseudo_none_array<T>() -> [Option<T>; PSEUDO_COUNT] { [ @@ -100,16 +105,22 @@ impl PseudoElement { match *self { % for pseudo in TREE_PSEUDOS: ${pseudo_element_variant(pseudo)} => true, % endfor _ => false, } } + /// Whether this pseudo-element is an unknown Webkit-prefixed pseudo-element. + #[inline] + pub fn is_unknown_webkit_pseudo_element(&self) -> bool { + matches!(*self, PseudoElement::UnknownWebkit(..)) + } + /// Gets the flags associated to this pseudo-element, or 0 if it's an /// anonymous box. pub fn flags(&self) -> u32 { match *self { % for pseudo in PSEUDOS: ${pseudo_element_variant(pseudo)} => % if pseudo.is_tree_pseudo_element(): if unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_tree_pseudos_content_enabled } { @@ -118,16 +129,17 @@ impl PseudoElement { structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME }, % elif pseudo.is_anon_box(): structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS, % else: structs::SERVO_CSS_PSEUDO_ELEMENT_FLAGS_${pseudo.pseudo_ident}, % endif % endfor + PseudoElement::UnknownWebkit(..) => 0, } } /// Construct a pseudo-element from a `CSSPseudoElementType`. #[inline] pub fn from_pseudo_type(type_: CSSPseudoElementType) -> Option<Self> { match type_ { % for pseudo in PSEUDOS: @@ -138,31 +150,32 @@ impl PseudoElement { % endif % endfor _ => None, } } /// Construct a `CSSPseudoElementType` from a pseudo-element #[inline] - pub fn pseudo_type(&self) -> CSSPseudoElementType { + fn pseudo_type(&self) -> CSSPseudoElementType { use gecko_bindings::structs::CSSPseudoElementType_InheritingAnonBox; match *self { % for pseudo in PSEUDOS: % if not pseudo.is_anon_box(): PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::${pseudo.pseudo_ident}, % elif pseudo.is_tree_pseudo_element(): PseudoElement::${pseudo.capitalized_pseudo()}(..) => CSSPseudoElementType::XULTree, % elif pseudo.is_inheriting_anon_box(): PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType_InheritingAnonBox, % else: PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::NonInheritingAnonBox, % endif % endfor + PseudoElement::UnknownWebkit(..) => unreachable!(), } } /// Get a PseudoInfo for a pseudo pub fn pseudo_info(&self) -> (*mut structs::nsAtom, CSSPseudoElementType) { (self.atom().as_ptr(), self.pseudo_type()) } @@ -240,16 +253,25 @@ impl PseudoElement { } "-moz-placeholder" => { return Some(PseudoElement::Placeholder); } _ => { if starts_with_ignore_ascii_case(name, "-moz-tree-") { return PseudoElement::tree_pseudo_element(name, Box::new([])) } + if unsafe { + structs::StaticPrefs_sVarCache_layout_css_unknown_webkit_pseudo_element + } { + const WEBKIT_PREFIX: &str = "-webkit-"; + if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) { + let part = string_as_ascii_lowercase(&name[WEBKIT_PREFIX.len()..]); + return Some(PseudoElement::UnknownWebkit(part.into())); + } + } } } None } /// Constructs a tree pseudo-element from the given name and arguments. /// "name" must start with "-moz-tree-". @@ -270,16 +292,20 @@ impl PseudoElement { impl ToCss for PseudoElement { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { dest.write_char(':')?; match *self { % for pseudo in PSEUDOS: ${pseudo_element_variant(pseudo)} => dest.write_str("${pseudo.value}")?, % endfor + PseudoElement::UnknownWebkit(ref atom) => { + dest.write_str(":-webkit-")?; + serialize_atom_identifier(atom, dest)?; + } } if let Some(args) = self.tree_pseudo_args() { if !args.is_empty() { dest.write_char('(')?; let mut iter = args.iter(); if let Some(first) = iter.next() { serialize_atom_identifier(&first, dest)?; for item in iter {
--- a/servo/components/style/stylist.rs +++ b/servo/components/style/stylist.rs @@ -1876,17 +1876,19 @@ struct ElementAndPseudoRules { impl ElementAndPseudoRules { #[inline(always)] fn insert( &mut self, rule: Rule, pseudo_element: Option<&PseudoElement>, quirks_mode: QuirksMode, ) -> Result<(), FailedAllocationError> { - debug_assert!(pseudo_element.map_or(true, |pseudo| !pseudo.is_precomputed())); + debug_assert!(pseudo_element.map_or(true, |pseudo| { + !pseudo.is_precomputed() && !pseudo.is_unknown_webkit_pseudo_element() + })); let map = match pseudo_element { None => &mut self.element_map, Some(pseudo) => self.pseudos_map .get_or_insert_with(pseudo, || Box::new(SelectorMap::new())), }; map.insert(rule, quirks_mode) @@ -2189,16 +2191,19 @@ impl CascadeData { StyleSource::from_rule(locked.clone()), self.rules_source_order, CascadeLevel::UANormal, selector.specificity(), 0, )); continue; } + if pseudo.is_unknown_webkit_pseudo_element() { + continue; + } } let hashes = AncestorHashes::new(&selector, quirks_mode); let rule = Rule::new( selector.clone(), hashes, locked.clone(),
--- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -324783,16 +324783,22 @@ ] ], "compat/idlharness.window.js": [ [ "/compat/idlharness.window.html", {} ] ], + "compat/webkit-pseudo-element.html": [ + [ + "/compat/webkit-pseudo-element.html", + {} + ] + ], "compat/webkit-text-fill-color-currentColor.html": [ [ "/compat/webkit-text-fill-color-currentColor.html", {} ] ], "console/console-is-a-namespace.any.js": [ [ @@ -434268,16 +434274,20 @@ "compat/webkit-linear-gradient-line-right.html": [ "0f1a4b9500c362b67430ccbc9caeb165ee5327f4", "reftest" ], "compat/webkit-linear-gradient-line-top.html": [ "579d88220610e4f2ea7e884018b655cf1c5c8dca", "reftest" ], + "compat/webkit-pseudo-element.html": [ + "8f69477489a8eee76a6b379f07dcbcafda539c5a", + "testharness" + ], "compat/webkit-text-fill-color-currentColor.html": [ "f4912c93450edf03b43b220d205460cc82ef9ba2", "testharness" ], "compat/webkit-text-fill-color-property-001-ref.html": [ "8d9b8cc22e77bd92873e9846780add24cbc61e32", "support" ],
new file mode 100644 --- /dev/null +++ b/testing/web-platform/meta/compat/webkit-pseudo-element.html.ini @@ -0,0 +1,2 @@ +[webkit-pseudo-element.html] + prefs: [layout.css.unknown-webkit-pseudo-element:true]
new file mode 100644 --- /dev/null +++ b/testing/web-platform/tests/compat/webkit-pseudo-element.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<title>WebKit-prefixed pseudo-elements</title> +<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org"> +<link rel="help" href="https://compat.spec.whatwg.org/#css-webkit-pseudo-elements"> +<meta name="assert" content="WebKit-prefixed pseudo-elements should always be valid"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style id="style"> +#test { + color: rgb(255, 0, 0); +} +span::-webkit-something-invalid, #test, ::-WeBkIt-sOmEtHiNg-NoNeXiSt123 { + color: rgb(0, 255, 0); +} +::-webkitfoo, #test { + color: rgb(255, 0, 0); +} +</style> +<body> +<div id="test"></div> +<script> + test(() => { + let elem = document.getElementById("test"); + assert_equals(getComputedStyle(elem).color, "rgb(0, 255, 0)"); + }, "rules include webkit-prefixed pseudo-element should be cascaded"); + + test(() => { + let sheet = document.getElementById("style").sheet; + assert_equals(sheet.cssRules[1].selectorText, + "span::-webkit-something-invalid, " + + "#test, ::-webkit-something-nonexist123"); + }, "webkit-prefixed pseudo-element selectors should be accessible from CSSOM"); + + test(() => { + document.querySelector("span::-webkit-something-invalid"); + document.querySelectorAll("span::-webkit-something-invalid"); + }, "qS and qSA shouldn't throw exception"); + + test(() => { + let sheet = document.getElementById("style").sheet; + assert_equals(sheet.cssRules.length, 2); + assert_throws("SyntaxError", () => document.querySelector("span::-webkitfoo")); + assert_throws("SyntaxError", () => document.querySelectorAll("span::-webkitfoo")); + }, "webkit-prefix without dash is invalid"); +</script> +</body>