style: Remove support for XBL resources.

So much unsound code going away :-)

Differential Revision: https://phabricator.services.mozilla.com/D28380
This commit is contained in:
Emilio Cobos Álvarez 2019-04-23 16:43:15 +00:00
parent 50312e1457
commit e5b5cd78a9
10 changed files with 22 additions and 208 deletions

View file

@ -279,13 +279,13 @@ where
/// Runs F with a given shadow host which is the root of the tree whose
/// rules we're matching.
#[inline]
pub fn with_shadow_host<F, E, R>(&mut self, host: Option<E>, f: F) -> R
pub fn with_shadow_host<F, E, R>(&mut self, host: E, f: F) -> R
where
E: Element,
F: FnOnce(&mut Self) -> R,
{
let original_host = self.current_host.take();
self.current_host = host.map(|h| h.opaque());
self.current_host = Some(host.opaque());
let result = f(self);
self.current_host = original_host;
result

View file

@ -3,7 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! A set of author stylesheets and their computed representation, such as the
//! ones used for ShadowRoot and XBL.
//! ones used for ShadowRoot.
use crate::context::QuirksMode;
use crate::dom::TElement;
@ -17,7 +17,7 @@ use crate::stylesheets::StylesheetInDocument;
use crate::stylist::CascadeData;
/// A set of author stylesheets and their computed representation, such as the
/// ones used for ShadowRoot and XBL.
/// ones used for ShadowRoot.
#[derive(MallocSizeOf)]
pub struct AuthorStyles<S>
where
@ -28,9 +28,6 @@ where
pub stylesheets: AuthorStylesheetSet<S>,
/// The actual cascade data computed from the stylesheets.
pub data: CascadeData,
/// The quirks mode of the last stylesheet flush, used because XBL sucks and
/// we should really fix it, see bug 1406875.
pub quirks_mode: QuirksMode,
}
impl<S> AuthorStyles<S>
@ -43,7 +40,6 @@ where
Self {
stylesheets: AuthorStylesheetSet::new(),
data: CascadeData::new(),
quirks_mode: QuirksMode::NoQuirks,
}
}
@ -65,10 +61,6 @@ where
.stylesheets
.flush::<E>(/* host = */ None, /* snapshot_map = */ None);
if flusher.sheets.dirty() {
self.quirks_mode = quirks_mode;
}
// Ignore OOM.
let _ = self
.data

View file

