--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -783,34 +783,16 @@ nsBindingManager::MediumFeaturesChanged(
return rulesChanged;
#else
MOZ_CRASH("old style system disabled");
return false;
#endif
}
void
-nsBindingManager::UpdateBoundContentBindingsForServo(nsPresContext* aPresContext)
-{
- MOZ_ASSERT(mDocument->IsStyledByServo(),
- "This should be called only by servo-backend!");
-
- RefPtr<nsPresContext> presContext = aPresContext;
-
- EnumerateBoundContentBindings([=](nsXBLBinding* aBinding) {
- nsXBLPrototypeBinding* protoBinding = aBinding->PrototypeBinding();
- ServoStyleSet* styleSet = protoBinding->GetServoStyleSet();
- if (styleSet && styleSet->StyleSheetsHaveChanged()) {
- protoBinding->ComputeServoStyleSet(presContext);
- }
- return true;
- });
-}
-
-void
nsBindingManager::AppendAllSheets(nsTArray<StyleSheet*>& aArray)
{
EnumerateBoundContentBindings([&aArray](nsXBLBinding* aBinding) {
aBinding->PrototypeBinding()->AppendStyleSheetsTo(aArray);
return true;
});
}
--- a/dom/xbl/nsBindingManager.h
+++ b/dom/xbl/nsBindingManager.h
@@ -137,20 +137,16 @@ public:
// Do any processing that needs to happen as a result of a change in the
// characteristics of the medium, and return whether this rule processor's
// rules or the servo style set have changed (e.g., because of media
// queries).
bool MediumFeaturesChanged(nsPresContext* aPresContext,
mozilla::MediaFeatureChangeReason);
- // Update the content bindings in mBoundContentSet due to medium features
- // changed.
- void UpdateBoundContentBindingsForServo(nsPresContext* aPresContext);
-
void AppendAllSheets(nsTArray<mozilla::StyleSheet*>& aArray);
void Traverse(nsIContent *aContent,
nsCycleCollectionTraversalCallback &cb);
NS_DECL_CYCLE_COLLECTION_CLASS(nsBindingManager)
// Notify the binding manager when an outermost update begins and
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -833,20 +833,20 @@ nsXBLBinding::WalkRules(nsIStyleRuleProc
mNextBinding->WalkRules(aFunc, aData);
nsIStyleRuleProcessor *rules = mPrototypeBinding->GetRuleProcessor();
if (rules)
(*aFunc)(rules, aData);
}
#endif
-ServoStyleSet*
-nsXBLBinding::GetServoStyleSet() const
+const RawServoAuthorStyles*
+nsXBLBinding::GetServoStyles() const
{
- return mPrototypeBinding->GetServoStyleSet();
+ return mPrototypeBinding->GetServoStyles();
}
// Internal helper methods ////////////////////////////////////////////////////////////////
// Get or create a WeakMap object on a given XBL-hosting global.
//
// The scheme is as follows. XBL-hosting globals (either privileged content
// Windows or XBL scopes) get two lazily-defined WeakMap properties. Each
--- a/dom/xbl/nsXBLBinding.h
+++ b/dom/xbl/nsXBLBinding.h
@@ -18,19 +18,19 @@
#include "nsCycleCollectionParticipant.h"
#include "nsISupportsImpl.h"
#include "js/TypeDecls.h"
class nsXBLPrototypeBinding;
class nsIContent;
class nsAtom;
class nsIDocument;
+struct RawServoAuthorStyles;
namespace mozilla {
-class ServoStyleSet;
namespace dom {
class ShadowRoot;
class XBLChildrenElement;
} // namespace dom
} // namespace mozilla
@@ -130,17 +130,17 @@ public:
bool aRemoveFlag, bool aNotify);
void ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument);
#ifdef MOZ_OLD_STYLE
void WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData);
#endif
- mozilla::ServoStyleSet* GetServoStyleSet() const;
+ const RawServoAuthorStyles* GetServoStyles() const;
static nsresult DoInitJSClass(JSContext *cx, JS::Handle<JSObject*> obj,
const nsString& aClassName,
nsXBLPrototypeBinding* aProtoBinding,
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew);
bool AllowScripts();
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -574,30 +574,16 @@ nsXBLPrototypeBinding::GetRuleProcessor(
return mResources->GetRuleProcessor();
}
return nullptr;
}
#endif
void
-nsXBLPrototypeBinding::ComputeServoStyleSet(nsPresContext* aPresContext)
-{
- if (mResources) {
- mResources->ComputeServoStyleSet(aPresContext);
- }
-}
-
-ServoStyleSet*
-nsXBLPrototypeBinding::GetServoStyleSet() const
-{
- return mResources ? mResources->GetServoStyleSet() : nullptr;
-}
-
-void
nsXBLPrototypeBinding::EnsureAttributeTable()
{
if (!mAttributeTable) {
mAttributeTable =
new nsClassHashtable<nsUint32HashKey, InnerAttributeTable>(2);
}
}
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -130,18 +130,31 @@ public:
mozilla::StyleSheet* StyleSheetAt(size_t aIndex) const;
size_t SheetCount() const;
bool HasStyleSheets() const;
void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheet*>& aResult) const;
#ifdef MOZ_OLD_STYLE
nsIStyleRuleProcessor* GetRuleProcessor();
#endif
- void ComputeServoStyleSet(nsPresContext* aPresContext);
- mozilla::ServoStyleSet* GetServoStyleSet() const;
+ const RawServoAuthorStyles* GetServoStyles() const
+ {
+ return mResources ? mResources->GetServoStyles() : nullptr;
+ }
+ RawServoAuthorStyles* GetServoStyles()
+ {
+ return mResources
+ ? const_cast<RawServoAuthorStyles*>(mResources->GetServoStyles())
+ : nullptr;
+ }
+
+ mozilla::ServoStyleRuleMap* GetServoStyleRuleMap()
+ {
+ return mResources ? mResources->GetServoStyleRuleMap() : nullptr;
+ }
nsresult FlushSkinSheets();
nsAtom* GetBaseTag(int32_t* aNamespaceID);
void SetBaseTag(int32_t aNamespaceID, nsAtom* aTag);
bool ImplementsInterface(REFNSIID aIID) const;
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -37,19 +37,16 @@ nsXBLPrototypeResources::nsXBLPrototypeR
}
nsXBLPrototypeResources::~nsXBLPrototypeResources()
{
MOZ_COUNT_DTOR(nsXBLPrototypeResources);
if (mLoader) {
mLoader->mResources = nullptr;
}
- if (mServoStyleSet) {
- mServoStyleSet->Shutdown();
- }
}
void
nsXBLPrototypeResources::AddResource(nsAtom* aResourceType, const nsAString& aSrc)
{
if (mLoader)
mLoader->AddResource(aResourceType, aSrc);
}
@@ -117,17 +114,17 @@ nsXBLPrototypeResources::FlushSkinSheets
if (doc->IsStyledByServo()) {
// There may be no shell during unlink.
//
// FIXME(emilio): We shouldn't skip shadow root style updates just because?
// Though during unlink is fine I guess...
if (auto* shell = doc->GetShell()) {
MOZ_ASSERT(shell->GetPresContext());
- ComputeServoStyleSet(shell->GetPresContext());
+ ComputeServoStyles(*shell->StyleSet()->AsServo());
}
} else {
#ifdef MOZ_OLD_STYLE
GatherRuleProcessor();
#else
MOZ_CRASH("old style system disabled");
#endif
}
@@ -185,26 +182,39 @@ nsXBLPrototypeResources::GatherRuleProce
mRuleProcessor = new nsCSSRuleProcessor(Move(sheets),
SheetType::Doc,
nullptr,
mRuleProcessor);
}
#endif
void
-nsXBLPrototypeResources::ComputeServoStyleSet(nsPresContext* aPresContext)
+nsXBLPrototypeResources::ComputeServoStyles(const ServoStyleSet& aMasterStyleSet)
{
- nsTArray<RefPtr<ServoStyleSheet>> sheets(mStyleSheetList.Length());
- for (StyleSheet* sheet : mStyleSheetList) {
- MOZ_ASSERT(sheet->IsServo(),
- "This should only be called with Servo-flavored style backend!");
- sheets.AppendElement(sheet->AsServo());
+ mStyleRuleMap.reset(nullptr);
+ mServoStyles.reset(Servo_AuthorStyles_Create());
+ for (auto& sheet : mStyleSheetList) {
+ Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(), sheet->AsServo());
+ }
+ Servo_AuthorStyles_Flush(mServoStyles.get(), aMasterStyleSet.RawSet());
+}
+
+ServoStyleRuleMap*
+nsXBLPrototypeResources::GetServoStyleRuleMap()
+{
+ if (!HasStyleSheets() || !mServoStyles) {
+ return nullptr;
}
- mServoStyleSet = ServoStyleSet::CreateXBLServoStyleSet(aPresContext, sheets);
+ if (!mStyleRuleMap) {
+ mStyleRuleMap = MakeUnique<ServoStyleRuleMap>();
+ }
+
+ mStyleRuleMap->EnsureTable(*this);
+ return mStyleRuleMap.get();
}
void
nsXBLPrototypeResources::AppendStyleSheet(StyleSheet* aSheet)
{
mStyleSheetList.AppendElement(aSheet);
}
@@ -215,32 +225,14 @@ nsXBLPrototypeResources::RemoveStyleShee
}
void
nsXBLPrototypeResources::InsertStyleSheetAt(size_t aIndex, StyleSheet* aSheet)
{
mStyleSheetList.InsertElementAt(aIndex, aSheet);
}
-StyleSheet*
-nsXBLPrototypeResources::StyleSheetAt(size_t aIndex) const
-{
- return mStyleSheetList[aIndex];
-}
-
-size_t
-nsXBLPrototypeResources::SheetCount() const
-{
- return mStyleSheetList.Length();
-}
-
-bool
-nsXBLPrototypeResources::HasStyleSheets() const
-{
- return !mStyleSheetList.IsEmpty();
-}
-
void
nsXBLPrototypeResources::AppendStyleSheetsTo(
nsTArray<StyleSheet*>& aResult) const
{
aResult.AppendElements(mStyleSheetList);
}
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -3,27 +3,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsXBLPrototypeResources_h__
#define nsXBLPrototypeResources_h__
#include "mozilla/StyleSheet.h"
+#include "mozilla/ServoStyleRuleMap.h"
#include "nsICSSLoaderObserver.h"
class nsCSSRuleProcessor;
class nsAtom;
class nsIContent;
class nsXBLPrototypeBinding;
class nsXBLResourceLoader;
+struct RawServoAuthorStyles;
namespace mozilla {
class CSSStyleSheet;
class ServoStyleSet;
+class ServoStyleRuleMap;
} // namespace mozilla
// *********************************************************************/
// The XBLPrototypeResources class
class nsXBLPrototypeResources
{
public:
@@ -40,51 +43,71 @@ public:
void Traverse(nsCycleCollectionTraversalCallback &cb);
void Unlink();
void ClearLoader();
void AppendStyleSheet(mozilla::StyleSheet* aSheet);
void RemoveStyleSheet(mozilla::StyleSheet* aSheet);
void InsertStyleSheetAt(size_t aIndex, mozilla::StyleSheet* aSheet);
- mozilla::StyleSheet* StyleSheetAt(size_t aIndex) const;
- size_t SheetCount() const;
- bool HasStyleSheets() const;
+
+ mozilla::StyleSheet* StyleSheetAt(size_t aIndex) const
+ {
+ return mStyleSheetList[aIndex];
+ }
+
+ size_t SheetCount() const
+ {
+ return mStyleSheetList.Length();
+ }
+
+ bool HasStyleSheets() const
+ {
+ return !mStyleSheetList.IsEmpty();
+ }
+
void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheet*>& aResult) const;
#ifdef MOZ_OLD_STYLE
/**
* Recreates mRuleProcessor to represent the current list of style sheets
* stored in mStyleSheetList. (Named GatherRuleProcessor to parallel
* nsStyleSet::GatherRuleProcessors.)
*/
void GatherRuleProcessor();
nsCSSRuleProcessor* GetRuleProcessor() const { return mRuleProcessor; }
#endif
+ const RawServoAuthorStyles* GetServoStyles() const
+ {
+ return mServoStyles.get();
+ }
+
+ mozilla::ServoStyleRuleMap* GetServoStyleRuleMap();
+
// Updates the ServoStyleSet object that holds the result of cascading the
// sheets in mStyleSheetList. Equivalent to GatherRuleProcessor(), but for
// the Servo style backend.
- void ComputeServoStyleSet(nsPresContext* aPresContext);
-
- mozilla::ServoStyleSet* GetServoStyleSet() const { return mServoStyleSet.get(); }
+ void ComputeServoStyles(const mozilla::ServoStyleSet& aMasterStyleSet);
private:
// A loader object. Exists only long enough to load resources, and then it dies.
RefPtr<nsXBLResourceLoader> mLoader;
// A list of loaded stylesheets for this binding.
+ //
+ // FIXME(emilio): Remove when the old style system is gone, defer to
+ // mServoStyles.
nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheetList;
#ifdef MOZ_OLD_STYLE
// The list of stylesheets converted to a rule processor.
RefPtr<nsCSSRuleProcessor> mRuleProcessor;
#endif
// The result of cascading the XBL style sheets like mRuleProcessor, but
// for the Servo style backend.
- // XXX: We might want to design a better representation for the result of
- // cascading the XBL style sheets, like a collection of SelectorMaps.
- mozilla::UniquePtr<mozilla::ServoStyleSet> mServoStyleSet;
+ mozilla::UniquePtr<RawServoAuthorStyles> mServoStyles;
+ mozilla::UniquePtr<mozilla::ServoStyleRuleMap> mStyleRuleMap;
};
#endif
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -193,18 +193,18 @@ nsXBLResourceLoader::StyleSheetLoaded(St
// All stylesheets are loaded.
if (aSheet->IsGecko()) {
#ifdef MOZ_OLD_STYLE
mResources->GatherRuleProcessor();
#else
MOZ_CRASH("old style system disabled");
#endif
} else {
- mResources->ComputeServoStyleSet(
- mBoundDocument->GetShell()->GetPresContext());
+ mResources->ComputeServoStyles(
+ *mBoundDocument->GetShell()->StyleSet()->AsServo());
}
// XXX Check for mPendingScripts when scripts also come online.
if (!mInLoadResourcesFunc)
NotifyBoundElements();
}
return NS_OK;
}
--- a/layout/inspector/InspectorUtils.cpp
+++ b/layout/inspector/InspectorUtils.cpp
@@ -225,28 +225,28 @@ InspectorUtils::GetCSSStyleRules(GlobalO
ServoStyleContext* servo = styleContext->AsServo();
nsTArray<const RawServoStyleRule*> rawRuleList;
Servo_ComputedValues_GetStyleRuleList(servo, &rawRuleList);
AutoTArray<ServoStyleRuleMap*, 1> maps;
{
ServoStyleSet* styleSet = shell->StyleSet()->AsServo();
ServoStyleRuleMap* map = styleSet->StyleRuleMap();
- map->EnsureTable();
maps.AppendElement(map);
}
// Collect style rule maps for bindings.
for (nsIContent* bindingContent = &aElement; bindingContent;
bindingContent = bindingContent->GetBindingParent()) {
for (nsXBLBinding* binding = bindingContent->GetXBLBinding();
binding; binding = binding->GetBaseBinding()) {
- if (ServoStyleSet* styleSet = binding->GetServoStyleSet()) {
- ServoStyleRuleMap* map = styleSet->StyleRuleMap();
- map->EnsureTable();
+ // TODO(emilio): We're going to need to figure out something for Shadow
+ // DOM and inspector, since those rules can definitely mutate and
+ // such...
+ if (auto* map = binding->PrototypeBinding()->GetServoStyleRuleMap()) {
maps.AppendElement(map);
}
}
// Note that we intentionally don't cut off here, unlike when we
// do styling, because even if style rules from parent binding
// do not apply to the element directly in those cases, their
// rules may still show up in the list we get above due to the
// inheritance in cascading.
--- a/layout/inspector/ServoStyleRuleMap.cpp
+++ b/layout/inspector/ServoStyleRuleMap.cpp
@@ -13,40 +13,42 @@
#include "mozilla/ServoStyleSet.h"
#include "mozilla/ServoImportRule.h"
#include "mozilla/StyleSheetInlines.h"
#include "nsDocument.h"
#include "nsStyleSheetService.h"
namespace mozilla {
-ServoStyleRuleMap::ServoStyleRuleMap(ServoStyleSet* aStyleSet)
- : mStyleSet(aStyleSet)
-{
-}
-
-ServoStyleRuleMap::~ServoStyleRuleMap()
-{
-}
-
void
-ServoStyleRuleMap::EnsureTable()
+ServoStyleRuleMap::EnsureTable(ServoStyleSet& aStyleSet)
{
if (!IsEmpty()) {
return;
}
- mStyleSet->EnumerateStyleSheetArrays(
+ aStyleSet.EnumerateStyleSheetArrays(
[this](const nsTArray<RefPtr<ServoStyleSheet>>& aArray) {
for (auto& sheet : aArray) {
FillTableFromStyleSheet(*sheet);
}
});
}
void
+ServoStyleRuleMap::EnsureTable(nsXBLPrototypeResources& aXBLResources)
+{
+ if (!IsEmpty() || !aXBLResources.GetServoStyles()) {
+ return;
+ }
+ for (auto index : IntegerRange(aXBLResources.SheetCount())) {
+ FillTableFromStyleSheet(*aXBLResources.StyleSheetAt(index)->AsServo());
+ }
+}
+
+void
ServoStyleRuleMap::SheetAdded(ServoStyleSheet& aStyleSheet)
{
if (!IsEmpty()) {
FillTableFromStyleSheet(aStyleSheet);
}
}
void
--- a/layout/inspector/ServoStyleRuleMap.h
+++ b/layout/inspector/ServoStyleRuleMap.h
@@ -7,55 +7,57 @@
#ifndef mozilla_ServoStyleRuleMap_h
#define mozilla_ServoStyleRuleMap_h
#include "mozilla/ServoStyleRule.h"
#include "nsDataHashtable.h"
struct RawServoStyleRule;
+class nsXBLPrototypeResources;
namespace mozilla {
class ServoCSSRuleList;
class ServoStyleSet;
namespace css {
class Rule;
} // namespace css
class ServoStyleRuleMap
{
public:
- explicit ServoStyleRuleMap(ServoStyleSet* aStyleSet);
+ ServoStyleRuleMap() = default;
- void EnsureTable();
- ServoStyleRule* Lookup(const RawServoStyleRule* aRawRule) const {
+ void EnsureTable(ServoStyleSet&);
+ void EnsureTable(nsXBLPrototypeResources&);
+ ServoStyleRule* Lookup(const RawServoStyleRule* aRawRule) const
+ {
return mTable.Get(aRawRule);
}
- void SheetAdded(ServoStyleSheet& aStyleSheet);
- void SheetRemoved(ServoStyleSheet& aStyleSheet);
+ void SheetAdded(ServoStyleSheet&);
+ void SheetRemoved(ServoStyleSheet&);
void RuleAdded(ServoStyleSheet& aStyleSheet, css::Rule&);
- void RuleRemoved(ServoStyleSheet& aStyleSheet, css::Rule& aStyleRule);
+ void RuleRemoved(ServoStyleSheet& aStyleSheet, css::Rule&);
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
- ~ServoStyleRuleMap();
+ ~ServoStyleRuleMap() = default;
private:
// Since we would never have a document which contains no style rule,
// we use IsEmpty as an indication whether we need to walk through
// all stylesheets to fill the table.
bool IsEmpty() const { return mTable.Count() == 0; }
void FillTableFromRule(css::Rule& aRule);
void FillTableFromRuleList(ServoCSSRuleList& aRuleList);
void FillTableFromStyleSheet(ServoStyleSheet& aSheet);
typedef nsDataHashtable<nsPtrHashKey<const RawServoStyleRule>,
WeakPtr<ServoStyleRule>> Hashtable;
Hashtable mTable;
- ServoStyleSet* mStyleSet;
};
} // namespace mozilla
#endif // mozilla_ServoStyleRuleMap_h
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -38,17 +38,18 @@ SERVO_BINDING_FUNC(Servo_Element_IsDispl
bool,
RawGeckoElementBorrowed element)
SERVO_BINDING_FUNC(Servo_Element_IsPrimaryStyleReusedViaRuleNode,
bool,
RawGeckoElementBorrowed element)
SERVO_BINDING_FUNC(Servo_InvalidateStyleForDocStateChanges,
void,
RawGeckoElementBorrowed root,
- const nsTArray<RawServoStyleSetBorrowed>* sets,
+ RawServoStyleSetBorrowed doc_styles,
+ const nsTArray<RawServoAuthorStylesBorrowed>* non_document_styles,
uint64_t aStatesChanged)
// Styleset and Stylesheet management
SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes,
RawServoStyleSheetContentsStrong,
mozilla::css::Loader* loader,
mozilla::ServoStyleSheet* gecko_stylesheet,
const uint8_t* data,
@@ -78,23 +79,24 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_GetS
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
// work as return values with the Linux 32-bit ABI at the moment because
// they wrap the value in a struct.
SERVO_BINDING_FUNC(Servo_StyleSheet_GetOrigin, uint8_t,
RawServoStyleSheetContentsBorrowed sheet)
SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSet*, RawGeckoPresContextOwned pres_context)
SERVO_BINDING_FUNC(Servo_StyleSet_RebuildCachedData, void,
RawServoStyleSetBorrowed set)
+
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
// work as return values with the Linux 32-bit ABI at the moment because
// they wrap the value in a struct.
SERVO_BINDING_FUNC(Servo_StyleSet_MediumFeaturesChanged,
MediumFeaturesChangedResult,
RawServoStyleSetBorrowed document_set,
- const nsTArray<mozilla::ServoStyleSet*>* non_document_sets,
+ nsTArray<RawServoAuthorStylesBorrowed>* non_document_sets,
bool may_affect_default_style)
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
// work as return values with the Linux 32-bit ABI at the moment because
// they wrap the value in a struct.
SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
SERVO_BINDING_FUNC(Servo_StyleSet_CompatModeChanged, void,
RawServoStyleSetBorrowed raw_data)
SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
@@ -168,16 +170,30 @@ SERVO_BINDING_FUNC(Servo_StyleSet_AddSiz
mozilla::MallocSizeOf malloc_size_of,
mozilla::MallocSizeOf malloc_enclosing_size_of,
mozilla::ServoStyleSetSizes* sizes,
RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_UACache_AddSizeOf, void,
mozilla::MallocSizeOf malloc_size_of,
mozilla::MallocSizeOf malloc_enclosing_size_of,
mozilla::ServoStyleSetSizes* sizes)
+
+// AuthorStyles
+SERVO_BINDING_FUNC(Servo_AuthorStyles_Create, RawServoAuthorStyles*)
+// TODO(emilio): This will need to take an optional master style set to
+// implement invalidation for Shadow DOM.
+SERVO_BINDING_FUNC(Servo_AuthorStyles_AppendStyleSheet, void,
+ RawServoAuthorStylesBorrowedMut self,
+ const mozilla::ServoStyleSheet* gecko_sheet)
+// TODO(emilio): This will need to take an element to implement invalidation for
+// Shadow DOM.
+SERVO_BINDING_FUNC(Servo_AuthorStyles_Flush, void,
+ RawServoAuthorStylesBorrowedMut self,
+ RawServoStyleSetBorrowed document_styles)
+
SERVO_BINDING_FUNC(Servo_StyleContext_AddRef, void, ServoStyleContextBorrowed ctx);
SERVO_BINDING_FUNC(Servo_StyleContext_Release, void, ServoStyleContextBorrowed ctx);
SERVO_BINDING_FUNC(Servo_StyleSet_MightHaveAttributeDependency, bool,
RawServoStyleSetBorrowed set,
RawGeckoElementBorrowed element,
nsAtom* local_name)
SERVO_BINDING_FUNC(Servo_StyleSet_HasStateDependency, bool,
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -10,16 +10,17 @@
#include "mozilla/RefPtr.h"
#include "mozilla/ServoTypes.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/gfx/Types.h"
#include "nsCSSPropertyID.h"
#include "nsStyleAutoArray.h"
#include "nsTArray.h"
+struct RawServoAuthorStyles;
struct RawServoStyleSet;
struct RawServoSelectorList;
struct RawServoSourceSizeList;
struct RawServoAnimationValueMap;
struct RustString;
#define SERVO_ARC_TYPE(name_, type_) struct type_;
#include "mozilla/ServoArcTypeList.h"
@@ -130,17 +131,18 @@ struct MOZ_MUST_USE_TYPE ServoStyleConte
#define DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_) \
typedef type_* type_##OwnedOrNull; \
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_) \
DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR(type_)
// This is a reference to a reference of RawServoDeclarationBlock, which
// corresponds to Option<&Arc<RawServoDeclarationBlock>> in Servo side.
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoDeclarationBlockStrong)
-
+DECL_OWNED_REF_TYPE_FOR(RawServoAuthorStyles)
+DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoAuthorStyles)
DECL_OWNED_REF_TYPE_FOR(RawServoStyleSet)
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoStyleSet)
DECL_NULLABLE_OWNED_REF_TYPE_FOR(StyleChildrenIterator)
DECL_OWNED_REF_TYPE_FOR(StyleChildrenIterator)
DECL_OWNED_REF_TYPE_FOR(ServoElementSnapshot)
DECL_OWNED_REF_TYPE_FOR(RawServoAnimationValueMap)
// We don't use BorrowedMut because the nodes may alias
@@ -223,14 +225,15 @@ DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawS
void operator()(type_* aPtr) const \
{ \
Servo_##name_##_Drop(aPtr); \
} \
}; \
}
DEFINE_BOXED_TYPE(StyleSet, RawServoStyleSet);
+DEFINE_BOXED_TYPE(AuthorStyles, RawServoAuthorStyles);
DEFINE_BOXED_TYPE(SelectorList, RawServoSelectorList);
DEFINE_BOXED_TYPE(SourceSizeList, RawServoSourceSizeList);
#undef DEFINE_BOXED_TYPE
#endif // mozilla_ServoBindingTypes_h
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -2429,21 +2429,20 @@ Gecko_GetBindingParent(RawGeckoElementBo
}
RawGeckoXBLBindingBorrowedOrNull
Gecko_GetXBLBinding(RawGeckoElementBorrowed aElement)
{
return aElement->GetXBLBinding();
}
-RawServoStyleSetBorrowedOrNull
-Gecko_XBLBinding_GetRawServoStyleSet(RawGeckoXBLBindingBorrowed aXBLBinding)
+RawServoAuthorStylesBorrowedOrNull
+Gecko_XBLBinding_GetRawServoStyles(RawGeckoXBLBindingBorrowed aXBLBinding)
{
- const ServoStyleSet* set = aXBLBinding->GetServoStyleSet();
- return set ? set->RawSet() : nullptr;
+ return aXBLBinding->GetServoStyles();
}
bool
Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding)
{
return aXBLBinding->InheritsStyle();
}
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -602,17 +602,17 @@ void Gecko_nsStyleFont_PrefillDefaultFor
uint8_t generic_id);
void Gecko_nsStyleFont_FixupMinFontSize(nsStyleFont* font,
RawGeckoPresContextBorrowed pres_context);
FontSizePrefs Gecko_GetBaseSize(nsAtom* lang);
// XBL related functions.
RawGeckoElementBorrowedOrNull Gecko_GetBindingParent(RawGeckoElementBorrowed aElement);
RawGeckoXBLBindingBorrowedOrNull Gecko_GetXBLBinding(RawGeckoElementBorrowed aElement);
-RawServoStyleSetBorrowedOrNull Gecko_XBLBinding_GetRawServoStyleSet(RawGeckoXBLBindingBorrowed aXBLBinding);
+RawServoAuthorStylesBorrowedOrNull Gecko_XBLBinding_GetRawServoStyles(RawGeckoXBLBindingBorrowed aXBLBinding);
bool Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding);
struct GeckoFontMetrics
{
nscoord mChSize;
nscoord mXSize;
};
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -465,17 +465,16 @@ structs-types = [
"mozilla::css::ErrorReporter",
"mozilla::css::ImageValue",
"mozilla::css::URLValue",
"mozilla::css::URLValueData",
"mozilla::dom::CallerType",
"mozilla::AnonymousCounterStyle",
"mozilla::AtomArray",
"mozilla::MallocSizeOf",
- "mozilla::ServoStyleSet",
"mozilla::OriginFlags",
"mozilla::UniquePtr",
"ServoRawOffsetArc",
"nsIContent",
"nsIDocument",
"nsIDocument_DocumentTheme",
"nsSimpleContentList",
"MediumFeaturesChangedResult",
@@ -614,16 +613,17 @@ structs-types = [
"FontFamilyName",
"mozilla::SharedFontList",
]
array-types = [
{ cpp-type = "uintptr_t", rust-type = "usize" },
]
servo-owned-types = [
{ name = "RawServoStyleSet", opaque = true },
+ { name = "RawServoAuthorStyles", opaque = true },
{ name = "RawServoSelectorList", opaque = false },
{ name = "RawServoSourceSizeList", opaque = false },
{ name = "ServoElementSnapshot", opaque = false },
{ name = "RawServoAnimationValueMap", opaque = true },
]
servo-immutable-borrow-types = [
"RawGeckoNode",
"RawGeckoElement",
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -227,30 +227,29 @@ ServoStyleSet::InvalidateStyleForDocumen
if (!root) {
return;
}
// TODO(emilio): It may be nicer to just invalidate stuff in a given subtree
// for XBL sheets / shadow DOM. Consider just enumerating bound content
// instead and run invalidation individually, passing mRawSet for the UA /
// User sheets.
- AutoTArray<RawServoStyleSetBorrowed, 20> styleSets;
- styleSets.AppendElement(mRawSet.get());
+ AutoTArray<RawServoAuthorStylesBorrowed, 20> xblStyles;
// FIXME(emilio): When bug 1425759 is fixed we need to enumerate ShadowRoots
// too.
mDocument->BindingManager()->EnumerateBoundContentBindings(
[&](nsXBLBinding* aBinding) {
- if (ServoStyleSet* set = aBinding->PrototypeBinding()->GetServoStyleSet()) {
- styleSets.AppendElement(set->RawSet());
+ if (auto* authorStyles = aBinding->PrototypeBinding()->GetServoStyles()) {
+ xblStyles.AppendElement(authorStyles);
}
return true;
});
Servo_InvalidateStyleForDocStateChanges(
- root, &styleSets, aStatesChanged.ServoValue());
+ root, mRawSet.get(), &xblStyles, aStatesChanged.ServoValue());
}
static const MediaFeatureChangeReason kMediaFeaturesAffectingDefaultStyle =
// Zoom changes change the meaning of em units.
MediaFeatureChangeReason::ZoomChange |
// Changes the meaning of em units, depending on which one is the actual
// min-font-size.
MediaFeatureChangeReason::MinFontSizeChange |
@@ -258,35 +257,35 @@ static const MediaFeatureChangeReason kM
// structs (Border, Outline, Column) store for clamping. We should arguably
// not do that, maybe doing it on layout directly, to try to avoid relying on
// the pres context (bug 1418159).
MediaFeatureChangeReason::ResolutionChange;
nsRestyleHint
ServoStyleSet::MediumFeaturesChanged(MediaFeatureChangeReason aReason)
{
- AutoTArray<ServoStyleSet*, 20> nonDocumentStyleSets;
+ AutoTArray<RawServoAuthorStylesBorrowed, 20> nonDocumentStyles;
// FIXME(emilio): When bug 1425759 is fixed we need to enumerate ShadowRoots
// too.
//
// FIXME(emilio): This is broken for XBL. See bug 1406875.
mDocument->BindingManager()->EnumerateBoundContentBindings(
[&](nsXBLBinding* aBinding) {
- if (ServoStyleSet* set = aBinding->PrototypeBinding()->GetServoStyleSet()) {
- nonDocumentStyleSets.AppendElement(set);
+ if (auto* authorStyles = aBinding->PrototypeBinding()->GetServoStyles()) {
+ nonDocumentStyles.AppendElement(authorStyles);
}
return true;
});
bool mayAffectDefaultStyle =
bool(aReason & kMediaFeaturesAffectingDefaultStyle);
const MediumFeaturesChangedResult result =
Servo_StyleSet_MediumFeaturesChanged(
- mRawSet.get(), &nonDocumentStyleSets, mayAffectDefaultStyle);
+ mRawSet.get(), &nonDocumentStyles, mayAffectDefaultStyle);
const bool rulesChanged =
result.mAffectsDocumentRules || result.mAffectsNonDocumentRules;
if (result.mAffectsDocumentRules) {
SetStylistStyleSheetsDirty();
}
@@ -1456,20 +1455,23 @@ ServoStyleSet::UpdateStylist()
snapshots = &pc->RestyleManager()->AsServo()->Snapshots();
}
Servo_StyleSet_FlushStyleSheets(mRawSet.get(), root, snapshots);
}
if (MOZ_UNLIKELY(mStylistState & StylistState::XBLStyleSheetsDirty)) {
MOZ_ASSERT(IsMaster(), "Only master styleset can mark XBL stylesets dirty!");
MOZ_ASSERT(GetPresContext(), "How did they get dirty?");
- // NOTE(emilio): This right now rebuilds the stylist in the prototype
- // binding. That is fine, and if we wanted to be more incremental, which we
- // probably should, we need to move away from using a StyleSet for XBL.
- mDocument->BindingManager()->UpdateBoundContentBindingsForServo(GetPresContext());
+ mDocument->BindingManager()->EnumerateBoundContentBindings(
+ [&](nsXBLBinding* aBinding) {
+ if (auto* authorStyles = aBinding->PrototypeBinding()->GetServoStyles()) {
+ Servo_AuthorStyles_Flush(authorStyles, mRawSet.get());
+ }
+ return true;
+ });
}
mStylistState = StylistState::NotDirty;
}
void
ServoStyleSet::MaybeGCRuleTree()
{
@@ -1563,18 +1565,19 @@ ServoStyleSet::RunPostTraversalTasks()
task.Run();
}
}
ServoStyleRuleMap*
ServoStyleSet::StyleRuleMap()
{
if (!mStyleRuleMap) {
- mStyleRuleMap = MakeUnique<ServoStyleRuleMap>(this);
+ mStyleRuleMap = MakeUnique<ServoStyleRuleMap>();
}
+ mStyleRuleMap->EnsureTable(*this);
return mStyleRuleMap.get();
}
bool
ServoStyleSet::MightHaveAttributeDependency(const Element& aElement,
nsAtom* aAttribute) const
{
return Servo_StyleSet_MightHaveAttributeDependency(
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -113,18 +113,18 @@ public:
dom::CSSImportRule* aCloneOwnerRule,
nsIDocument* aCloneDocument,
nsINode* aCloneOwningNode) const final override;
// nsICSSLoaderObserver interface
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
nsresult aStatus) final override;
- // Internal GetCssRules method which do not have security check and
- // completelness check.
+ // Internal GetCssRules methods which do not have security check and
+ // completeness check.
ServoCSSRuleList* GetCssRulesInternal();
// Returns the stylesheet's Servo origin as an OriginFlags value.
OriginFlags GetOrigin();
protected:
virtual ~ServoStyleSheet();
new file mode 100644
--- /dev/null
+++ b/servo/components/style/author_styles.rs
@@ -0,0 +1,87 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! A set of author stylesheets and their computed representation, such as the
+//! ones used for ShadowRoot and XBL.
+
+use context::QuirksMode;
+use dom::TElement;
+#[cfg(feature = "gecko")]
+use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
+use invalidation::media_queries::ToMediaListKey;
+use media_queries::Device;
+use shared_lock::SharedRwLockReadGuard;
+use stylesheet_set::AuthorStylesheetSet;
+use stylesheets::StylesheetInDocument;
+use stylist::CascadeData;
+
+
+/// A set of author stylesheets and their computed representation, such as the
+/// ones used for ShadowRoot and XBL.
+pub struct AuthorStyles<S>
+where
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ /// The sheet collection, which holds the sheet pointers, the invalidations,
+ /// and all that stuff.
+ 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>
+where
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ /// Create an empty AuthorStyles.
+ #[inline]
+ pub fn new() -> Self {
+ Self {
+ stylesheets: AuthorStylesheetSet::new(),
+ data: CascadeData::new(),
+ quirks_mode: QuirksMode::NoQuirks,
+ }
+ }
+
+ /// Flush the pending sheet changes, updating `data` as appropriate.
+ ///
+ /// TODO(emilio): Need a host element and a snapshot map to do invalidation
+ /// properly.
+ #[inline]
+ pub fn flush<E>(
+ &mut self,
+ device: &Device,
+ quirks_mode: QuirksMode,
+ guard: &SharedRwLockReadGuard,
+ )
+ where
+ E: TElement,
+ S: ToMediaListKey,
+ {
+ let flusher = self.stylesheets.flush::<E>(
+ /* host = */ None,
+ /* snapshot_map = */ None,
+ );
+
+ // Ignore OOM.
+ let _ = self.data.rebuild(
+ device,
+ quirks_mode,
+ flusher.sheets,
+ guard,
+ );
+ }
+}
+
+#[cfg(feature = "gecko")]
+unsafe impl HasFFI for AuthorStyles<::gecko::data::GeckoStyleSheet> {
+ type FFIType = ::gecko_bindings::bindings::RawServoAuthorStyles;
+}
+#[cfg(feature = "gecko")]
+unsafe impl HasSimpleFFI for AuthorStyles<::gecko::data::GeckoStyleSheet> {}
+#[cfg(feature = "gecko")]
+unsafe impl HasBoxFFI for AuthorStyles<::gecko::data::GeckoStyleSheet> {}
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -749,29 +749,29 @@ pub trait TElement
}
/// Implements Gecko's `nsBindingManager::WalkRules`.
///
/// Returns whether to cut off the inheritance.
fn each_xbl_cascade_data<'a, F>(&self, _: F) -> bool
where
Self: 'a,
- F: FnMut(AtomicRef<'a, CascadeData>, QuirksMode),
+ 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).
///
/// 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(AtomicRef<'a, CascadeData>, QuirksMode),
+ F: FnMut(&'a CascadeData, QuirksMode),
{
let cut_off_inheritance = self.each_xbl_cascade_data(&mut f);
let mut current = self.assigned_slot();
while let Some(slot) = current {
slot.each_xbl_cascade_data(&mut f);
current = slot.assigned_slot();
}
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -12,23 +12,24 @@
//!
//! This theoretically should live in its own crate, but now it lives in the
//! style system it's kind of pointless in the Stylo case, and only Servo forces
//! the separation between the style system implementation and everything else.
use CaseSensitivityExt;
use app_units::Au;
use applicable_declarations::ApplicableDeclarationBlock;
-use atomic_refcell::{AtomicRefCell, AtomicRef, AtomicRefMut};
+use atomic_refcell::{AtomicRefCell, AtomicRefMut};
+use author_styles::AuthorStyles;
use context::{QuirksMode, SharedStyleContext, PostAnimationTasks, UpdateAnimationsTasks};
use data::ElementData;
use dom::{LayoutIterator, NodeInfo, OpaqueNode, TElement, TDocument, TNode};
use element_state::{ElementState, DocumentState};
use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
-use gecko::data::PerDocumentStyleData;
+use gecko::data::GeckoStyleSheet;
use gecko::global_style_data::GLOBAL_STYLE_DATA;
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
use gecko::snapshot_helpers;
use gecko_bindings::bindings;
use gecko_bindings::bindings::{Gecko_ConstructStyleChildrenIterator, Gecko_DestroyStyleChildrenIterator};
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme};
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetNextStyleChild};
use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement};
@@ -426,30 +427,29 @@ impl<'lb> GeckoXBLBinding<'lb> {
return Some(binding);
}
binding = binding.base_binding()?;
}
}
fn each_xbl_cascade_data<F>(&self, f: &mut F)
where
- F: FnMut(AtomicRef<'lb, CascadeData>, QuirksMode),
+ F: FnMut(&'lb CascadeData, QuirksMode),
{
if let Some(base) = self.base_binding() {
base.each_xbl_cascade_data(f);
}
- let raw_data = unsafe {
- bindings::Gecko_XBLBinding_GetRawServoStyleSet(self.0)
+ let data = unsafe {
+ bindings::Gecko_XBLBinding_GetRawServoStyles(self.0)
};
- if let Some(raw_data) = raw_data {
- let data = PerDocumentStyleData::from_ffi(&*raw_data).borrow();
- let quirks_mode = data.stylist.quirks_mode();
- f(AtomicRef::map(data, |d| d.stylist.author_cascade_data()), quirks_mode);
+ 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.
#[derive(Clone, Copy)]
pub struct GeckoElement<'le>(pub &'le RawGeckoElement);
@@ -1373,17 +1373,17 @@ impl<'le> TElement for GeckoElement<'le>
fn has_css_transitions(&self) -> bool {
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(AtomicRef<'a, CascadeData>, QuirksMode),
+ 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());
--- a/servo/components/style/gecko_bindings/sugar/ns_t_array.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_t_array.rs
@@ -31,16 +31,17 @@ impl<T> DerefMut for nsTArray<T> {
}
impl<T> nsTArray<T> {
#[inline]
fn header<'a>(&'a self) -> &'a nsTArrayHeader {
debug_assert!(!self.mBuffer.is_null());
unsafe { mem::transmute(self.mBuffer) }
}
+
// unsafe, since header may be in shared static or something
unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
debug_assert!(!self.mBuffer.is_null());
mem::transmute(self.mBuffer)
}
#[inline]
--- a/servo/components/style/invalidation/element/state_and_attributes.rs
+++ b/servo/components/style/invalidation/element/state_and_attributes.rs
@@ -1,17 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! An invalidation processor for style changes due to state and attribute
//! changes.
use Atom;
-use atomic_refcell::AtomicRef;
use context::{QuirksMode, SharedStyleContext};
use data::ElementData;
use dom::TElement;
use element_state::ElementState;
use invalidation::element::element_wrapper::{ElementSnapshot, ElementWrapper};
use invalidation::element::invalidation_map::*;
use invalidation::element::invalidator::{DescendantInvalidationLists, InvalidationVector};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
@@ -52,28 +51,28 @@ where
sibling_invalidations: &'a mut InvalidationVector<'selectors>,
invalidates_self: bool,
}
/// An invalidation processor for style changes due to state and attribute
/// changes.
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E: TElement> {
shared_context: &'a SharedStyleContext<'b>,
- shadow_rule_datas: &'a [(AtomicRef<'b, CascadeData>, QuirksMode)],
+ shadow_rule_datas: &'a [(&'b CascadeData, QuirksMode)],
cut_off_inheritance: bool,
element: E,
data: &'a mut ElementData,
matching_context: MatchingContext<'a, E::Impl>,
}
impl<'a, 'b: 'a, E: TElement> StateAndAttrInvalidationProcessor<'a, 'b, E> {
/// Creates a new StateAndAttrInvalidationProcessor.
pub fn new(
shared_context: &'a SharedStyleContext<'b>,
- shadow_rule_datas: &'a [(AtomicRef<'b, CascadeData>, QuirksMode)],
+ shadow_rule_datas: &'a [(&'b CascadeData, QuirksMode)],
cut_off_inheritance: bool,
element: E,
data: &'a mut ElementData,
nth_index_cache: &'a mut NthIndexCache,
) -> Self {
let matching_context = MatchingContext::new_for_visited(
MatchingMode::Normal,
None,
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -82,16 +82,17 @@ extern crate void;
#[macro_use]
mod macros;
#[cfg(feature = "servo")] pub mod animation;
pub mod applicable_declarations;
#[allow(missing_docs)] // TODO.
#[cfg(feature = "servo")] pub mod attr;
+pub mod author_styles;
pub mod bezier;
pub mod bloom;
pub mod context;
pub mod counter_style;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod dom_apis;
--- a/servo/components/style/stylesheet_set.rs
+++ b/servo/components/style/stylesheet_set.rs
@@ -578,26 +578,51 @@ where
/// Whether any sheet invalidation matched.
pub had_invalidations: bool,
}
impl<S> AuthorStylesheetSet<S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
+ /// Create a new empty AuthorStylesheetSet.
+ #[inline]
+ pub fn new() -> Self {
+ Self {
+ collection: Default::default(),
+ invalidations: StylesheetInvalidationSet::new(),
+ }
+ }
+
+ /// Whether anything has changed since the last time this was flushed.
+ pub fn dirty(&self) -> bool {
+ self.collection.dirty
+ }
+
fn collection_for(
&mut self,
_sheet: &S,
_guard: &SharedRwLockReadGuard,
) -> &mut SheetCollection<S> {
&mut self.collection
}
sheet_set_methods!("AuthorStylesheetSet");
+ /// Iterate over the list of stylesheets.
+ pub fn iter(&self) -> StylesheetCollectionIterator<S> {
+ self.collection.iter()
+ }
+
+ /// Mark the sheet set dirty, as appropriate.
+ pub fn force_dirty(&mut self) {
+ self.invalidations.invalidate_fully();
+ self.collection.set_data_validity_at_least(DataValidity::FullyInvalid);
+ }
+
/// Flush the stylesheets for this author set.
///
/// `host` is the root of the affected subtree, like the shadow host, for
/// example.
pub fn flush<E>(
&mut self,
host: Option<E>,
snapshots: Option<&SnapshotMap>,
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -1978,17 +1978,18 @@ pub struct CascadeData {
/// The total number of selectors.
num_selectors: usize,
/// The total number of declarations.
num_declarations: usize,
}
impl CascadeData {
- fn new() -> Self {
+ /// Creates an empty `CascadeData`.
+ pub fn new() -> Self {
Self {
normal_rules: ElementAndPseudoRules::default(),
slotted_rules: None,
invalidation_map: InvalidationMap::new(),
attribute_dependencies: NonCountingBloomFilter::new(),
style_attribute_dependency: false,
state_dependencies: ElementState::empty(),
document_state_dependencies: DocumentState::empty(),
@@ -2000,17 +2001,17 @@ impl CascadeData {
rules_source_order: 0,
num_selectors: 0,
num_declarations: 0,
}
}
/// Rebuild the cascade data from a given SheetCollection, incrementally if
/// possible.
- fn rebuild<'a, S>(
+ pub fn rebuild<'a, S>(
&mut self,
device: &Device,
quirks_mode: QuirksMode,
collection: SheetCollectionFlusher<S>,
guard: &SharedRwLockReadGuard,
) -> Result<(), FailedAllocationError>
where
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
@@ -2276,17 +2277,17 @@ impl CascadeData {
}
}
Ok(())
}
/// Returns whether all the media-feature affected values matched before and
/// match now in the given stylesheet.
- fn media_feature_affected_matches<S>(
+ pub fn media_feature_affected_matches<S>(
&self,
stylesheet: &S,
guard: &SharedRwLockReadGuard,
device: &Device,
quirks_mode: QuirksMode,
) -> bool
where
S: StylesheetInDocument + ToMediaListKey + 'static,
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -12,16 +12,17 @@ use servo_arc::{Arc, ArcBorrow, RawOffse
use smallvec::SmallVec;
use std::cell::RefCell;
use std::env;
use std::fmt::Write;
use std::iter;
use std::mem;
use std::ptr;
use style::applicable_declarations::ApplicableDeclarationBlock;
+use style::author_styles::AuthorStyles;
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
use style::context::ThreadLocalStyleContext;
use style::counter_style;
use style::data::{ElementStyles, self};
use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
use style::driver;
use style::element_state::{DocumentState, ElementState};
use style::error_reporting::{ContextualParseError, NullReporter, ParseErrorReporter};
@@ -46,16 +47,17 @@ use style::gecko_bindings::bindings::{Ra
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoSelectorListBorrowed, RawServoSelectorListOwned};
use style::gecko_bindings::bindings::{RawServoSourceSizeListBorrowedOrNull, RawServoSourceSizeListOwned};
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetBorrowedOrNull, RawServoStyleSetOwned};
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsBorrowed, ServoComputedDataBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoStyleContextBorrowed};
use style::gecko_bindings::bindings::{RawServoSupportsRule, RawServoSupportsRuleBorrowed};
+use style::gecko_bindings::bindings::{RawServoAuthorStylesBorrowed, RawServoAuthorStylesBorrowedMut, RawServoAuthorStylesOwned};
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
use style::gecko_bindings::bindings::{nsACString, nsAString, nsCSSPropertyIDSetBorrowedMut};
use style::gecko_bindings::bindings::Gecko_AddPropertyToSet;
use style::gecko_bindings::bindings::Gecko_AppendPropertyValuePair;
use style::gecko_bindings::bindings::Gecko_ConstructFontFeatureValueSet;
use style::gecko_bindings::bindings::Gecko_GetOrCreateFinalKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
@@ -1116,19 +1118,79 @@ pub extern "C" fn Servo_StyleSet_AppendS
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let data = &mut *data;
let guard = global_style_data.shared_lock.read();
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
data.stylist.append_stylesheet(sheet, &guard);
}
#[no_mangle]
+pub extern "C" fn Servo_AuthorStyles_Create() -> *mut AuthorStyles<GeckoStyleSheet> {
+ Box::into_raw(Box::new(AuthorStyles::new()))
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_AuthorStyles_Drop(
+ styles: RawServoAuthorStylesOwned,
+) {
+ let _ = styles.into_box::<AuthorStyles<_>>();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_AuthorStyles_AppendStyleSheet(
+ styles: RawServoAuthorStylesBorrowedMut,
+ sheet: *const ServoStyleSheet,
+) {
+ let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
+
+ let global_style_data = &*GLOBAL_STYLE_DATA;
+ let guard = global_style_data.shared_lock.read();
+ let sheet = GeckoStyleSheet::new(sheet);
+ styles.stylesheets.append_stylesheet(None, sheet, &guard);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_AuthorStyles_Flush(
+ styles: RawServoAuthorStylesBorrowedMut,
+ document_set: RawServoStyleSetBorrowed,
+) {
+ let styles = AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(styles);
+ // Try to avoid the atomic borrow below if possible.
+ if !styles.stylesheets.dirty() {
+ return;
+ }
+
+ let global_style_data = &*GLOBAL_STYLE_DATA;
+ let guard = global_style_data.shared_lock.read();
+
+ // NOTE(emilio): We don't actually need to flush the stylist here and ensure
+ // it's up to date.
+ //
+ // In case it isn't we would trigger a rebuild + restyle as needed too.
+ //
+ // We need to ensure the default computed values are up to date though,
+ // because those can influence the result of media query evaluation.
+ let document_data =
+ PerDocumentStyleData::from_ffi(document_set).borrow();
+
+ let stylist = &document_data.stylist;
+
+ // TODO(emilio): This is going to need an element or something to do proper
+ // invalidation in Shadow roots.
+ styles.flush::<GeckoElement>(
+ stylist.device(),
+ stylist.quirks_mode(),
+ &guard,
+ );
+}
+
+#[no_mangle]
pub unsafe extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
document_set: RawServoStyleSetBorrowed,
- non_document_sets: *const nsTArray<*mut structs::ServoStyleSet>,
+ non_document_styles: *mut nsTArray<RawServoAuthorStylesBorrowedMut>,
may_affect_default_style: bool,
) -> structs::MediumFeaturesChangedResult {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
// NOTE(emilio): We don't actually need to flush the stylist here and ensure
// it's up to date.
//
@@ -1151,37 +1213,30 @@ pub unsafe extern "C" fn Servo_StyleSet_
);
let affects_document_rules = !origins_in_which_rules_changed.is_empty();
if affects_document_rules {
document_data.stylist.force_stylesheet_origins_dirty(origins_in_which_rules_changed);
}
let mut affects_non_document_rules = false;
- for non_document_style_set in &**non_document_sets {
- let non_document_data = &*(**non_document_style_set).mRawSet.mPtr;
- let non_document_data =
- mem::transmute::<&structs::RawServoStyleSet, &bindings::RawServoStyleSet>(non_document_data);
- let mut non_document_data =
- PerDocumentStyleData::from_ffi(non_document_data).borrow_mut();
-
- let origins_changed =
- non_document_data.stylist.media_features_change_changed_style(
- &guards,
+ for author_styles in &mut **non_document_styles {
+ let author_styles =
+ AuthorStyles::<GeckoStyleSheet>::from_ffi_mut(&mut *author_styles);
+ let affected_style = author_styles.stylesheets.iter().any(|sheet| {
+ !author_styles.data.media_feature_affected_matches(
+ sheet,
+ &guards.author,
document_data.stylist.device(),
- );
- if !origins_changed.is_empty() {
+ document_data.stylist.quirks_mode(),
+ )
+ });
+ if affected_style {
affects_non_document_rules = true;
- // XBL stylesets are rebuilt entirely, so we need to mark them
- // dirty from here instead of going through the stylist
- // force_origin_dirty stuff, which would be useless.
- //
- // FIXME(emilio, bug 1436059): This is super-hacky, make XBL /
- // Shadow DOM not use a style set at all.
- (**non_document_style_set).mStylistState = structs::StylistState_StyleSheetsDirty;
+ author_styles.stylesheets.force_dirty();
}
}
let uses_viewport_units =
document_data.stylist.device().used_viewport_size();
structs::MediumFeaturesChangedResult {
mAffectsDocumentRules: affects_document_rules,
@@ -4925,29 +4980,35 @@ pub extern "C" fn Servo_ParseCounterStyl
Ok(name) => name.0.into_addrefed(),
Err(_) => ptr::null_mut(),
}
}
#[no_mangle]
pub unsafe extern "C" fn Servo_InvalidateStyleForDocStateChanges(
root: RawGeckoElementBorrowed,
- raw_style_sets: *const nsTArray<RawServoStyleSetBorrowed>,
+ document_style: RawServoStyleSetBorrowed,
+ non_document_styles: *const nsTArray<RawServoAuthorStylesBorrowed>,
states_changed: u64,
) {
use style::invalidation::element::document_state::DocumentStateInvalidationProcessor;
use style::invalidation::element::invalidator::TreeStyleInvalidator;
- let mut borrows = SmallVec::<[_; 20]>::with_capacity((*raw_style_sets).len());
- for style_set in &**raw_style_sets {
- borrows.push(PerDocumentStyleData::from_ffi(*style_set).borrow());
- }
+ let document_data = PerDocumentStyleData::from_ffi(document_style).borrow();
+
+ let iter =
+ document_data.stylist.iter_origins().map(|(data, _origin)| data)
+ .chain((*non_document_styles).iter().map(|author_styles| {
+ let styles: &_ = AuthorStyles::<GeckoStyleSheet>::from_ffi(author_styles);
+ &styles.data
+ }));
+
let root = GeckoElement(root);
let mut processor = DocumentStateInvalidationProcessor::new(
- borrows.iter().flat_map(|b| b.stylist.iter_origins().map(|(data, _origin)| data)),
+ iter,
DocumentState::from_bits_truncate(states_changed),
root.as_node().owner_doc().quirks_mode(),
);
let result = TreeStyleInvalidator::new(
root,
/* stack_limit_checker = */ None,
&mut processor,