@ -761,7 +761,7 @@ pub trait TElement:
/// Returns the anonymous content for the current element's XBL binding,
/// given if any.
///
/// This is used in Gecko for XBL and shadow DOM.
/// This is used in Gecko for XBL.
fn xbl_binding_anonymous_content(&self) -> Option<Self::ConcreteNode> {
None
}
@ -772,11 +772,6 @@ pub trait TElement:
/// The shadow root which roots the subtree this element is contained in.
fn containing_shadow(&self) -> Option<<Self::ConcreteNode as TNode>::ConcreteShadowRoot>;
/// XBL hack for style sharing. :(
fn has_same_xbl_proto_binding_as(&self, _other: Self) -> bool {
true
}
/// Return the element which we can use to look up rules in the selector
/// maps.
///
@ -792,56 +787,34 @@ pub trait TElement:
}
}
/// Implements Gecko's `nsBindingManager::WalkRules`.
///
/// Returns whether to cut off the binding inheritance, that is, whether
/// document rules should _not_ apply.
fn each_xbl_cascade_data<'a, F>(&self, _: F) -> bool
where
Self: 'a,
F: FnMut(&'a CascadeData, QuirksMode),
{
false
}
/// Executes the callback for each applicable style rule data which isn't
/// the main document's data (which stores UA / author rules).
///
/// The element passed to the callback is the containing shadow host for the
/// data if it comes from Shadow DOM, None if it comes from XBL.
/// data if it comes from Shadow DOM.
///
/// Returns whether normal document author rules should apply.
fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
where
Self: 'a,
F: FnMut(&'a CascadeData, QuirksMode, Option<Self>),
F: FnMut(&'a CascadeData, Self),
{
use rule_collector::containing_shadow_ignoring_svg_use;
let mut doc_rules_apply = !self.each_xbl_cascade_data(|data, quirks_mode| {
f(data, quirks_mode, None);
});
let mut doc_rules_apply = self.matches_user_and_author_rules();
// Use the same rules to look for the containing host as we do for rule
// collection.
if let Some(shadow) = containing_shadow_ignoring_svg_use(*self) {
doc_rules_apply = false;
if let Some(data) = shadow.style_data() {
f(
data,
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
f(data, shadow.host());
}
}
if let Some(shadow) = self.shadow_root() {
if let Some(data) = shadow.style_data() {
f(
data,
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
f(data, shadow.host());
}
}
@ -850,11 +823,7 @@ pub trait TElement:
// Slots can only have assigned nodes when in a shadow tree.
let shadow = slot.containing_shadow().unwrap();
if let Some(data) = shadow.style_data() {
f(
data,
self.as_node().owner_doc().quirks_mode(),
Some(shadow.host()),
);
f(data, shadow.host());
}
current = slot.assigned_slot();
}

View file

@ -145,11 +145,6 @@ impl PerDocumentStyleData {
/// Create a `PerDocumentStyleData`.
pub fn new(document: *const structs::Document) -> Self {
let device = Device::new(document);
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
// right now not always honored, see bug 1405543...
//
// Should we just force XBL Stylists to be NoQuirks?
let quirks_mode = device.document().mCompatMode;
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {

View file

@ -172,15 +172,7 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> {
Self: 'a,
{
let author_styles = unsafe { self.0.mServoStyles.mPtr.as_ref()? };
let author_styles = AuthorStyles::<GeckoStyleSheet>::from_ffi(author_styles);
debug_assert!(
author_styles.quirks_mode == self.as_node().owner_doc().quirks_mode() ||
author_styles.stylesheets.is_empty() ||
author_styles.stylesheets.dirty()
);
Some(&author_styles.data)
}
@ -536,11 +528,6 @@ impl<'lb> GeckoXBLBinding<'lb> {
self.0.mContent.raw::<nsIContent>()
}
#[inline]
fn inherits_style(&self) -> bool {
unsafe { bindings::Gecko_XBLBinding_InheritsStyle(self.0) }
}
// This duplicates the logic in Gecko's
// nsBindingManager::GetBindingWithContent.
fn binding_with_content(&self) -> Option<Self> {
@ -552,22 +539,6 @@ impl<'lb> GeckoXBLBinding<'lb> {
binding = binding.base_binding()?;
}
}
fn each_xbl_cascade_data<F>(&self, f: &mut F)
where
F: FnMut(&'lb CascadeData, QuirksMode),
{
if let Some(base) = self.base_binding() {
base.each_xbl_cascade_data(f);
}
let data = unsafe { bindings::Gecko_XBLBinding_GetRawServoStyles(self.0).as_ref() };
if let Some(data) = data {
let data: &'lb _ = AuthorStyles::<GeckoStyleSheet>::from_ffi(data);
f(&data.data, data.quirks_mode)
}
}
}
/// A simple wrapper over a non-null Gecko `Element` pointer.
@ -1250,14 +1221,6 @@ impl<'le> TElement for GeckoElement<'le> {
}
}
fn has_same_xbl_proto_binding_as(&self, other: Self) -> bool {
match (self.xbl_binding(), other.xbl_binding()) {
(None, None) => true,
(Some(a), Some(b)) => a.0.mPrototypeBinding == b.0.mPrototypeBinding,
_ => false,
}
}
fn each_anonymous_content_child<F>(&self, mut f: F)
where
F: FnMut(Self),
@ -1436,7 +1399,7 @@ impl<'le> TElement for GeckoElement<'le> {
#[inline]
fn matches_user_and_author_rules(&self) -> bool {
!self.is_in_native_anonymous_subtree()
!self.rule_hash_target().is_in_native_anonymous_subtree()
}
#[inline]
@ -1599,43 +1562,6 @@ impl<'le> TElement for GeckoElement<'le> {
self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) }
}
fn each_xbl_cascade_data<'a, F>(&self, mut f: F) -> bool
where
'le: 'a,
F: FnMut(&'a CascadeData, QuirksMode),
{
// Walk the binding scope chain, starting with the binding attached to
// our content, up till we run out of scopes or we get cut off.
//
// If we are a NAC pseudo-element, we want to get rules from our
// rule_hash_target, that is, our originating element.
let mut current = Some(self.rule_hash_target());
while let Some(element) = current {
if let Some(binding) = element.xbl_binding() {
binding.each_xbl_cascade_data(&mut f);
// If we're not looking at our original element, allow the
// binding to cut off style inheritance.
if element != *self && !binding.inherits_style() {
// Go no further; we're not inheriting style from
// anything above here.
break;
}
}
if element.is_root_of_native_anonymous_subtree() {
// Deliberately cut off style inheritance here.
break;
}
current = element.xbl_binding_parent();
}
// If current has something, this means we cut off inheritance at some
// point in the loop.
current.is_some()
}
fn xbl_binding_anonymous_content(&self) -> Option<GeckoNode<'le>> {
self.xbl_binding_with_content()
.map(|b| unsafe { GeckoNode::from_content(&*b.anon_content()) })

View file

@ -224,8 +224,8 @@ where
let mut shadow_rule_datas = SmallVec::<[_; 3]>::new();
let matches_document_author_rules =
element.each_applicable_non_document_style_rule_data(|data, quirks_mode, host| {
shadow_rule_datas.push((data, quirks_mode, host.map(|h| h.opaque())))
element.each_applicable_non_document_style_rule_data(|data, host| {
shadow_rule_datas.push((data, host.opaque()))
});
let invalidated_self = {
@ -258,12 +258,8 @@ where
}
}
for &(ref data, quirks_mode, ref host) in &shadow_rule_datas {
// FIXME(emilio): Replace with assert / remove when we figure
// out what to do with the quirks mode mismatches
// (that is, when bug 1406875 is properly fixed).
collector.matching_context.set_quirks_mode(quirks_mode);
collector.matching_context.current_host = host.clone();
for &(ref data, ref host) in &shadow_rule_datas {
collector.matching_context.current_host = Some(host.clone());
collector.collect_dependencies_in_invalidation_map(data.invalidation_map());
}

View file

@ -98,7 +98,7 @@ where
flags_setter: &'a mut F,
) -> Self {
let rule_hash_target = element.rule_hash_target();
let matches_user_and_author_rules = rule_hash_target.matches_user_and_author_rules();
let matches_user_and_author_rules = element.matches_user_and_author_rules();
// Gecko definitely has pseudo-elements with style attributes, like
// ::-moz-color-swatch.
@ -198,7 +198,7 @@ where
let rules = &mut self.rules;
let flags_setter = &mut self.flags_setter;
let shadow_cascade_order = self.shadow_cascade_order;
self.context.with_shadow_host(Some(shadow_host), |context| {
self.context.with_shadow_host(shadow_host, |context| {
map.get_all_matching_rules(
element,
rule_hash_target,
@ -303,42 +303,6 @@ where
self.collect_stylist_rules(Origin::Author);
}
fn collect_xbl_rules(&mut self) {
let element = self.element;
let cut_xbl_binding_inheritance =
element.each_xbl_cascade_data(|cascade_data, quirks_mode| {
let map = match cascade_data.normal_rules(self.pseudo_element) {
Some(m) => m,
None => return,
};
// NOTE(emilio): This is needed because the XBL stylist may
// think it has a different quirks mode than the document.
let mut matching_context = MatchingContext::new(
self.context.matching_mode(),
self.context.bloom_filter,
self.context.nth_index_cache.as_mut().map(|s| &mut **s),
quirks_mode,
);
matching_context.pseudo_element_matching_fn =
self.context.pseudo_element_matching_fn;
// SameTreeAuthorNormal instead of InnerShadowNormal to
// preserve behavior, though that's kinda fishy...
map.get_all_matching_rules(
self.element,
self.rule_hash_target,
self.rules,
&mut matching_context,
self.flags_setter,
CascadeLevel::SameTreeAuthorNormal,
self.shadow_cascade_order,
);
});
self.matches_document_author_rules &= !cut_xbl_binding_inheritance;
}
fn collect_style_attribute_and_animation_rules(&mut self) {
if let Some(sa) = self.style_attribute {
self.rules
@ -396,7 +360,6 @@ where
self.collect_host_rules();
self.collect_slotted_rules();
self.collect_normal_rules_from_containing_shadow_tree();
self.collect_xbl_rules();
self.collect_document_author_rules();
self.collect_style_attribute_and_animation_rules();
}

View file

@ -727,27 +727,6 @@ impl<E: TElement> StyleSharingCache<E> {
return None;
}
// Note that in theory we shouldn't need this XBL check. However, XBL is
// absolutely broken in all sorts of ways.
//
// A style change that changes which XBL binding applies to an element
// arrives there, with the element still having the old prototype
// binding attached. And thus we try to match revalidation selectors
// with the old XBL binding, because we can't look at the new ones of
// course. And that causes us to revalidate with the wrong selectors and
// hit assertions.
//
// Other than this, we don't need anything else like the containing XBL
// binding parent or what not, since two elements with different XBL
// bindings will necessarily end up with different style.
if !target
.element
.has_same_xbl_proto_binding_as(candidate.element)
{
trace!("Miss: Different proto bindings");
return None;
}
// If the elements are not assigned to the same slot they could match
// different ::slotted() rules in the slot scope.
//

View file

@ -546,7 +546,7 @@ where
}
}
/// The set of stylesheets effective for a given XBL binding or Shadow Root.
/// The set of stylesheets effective for a given Shadow Root.
#[derive(MallocSizeOf)]
pub struct AuthorStylesheetSet<S>
where

View file

@ -636,7 +636,7 @@ impl Stylist {
let mut maybe = false;
let doc_author_rules_apply =
element.each_applicable_non_document_style_rule_data(|data, _, _| {
element.each_applicable_non_document_style_rule_data(|data, _| {
maybe = maybe || f(&*data);
});
@ -1072,12 +1072,6 @@ impl Stylist {
/// Returns whether, given a media feature change, any previously-applicable
/// style has become non-applicable, or vice-versa for each origin, using
/// `device`.
///
/// Passing `device` is needed because this is used for XBL in Gecko, which
/// can be stale in various ways, so we need to pass the device of the
/// document itself, which is what is kept up-to-date.
///
/// Arguably XBL should use something more lightweight than a Stylist.
pub fn media_features_change_changed_style(
&self,
guards: &StylesheetGuards,
@ -1261,11 +1255,11 @@ impl Stylist {
let mut results = SmallBitVec::new();
let matches_document_rules =
element.each_applicable_non_document_style_rule_data(|data, quirks_mode, host| {
element.each_applicable_non_document_style_rule_data(|data, host| {
matching_context.with_shadow_host(host, |matching_context| {
data.selectors_for_cache_revalidation.lookup(
element,
quirks_mode,
self.quirks_mode,
|selector_and_hashes| {
results.push(matches_selector(
&selector_and_hashes.selector,