--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2839,17 +2839,17 @@ CreateDeclarationForServo(nsCSSPropertyI
static already_AddRefed<RawServoDeclarationBlock>
CreateFontDeclarationForServo(const nsAString& aFont,
nsIDocument* aDocument)
{
return CreateDeclarationForServo(eCSSProperty_font, aFont, aDocument);
}
-static already_AddRefed<ServoComputedValues>
+static already_AddRefed<ServoStyleContext>
GetFontStyleForServo(Element* aElement, const nsAString& aFont,
nsIPresShell* aPresShell,
nsAString& aOutUsedFont,
ErrorResult& aError)
{
MOZ_ASSERT(aPresShell->StyleSet()->IsServo());
RefPtr<RawServoDeclarationBlock> declarations =
@@ -2864,44 +2864,45 @@ GetFontStyleForServo(Element* aElement,
// at font-size-adjust, which the font shorthand resets to 'none'.
if (Servo_DeclarationBlock_HasCSSWideKeyword(declarations,
eCSSProperty_font_size_adjust)) {
return nullptr;
}
ServoStyleSet* styleSet = aPresShell->StyleSet()->AsServo();
- RefPtr<ServoComputedValues> parentStyle;
+ RefPtr<ServoStyleContext> parentStyle;
// have to get a parent style context for inherit-like relative
// values (2em, bolder, etc.)
if (aElement && aElement->IsInUncomposedDoc()) {
// Inherit from the canvas element.
aPresShell->FlushPendingNotifications(FlushType::Style);
// We need to use ResolveTransientServoStyle, which involves traversal,
// instead of ResolveServoStyle() because we need up-to-date style even if
// the canvas element is display:none.
parentStyle =
styleSet->ResolveTransientServoStyle(aElement,
- CSSPseudoElementType::NotPseudo);
+ CSSPseudoElementType::NotPseudo,
+ nullptr);
} else {
RefPtr<RawServoDeclarationBlock> declarations =
CreateFontDeclarationForServo(NS_LITERAL_STRING("10px sans-serif"),
aPresShell->GetDocument());
MOZ_ASSERT(declarations);
parentStyle = aPresShell->StyleSet()->AsServo()->
ResolveForDeclarations(nullptr, declarations);
}
MOZ_RELEASE_ASSERT(parentStyle, "Should have a valid parent style");
MOZ_ASSERT(!aPresShell->IsDestroying(),
"GetFontParentStyleContext should have returned an error if the presshell is being destroyed.");
- RefPtr<ServoComputedValues> sc =
+ RefPtr<ServoStyleContext> sc =
styleSet->ResolveForDeclarations(parentStyle, declarations);
// The font getter is required to be reserialized based on what we
// parsed (including having line-height removed). (Older drafts of
// the spec required font sizes be converted to pixels, but that no
// longer seems to be required.)
Servo_SerializeFontValueForCanvas(declarations, &aOutUsedFont);
@@ -2955,19 +2956,19 @@ ResolveFilterStyle(const nsAString& aFil
static already_AddRefed<RawServoDeclarationBlock>
CreateFilterDeclarationForServo(const nsAString& aFilter,
nsIDocument* aDocument)
{
return CreateDeclarationForServo(eCSSProperty_filter, aFilter, aDocument);
}
-static already_AddRefed<ServoComputedValues>
+static already_AddRefed<ServoStyleContext>
ResolveFilterStyleForServo(const nsAString& aFilterString,
- const ServoComputedValues* aParentStyle,
+ const ServoStyleContext* aParentStyle,
nsIPresShell* aPresShell,
ErrorResult& aError)
{
MOZ_ASSERT(aPresShell->StyleSet()->IsServo());
RefPtr<RawServoDeclarationBlock> declarations =
CreateFilterDeclarationForServo(aFilterString, aPresShell->GetDocument());
if (!declarations) {
@@ -2978,17 +2979,17 @@ ResolveFilterStyleForServo(const nsAStri
// In addition to unparseable values, the spec says we need to reject
// 'inherit' and 'initial'.
if (Servo_DeclarationBlock_HasCSSWideKeyword(declarations,
eCSSProperty_filter)) {
return nullptr;
}
ServoStyleSet* styleSet = aPresShell->StyleSet()->AsServo();
- RefPtr<ServoComputedValues> computedValues =
+ RefPtr<ServoStyleContext> computedValues =
styleSet->ResolveForDeclarations(aParentStyle, declarations);
return computedValues.forget();
}
bool
CanvasRenderingContext2D::ParseFilter(const nsAString& aString,
nsTArray<nsStyleFilter>& aFilterChain,
@@ -3023,36 +3024,36 @@ CanvasRenderingContext2D::ParseFilter(co
}
aFilterChain = sc->StyleEffects()->mFilters;
return true;
}
// For stylo
MOZ_ASSERT(presShell->StyleSet()->IsServo());
- RefPtr<ServoComputedValues> parentStyle =
+ RefPtr<ServoStyleContext> parentStyle =
GetFontStyleForServo(mCanvasElement,
GetFont(),
presShell,
usedFont,
aError);
if (!parentStyle) {
return false;
}
- RefPtr<ServoComputedValues> computedValues =
+ RefPtr<ServoStyleContext> computedValues =
ResolveFilterStyleForServo(aString,
parentStyle,
presShell,
aError);
if (!computedValues) {
return false;
}
- const nsStyleEffects* effects = Servo_GetStyleEffects(computedValues);
+ const nsStyleEffects* effects = Servo_GetStyleEffects(computedValues->ComputedValues());
// XXX: This mFilters is a one shot object, we probably could avoid copying.
aFilterChain = effects->mFilters;
return true;
}
void
CanvasRenderingContext2D::SetFilter(const nsAString& aFilter, ErrorResult& aError)
{
@@ -3950,29 +3951,29 @@ CanvasRenderingContext2D::SetFontInterna
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (!presShell) {
aError.Throw(NS_ERROR_FAILURE);
return false;
}
RefPtr<nsStyleContext> sc;
- RefPtr<ServoComputedValues> computedValues;
+ RefPtr<ServoStyleContext> computedValues;
nsString usedFont;
const nsStyleFont* fontStyle;
if (presShell->StyleSet()->IsServo()) {
computedValues = GetFontStyleForServo(mCanvasElement,
aFont,
presShell,
usedFont,
aError);
if (!computedValues) {
return false;
}
- fontStyle = Servo_GetStyleFont(computedValues);
+ fontStyle = Servo_GetStyleFont(computedValues->ComputedValues());
} else {
sc = GetFontStyleContext(mCanvasElement,
aFont,
presShell,
usedFont,
aError);
if (!sc) {
return false;
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -427,16 +427,17 @@ UpdateFramePseudoElementStyles(nsIFrame*
}
bool
ServoRestyleManager::ProcessPostTraversal(Element* aElement,
nsStyleContext* aParentContext,
ServoRestyleState& aRestyleState)
{
nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(aElement);
+ ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
// NOTE(emilio): This is needed because for table frames the bit is set on the
// table wrapper (which is the primary frame), not on the table itself.
const bool isOutOfFlow =
aElement->GetPrimaryFrame() &&
aElement->GetPrimaryFrame()->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
// Grab the change hint from Servo.
@@ -494,31 +495,31 @@ ServoRestyleManager::ProcessPostTraversa
if (!oldStyleContext) {
displayContentsNode =
PresContext()->FrameConstructor()->GetDisplayContentsNodeFor(aElement);
if (displayContentsNode) {
oldStyleContext = displayContentsNode->mStyle->AsServo();
}
}
- RefPtr<ServoComputedValues> computedValues =
+ RefPtr<ServoStyleContext> currentContext =
aRestyleState.StyleSet().ResolveServoStyle(aElement);
// Note that we rely in the fact that we don't cascade pseudo-element styles
// separately right now (that is, if a pseudo style changes, the normal style
// changes too).
//
// Otherwise we should probably encode that information somehow to avoid
// expensive checks in the common case.
//
// Also, we're going to need to check for pseudos of display: contents
// elements, though that is buggy right now even in non-stylo mode, see
// bug 1251799.
const bool recreateContext = oldStyleContext &&
- oldStyleContext->ComputedValues() != computedValues;
+ oldStyleContext->ComputedValues() != currentContext->ComputedValues();
Maybe<ServoRestyleState> thisFrameRestyleState;
if (styleFrame) {
auto type = isOutOfFlow
? ServoRestyleState::Type::OutOfFlow
: ServoRestyleState::Type::InFlow;
thisFrameRestyleState.emplace(*styleFrame, aRestyleState, changeHint, type);
@@ -532,18 +533,22 @@ ServoRestyleManager::ProcessPostTraversa
RefPtr<ServoStyleContext> newContext = nullptr;
if (recreateContext) {
MOZ_ASSERT(styleFrame || displayContentsNode);
auto pseudo = aElement->GetPseudoElementType();
nsIAtom* pseudoTag = pseudo == CSSPseudoElementType::NotPseudo
? nullptr : nsCSSPseudoElements::GetPseudoAtom(pseudo);
- newContext = aRestyleState.StyleSet().GetContext(
- computedValues.forget(), aParentContext, pseudoTag, pseudo, aElement);
+ // XXXManishearth we should just reuse the old one here
+ RefPtr<ServoStyleContext> tempContext =
+ Servo_StyleContext_NewContext(currentContext->ComputedValues(), parent,
+ PresContext(), pseudo, pseudoTag).Consume();
+ newContext = aRestyleState.StyleSet().GetContext(tempContext.forget(), aParentContext,
+ pseudoTag, pseudo, aElement);
newContext->ResolveSameStructsAs(PresContext(), oldStyleContext);
// We want to walk all the continuations here, even the ones with different
// styles. In practice, the only reason we get continuations with different
// styles here is ::first-line (::first-letter never affects element
// styles). But in that case, newContext is the right context for the
// _later_ continuations anyway (the ones not affected by ::first-line), not
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1920,21 +1920,21 @@ nsCSSFrameConstructor::CreateGeneratedCo
return;
}
// Servo has already eagerly computed the style for the container, so we can
// just stick the style on the element and avoid an additional traversal.
//
// We don't do this for pseudos that may trigger animations or transitions,
// since those need to be kicked off by the traversal machinery.
- bool isServo = pseudoStyleContext->IsServo();
bool hasServoAnimations = false;
- if (isServo) {
- ServoComputedValues* servoStyle = pseudoStyleContext->ComputedValues();
- hasServoAnimations = Servo_ComputedValues_SpecifiesAnimationsOrTransitions(servoStyle);
+ ServoStyleContext* servoStyle = pseudoStyleContext->GetAsServo();
+ if (servoStyle) {
+ hasServoAnimations =
+ Servo_ComputedValues_SpecifiesAnimationsOrTransitions(servoStyle->ComputedValues());
if (!hasServoAnimations) {
Servo_SetExplicitStyle(container, servoStyle);
}
}
// stylo: ServoRestyleManager does not handle transitions yet, and when it
// does it probably won't need to track reframed style contexts to start
// transitions correctly.
@@ -1966,17 +1966,17 @@ nsCSSFrameConstructor::CreateGeneratedCo
container->AppendChildTo(content, false);
if (content->IsElement()) {
createdChildElement = true;
}
}
}
// We may need to do a synchronous servo traversal in various uncommon cases.
- if (isServo) {
+ if (servoStyle) {
if (hasServoAnimations) {
// If animations are involved, we avoid the SetExplicitStyle optimization
// above.
mPresShell->StyleSet()->AsServo()->StyleNewSubtree(container);
} else if (createdChildElement) {
// If we created any children elements, Servo needs to traverse them, but
// the root is already set up.
mPresShell->StyleSet()->AsServo()->StyleNewChildren(container);
--- a/layout/style/GeckoStyleContext.h
+++ b/layout/style/GeckoStyleContext.h
@@ -105,16 +105,40 @@ public:
bool HasNoChildren() const;
nsRuleNode* RuleNode() const {
MOZ_ASSERT(mRuleNode);
return mRuleNode;
}
+ void AddRef() {
+ if (mRefCnt == UINT32_MAX) {
+ NS_WARNING("refcount overflow, leaking object");
+ return;
+ }
+ ++mRefCnt;
+ NS_LOG_ADDREF(this, mRefCnt, "nsStyleContext", sizeof(nsStyleContext));
+ return;
+ }
+
+ void Release() {
+ if (mRefCnt == UINT32_MAX) {
+ NS_WARNING("refcount overflow, leaking object");
+ return;
+ }
+ --mRefCnt;
+ NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
+ if (mRefCnt == 0) {
+ Destroy();
+ return;
+ }
+ return;
+ }
+
~GeckoStyleContext() {
Destructor();
}
/**
* Swaps owned style struct pointers between this and aNewContext, on
* the assumption that aNewContext is the new style context for a frame
* and this is the old one. aStructs indicates which structs to consider
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -75,19 +75,19 @@ SERVO_BINDING_FUNC(Servo_StyleSet_GetKey
nsTimingFunctionBorrowed timing_function,
RawGeckoKeyframeListBorrowedMut keyframe_list)
SERVO_BINDING_FUNC(Servo_StyleSet_GetFontFaceRules, void,
RawServoStyleSetBorrowed set,
RawGeckoFontFaceRuleListBorrowedMut list)
SERVO_BINDING_FUNC(Servo_StyleSet_GetCounterStyleRule, nsCSSCounterStyleRule*,
RawServoStyleSetBorrowed set, nsIAtom* name)
SERVO_BINDING_FUNC(Servo_StyleSet_ResolveForDeclarations,
- ServoComputedValuesStrong,
+ ServoStyleContextStrong,
RawServoStyleSetBorrowed set,
- ServoComputedValuesBorrowedOrNull parent_style,
+ ServoStyleContextBorrowedOrNull parent_style,
RawServoDeclarationBlockBorrowed declarations)
SERVO_BINDING_FUNC(Servo_StyleSet_MightHaveAttributeDependency, bool,
RawServoStyleSetBorrowed set,
RawGeckoElementBorrowed element,
nsIAtom* local_name)
SERVO_BINDING_FUNC(Servo_StyleSet_HasStateDependency, bool,
RawServoStyleSetBorrowed set,
RawGeckoElementBorrowed element,
@@ -454,72 +454,88 @@ SERVO_BINDING_FUNC(Servo_MediaList_Delet
// CSS supports()
SERVO_BINDING_FUNC(Servo_CSSSupports2, bool,
const nsACString* name, const nsACString* value)
SERVO_BINDING_FUNC(Servo_CSSSupports, bool,
const nsACString* cond)
// Computed style data
SERVO_BINDING_FUNC(Servo_ComputedValues_GetForAnonymousBox,
- ServoComputedValuesStrong,
- ServoComputedValuesBorrowedOrNull parent_style_or_null,
+ ServoStyleContextStrong,
+ ServoStyleContextBorrowedOrNull parent_style_or_null,
+ mozilla::CSSPseudoElementType pseudo_type,
nsIAtom* pseudo_tag, bool skip_display_fixup,
RawServoStyleSetBorrowed set)
-SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ServoComputedValuesStrong,
+SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ServoStyleContextStrong,
RawServoStyleSetBorrowed set,
- ServoComputedValuesBorrowedOrNull parent_style,
+ mozilla::CSSPseudoElementType pseudo_type,
+ nsIAtom* pseudo_tag,
+ ServoStyleContextBorrowedOrNull parent_style,
mozilla::InheritTarget target)
SERVO_BINDING_FUNC(Servo_ComputedValues_GetVisitedStyle,
- ServoComputedValuesStrong,
+ ServoStyleContextStrong,
ServoComputedValuesBorrowed values)
// Gets the source style rules for the computed values. This returns
// the result via rules, which would include a list of unowned pointers
// to RawServoStyleRule.
SERVO_BINDING_FUNC(Servo_ComputedValues_GetStyleRuleList, void,
ServoComputedValuesBorrowed values,
RawGeckoServoStyleRuleListBorrowedMut rules)
+SERVO_BINDING_FUNC(Servo_StyleContext_NewContext,
+ ServoStyleContextStrong,
+ ServoComputedValuesBorrowed values,
+ ServoStyleContextBorrowedOrNull parent,
+ RawGeckoPresContextBorrowed pres_context,
+ mozilla::CSSPseudoElementType pseudo_type,
+ nsIAtom* pseudo_tag)
+
+
// Initialize Servo components. Should be called exactly once at startup.
SERVO_BINDING_FUNC(Servo_Initialize, void,
RawGeckoURLExtraData* dummy_url_data)
// Shut down Servo components. Should be called exactly once at shutdown.
SERVO_BINDING_FUNC(Servo_Shutdown, void)
// Restyle and change hints.
SERVO_BINDING_FUNC(Servo_NoteExplicitHints, void, RawGeckoElementBorrowed element,
nsRestyleHint restyle_hint, nsChangeHint change_hint)
SERVO_BINDING_FUNC(Servo_TakeChangeHint, nsChangeHint, RawGeckoElementBorrowed element)
-SERVO_BINDING_FUNC(Servo_ResolveStyle, ServoComputedValuesStrong,
+SERVO_BINDING_FUNC(Servo_ResolveStyle, ServoStyleContextStrong,
RawGeckoElementBorrowed element,
RawServoStyleSetBorrowed set)
-SERVO_BINDING_FUNC(Servo_ResolvePseudoStyle, ServoComputedValuesStrong,
+SERVO_BINDING_FUNC(Servo_ResolvePseudoStyle, ServoStyleContextStrong,
RawGeckoElementBorrowed element,
mozilla::CSSPseudoElementType pseudo_type,
+ nsIAtom* pseudo_tag,
bool is_probe,
ServoComputedValuesBorrowedOrNull inherited_style,
+ ServoStyleContextBorrowedOrNull parent_style_context,
RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_SetExplicitStyle, void,
RawGeckoElementBorrowed element,
- ServoComputedValuesBorrowed primary_style)
+ ServoStyleContextBorrowed primary_style)
SERVO_BINDING_FUNC(Servo_HasAuthorSpecifiedRules, bool,
RawGeckoElementBorrowed element,
uint32_t rule_type_mask,
bool author_colors_allowed)
// Resolves style for an element or pseudo-element without processing pending
// restyles first. The Element and its ancestors may be unstyled, have pending
// restyles, or be in a display:none subtree. Styles are cached when possible,
// though caching is not possible within display:none subtrees, and the styles
// may be invalidated by already-scheduled restyles.
//
// The tree must be in a consistent state such that a normal traversal could be
// performed, and this function maintains that invariant.
-SERVO_BINDING_FUNC(Servo_ResolveStyleLazily, ServoComputedValuesStrong,
+SERVO_BINDING_FUNC(Servo_ResolveStyleLazily, ServoStyleContextStrong,
RawGeckoElementBorrowed element,
mozilla::CSSPseudoElementType pseudo_type,
+ nsIAtom* pseudo_tag,
+ ServoStyleContextBorrowedOrNull parent_style_context,
mozilla::StyleRuleInclusion rule_inclusion,
const mozilla::ServoElementSnapshotTable* snapshots,
RawServoStyleSetBorrowed set)
// Use ServoStyleSet::PrepareAndTraverseSubtree instead of calling this
// directly
SERVO_BINDING_FUNC(Servo_TraverseSubtree,
bool,
@@ -533,17 +549,17 @@ SERVO_BINDING_FUNC(Servo_TraverseSubtree
SERVO_BINDING_FUNC(Servo_AssertTreeIsClean, void, RawGeckoElementBorrowed root)
// Checks whether the rule tree has crossed its threshold for unused rule nodes,
// and if so, frees them.
SERVO_BINDING_FUNC(Servo_MaybeGCRuleTree, void, RawServoStyleSetBorrowed set)
// Returns computed values for the given element without any animations rules.
SERVO_BINDING_FUNC(Servo_StyleSet_GetBaseComputedValuesForElement,
- ServoComputedValuesStrong,
+ ServoStyleContextStrong,
RawServoStyleSetBorrowed set,
RawGeckoElementBorrowed element,
const mozilla::ServoElementSnapshotTable* snapshots,
mozilla::CSSPseudoElementType pseudo_type)
// For canvas font.
SERVO_BINDING_FUNC(Servo_SerializeFontValueForCanvas, void,
RawServoDeclarationBlockBorrowed declarations,
@@ -559,17 +575,17 @@ SERVO_BINDING_FUNC(Servo_GetCustomProper
SERVO_BINDING_FUNC(Servo_GetCustomPropertyNameAt, bool,
ServoComputedValuesBorrowed, uint32_t index,
nsAString* name)
// Style-struct management.
#define STYLE_STRUCT(name, checkdata_cb) \
struct nsStyle##name; \
- SERVO_BINDING_FUNC(Servo_GetStyle##name, const nsStyle##name*, \
+ SERVO_BINDING_FUNC(Servo_GetStyle##name, const nsStyle##name*, \
ServoComputedValuesBorrowedOrNull computed_values)
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
// AddRef / Release functions
#define SERVO_ARC_TYPE(name_, type_) \
SERVO_BINDING_FUNC(Servo_##name_##_AddRef, void, type_##Borrowed) \
SERVO_BINDING_FUNC(Servo_##name_##_Release, void, type_##Borrowed)
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -19,16 +19,17 @@ struct RawServoStyleSet;
struct RawServoAnimationValueMap;
#define SERVO_ARC_TYPE(name_, type_) struct type_;
#include "mozilla/ServoArcTypeList.h"
#undef SERVO_ARC_TYPE
namespace mozilla {
class ServoElementSnapshot;
+class ServoStyleContext;
struct StyleAnimation;
struct URLExtraData;
namespace dom {
class Element;
class StyleChildrenIterator;
} // namespace dom
struct AnimationPropertySegment;
struct ComputedTiming;
@@ -97,16 +98,24 @@ typedef mozilla::dom::StyleChildrenItera
struct MOZ_MUST_USE_TYPE type_##Strong \
{ \
type_* mPtr; \
already_AddRefed<type_> Consume(); \
};
#include "mozilla/ServoArcTypeList.h"
#undef SERVO_ARC_TYPE
+typedef mozilla::ServoStyleContext const* ServoStyleContextBorrowed;
+typedef mozilla::ServoStyleContext const* ServoStyleContextBorrowedOrNull;
+struct MOZ_MUST_USE_TYPE ServoStyleContextStrong
+{
+ mozilla::ServoStyleContext* mPtr;
+ already_AddRefed<mozilla::ServoStyleContext> Consume();
+};
+
#define DECL_OWNED_REF_TYPE_FOR(type_) \
typedef type_* type_##Owned; \
DECL_BORROWED_REF_TYPE_FOR(type_) \
DECL_BORROWED_MUT_REF_TYPE_FOR(type_)
#define DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_) \
typedef type_* type_##OwnedOrNull; \
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(type_) \
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -77,19 +77,19 @@ using namespace mozilla::dom;
#define SERVO_ARC_TYPE(name_, type_) \
already_AddRefed<type_> \
type_##Strong::Consume() { \
RefPtr<type_> result; \
result.swap(mPtr); \
return result.forget(); \
}
#include "mozilla/ServoArcTypeList.h"
+SERVO_ARC_TYPE(StyleContext, ServoStyleContext)
#undef SERVO_ARC_TYPE
-
static Mutex* sServoFontMetricsLock = nullptr;
static RWLock* sServoLangFontPrefsLock = nullptr;
static
const nsFont*
ThreadSafeGetDefaultFontHelper(const nsPresContext* aPresContext,
nsIAtom* aLanguage, uint8_t aGenericId)
@@ -202,16 +202,36 @@ Gecko_GetAnonymousContentForElement(RawG
void
Gecko_DestroyAnonymousContentList(nsTArray<nsIContent*>* aAnonContent)
{
MOZ_ASSERT(aAnonContent);
delete aAnonContent;
}
void
+Gecko_ServoStyleContext_Init(ServoStyleContext* aContext,
+ const ServoStyleContext* aParentContext,
+ RawGeckoPresContextBorrowed aPresContext, ServoComputedValuesStrong aValues,
+ mozilla::CSSPseudoElementType aPseudoType, nsIAtom* aPseudoTag)
+{
+ // because it is within an Arc it is unsafe for the Rust side to ever
+ // carry around a mutable non opaque reference to the context, so we
+ // cast it here.
+ ServoStyleContext* parent = const_cast<ServoStyleContext*>(aParentContext);
+ nsPresContext* pres = const_cast<nsPresContext*>(aPresContext);
+ new (KnownNotNull, aContext) ServoStyleContext(parent, pres, aPseudoTag, aPseudoType, aValues.Consume());
+}
+
+void
+Gecko_ServoStyleContext_Destroy(ServoStyleContext* aContext)
+{
+ aContext->~ServoStyleContext();
+}
+
+void
Gecko_ConstructStyleChildrenIterator(
RawGeckoElementBorrowed aElement,
RawGeckoStyleChildrenIteratorBorrowedMut aIterator)
{
MOZ_ASSERT(aElement);
MOZ_ASSERT(aIterator);
new (aIterator) StyleChildrenIterator(aElement);
}
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -45,16 +45,17 @@ namespace mozilla {
struct ImageValue;
class LoaderReusableStyleSheets;
};
namespace dom {
enum class IterationCompositeOperation : uint8_t;
};
enum class UpdateAnimationsTasks : uint8_t;
struct LangGroupFontPrefs;
+ class ServoStyleContext;
class ServoStyleSheet;
class ServoElementSnapshotTable;
}
using mozilla::FontFamilyList;
using mozilla::FontFamilyType;
using mozilla::ServoElementSnapshot;
class nsCSSCounterStyleRule;
class nsCSSFontFaceRule;
@@ -135,16 +136,22 @@ bool Gecko_IsSignificantChild(RawGeckoNo
bool text_is_significant,
bool whitespace_is_significant);
RawGeckoNodeBorrowedOrNull Gecko_GetLastChild(RawGeckoNodeBorrowed node);
RawGeckoNodeBorrowedOrNull Gecko_GetFlattenedTreeParentNode(RawGeckoNodeBorrowed node);
RawGeckoElementBorrowedOrNull Gecko_GetBeforeOrAfterPseudo(RawGeckoElementBorrowed element, bool is_before);
nsTArray<nsIContent*>* Gecko_GetAnonymousContentForElement(RawGeckoElementBorrowed element);
void Gecko_DestroyAnonymousContentList(nsTArray<nsIContent*>* anon_content);
+void Gecko_ServoStyleContext_Init(mozilla::ServoStyleContext* context,
+ ServoStyleContextBorrowedOrNull parent_context,
+ RawGeckoPresContextBorrowed pres_context, ServoComputedValuesStrong values,
+ mozilla::CSSPseudoElementType pseudo_type, nsIAtom* pseudo_tag);
+void Gecko_ServoStyleContext_Destroy(mozilla::ServoStyleContext* context);
+
// By default, Servo walks the DOM by traversing the siblings of the DOM-view
// first child. This generally works, but misses anonymous children, which we
// want to traverse during styling. To support these cases, we create an
// optional stack-allocated iterator in aIterator for nodes that need it.
void Gecko_ConstructStyleChildrenIterator(RawGeckoElementBorrowed aElement,
RawGeckoStyleChildrenIteratorBorrowedMut aIterator);
void Gecko_DestroyStyleChildrenIterator(RawGeckoStyleChildrenIteratorBorrowedMut aIterator);
RawGeckoNodeBorrowedOrNull Gecko_GetNextStyleChild(RawGeckoStyleChildrenIteratorBorrowedMut it);
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -58,16 +58,17 @@ headers = [
"mozilla/ServoElementSnapshotTable.h",
"mozilla/css/ErrorReporter.h",
"mozilla/dom/Element.h",
"mozilla/dom/ChildIterator.h",
"mozilla/dom/NameSpaceConstants.h",
"mozilla/LookAndFeel.h",
"mozilla/ServoBindings.h",
"mozilla/ServoMediaList.h",
+ "mozilla/ServoStyleContext.h",
"nsCSSCounterStyleRule.h",
"nsCSSFontFaceRule.h",
"nsMediaFeatures.h",
"nsMediaList.h",
"nsXBLBinding.h",
]
raw-lines = [
# FIXME(emilio): Incrementally remove these "pub use"s. Probably
@@ -115,18 +116,18 @@ whitelist-vars = [
"kPresContext_.*",
]
whitelist-types = [
"RawGecko.*",
"mozilla::AnimationPropertySegment",
"mozilla::ComputedTiming",
"mozilla::ComputedTimingFunction",
"mozilla::ComputedTimingFunction::BeforeFlag",
- "mozilla::ServoComputedValues2",
"mozilla::ServoElementSnapshot.*",
+ "mozilla::ServoStyleContext",
"mozilla::ServoStyleSheetInner",
"mozilla::CSSPseudoClassType",
"mozilla::css::ErrorReporter",
"mozilla::css::SheetParsingMode",
"mozilla::css::URLMatchingFunction",
"mozilla::dom::IterationCompositeOperation",
"mozilla::dom::StyleChildrenIterator",
"mozilla::HalfCorner",
@@ -241,17 +242,21 @@ whitelist-types = [
"nsStyleXUL",
"nsTArray",
"nsTArrayHeader",
"Position",
"PropertyValuePair",
"Runnable",
"ServoAttrSnapshot",
"ServoBundledURI",
+ "ServoComputedValues",
"ServoElementSnapshot",
+ "ServoStyleContextStrong",
+ "ServoStyleContextBorrowed",
+ "ServoStyleContextBorrowedOrNull",
"SheetParsingMode",
"StaticRefPtr",
"StyleAnimation",
"StyleBasicShape",
"StyleBasicShapeType",
"StyleGeometryBox",
"StyleShapeSource",
"StyleTransition",
@@ -313,33 +318,38 @@ mapped-generic-types = [
{ generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
{ generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
{ generic = false, gecko = "mozilla::ServoFontComputationData", servo = "::properties::FontComputationData" },
{ generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::stylearc::Arc<::custom_properties::CustomPropertiesMap>>" },
{ generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
{ generic = false, gecko = "mozilla::ServoVisitedStyle", servo = "Option<::stylearc::Arc<::properties::ComputedValues>>" },
{ generic = false, gecko = "mozilla::ServoComputedValueFlags", servo = "::properties::computed_value_flags::ComputedValueFlags" },
{ generic = true, gecko = "mozilla::ServoRawOffsetArc", servo = "::stylearc::RawOffsetArc" },
+ { generic = false, gecko = "ServoStyleContextStrong", servo = "::gecko_bindings::sugar::ownership::Strong<ServoStyleContext>" },
]
fixups = [
{ pat = "root::nsString", rep = "::nsstring::nsStringRepr" },
]
[bindings]
headers = ["mozilla/ServoBindings.h"]
hide-types = [
"nsACString_internal",
"nsAString_internal",
+ "ServoStyleContextBorrowed",
+ "ServoStyleContextBorrowedOrNull",
]
raw-lines = [
"pub use nsstring::{nsACString, nsAString, nsString, nsStringRepr};",
"use gecko_bindings::structs::nsStyleTransformMatrix;",
"use gecko_bindings::structs::nsTArray;",
"type nsACString_internal = nsACString;",
"type nsAString_internal = nsAString;",
+ "pub type ServoStyleContextBorrowed<'a> = &'a ServoStyleContext;",
+ "pub type ServoStyleContextBorrowedOrNull<'a> = Option<&'a ::properties::ComputedValues>;",
]
whitelist-functions = ["Servo_.*", "Gecko_.*"]
structs-types = [
"mozilla::css::GridTemplateAreasValue",
"mozilla::css::ErrorReporter",
"mozilla::css::ImageValue",
"mozilla::css::URLValue",
"mozilla::css::URLValueData",
@@ -455,16 +465,19 @@ structs-types = [
"nsStyleXUL",
"nsTimingFunction",
"nscolor",
"nscoord",
"nsresult",
"Loader",
"LoaderReusableStyleSheets",
"ServoStyleSheet",
+ "ServoComputedValues",
+ "ServoStyleContext",
+ "ServoStyleContextStrong",
"EffectCompositor_CascadeLevel",
"UpdateAnimationsTasks",
"ParsingMode",
"InheritTarget",
"URLMatchingFunction",
"StyleRuleInclusion",
"nsStyleTransformMatrix::MatrixTransformOperator",
"RawGeckoGfxMatrix4x4",
--- a/layout/style/ServoStyleContext.h
+++ b/layout/style/ServoStyleContext.h
@@ -8,37 +8,38 @@
#define mozilla_ServoStyleContext_h
#include "nsStyleContext.h"
namespace mozilla {
class ServoStyleContext final : public nsStyleContext {
public:
-
- static already_AddRefed<ServoStyleContext>
- Create(nsStyleContext* aParentContext,
- nsPresContext* aPresContext,
- nsIAtom* aPseudoTag,
- mozilla::CSSPseudoElementType aPseudoType,
- already_AddRefed<ServoComputedValues> aComputedValues);
-
ServoStyleContext(nsStyleContext* aParent,
nsPresContext* aPresContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<ServoComputedValues> aComputedValues);
nsPresContext* PresContext() const {
return mPresContext;
}
ServoComputedValues* ComputedValues() const {
return mSource;
}
+
+ void AddRef() {
+ Servo_StyleContext_AddRef(this);
+ }
+
+ void Release() {
+ Servo_StyleContext_Release(this);
+ }
+
~ServoStyleContext() {
Destructor();
}
/**
* Makes this context match |aOther| in terms of which style structs have
* been resolved.
*/
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -182,80 +182,85 @@ ServoStyleSet::GetContext(nsIContent* aC
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
LazyComputeBehavior aMayCompute)
{
MOZ_ASSERT(aContent->IsElement());
Element* element = aContent->AsElement();
- RefPtr<ServoComputedValues> computedValues;
+ RefPtr<ServoStyleContext> computedValues;
+ ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
if (aMayCompute == LazyComputeBehavior::Allow) {
PreTraverseSync();
- computedValues =
- ResolveStyleLazily(element, CSSPseudoElementType::NotPseudo);
+ RefPtr<ServoStyleContext> tmp =
+ ResolveStyleLazily(element, CSSPseudoElementType::NotPseudo, aPseudoTag, parent);
+ computedValues = GetContext(tmp.forget(), parent, aPseudoTag, aPseudoType,
+ element);
} else {
computedValues = ResolveServoStyle(element);
}
MOZ_ASSERT(computedValues);
- return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType,
- element);
+ return computedValues.forget();
}
already_AddRefed<ServoStyleContext>
-ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
+ServoStyleSet::GetContext(already_AddRefed<ServoStyleContext> aComputedValues,
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
Element* aElementForAnimation)
{
bool isLink = false;
bool isVisitedLink = false;
// If we need visited styles for callers where `aElementForAnimation` is null,
// we can precompute these and pass them as flags, similar to nsStyleSet.cpp.
if (aElementForAnimation) {
isLink = nsCSSRuleProcessor::IsLink(aElementForAnimation);
isVisitedLink = nsCSSRuleProcessor::GetContentState(aElementForAnimation)
.HasState(NS_EVENT_STATE_VISITED);
}
- RefPtr<ServoComputedValues> computedValues = Move(aComputedValues);
- RefPtr<ServoComputedValues> visitedComputedValues =
+ RefPtr<ServoStyleContext> result = Move(aComputedValues);
+ RefPtr<ServoComputedValues> computedValues = result->ComputedValues();
+
+ MOZ_ASSERT(result->GetPseudoType() == aPseudoType);
+ MOZ_ASSERT(result->GetPseudo() == aPseudoTag);
+
+ RefPtr<ServoStyleContext> resultIfVisited =
Servo_ComputedValues_GetVisitedStyle(computedValues).Consume();
- // If `visitedComputedValues` is non-null, then there was a relevant link and
+ // If `resultIfVisited` is non-null, then there was a relevant link and
// visited styles were computed. This corresponds to the cases where Gecko's
// style system produces `aVisitedRuleNode`.
// Set up `parentIfVisited` depending on whether our parent context has a
// a visited style. If it doesn't but we do have visited styles, use the
// regular parent context for visited.
nsStyleContext *parentIfVisited =
aParentContext ? aParentContext->GetStyleIfVisited() : nullptr;
if (!parentIfVisited) {
- if (visitedComputedValues) {
+ if (resultIfVisited) {
parentIfVisited = aParentContext;
}
}
+ ServoStyleContext* parentIfVisitedServo = parentIfVisited ? parentIfVisited->AsServo() : nullptr;
+
// The true visited state of the relevant link is used to decided whether
// visited styles should be consulted for all visited dependent properties.
bool relevantLinkVisited = isLink ? isVisitedLink :
(aParentContext && aParentContext->RelevantLinkVisited());
- RefPtr<ServoStyleContext> result =
- ServoStyleContext::Create(aParentContext, mPresContext, aPseudoTag, aPseudoType,
- computedValues.forget());
-
- if (visitedComputedValues) {
- RefPtr<ServoStyleContext> resultIfVisited =
- ServoStyleContext::Create(parentIfVisited, mPresContext, aPseudoTag, aPseudoType,
- visitedComputedValues.forget());
- resultIfVisited->SetIsStyleIfVisited();
- result->SetStyleIfVisited(resultIfVisited.forget());
+ if (resultIfVisited) {
+ RefPtr<ServoStyleContext> visitedContext =
+ Servo_StyleContext_NewContext(resultIfVisited->ComputedValues(), parentIfVisitedServo,
+ mPresContext, aPseudoType, aPseudoTag).Consume();
+ visitedContext->SetIsStyleIfVisited();
+ result->SetStyleIfVisited(visitedContext.forget());
if (relevantLinkVisited) {
result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
}
}
// Set the body color on the pres context. See nsStyleSet::GetContext
if (aElementForAnimation &&
@@ -420,36 +425,36 @@ ServoStyleSet::ResolveStyleForText(nsICo
MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
MOZ_ASSERT(aTextNode->GetParent());
MOZ_ASSERT(aParentContext);
// Gecko expects text node style contexts to be like elements that match no
// rules: inherit the inherit structs, reset the reset structs. This is cheap
// enough to do on the main thread, which means that the parallel style system
// can avoid worrying about text nodes.
- const ServoComputedValues* parentComputedValues =
- aParentContext->ComputedValues();
- RefPtr<ServoComputedValues> computedValues =
+ RefPtr<ServoStyleContext> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(),
- parentComputedValues,
+ CSSPseudoElementType::InheritingAnonBox,
+ nsCSSAnonBoxes::mozText,
+ aParentContext->AsServo(),
InheritTarget::Text).Consume();
-
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::mozText,
CSSPseudoElementType::InheritingAnonBox,
nullptr);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
{
- const ServoComputedValues* parent =
- aParentContext->ComputedValues();
- RefPtr<ServoComputedValues> computedValues =
+ ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+ RefPtr<ServoStyleContext> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(),
+ CSSPseudoElementType::InheritingAnonBox,
+ nsCSSAnonBoxes::firstLetterContinuation,
parent,
InheritTarget::FirstLetterContinuation)
.Consume();
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::firstLetterContinuation,
CSSPseudoElementType::InheritingAnonBox,
@@ -461,18 +466,20 @@ ServoStyleSet::ResolveStyleForPlaceholde
{
RefPtr<nsStyleContext>& cache =
mNonInheritingStyleContexts[nsCSSAnonBoxes::NonInheriting::oofPlaceholder];
if (cache) {
RefPtr<nsStyleContext> retval = cache;
return retval.forget();
}
- RefPtr<ServoComputedValues> computedValues =
+ RefPtr<ServoStyleContext> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(),
+ CSSPseudoElementType::NonInheritingAnonBox,
+ nsCSSAnonBoxes::oofPlaceholder,
nullptr,
InheritTarget::PlaceholderFrame)
.Consume();
MOZ_ASSERT(computedValues);
RefPtr<nsStyleContext> retval =
GetContext(computedValues.forget(), nullptr,
nsCSSAnonBoxes::oofPlaceholder,
@@ -487,84 +494,88 @@ ServoStyleSet::ResolvePseudoElementStyle
CSSPseudoElementType aType,
nsStyleContext* aParentContext,
Element* aPseudoElement)
{
UpdateStylistIfNeeded();
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
- RefPtr<ServoComputedValues> computedValues;
+ RefPtr<ServoStyleContext> computedValues;
+
+ nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
if (aPseudoElement) {
MOZ_ASSERT(aType == aPseudoElement->GetPseudoElementType());
computedValues = Servo_ResolveStyle(aPseudoElement,
mRawSet.get()).Consume();
} else {
const ServoComputedValues* parentStyle =
aParentContext ? aParentContext->ComputedValues() : nullptr;
+ ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
computedValues =
Servo_ResolvePseudoStyle(aOriginatingElement,
aType,
+ pseudoTag,
/* is_probe = */ false,
parentStyle,
+ parent,
mRawSet.get()).Consume();
}
MOZ_ASSERT(computedValues);
bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
aType == CSSPseudoElementType::after;
- nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
isBeforeOrAfter ? aOriginatingElement : nullptr);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveTransientStyle(Element* aElement,
+ CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
- CSSPseudoElementType aPseudoType,
StyleRuleInclusion aRuleInclusion)
{
- RefPtr<ServoComputedValues> computedValues =
- ResolveTransientServoStyle(aElement, aPseudoType, aRuleInclusion);
+ RefPtr<ServoStyleContext> computedValues =
+ ResolveTransientServoStyle(aElement, aPseudoType, aPseudoTag, aRuleInclusion);
return GetContext(computedValues.forget(),
nullptr,
aPseudoTag,
aPseudoType, nullptr);
}
-already_AddRefed<ServoComputedValues>
+already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveTransientServoStyle(
Element* aElement,
CSSPseudoElementType aPseudoType,
+ nsIAtom* aPseudoTag,
StyleRuleInclusion aRuleInclusion)
{
PreTraverseSync();
- return ResolveStyleLazily(aElement, aPseudoType, aRuleInclusion);
+ return ResolveStyleLazily(aElement, aPseudoType, aPseudoTag, nullptr, aRuleInclusion);
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
nsStyleContext* aParentContext)
{
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
!nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
UpdateStylistIfNeeded();
bool skipFixup =
nsCSSAnonBoxes::AnonBoxSkipsParentDisplayBasedStyleFixup(aPseudoTag);
- const ServoComputedValues* parentStyle =
- aParentContext ? aParentContext->ComputedValues()
- : nullptr;
- RefPtr<ServoComputedValues> computedValues =
- Servo_ComputedValues_GetForAnonymousBox(parentStyle, aPseudoTag, skipFixup,
+ ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+ RefPtr<ServoStyleContext> computedValues =
+ Servo_ComputedValues_GetForAnonymousBox(parent, CSSPseudoElementType::InheritingAnonBox,
+ aPseudoTag, skipFixup,
mRawSet.get()).Consume();
#ifdef DEBUG
if (!computedValues) {
nsString pseudo;
aPseudoTag->ToString(pseudo);
NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
NS_ConvertUTF16toUTF8(pseudo).get()).get());
MOZ_CRASH();
@@ -597,18 +608,19 @@ ServoStyleSet::ResolveNonInheritingAnony
UpdateStylistIfNeeded();
// We always want to skip parent-based display fixup here. It never makes
// sense for non-inheriting anonymous boxes. (Static assertions in
// nsCSSAnonBoxes.cpp ensure that all non-inheriting non-anonymous boxes
// are indeed annotated as skipping this fixup.)
MOZ_ASSERT(!nsCSSAnonBoxes::IsNonInheritingAnonBox(nsCSSAnonBoxes::viewport),
"viewport needs fixup to handle blockifying it");
- RefPtr<ServoComputedValues> computedValues =
- Servo_ComputedValues_GetForAnonymousBox(nullptr, aPseudoTag, true,
+ RefPtr<ServoStyleContext> computedValues =
+ Servo_ComputedValues_GetForAnonymousBox(nullptr, CSSPseudoElementType::NonInheritingAnonBox,
+ aPseudoTag, true,
mRawSet.get()).Consume();
#ifdef DEBUG
if (!computedValues) {
nsString pseudo;
aPseudoTag->ToString(pseudo);
NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
NS_ConvertUTF16toUTF8(pseudo).get()).get());
MOZ_CRASH();
@@ -827,41 +839,43 @@ ServoStyleSet::ProbePseudoElementStyle(E
UpdateStylistIfNeeded();
// NB: We ignore aParentContext, because in some cases
// (first-line/first-letter on anonymous box blocks) Gecko passes something
// nonsensical there. In all other cases we want to inherit directly from
// aOriginatingElement's styles anyway.
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
- RefPtr<ServoComputedValues> computedValues =
- Servo_ResolvePseudoStyle(aOriginatingElement, aType,
+ nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
+ ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+ RefPtr<ServoStyleContext> computedValues =
+ Servo_ResolvePseudoStyle(aOriginatingElement, aType, pseudoTag,
/* is_probe = */ true,
nullptr,
+ parent,
mRawSet.get()).Consume();
if (!computedValues) {
return nullptr;
}
// For :before and :after pseudo-elements, having display: none or no
// 'content' property is equivalent to not having the pseudo-element
// at all.
bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
aType == CSSPseudoElementType::after;
if (isBeforeOrAfter) {
- const nsStyleDisplay* display = Servo_GetStyleDisplay(computedValues);
- const nsStyleContent* content = Servo_GetStyleContent(computedValues);
+ const nsStyleDisplay* display = Servo_GetStyleDisplay(computedValues->ComputedValues());
+ const nsStyleContent* content = Servo_GetStyleContent(computedValues->ComputedValues());
// XXXldb What is contentCount for |content: ""|?
if (display->mDisplay == StyleDisplay::None ||
content->ContentCount() == 0) {
return nullptr;
}
}
- nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
isBeforeOrAfter ? aOriginatingElement : nullptr);
}
nsRestyleHint
ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
EventStates aStateMask)
{
@@ -1075,22 +1089,20 @@ ServoStyleSet::GetAnimationValues(
already_AddRefed<ServoStyleContext>
ServoStyleSet::GetBaseContextForElement(dom::Element* aElement,
nsStyleContext* aParentContext,
nsPresContext* aPresContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType)
{
- RefPtr<ServoComputedValues> cv = Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
+ return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
aElement,
&Snapshots(),
aPseudoType).Consume();
- return ServoStyleContext::Create(nullptr, aPresContext, aPseudoTag,
- aPseudoType, cv.forget());
}
already_AddRefed<RawServoAnimationValue>
ServoStyleSet::ComputeAnimationValue(
Element* aElement,
RawServoDeclarationBlock* aDeclarations,
ServoComputedValuesBorrowed aComputedValues)
{
@@ -1147,34 +1159,36 @@ ServoStyleSet::ClearDataAndMarkDeviceDir
}
void
ServoStyleSet::CompatibilityModeChanged()
{
Servo_StyleSet_CompatModeChanged(mRawSet.get());
}
-already_AddRefed<ServoComputedValues>
+already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveServoStyle(Element* aElement)
{
UpdateStylistIfNeeded();
return Servo_ResolveStyle(aElement, mRawSet.get()).Consume();
}
void
ServoStyleSet::ClearNonInheritingStyleContexts()
{
for (RefPtr<nsStyleContext>& ptr : mNonInheritingStyleContexts) {
ptr = nullptr;
}
}
-already_AddRefed<ServoComputedValues>
+already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveStyleLazily(Element* aElement,
CSSPseudoElementType aPseudoType,
+ nsIAtom* aPseudoTag,
+ const ServoStyleContext* aParentContext,
StyleRuleInclusion aRuleInclusion)
{
mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType);
MOZ_ASSERT(!StylistNeedsUpdate());
AutoSetInServoTraversal guard(this);
/**
@@ -1197,27 +1211,31 @@ ServoStyleSet::ResolveStyleLazily(Elemen
}
} else if (aPseudoType == CSSPseudoElementType::after) {
if (Element* pseudo = nsLayoutUtils::GetAfterPseudo(aElement)) {
elementForStyleResolution = pseudo;
pseudoTypeForStyleResolution = CSSPseudoElementType::NotPseudo;
}
}
- RefPtr<ServoComputedValues> computedValues =
+ RefPtr<ServoStyleContext> computedValues =
Servo_ResolveStyleLazily(elementForStyleResolution,
pseudoTypeForStyleResolution,
+ aPseudoTag,
+ aParentContext,
aRuleInclusion,
&Snapshots(),
mRawSet.get()).Consume();
if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType)) {
computedValues =
Servo_ResolveStyleLazily(elementForStyleResolution,
pseudoTypeForStyleResolution,
+ aPseudoTag,
+ aParentContext,
aRuleInclusion,
&Snapshots(),
mRawSet.get()).Consume();
}
return computedValues.forget();
}
@@ -1230,19 +1248,19 @@ ServoStyleSet::AppendFontFaceRules(nsTAr
}
nsCSSCounterStyleRule*
ServoStyleSet::CounterStyleRuleForName(nsIAtom* aName)
{
return Servo_StyleSet_GetCounterStyleRule(mRawSet.get(), aName);
}
-already_AddRefed<ServoComputedValues>
+already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveForDeclarations(
- ServoComputedValuesBorrowedOrNull aParentOrNull,
+ const ServoStyleContext* aParentOrNull,
RawServoDeclarationBlockBorrowed aDeclarations)
{
UpdateStylistIfNeeded();
return Servo_StyleSet_ResolveForDeclarations(mRawSet.get(),
aParentOrNull,
aDeclarations).Consume();
}
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -183,26 +183,27 @@ public:
dom::Element* aPseudoElement);
// Resolves style for a (possibly-pseudo) Element without assuming that the
// style has been resolved, and without worrying about setting the style
// context up to live in the style context tree (a null parent is used).
// |aPeudoTag| and |aPseudoType| must match.
already_AddRefed<nsStyleContext>
ResolveTransientStyle(dom::Element* aElement,
+ CSSPseudoElementType aPseudoType,
nsIAtom* aPseudoTag,
- CSSPseudoElementType aPseudoType,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
// Similar to ResolveTransientStyle() but returns ServoComputedValues.
// Unlike ResolveServoStyle() this function calls PreTraverseSync().
- already_AddRefed<ServoComputedValues>
+ already_AddRefed<ServoStyleContext>
ResolveTransientServoStyle(dom::Element* aElement,
- CSSPseudoElementType aPseudoTag,
+ CSSPseudoElementType aPseudoType,
+ nsIAtom* aPseudoTag,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
// Get a style context for an anonymous box. aPseudoTag is the pseudo-tag to
// use and must be non-null. It must be an anon box, and must be one that
// inherits style from the given aParentContext.
already_AddRefed<ServoStyleContext>
ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
@@ -356,17 +357,17 @@ public:
* Notifies the Servo stylesheet that the document's compatibility mode has changed.
*/
void CompatibilityModeChanged();
/**
* Resolve style for the given element, and return it as a
* ServoComputedValues, not an nsStyleContext.
*/
- already_AddRefed<ServoComputedValues> ResolveServoStyle(dom::Element* aElement);
+ already_AddRefed<ServoStyleContext> ResolveServoStyle(dom::Element* aElement);
bool GetKeyframesForName(const nsString& aName,
const nsTimingFunction& aTimingFunction,
nsTArray<Keyframe>& aKeyframes);
nsTArray<ComputedKeyframeValues>
GetComputedKeyframeValuesFor(const nsTArray<Keyframe>& aKeyframes,
dom::Element* aElement,
@@ -389,18 +390,18 @@ public:
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType);
/**
* Resolve style for a given declaration block with/without the parent style.
* If the parent style is not specified, the document default computed values
* is used.
*/
- already_AddRefed<ServoComputedValues>
- ResolveForDeclarations(ServoComputedValuesBorrowedOrNull aParentOrNull,
+ already_AddRefed<ServoStyleContext>
+ ResolveForDeclarations(const ServoStyleContext* aParentOrNull,
RawServoDeclarationBlockBorrowed aDeclarations);
already_AddRefed<RawServoAnimationValue>
ComputeAnimationValue(dom::Element* aElement,
RawServoDeclarationBlock* aDeclaration,
ServoComputedValuesBorrowed aComputedValues);
void AppendTask(PostTraversalTask aTask)
@@ -471,17 +472,17 @@ private:
sInServoTraversal = nullptr;
mSet->RunPostTraversalTasks();
}
private:
ServoStyleSet* mSet;
};
- already_AddRefed<ServoStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
+ already_AddRefed<ServoStyleContext> GetContext(already_AddRefed<ServoStyleContext>,
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
dom::Element* aElementForAnimation);
already_AddRefed<ServoStyleContext> GetContext(nsIContent* aContent,
nsStyleContext* aParentContext,
nsIAtom* aPseudoTag,
@@ -553,19 +554,21 @@ private:
/**
* Update the stylist as needed to ensure style data is up-to-date.
*
* This should only be called if StylistNeedsUpdate returns true.
*/
void UpdateStylist();
- already_AddRefed<ServoComputedValues>
+ already_AddRefed<ServoStyleContext>
ResolveStyleLazily(dom::Element* aElement,
CSSPseudoElementType aPseudoType,
+ nsIAtom* aPseudoTag,
+ const ServoStyleContext* aParentContext,
StyleRuleInclusion aRules =
StyleRuleInclusion::All);
void RunPostTraversalTasks();
void PrependSheetOfType(SheetType aType,
ServoStyleSheet* aSheet);
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -160,43 +160,43 @@ struct ServoComputedValueFlags {
};
#define STYLE_STRUCT(name_, checkdata_cb_) struct Gecko##name_;
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
+} // namespace mozilla
+
/**
* We want C++ to be abe to read the style struct fields of ComputedValues
* so we define this type on the C++ side and use the bindgenned version
* on the Rust side.
*
* C++ just sees pointers and opaque types here, so bindgen will attempt to generate a Copy
* impl. This will fail because the bindgenned version contains owned types. Opt out.
*
* <div rustbindgen nocopy></div>
*/
-struct ServoComputedValues2 {
-#define STYLE_STRUCT(name_, checkdata_cb_) ServoRawOffsetArc<Gecko##name_> name_;
+struct ServoComputedValues {
+#define STYLE_STRUCT(name_, checkdata_cb_) mozilla::ServoRawOffsetArc<mozilla::Gecko##name_> name_;
#define STYLE_STRUCT_LIST_IGNORE_VARIABLES
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
- ServoCustomPropertiesMap custom_properties;
- ServoWritingMode writing_mode;
- ServoFontComputationData font_computation_data;
+ mozilla::ServoCustomPropertiesMap custom_properties;
+ mozilla::ServoWritingMode writing_mode;
+ mozilla::ServoFontComputationData font_computation_data;
/// The rule node representing the ordered list of rules matched for this
/// node. Can be None for default values and text nodes. This is
/// essentially an optimization to avoid referencing the root rule node.
- ServoRuleNode rules;
+ mozilla::ServoRuleNode rules;
/// The element's computed values if visited, only computed if there's a
/// relevant link for this element. A element's "relevant link" is the
/// element being matched if it is a link or the nearest ancestor link.
- ServoVisitedStyle visited_style;
- ServoComputedValueFlags flags;
- ~ServoComputedValues2() {} // do nothing, but prevent Copy from being impl'd by bindgen
+ mozilla::ServoVisitedStyle visited_style;
+ mozilla::ServoComputedValueFlags flags;
+ ~ServoComputedValues() {} // do nothing, but prevent Copy from being impl'd by bindgen
};
-} // namespace mozilla
-
#endif // mozilla_ServoTypes_h
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -664,17 +664,17 @@ nsComputedDOMStyle::DoGetStyleContextNoF
// For Servo, compute the result directly without recursively building up
// a throwaway style context chain.
if (ServoStyleSet* servoSet = styleSet->GetAsServo()) {
StyleRuleInclusion rules = aStyleType == eDefaultOnly
? StyleRuleInclusion::DefaultOnly
: StyleRuleInclusion::All;
RefPtr<nsStyleContext> result =
- servoSet->ResolveTransientStyle(aElement, aPseudo, pseudoType, rules);
+ servoSet->ResolveTransientStyle(aElement, pseudoType, aPseudo, rules);
if (aAnimationFlag == eWithAnimation) {
return result.forget();
}
return servoSet->GetBaseContextForElement(aElement, nullptr, presContext,
aPseudo, pseudoType);
}
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -161,23 +161,22 @@ nsStyleContext::Destructor()
"destroying style context from old rule tree too late");
if (mParent) {
mParent->RemoveChild(this);
} else {
presContext->StyleSet()->RootStyleContextRemoved();
}
- // Free up our data structs.
+ // Free up our caches.
if (gecko) {
gecko->DestroyCachedStructs(presContext);
+ // Servo doesn't store things here, and it's not threadsafe
+ CSSVariableImageTable::RemoveAll(this);
}
-
- // Free any ImageValues we were holding on to for CSS variable values.
- CSSVariableImageTable::RemoveAll(this);
}
void nsStyleContext::AddChild(nsStyleContext* aChild)
{
if (GeckoStyleContext* gecko = GetAsGecko()) {
gecko->AddChild(aChild->AsGecko());
}
}
@@ -480,16 +479,44 @@ nsStyleContext::CalcStyleDifference(nsSt
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs)
{
return CalcStyleDifferenceInternal(aNewContext,
aEqualStructs,
aSamePointerStructs);
}
+void
+nsStyleContext::SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited)
+{
+ MOZ_ASSERT(!IsStyleIfVisited(), "this context is not visited data");
+ NS_ASSERTION(!mStyleIfVisited, "should only be set once");
+
+ mStyleIfVisited = aStyleIfVisited;
+
+ MOZ_ASSERT(mStyleIfVisited->IsStyleIfVisited(),
+ "other context is visited data");
+ MOZ_ASSERT(!mStyleIfVisited->GetStyleIfVisited(),
+ "other context does not have visited data");
+ NS_ASSERTION(GetStyleIfVisited()->GetPseudo() == GetPseudo(),
+ "pseudo tag mismatch");
+ if (GetParentAllowServo() && GetParentAllowServo()->GetStyleIfVisited()) {
+ NS_ASSERTION(GetStyleIfVisited()->GetParentAllowServo() ==
+ GetParentAllowServo()->GetStyleIfVisited() ||
+ GetStyleIfVisited()->GetParentAllowServo() ==
+ GetParentAllowServo(),
+ "parent mismatch");
+ } else {
+ NS_ASSERTION(GetStyleIfVisited()->GetParentAllowServo() ==
+ GetParentAllowServo(),
+ "parent mismatch");
+ }
+}
+
+
class MOZ_STACK_CLASS FakeStyleContext
{
public:
explicit FakeStyleContext(const ServoComputedValues* aComputedValues)
: mComputedValues(aComputedValues) {}
nsStyleContext* GetStyleIfVisited() {
// Bug 1364484: Figure out what to do here for Stylo visited values. We can
@@ -623,33 +650,16 @@ NS_NewStyleContext(nsStyleContext* aPare
RefPtr<nsRuleNode> node = aRuleNode;
RefPtr<GeckoStyleContext> context =
new (aRuleNode->PresContext())
GeckoStyleContext(aParentContext, aPseudoTag, aPseudoType, node.forget(),
aSkipParentDisplayBasedStyleFixup);
return context.forget();
}
-namespace mozilla {
-
-already_AddRefed<ServoStyleContext>
-ServoStyleContext::Create(nsStyleContext* aParentContext,
- nsPresContext* aPresContext,
- nsIAtom* aPseudoTag,
- CSSPseudoElementType aPseudoType,
- already_AddRefed<ServoComputedValues> aComputedValues)
-{
- RefPtr<ServoStyleContext> context =
- new ServoStyleContext(aParentContext, aPresContext, aPseudoTag, aPseudoType,
- Move(aComputedValues));
- return context.forget();
-}
-
-} // namespace mozilla
-
nsIPresShell*
nsStyleContext::Arena()
{
return PresContext()->PresShell();
}
template<typename Func>
static nscolor
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -21,16 +21,18 @@ class nsPresContext;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
class GeckoStyleContext;
class ServoStyleContext;
} // namespace mozilla
extern "C" {
+ void Servo_StyleContext_AddRef(mozilla::ServoStyleContext* aContext);
+ void Servo_StyleContext_Release(mozilla::ServoStyleContext* aContext);
#define STYLE_STRUCT(name_, checkdata_cb_) \
struct nsStyle##name_; \
const nsStyle##name_* Servo_GetStyle##name_( \
ServoComputedValuesBorrowedOrNull computed_values);
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
}
@@ -77,39 +79,18 @@ public:
#ifdef DEBUG
/**
* Initializes a cached pref, which is only used in DEBUG code.
*/
static void Initialize();
#endif
- nsrefcnt AddRef() {
- if (mRefCnt == UINT32_MAX) {
- NS_WARNING("refcount overflow, leaking object");
- return mRefCnt;
- }
- ++mRefCnt;
- NS_LOG_ADDREF(this, mRefCnt, "nsStyleContext", sizeof(nsStyleContext));
- return mRefCnt;
- }
-
- nsrefcnt Release() {
- if (mRefCnt == UINT32_MAX) {
- NS_WARNING("refcount overflow, leaking object");
- return mRefCnt;
- }
- --mRefCnt;
- NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
- if (mRefCnt == 0) {
- Destroy();
- return 0;
- }
- return mRefCnt;
- }
+ inline void AddRef();
+ inline void Release();
#ifdef DEBUG
void FrameAddRef() {
++mFrameRefCnt;
}
void FrameRelease() {
--mFrameRefCnt;
@@ -217,41 +198,17 @@ public:
// Structs on this context should never be examined without also
// examining the corresponding struct on |this|. Doing so will likely
// both (1) lead to a privacy leak and (2) lead to dynamic change bugs
// related to the Peek code in nsStyleContext::CalcStyleDifference.
nsStyleContext* GetStyleIfVisited() const
{ return mStyleIfVisited; }
// To be called only from nsStyleSet / ServoStyleSet.
- void SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited)
- {
- MOZ_ASSERT(!IsStyleIfVisited(), "this context is not visited data");
- NS_ASSERTION(!mStyleIfVisited, "should only be set once");
-
- mStyleIfVisited = aStyleIfVisited;
-
- MOZ_ASSERT(mStyleIfVisited->IsStyleIfVisited(),
- "other context is visited data");
- MOZ_ASSERT(!mStyleIfVisited->GetStyleIfVisited(),
- "other context does not have visited data");
- NS_ASSERTION(GetStyleIfVisited()->GetPseudo() == GetPseudo(),
- "pseudo tag mismatch");
- if (GetParentAllowServo() && GetParentAllowServo()->GetStyleIfVisited()) {
- NS_ASSERTION(GetStyleIfVisited()->GetParentAllowServo() ==
- GetParentAllowServo()->GetStyleIfVisited() ||
- GetStyleIfVisited()->GetParentAllowServo() ==
- GetParentAllowServo(),
- "parent mismatch");
- } else {
- NS_ASSERTION(GetStyleIfVisited()->GetParentAllowServo() ==
- GetParentAllowServo(),
- "parent mismatch");
- }
- }
+ void SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited);
// Does any descendant of this style context have any style values
// that were computed based on this style context's ancestors?
bool HasChildThatUsesGrandancestorStyle() const
{ return !!(mBits & NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE); }
// Is this style context shared with a sibling or cousin?
// (See nsStyleSet::GetContext.)
--- a/layout/style/nsStyleContextInlines.h
+++ b/layout/style/nsStyleContextInlines.h
@@ -32,16 +32,28 @@ nsStyleContext::RuleNode()
ServoComputedValues*
nsStyleContext::ComputedValues()
{
MOZ_RELEASE_ASSERT(IsServo());
return AsServo()->ComputedValues();
}
+void
+nsStyleContext::AddRef()
+{
+ MOZ_STYLO_FORWARD(AddRef, ())
+}
+
+void
+nsStyleContext::Release()
+{
+ MOZ_STYLO_FORWARD(Release, ())
+}
+
#define STYLE_STRUCT(name_, checkdata_cb_) \
const nsStyle##name_ * \
nsStyleContext::Style##name_() { \
return DoGetStyle##name_<true>(); \
} \
const nsStyle##name_ * \
nsStyleContext::ThreadsafeStyle##name_() { \
if (mozilla::ServoStyleSet::IsInServoTraversal()) { \
@@ -191,9 +203,10 @@ nsStyleContext::IsLinkContext() const
void
nsStyleContext::StartBackgroundImageLoads()
{
// Just get our background struct; that should do the trick
StyleBackground();
}
+
#endif // nsStyleContextInlines_h
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -1114,17 +1114,17 @@ impl BaseFlow {
scroll_root_id: None,
}
}
/// Update the 'flags' field when computed styles have changed.
///
/// These flags are initially set during flow construction. They only need to be updated here
/// if they are based on properties that can change without triggering `RECONSTRUCT_FLOW`.
- pub fn update_flags_if_needed(&mut self, style: &ServoComputedValues) {
+ pub fn update_flags_if_needed(&mut self, style: &ComputedValues) {
// For absolutely-positioned flows, changes to top/bottom/left/right can cause these flags
// to get out of date:
if self.restyle_damage.contains(REFLOW_OUT_OF_FLOW) {
// Note: We don't need to check whether IS_ABSOLUTELY_POSITIONED has changed, because
// changes to the 'position' property trigger flow reconstruction.
if self.flags.contains(IS_ABSOLUTELY_POSITIONED) {
let logical_position = style.logical_position();
self.flags.set(INLINE_POSITION_IS_STATIC,
--- a/servo/components/script/dom/cssrulelist.rs
+++ b/servo/components/script/dom/cssrulelist.rs
@@ -85,23 +85,25 @@ impl CSSRuleList {
panic!("Called insert_rule on non-CssRule-backed CSSRuleList");
};
let global = self.global();
let window = global.as_window();
let index = idx as usize;
let parent_stylesheet = self.parent_stylesheet.style_stylesheet();
- let new_rule =
- css_rules.insert_rule(&parent_stylesheet.shared_lock,
- rule,
- &parent_stylesheet.contents,
- index,
- nested,
- None)?;
+ let new_rule = css_rules.with_raw_offset_arc(|arc| {
+ arc.insert_rule(&parent_stylesheet.shared_lock,
+ rule,
+ &parent_stylesheet.contents,
+ index,
+ nested,
+ None)
+ })?;
+
let parent_stylesheet = &*self.parent_stylesheet;
let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule);
self.dom_rules.borrow_mut().insert(index, MutNullableJS::new(Some(&*dom_rule)));
Ok((idx))
}
// In case of a keyframe rule, index must be valid.
--- a/servo/components/script/layout_wrapper.rs
+++ b/servo/components/script/layout_wrapper.rs
@@ -72,17 +72,17 @@ use style::dom::{DescendantsBit, DirtyDe
use style::dom::{PresentationalHintsSynthesizer, TElement, TNode, UnsafeNode};
use style::element_state::*;
use style::font_metrics::ServoMetricsProvider;
use style::properties::{ComputedValues, PropertyDeclarationBlock};
use style::selector_parser::{AttrValue as SelectorAttrValue, NonTSPseudoClass, PseudoClassStringArg};
use style::selector_parser::{PseudoElement, SelectorImpl, extended_filtering};
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked};
use style::str::is_whitespace;
-use style::stylearc::Arc;
+use style::stylearc::{Arc, ArcBorrow};
#[derive(Copy, Clone)]
pub struct ServoLayoutNode<'a> {
/// The wrapped node.
node: LayoutJS<Node>,
/// Being chained to a PhantomData prevents `LayoutNode`s from escaping.
chain: PhantomData<&'a ()>,
@@ -389,19 +389,19 @@ impl<'le> TElement for ServoLayoutElemen
type ConcreteNode = ServoLayoutNode<'le>;
type FontMetricsProvider = ServoMetricsProvider;
fn as_node(&self) -> ServoLayoutNode<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast())
}
- fn style_attribute(&self) -> Option<&Arc<StyleLocked<PropertyDeclarationBlock>>> {
+ fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
unsafe {
- (*self.element.style_attribute()).as_ref()
+ (*self.element.style_attribute()).as_ref().map(|x| x.borrow_arc())
}
}
fn get_state(&self) -> ElementState {
self.element.get_state_for_layout()
}
#[inline]
--- a/servo/components/script_layout_interface/wrapper_traits.rs
+++ b/servo/components/script_layout_interface/wrapper_traits.rs
@@ -410,29 +410,29 @@ pub trait ThreadSafeLayoutElement: Clone
.unwrap().clone()
},
PseudoElementCascadeType::Precomputed => {
context.stylist.precomputed_values_for_pseudo(
&context.guards,
&style_pseudo,
Some(data.styles.primary()),
CascadeFlags::empty(),
- &ServoMetricsProvider)
+ &ServoMetricsProvider, (), ())
.clone()
}
PseudoElementCascadeType::Lazy => {
context.stylist
.lazily_compute_pseudo_element_style(
&context.guards,
unsafe { &self.unsafe_get() },
&style_pseudo,
RuleInclusion::All,
data.styles.primary(),
/* is_probe = */ false,
- &ServoMetricsProvider)
+ &ServoMetricsProvider, (), ())
.unwrap()
.clone()
}
}
}
}
}
--- a/servo/components/style/gecko/arc_types.rs
+++ b/servo/components/style/gecko/arc_types.rs
@@ -5,24 +5,25 @@
//! This file lists all arc FFI types and defines corresponding addref
//! and release functions. This list corresponds to ServoArcTypeList.h
//! file in Gecko.
#![allow(non_snake_case, missing_docs)]
use gecko_bindings::bindings::{RawServoImportRule, RawServoSupportsRule};
use gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframesRule};
+use gecko_bindings::bindings::RawServoMediaRule;
use gecko_bindings::bindings::{RawServoNamespaceRule, RawServoPageRule};
-use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule, RawServoMediaRule};
-use gecko_bindings::bindings::{ServoComputedValues, ServoCssRules};
+use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule};
+use gecko_bindings::bindings::ServoCssRules;
use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock, RawServoStyleRule, RawServoMediaList};
-use gecko_bindings::structs::RawServoStyleSheetContents;
+use gecko_bindings::structs::{RawServoStyleSheetContents, ServoComputedValues, ServoStyleContext};
use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
use media_queries::MediaList;
-use properties::{ComputedValues, PropertyDeclarationBlock};
+use properties::{ComputedValues, ComputedValuesInner, PropertyDeclarationBlock};
use properties::animated_properties::AnimationValue;
use rule_tree::StrongRuleNode;
use shared_lock::Locked;
use std::{mem, ptr};
use stylesheets::{CssRules, StylesheetContents, StyleRule, ImportRule, KeyframesRule, MediaRule};
use stylesheets::{NamespaceRule, PageRule, SupportsRule, DocumentRule};
use stylesheets::keyframes_rule::Keyframe;
@@ -46,19 +47,22 @@ macro_rules! impl_arc_ffi {
}
impl_arc_ffi!(Locked<CssRules> => ServoCssRules
[Servo_CssRules_AddRef, Servo_CssRules_Release]);
impl_arc_ffi!(StylesheetContents => RawServoStyleSheetContents
[Servo_StyleSheetContents_AddRef, Servo_StyleSheetContents_Release]);
-impl_arc_ffi!(ComputedValues => ServoComputedValues
+impl_arc_ffi!(ComputedValuesInner => ServoComputedValues
[Servo_ComputedValues_AddRef, Servo_ComputedValues_Release]);
+impl_arc_ffi!(ComputedValues => ServoStyleContext
+ [Servo_StyleContext_AddRef, Servo_StyleContext_Release]);
+
impl_arc_ffi!(Locked<PropertyDeclarationBlock> => RawServoDeclarationBlock
[Servo_DeclarationBlock_AddRef, Servo_DeclarationBlock_Release]);
impl_arc_ffi!(Locked<StyleRule> => RawServoStyleRule
[Servo_StyleRule_AddRef, Servo_StyleRule_Release]);
impl_arc_ffi!(Locked<ImportRule> => RawServoImportRule
[Servo_ImportRule_AddRef, Servo_ImportRule_Release]);
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
@@ -86,16 +86,35 @@ impl PseudoElement {
Some(PseudoElement::${pseudo.capitalized()})
},
% endif
% endfor
_ => None,
}
}
+
+ /// Construct a `CSSPseudoElementType` from a pseudo-element
+ #[inline]
+ pub fn pseudo_type(&self) -> CSSPseudoElementType {
+ match *self {
+ % for pseudo in PSEUDOS:
+ % if not pseudo.is_anon_box():
+ PseudoElement::${pseudo.capitalized()} => CSSPseudoElementType::${pseudo.original_ident},
+ % endif
+ % endfor
+ _ => CSSPseudoElementType::NotPseudo
+ }
+ }
+
+ /// Get a PseudoInfo for a pseudo
+ pub fn pseudo_info(&self) -> (*mut structs::nsIAtom, CSSPseudoElementType) {
+ (self.atom().as_ptr(), self.pseudo_type())
+ }
+
/// Construct a pseudo-element from an anonymous box `Atom`.
#[inline]
pub fn from_anon_box_atom(atom: &Atom) -> Option<Self> {
% for pseudo in PSEUDOS:
% if pseudo.is_anon_box():
if atom == &atom!("${pseudo.value}") {
return Some(PseudoElement::${pseudo.capitalized()});
}
--- a/servo/components/style/gecko/restyle_damage.rs
+++ b/servo/components/style/gecko/restyle_damage.rs
@@ -2,17 +2,16 @@
* 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/. */
//! Gecko's restyle damage computation (aka change hints, aka `nsChangeHint`).
use gecko_bindings::bindings;
use gecko_bindings::structs;
use gecko_bindings::structs::{nsChangeHint, nsStyleContext};
-use gecko_bindings::sugar::ownership::FFIArcHelpers;
use matching::{StyleChange, StyleDifference};
use properties::ComputedValues;
use std::ops::{BitAnd, BitOr, BitOrAssign, Not};
use stylearc::Arc;
/// The representation of Gecko's restyle damage is just a wrapper over
/// `nsChangeHint`.
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -51,17 +50,17 @@ impl GeckoRestyleDamage {
source: &nsStyleContext,
new_style: &Arc<ComputedValues>
) -> StyleDifference {
// TODO(emilio): Const-ify this?
let context = source as *const nsStyleContext as *mut nsStyleContext;
let mut any_style_changed: bool = false;
let hint = unsafe {
bindings::Gecko_CalcStyleDifference(context,
- new_style.as_borrowed(),
+ &new_style,
&mut any_style_changed)
};
let change = if any_style_changed { StyleChange::Changed } else { StyleChange::Unchanged };
StyleDifference::new(GeckoRestyleDamage(hint), change)
}
/// Returns true if this restyle damage contains all the damage of |other|.
pub fn contains(self, other: Self) -> bool {
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -59,17 +59,17 @@ use gecko_bindings::structs::{nsIAtom, n
use gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
use gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_SNAPSHOT;
use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
use gecko_bindings::structs::nsIDocument_DocumentTheme as DocumentTheme;
-use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasSimpleFFI};
+use gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
use logical_geometry::WritingMode;
use media_queries::Device;
use properties::{ComputedValues, parse_style_attribute};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use properties::animated_properties::{AnimatableLonghand, AnimationValue, AnimationValueMap};
use properties::animated_properties::TransitionProperty;
use properties::style_structs::Font;
use rule_tree::CascadeLevel as ServoCascadeLevel;
@@ -1099,20 +1099,19 @@ impl<'le> TElement for GeckoElement<'le>
before_change_style: Option<Arc<ComputedValues>>,
tasks: UpdateAnimationsTasks) {
// We have to update animations even if the element has no computed
// style since it means the element is in a display:none subtree, we
// should destroy all CSS animations in display:none subtree.
let computed_data = self.borrow_data();
let computed_values =
computed_data.as_ref().map(|d| d.styles.primary());
- let computed_values_opt =
- computed_values.map(|v| v.as_borrowed());
let before_change_values =
- before_change_style.as_ref().map(|v| v.as_borrowed());
+ before_change_style.as_ref().map(|x| &***x);
+ let computed_values_opt = computed_values.as_ref().map(|x| &****x);
unsafe {
Gecko_UpdateAnimations(self.0,
before_change_values,
computed_values_opt,
tasks.bits());
}
}
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -334,17 +334,18 @@ trait PrivateMatchMethods: TElement {
fn cascade_with_rules(&self,
shared_context: &SharedStyleContext,
font_metrics_provider: &FontMetricsProvider,
rule_node: &StrongRuleNode,
primary_style: Option<&Arc<ComputedValues>>,
cascade_target: CascadeTarget,
cascade_visited: CascadeVisitedMode,
parent_info: Option<&ParentElementAndStyle<Self>>,
- visited_values_to_insert: Option<Arc<ComputedValues>>)
+ visited_values_to_insert: Option<Arc<ComputedValues>>,
+ pseudo: Option<&PseudoElement>)
-> Arc<ComputedValues> {
let mut cascade_info = CascadeInfo::new();
let mut cascade_flags = CascadeFlags::empty();
if self.skip_root_and_item_based_display_fixup() {
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
}
if cascade_visited.visited_dependent_only() {
cascade_flags.insert(VISITED_DEPENDENT_ONLY);
@@ -380,45 +381,50 @@ trait PrivateMatchMethods: TElement {
let layout_parent_data;
let mut layout_parent_style = style_to_inherit_from;
if style_to_inherit_from.map_or(false, |s| s.is_display_contents()) {
layout_parent_el = Some(layout_parent_el.unwrap().layout_parent());
layout_parent_data = layout_parent_el.as_ref().unwrap().borrow_data().unwrap();
layout_parent_style = Some(cascade_visited.values(layout_parent_data.styles.primary()));
}
- let style_to_inherit_from = style_to_inherit_from.map(|x| &x.inner);
- let layout_parent_style = layout_parent_style.map(|x| &x.inner);
-
// Propagate the "can be fragmented" bit. It would be nice to
// encapsulate this better.
//
// Note that this is technically not needed for pseudos since we already
// do that when we resolve the non-pseudo style, but it doesn't hurt
// anyway.
//
// TODO(emilio): This is servo-only, move somewhere else?
if let Some(ref p) = layout_parent_style {
let can_be_fragmented =
p.is_multicol() ||
layout_parent_el.as_ref().unwrap().as_node().can_be_fragmented();
unsafe { self.as_node().set_can_be_fragmented(can_be_fragmented); }
}
+ #[cfg(feature = "gecko")]
+ let parent_style_context = style_to_inherit_from.map(|x| &**x);
+ #[cfg(feature = "servo")]
+ let parent_style_context = ();
+
// Invoke the cascade algorithm.
let values = cascade(shared_context.stylist.device(),
rule_node,
&shared_context.guards,
- style_to_inherit_from,
- layout_parent_style,
+ style_to_inherit_from.map(|x| &***x),
+ layout_parent_style.map(|x| &***x),
visited_values_to_insert,
Some(&mut cascade_info),
font_metrics_provider,
cascade_flags,
- shared_context.quirks_mode).to_outer();
+ shared_context.quirks_mode)
+ .to_outer(shared_context.stylist.device(),
+ parent_style_context,
+ pseudo.map(|x| x.pseudo_info()));
cascade_info.finish(&self.as_node());
values
}
/// A common path for the cascade used by both primary elements and eager
/// pseudo-elements.
///
@@ -427,17 +433,18 @@ trait PrivateMatchMethods: TElement {
/// `parent_info` is our style parent and its primary style, if
/// it's already been computed.
fn cascade_internal(&self,
context: &StyleContext<Self>,
primary_style: Option<&Arc<ComputedValues>>,
primary_inputs: &CascadeInputs,
eager_pseudo_inputs: Option<&CascadeInputs>,
parent_info: Option<&ParentElementAndStyle<Self>>,
- cascade_visited: CascadeVisitedMode)
+ cascade_visited: CascadeVisitedMode,
+ pseudo: Option<&PseudoElement>)
-> Arc<ComputedValues> {
if let Some(pseudo) = self.implemented_pseudo_element() {
debug_assert!(eager_pseudo_inputs.is_none());
// This is an element-backed pseudo, just grab the styles from the
// parent if it's eager, and recascade otherwise.
//
// We also recascade if the eager pseudo-style has any animation
@@ -491,17 +498,18 @@ trait PrivateMatchMethods: TElement {
self.cascade_with_rules(context.shared,
&context.thread_local.font_metrics_provider,
rule_node,
primary_style,
cascade_target,
cascade_visited,
parent_info,
- visited_values_to_insert)
+ visited_values_to_insert,
+ pseudo)
}
/// Computes values and damage for the primary style of an element, setting
/// them on the ElementData.
///
/// `parent_info` is our style parent and its primary style.
fn cascade_primary(&self,
context: &mut StyleContext<Self>,
@@ -533,17 +541,18 @@ trait PrivateMatchMethods: TElement {
}
// Compute the new values.
self.cascade_internal(context,
None,
primary_inputs,
None,
/* parent_info = */ None,
- cascade_visited)
+ cascade_visited,
+ self.implemented_pseudo_element().as_ref())
};
// NB: Animations for pseudo-elements in Gecko are handled while
// traversing the pseudo-elements themselves.
if !context.shared.traversal_flags.for_animation_only() &&
cascade_visited.should_process_animations() {
self.process_animations(context,
&mut old_values,
@@ -636,17 +645,18 @@ trait PrivateMatchMethods: TElement {
let primary_inputs = context.cascade_inputs().primary();
debug_assert!(cascade_visited.has_rules(primary_inputs));
self.cascade_internal(context,
data.styles.get_primary(),
primary_inputs,
Some(pseudo_inputs),
/* parent_info = */ None,
- cascade_visited)
+ cascade_visited,
+ Some(&pseudo))
};
if cascade_visited.should_accumulate_damage() {
self.accumulate_damage(&context.shared,
&mut data.restyle,
old_values.as_ref().map(|v| v.as_ref()),
&new_values,
Some(pseudo));
@@ -681,17 +691,18 @@ trait PrivateMatchMethods: TElement {
// well, along with updating the rest of the animation processing.
Some(self.cascade_with_rules(context.shared,
&context.thread_local.font_metrics_provider,
&without_transition_rules,
Some(primary_style),
CascadeTarget::Normal,
CascadeVisitedMode::Unvisited,
/* parent_info = */ None,
- primary_style.get_visited_style().cloned()))
+ primary_style.get_visited_style().cloned(),
+ /* pseudo */ None))
}
#[cfg(feature = "gecko")]
fn needs_animations_update(&self,
context: &mut StyleContext<Self>,
old_values: Option<&Arc<ComputedValues>>,
new_values: &ComputedValues)
-> bool {
@@ -1694,14 +1705,14 @@ pub trait MatchMethods : TElement {
// as existing browsers don't appear to animate visited styles.
self.cascade_with_rules(shared_context,
font_metrics_provider,
&without_animation_rules,
Some(primary_style),
CascadeTarget::Normal,
CascadeVisitedMode::Unvisited,
/* parent_info = */ None,
- None)
+ None, None)
}
}
impl<E: TElement> MatchMethods for E {}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -41,49 +41,64 @@ use gecko_bindings::bindings::Gecko_SetL
use gecko_bindings::bindings::Gecko_SetNullImageValue;
use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
use gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use gecko_bindings::structs;
use gecko_bindings::structs::nsCSSPropertyID;
use gecko_bindings::structs::nsStyleVariables;
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
-use gecko_bindings::sugar::ownership::HasArcFFI;
use gecko::values::convert_nscolor_to_rgba;
use gecko::values::convert_rgba_to_nscolor;
use gecko::values::GeckoStyleCoordConvertible;
use gecko::values::round_border_to_device_pixels;
use logical_geometry::WritingMode;
use media_queries::Device;
use properties::animated_properties::TransitionProperty;
use properties::computed_value_flags::ComputedValueFlags;
use properties::{longhands, FontComputationData, Importance, LonghandId};
use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
use rule_tree::StrongRuleNode;
-use std::mem::{forget, transmute, zeroed};
+use std::mem::{forget, uninitialized, transmute, zeroed};
use std::{cmp, ops, ptr};
use stylearc::{Arc, RawOffsetArc};
use values::{Auto, CustomIdent, Either, KeyframesName};
use values::computed::ToComputedValue;
use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
use values::specified::length::Percentage;
use computed_values::border_style;
pub mod style_structs {
% for style_struct in data.style_structs:
pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
% endfor
}
-pub use ::gecko_bindings::structs::mozilla::ServoComputedValues2 as ComputedValuesInner;
-
-#[derive(Clone, Debug)]
-pub struct ComputedValues {
- pub inner: ComputedValuesInner
+pub type ComputedValuesInner = ::gecko_bindings::structs::ServoComputedValues;
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct ComputedValues(::gecko_bindings::structs::mozilla::ServoStyleContext);
+
+impl Drop for ComputedValues {
+ fn drop(&mut self) {
+ unsafe {
+ bindings::Gecko_ServoStyleContext_Destroy(&mut self.0);
+ }
+ }
+}
+
+unsafe impl Sync for ComputedValues {}
+unsafe impl Send for ComputedValues {}
+
+impl Clone for ComputedValues {
+ fn clone(&self) -> Self {
+ unreachable!()
+ }
}
impl Clone for ComputedValuesInner {
fn clone(&self) -> Self {
ComputedValuesInner {
% for style_struct in data.style_structs:
${style_struct.gecko_name}: self.${style_struct.gecko_name}.clone(),
% endfor
@@ -92,16 +107,19 @@ impl Clone for ComputedValuesInner {
font_computation_data: self.font_computation_data.clone(),
flags: self.flags.clone(),
rules: self.rules.clone(),
visited_style: self.visited_style.clone(),
}
}
}
+pub type PseudoInfo = (*mut structs::nsIAtom, structs::CSSPseudoElementType);
+pub type ParentStyleContextInfo<'a> = Option< &'a ComputedValues>;
+
impl ComputedValuesInner {
pub fn new(custom_properties: Option<Arc<CustomPropertiesMap>>,
writing_mode: WritingMode,
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
flags: ComputedValueFlags,
rules: Option<StrongRuleNode>,
visited_style: Option<Arc<ComputedValues>>,
% for style_struct in data.style_structs:
@@ -129,31 +147,52 @@ impl ComputedValuesInner {
rules: None,
visited_style: None,
flags: ComputedValueFlags::initial(),
% for style_struct in data.style_structs:
${style_struct.gecko_name}: Arc::into_raw_offset(style_structs::${style_struct.name}::default(pres_context)),
% endfor
}
}
- pub fn to_outer(self) -> Arc<ComputedValues> {
- Arc::new(ComputedValues {inner: self})
+ pub fn to_outer(self, device: &Device, parent: ParentStyleContextInfo,
+ info: Option<PseudoInfo>) -> Arc<ComputedValues> {
+ let (tag, ty) = if let Some(info) = info {
+ info
+ } else {
+ (ptr::null_mut(), structs::CSSPseudoElementType::NotPseudo)
+ };
+
+ unsafe { Self::to_outer_from_arc(Arc::new(self), device.pres_context(), parent, ty, tag) }
+ }
+
+ pub unsafe fn to_outer_from_arc(s: Arc<Self>, pres_context: bindings::RawGeckoPresContextBorrowed,
+ parent: ParentStyleContextInfo,
+ pseudo_ty: structs::CSSPseudoElementType,
+ pseudo_tag: *mut structs::nsIAtom) -> Arc<ComputedValues> {
+ use gecko_bindings::sugar::ownership::FFIArcHelpers;
+ let arc = unsafe {
+ let arc: Arc<ComputedValues> = Arc::new(uninitialized());
+ bindings::Gecko_ServoStyleContext_Init(&arc.0 as *const _ as *mut _, parent, pres_context,
+ s.into_strong(), pseudo_ty, pseudo_tag);
+ arc
+ };
+ arc
}
}
impl ops::Deref for ComputedValues {
type Target = ComputedValuesInner;
fn deref(&self) -> &ComputedValuesInner {
- &self.inner
+ unsafe { &*self.0.mSource.mRawPtr }
}
}
impl ops::DerefMut for ComputedValues {
fn deref_mut(&mut self) -> &mut ComputedValuesInner {
- &mut self.inner
+ unsafe { &mut *self.0.mSource.mRawPtr }
}
}
impl ComputedValuesInner {
#[inline]
pub fn is_display_contents(&self) -> bool {
self.get_box().clone_display() == longhands::display::computed_value::T::contents
}
@@ -4791,17 +4830,17 @@ clip-path
}
</%self:impl_trait>
<%def name="define_ffi_struct_accessor(style_struct)">
#[no_mangle]
#[allow(non_snake_case, unused_variables)]
pub unsafe extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values:
ServoComputedValuesBorrowedOrNull) -> *const ${style_struct.gecko_ffi_name} {
- ComputedValues::arc_from_borrowed(&computed_values).unwrap().get_${style_struct.name_lower}().get_gecko()
+ computed_values.unwrap().get_${style_struct.name_lower}().get_gecko()
as *const ${style_struct.gecko_ffi_name}
}
</%def>
% for style_struct in data.style_structs:
${declare_style_struct(style_struct)}
${impl_style_struct(style_struct)}
% if not style_struct.name in data.manual_style_structs:
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -1797,19 +1797,24 @@ pub mod style_structs {
}
}
% endif
% endfor
% endfor
#[cfg(feature = "gecko")]
-pub use gecko_properties::ComputedValues;
-#[cfg(feature = "gecko")]
-pub use gecko_properties::ComputedValuesInner;
+pub use gecko_properties::{ComputedValues, ComputedValuesInner, ParentStyleContextInfo, PseudoInfo};
+
+#[cfg(feature = "servo")]
+/// Servo doesn't have style contexts so this is extraneous info
+pub type PseudoInfo = ();
+#[cfg(feature = "servo")]
+/// Servo doesn't have style contexts so this is extraneous info
+pub type ParentStyleContextInfo = ();
#[cfg(feature = "servo")]
#[cfg_attr(feature = "servo", derive(Clone, Debug))]
/// Actual data of ComputedValues, to match up with Gecko
pub struct ComputedValuesInner {
% for style_struct in data.active_style_structs():
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
@@ -1861,17 +1866,16 @@ impl ComputedValuesInner {
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
flags: ComputedValueFlags,
rules: Option<StrongRuleNode>,
visited_style: Option<Arc<ComputedValues>>,
% for style_struct in data.active_style_structs():
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
% endfor
) -> Self {
- let font_computation_data = FontComputationData::new(font_size_keyword);
ComputedValuesInner {
custom_properties: custom_properties,
writing_mode: writing_mode,
font_computation_data: FontComputationData::new(font_size_keyword),
rules: rules,
visited_style: visited_style,
flags: flags,
% for style_struct in data.active_style_structs():
@@ -1897,17 +1901,18 @@ impl ops::DerefMut for ComputedValues {
fn deref_mut(&mut self) -> &mut ComputedValuesInner {
&mut self.inner
}
}
#[cfg(feature = "servo")]
impl ComputedValuesInner {
/// Convert to an Arc<ComputedValues>
- pub fn to_outer(self) -> Arc<ComputedValues> {
+ pub fn to_outer(self, _: &Device, _: ParentStyleContextInfo,
+ _: Option<PseudoInfo>) -> Arc<ComputedValues> {
Arc::new(ComputedValues {inner: self})
}
% for style_struct in data.active_style_structs():
/// Clone the ${style_struct.name} struct.
#[inline]
pub fn clone_${style_struct.name_lower}(&self) -> Arc<style_structs::${style_struct.name}> {
self.${style_struct.ident}.clone()
@@ -2532,17 +2537,17 @@ mod lazy_static_module {
% endif
}),
% endfor
custom_properties: None,
writing_mode: WritingMode::empty(),
font_computation_data: FontComputationData::default_values(),
rules: None,
visited_style: None,
- flags: flags,
+ flags: ComputedValueFlags::initial(),
};
}
}
/// A per-longhand function that performs the CSS cascade for that longhand.
pub type CascadePropertyFn =
extern "Rust" fn(declaration: &PropertyDeclaration,
inherited_style: &ComputedValuesInner,
--- a/servo/components/style/servo/selector_parser.rs
+++ b/servo/components/style/servo/selector_parser.rs
@@ -161,16 +161,19 @@ impl PseudoElement {
}
}
/// Covert non-canonical pseudo-element to canonical one, and keep a
/// canonical one as it is.
pub fn canonical(&self) -> PseudoElement {
self.clone()
}
+
+ /// Stub, only Gecko needs this
+ pub fn pseudo_info(&self) -> () { () }
}
/// The type used for storing pseudo-class string arguments.
pub type PseudoClassStringArg = Box<str>;
/// A non tree-structural pseudo-class.
/// See https://drafts.csswg.org/selectors-4/#structural-pseudos
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -13,17 +13,17 @@ use element_state::ElementState;
use font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")]
use gecko_bindings::structs::{nsIAtom, StyleRuleInclusion};
use invalidation::element::invalidation_map::InvalidationMap;
use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey};
use matching::CascadeVisitedMode;
use media_queries::Device;
use properties::{self, CascadeFlags, ComputedValues, ComputedValuesInner};
-use properties::{AnimationRules, PropertyDeclarationBlock};
+use properties::{AnimationRules, PropertyDeclarationBlock, PseudoInfo, ParentStyleContextInfo};
#[cfg(feature = "servo")]
use properties::INHERIT_ALL;
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
use selector_map::{SelectorMap, SelectorMapEntry};
use selector_parser::{SelectorImpl, PseudoElement};
use selectors::attr::NamespaceConstraint;
use selectors::bloom::BloomFilter;
use selectors::matching::{ElementSelectorFlags, matches_selector, MatchingContext, MatchingMode};
@@ -596,17 +596,19 @@ impl Stylist {
/// parent; otherwise, non-inherited properties are reset to their initial
/// values. The flow constructor uses this flag when constructing anonymous
/// flows.
pub fn precomputed_values_for_pseudo(&self,
guards: &StylesheetGuards,
pseudo: &PseudoElement,
parent: Option<&ComputedValuesInner>,
cascade_flags: CascadeFlags,
- font_metrics: &FontMetricsProvider)
+ font_metrics: &FontMetricsProvider,
+ pseudo_info: PseudoInfo,
+ parent_style_context: ParentStyleContextInfo)
-> Arc<ComputedValues> {
debug_assert!(pseudo.is_precomputed());
let rule_node = match self.precomputed_pseudo_element_decls.get(pseudo) {
Some(declarations) => {
// FIXME(emilio): When we've taken rid of the cascade we can just
// use into_iter.
self.rule_tree.insert_ordered_rules_with_important(
@@ -634,17 +636,18 @@ impl Stylist {
&rule_node,
guards,
parent,
parent,
None,
None,
font_metrics,
cascade_flags,
- self.quirks_mode).to_outer()
+ self.quirks_mode).to_outer(self.device(), parent_style_context,
+ Some(pseudo_info))
}
/// Returns the style for an anonymous box of the given type.
#[cfg(feature = "servo")]
pub fn style_for_anonymous(&self,
guards: &StylesheetGuards,
pseudo: &PseudoElement,
parent_style: &ComputedValuesInner)
@@ -671,54 +674,60 @@ impl Stylist {
unreachable!("That pseudo doesn't represent an anonymous box!")
}
};
let mut cascade_flags = CascadeFlags::empty();
if inherit_all {
cascade_flags.insert(INHERIT_ALL);
}
self.precomputed_values_for_pseudo(guards, &pseudo, Some(parent_style), cascade_flags,
- &ServoMetricsProvider)
+ &ServoMetricsProvider, (), ())
}
/// Computes a pseudo-element style lazily during layout.
///
/// This can only be done for a certain set of pseudo-elements, like
/// :selection.
///
/// Check the documentation on lazy pseudo-elements in
/// docs/components/style.md
pub fn lazily_compute_pseudo_element_style<E>(&self,
guards: &StylesheetGuards,
element: &E,
pseudo: &PseudoElement,
rule_inclusion: RuleInclusion,
parent_style: &ComputedValuesInner,
is_probe: bool,
- font_metrics: &FontMetricsProvider)
+ font_metrics: &FontMetricsProvider,
+ pseudo_info: PseudoInfo,
+ parent_style_context: ParentStyleContextInfo)
-> Option<Arc<ComputedValues>>
where E: TElement,
{
let cascade_inputs =
self.lazy_pseudo_rules(guards, element, pseudo, is_probe, rule_inclusion);
self.compute_pseudo_element_style_with_inputs(&cascade_inputs,
guards,
parent_style,
- font_metrics)
+ font_metrics,
+ pseudo_info,
+ parent_style_context)
}
/// Computes a pseudo-element style lazily using the given CascadeInputs.
/// This can be used for truly lazy pseudo-elements or to avoid redoing
/// selector matching for eager pseudo-elements when we need to recompute
/// their style with a new parent style.
pub fn compute_pseudo_element_style_with_inputs(&self,
inputs: &CascadeInputs,
guards: &StylesheetGuards,
parent_style: &ComputedValuesInner,
- font_metrics: &FontMetricsProvider)
+ font_metrics: &FontMetricsProvider,
+ pseudo_info: PseudoInfo,
+ parent_style_context: ParentStyleContextInfo)
-> Option<Arc<ComputedValues>>
{
// We may have only visited rules in cases when we are actually
// resolving, not probing, pseudo-element style.
if !inputs.has_rules() && !inputs.has_visited_rules() {
return None
}
@@ -741,17 +750,18 @@ impl Stylist {
rule_node,
guards,
Some(inherited_style),
Some(inherited_style),
None,
None,
font_metrics,
CascadeFlags::empty(),
- self.quirks_mode).to_outer();
+ self.quirks_mode).to_outer(self.device(), parent_style_context,
+ Some(pseudo_info.clone()));
Some(computed)
} else {
None
};
// We may not have non-visited rules, if we only had visited ones. In
// that case we want to use the root rulenode for our non-visited rules.
@@ -771,17 +781,19 @@ impl Stylist {
rules,
guards,
Some(parent_style),
Some(parent_style),
visited_values,
None,
font_metrics,
CascadeFlags::empty(),
- self.quirks_mode).to_outer())
+ self.quirks_mode).to_outer(self.device(),
+ parent_style_context,
+ Some(pseudo_info)))
}
/// Computes the cascade inputs for a lazily-cascaded pseudo-element.
///
/// See the documentation on lazy pseudo-elements in
/// docs/components/style.md
pub fn lazy_pseudo_rules<E>(&self,
guards: &StylesheetGuards,
@@ -1331,17 +1343,18 @@ impl Stylist {
results
}
/// Computes styles for a given declaration with parent_style.
pub fn compute_for_declarations(&self,
guards: &StylesheetGuards,
parent_style: &ComputedValuesInner,
- declarations: Arc<Locked<PropertyDeclarationBlock>>)
+ declarations: Arc<Locked<PropertyDeclarationBlock>>,
+ parent_style_context: ParentStyleContextInfo)
-> Arc<ComputedValues> {
use font_metrics::get_metrics_provider_for_product;
let v = vec![
ApplicableDeclarationBlock::from_declarations(declarations.clone(),
CascadeLevel::StyleAttributeNormal)
];
let rule_node =
@@ -1355,17 +1368,17 @@ impl Stylist {
&rule_node,
guards,
Some(parent_style),
Some(parent_style),
None,
None,
&metrics,
CascadeFlags::empty(),
- self.quirks_mode).to_outer()
+ self.quirks_mode).to_outer(self.device(), parent_style_context, None)
}
/// Accessor for a shared reference to the device.
pub fn device(&self) -> &Device {
&self.device
}
/// Accessor for a mutable reference to the device.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -34,17 +34,17 @@ use style::gecko_bindings::bindings::{Ra
use style::gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframeBorrowed, RawServoKeyframeStrong};
use style::gecko_bindings::bindings::{RawServoKeyframesRule, RawServoKeyframesRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong};
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsBorrowed, ServoComputedValuesBorrowed};
-use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoComputedValuesStrong};
+use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoStyleContextBorrowed};
use style::gecko_bindings::bindings::{RawServoSupportsRule, RawServoSupportsRuleBorrowed};
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_GetOrCreateFinalKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
use style::gecko_bindings::bindings::Gecko_NewNoneTransform;
@@ -56,23 +56,24 @@ use style::gecko_bindings::bindings::Raw
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowed;
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowedMut;
use style::gecko_bindings::bindings::RawGeckoServoStyleRuleListBorrowedMut;
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
use style::gecko_bindings::bindings::RawServoAnimationValueMapBorrowedMut;
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
use style::gecko_bindings::bindings::RawServoStyleRuleBorrowed;
use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
+use style::gecko_bindings::bindings::ServoStyleContextBorrowedOrNull;
use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
use style::gecko_bindings::bindings::nsTimingFunctionBorrowed;
use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation, Loader};
-use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet};
-use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
+use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleContextStrong};
+use style::gecko_bindings::structs::{ServoStyleSheet, SheetParsingMode, nsIAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{nsCSSFontFaceRule, nsCSSCounterStyleRule};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
use style::gecko_bindings::structs::IterationCompositeOperation;
use style::gecko_bindings::structs::MallocSizeOf;
use style::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
use style::gecko_bindings::structs::ServoElementSnapshotTable;
use style::gecko_bindings::structs::StyleRuleInclusion;
@@ -87,17 +88,17 @@ use style::gecko_bindings::sugar::owners
use style::gecko_bindings::sugar::refptr::RefPtr;
use style::gecko_properties::{self, style_structs};
use style::invalidation::element::restyle_hints::{self, RestyleHint};
use style::media_queries::{MediaList, parse_media_query_list};
use style::parallel;
use style::parser::ParserContext;
use style::properties::{CascadeFlags, ComputedValues, ComputedValuesInner, Importance, SourcePropertyDeclaration};
use style::properties::{LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId, StyleBuilder};
-use style::properties::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
+use style::properties::{SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, PseudoInfo, ParentStyleContextInfo};
use style::properties::animated_properties::{Animatable, AnimatableLonghand, AnimationValue};
use style::properties::parse_one_declaration_into;
use style::rule_tree::StyleSource;
use style::selector_parser::PseudoElementCascadeType;
use style::sequential;
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
use style::string_cache::Atom;
use style::style_adjuster::StyleAdjuster;
@@ -651,17 +652,17 @@ pub extern "C" fn Servo_AnimationValue_U
PropertyDeclarationBlock::with_one(value.uncompute(), Importance::Normal))).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawServoStyleSetBorrowed,
element: RawGeckoElementBorrowed,
snapshots: *const ServoElementSnapshotTable,
pseudo_type: CSSPseudoElementType)
- -> ServoComputedValuesStrong
+ -> ServoStyleContextStrong
{
use style::matching::MatchMethods;
debug_assert!(!snapshots.is_null());
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let shared_context = create_shared_context(&global_style_data,
@@ -697,17 +698,16 @@ pub extern "C" fn Servo_ComputedValues_E
property_id: nsCSSPropertyID)
-> RawServoAnimationValueStrong
{
let property = match AnimatableLonghand::from_nscsspropertyid(property_id) {
Some(longhand) => longhand,
None => { return Strong::null(); }
};
- let computed_values = ComputedValues::as_arc(&computed_values);
Arc::new(AnimationValue::from_computed_values(&property, computed_values)).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_Property_IsAnimatable(property: nsCSSPropertyID) -> bool {
use style::properties::animated_properties;
animated_properties::nscsspropertyid_is_animatable(property)
}
@@ -1468,95 +1468,101 @@ pub extern "C" fn Servo_SupportsRule_Get
pub extern "C" fn Servo_DocumentRule_GetConditionText(rule: RawServoDocumentRuleBorrowed,
result: *mut nsAString) {
read_locked_arc(rule, |rule: &DocumentRule| {
rule.condition.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
})
}
#[no_mangle]
-pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowedOrNull,
+pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoStyleContextBorrowedOrNull,
+ pseudo_type: CSSPseudoElementType,
pseudo_tag: *mut nsIAtom,
skip_display_fixup: bool,
raw_data: RawServoStyleSetBorrowed)
- -> ServoComputedValuesStrong {
+ -> ServoStyleContextStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let guards = StylesheetGuards::same(&guard);
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let atom = Atom::from(pseudo_tag);
let pseudo = PseudoElement::from_anon_box_atom(&atom)
.expect("Not an anon box pseudo?");
-
- let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null)
- .map(|p| &p.inner);
let mut cascade_flags = CascadeFlags::empty();
if skip_display_fixup {
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
}
let metrics = get_metrics_provider_for_product();
- data.stylist.precomputed_values_for_pseudo(&guards, &pseudo, maybe_parent,
- cascade_flags, &metrics)
+ data.stylist.precomputed_values_for_pseudo(&guards, &pseudo, parent_style_or_null.map(|x| &**x),
+ cascade_flags, &metrics,
+ (pseudo_tag, pseudo_type),
+ parent_style_or_null)
.into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
pseudo_type: CSSPseudoElementType,
+ pseudo_tag: *mut nsIAtom,
is_probe: bool,
inherited_style: ServoComputedValuesBorrowedOrNull,
+ parent_style_context: ServoStyleContextBorrowedOrNull,
raw_data: RawServoStyleSetBorrowed)
- -> ServoComputedValuesStrong
+ -> ServoStyleContextStrong
{
let element = GeckoElement(element);
let data = unsafe { element.ensure_data() }.borrow_mut();
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
debug!("Servo_ResolvePseudoStyle: {:?} {:?}, is_probe: {}",
element, PseudoElement::from_pseudo_type(pseudo_type), is_probe);
// FIXME(bholley): Assert against this.
if !data.has_styles() {
warn!("Calling Servo_ResolvePseudoStyle on unstyled element");
return if is_probe {
Strong::null()
} else {
- doc_data.default_computed_values().clone().to_outer().into_strong()
+ doc_data.default_computed_values()
+ .clone().to_outer(doc_data.stylist.device(), parent_style_context,
+ Some((pseudo_tag, pseudo_type))).into_strong()
};
}
let pseudo = PseudoElement::from_pseudo_type(pseudo_type)
.expect("ResolvePseudoStyle with a non-pseudo?");
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let style = get_pseudo_style(
&guard,
element,
&pseudo,
RuleInclusion::All,
&data.styles,
- ComputedValues::arc_from_borrowed(&inherited_style).map(|x| &***x),
+ inherited_style,
&*doc_data,
- is_probe
+ is_probe,
+ (pseudo_tag, pseudo_type),
+ parent_style_context
);
match style {
Some(s) => s.into_strong(),
None => {
debug_assert!(is_probe);
Strong::null()
}
}
}
#[no_mangle]
pub extern "C" fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
- style: ServoComputedValuesBorrowed)
+ style: ServoStyleContextBorrowed)
{
let element = GeckoElement(element);
let style = ComputedValues::as_arc(&style);
debug!("Servo_SetExplicitStyle: {:?}", element);
// We only support this API for initial styling. There's no reason it couldn't
// work for other things, we just haven't had a reason to do so.
debug_assert!(element.get_data().is_none());
let mut data = unsafe { element.ensure_data() }.borrow_mut();
@@ -1587,16 +1593,18 @@ fn get_pseudo_style(
guard: &SharedRwLockReadGuard,
element: GeckoElement,
pseudo: &PseudoElement,
rule_inclusion: RuleInclusion,
styles: &ElementStyles,
inherited_styles: Option<&ComputedValuesInner>,
doc_data: &PerDocumentStyleDataImpl,
is_probe: bool,
+ pseudo_info: PseudoInfo,
+ parent_style_context: ParentStyleContextInfo,
) -> Option<Arc<ComputedValues>> {
let style = match pseudo.cascade_type() {
PseudoElementCascadeType::Eager => {
match *pseudo {
PseudoElement::FirstLetter => {
styles.pseudos.get(&pseudo).and_then(|pseudo_styles| {
// inherited_styles can be None when doing lazy resolution
// (e.g. for computed style) or when probing. In that case
@@ -1608,17 +1616,19 @@ fn get_pseudo_style(
let guards = StylesheetGuards::same(guard);
let metrics = get_metrics_provider_for_product();
let inputs = CascadeInputs::new_from_style(pseudo_styles);
doc_data.stylist
.compute_pseudo_element_style_with_inputs(
&inputs,
&guards,
inherited_styles,
- &metrics)
+ &metrics,
+ pseudo_info.clone(),
+ parent_style_context)
})
},
_ => {
debug_assert!(inherited_styles.is_none() ||
ptr::eq(&*inherited_styles.unwrap(),
&***styles.primary()));
styles.pseudos.get(&pseudo).cloned()
},
@@ -1639,73 +1649,96 @@ fn get_pseudo_style(
doc_data.stylist
.lazily_compute_pseudo_element_style(
&guards,
&element,
&pseudo,
rule_inclusion,
base,
is_probe,
- &metrics)
+ &metrics,
+ pseudo_info.clone(),
+ parent_style_context)
},
};
if is_probe {
return style;
}
Some(style.unwrap_or_else(|| {
StyleBuilder::for_inheritance(
styles.primary(),
doc_data.default_computed_values(),
- ).build().to_outer()
+ ).build().to_outer(doc_data.stylist.device(), parent_style_context,
+ Some(pseudo_info))
}))
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_Inherit(
raw_data: RawServoStyleSetBorrowed,
- parent_style: ServoComputedValuesBorrowedOrNull,
+ pseudo_type: CSSPseudoElementType,
+ pseudo_tag: *mut nsIAtom,
+ parent_style_context: ServoStyleContextBorrowedOrNull,
target: structs::InheritTarget
-) -> ServoComputedValuesStrong {
+) -> ServoStyleContextStrong {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
- let maybe_arc = ComputedValues::arc_from_borrowed(&parent_style);
let for_text = target == structs::InheritTarget::Text;
- let style = if let Some(reference) = maybe_arc.as_ref() {
+ let style = if let Some(reference) = parent_style_context {
let mut style =
StyleBuilder::for_inheritance(reference,
&data.default_computed_values());
if for_text {
StyleAdjuster::new(&mut style)
.adjust_for_text();
}
style.build()
} else {
debug_assert!(!for_text);
data.default_computed_values().clone()
};
- style.to_outer().into_strong()
+ let pseudo_info = if pseudo_tag.is_null() {
+ None
+ } else {
+ Some((pseudo_tag, pseudo_type))
+ };
+
+ style.to_outer(data.stylist.device(), parent_style_context, pseudo_info).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_GetVisitedStyle(values: ServoComputedValuesBorrowed)
- -> ServoComputedValuesStrong {
- match ComputedValues::as_arc(&values).get_visited_style() {
+ -> ServoStyleContextStrong {
+ match values.get_visited_style() {
Some(v) => v.clone().into_strong(),
None => Strong::null(),
}
}
#[no_mangle]
+pub extern "C" fn Servo_StyleContext_NewContext(values: ServoComputedValuesBorrowed,
+ parent: ServoStyleContextBorrowedOrNull,
+ pres_context: bindings::RawGeckoPresContextBorrowed,
+ pseudo_type: CSSPseudoElementType,
+ pseudo_tag: *mut nsIAtom)
+ -> ServoStyleContextStrong {
+ let arc = ComputedValuesInner::as_arc(&values);
+ unsafe {
+ ComputedValuesInner::to_outer_from_arc(arc.clone_arc(), pres_context, parent,
+ pseudo_type, pseudo_tag).into_strong()
+ }
+}
+
+#[no_mangle]
pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(values: ServoComputedValuesBorrowed)
-> bool {
- let values = ComputedValues::as_arc(&values);
let b = values.get_box();
b.specifies_animations() || b.specifies_transitions()
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoComputedValuesBorrowed,
rules: RawGeckoServoStyleRuleListBorrowedMut) {
if let Some(ref rule_node) = values.rules {
@@ -2700,39 +2733,43 @@ pub extern "C" fn Servo_TakeChangeHint(e
debug!("Servo_TakeChangeHint: {:?}, damage={:?}", element, damage);
damage.as_change_hint()
}
#[no_mangle]
pub extern "C" fn Servo_ResolveStyle(element: RawGeckoElementBorrowed,
raw_data: RawServoStyleSetBorrowed)
- -> ServoComputedValuesStrong
+ -> ServoStyleContextStrong
{
let element = GeckoElement(element);
debug!("Servo_ResolveStyle: {:?}", element);
let data = unsafe { element.ensure_data() }.borrow();
if !element.has_current_styles(&*data) {
debug_assert!(false, "Resolving style on element without current styles with lazy \
computation forbidden.");
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
- return per_doc_data.default_computed_values().clone().to_outer().into_strong();
+ return per_doc_data.default_computed_values().clone()
+ .to_outer(per_doc_data.stylist.device(), None, None)
+ .into_strong();
}
data.styles.primary().clone().into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
pseudo_type: CSSPseudoElementType,
+ pseudo_tag: *mut nsIAtom,
+ parent_style_context: ServoStyleContextBorrowedOrNull,
rule_inclusion: StyleRuleInclusion,
snapshots: *const ServoElementSnapshotTable,
raw_data: RawServoStyleSetBorrowed)
- -> ServoComputedValuesStrong
+ -> ServoStyleContextStrong
{
debug_assert!(!snapshots.is_null());
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let element = GeckoElement(element);
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
let data = doc_data.borrow();
let rule_inclusion = RuleInclusion::from(rule_inclusion);
@@ -2743,16 +2780,18 @@ pub extern "C" fn Servo_ResolveStyleLazi
&guard,
element,
pseudo,
rule_inclusion,
styles,
/* inherited_styles = */ None,
&*data,
/* is_probe = */ false,
+ (pseudo_tag, pseudo_type),
+ parent_style_context
).expect("We're not probing, so we should always get a style \
back")
}
None => styles.primary().clone(),
}
};
// In the common case we already have the style. Check that before setting
@@ -2815,21 +2854,21 @@ fn simulate_compute_values_failure(prope
#[cfg(not(feature = "gecko_debug"))]
fn simulate_compute_values_failure(_: &PropertyValuePair) -> bool {
false
}
fn create_context<'a>(per_doc_data: &'a PerDocumentStyleDataImpl,
font_metrics_provider: &'a FontMetricsProvider,
- style: &'a ComputedValues,
- parent_style: &'a Option<&Arc<ComputedValues>>)
+ style: &'a ComputedValuesInner,
+ parent_style: &'a Option<&ComputedValuesInner>)
-> Context<'a> {
let default_values = per_doc_data.default_computed_values();
- let inherited_style = parent_style.map(|x| &x.inner).unwrap_or(default_values);
+ let inherited_style = parent_style.unwrap_or(default_values);
Context {
is_root_element: false,
device: per_doc_data.stylist.device(),
inherited_style: inherited_style,
layout_parent_style: inherited_style,
style: StyleBuilder::for_derived_style(&style),
font_metrics_provider: font_metrics_provider,
@@ -2846,22 +2885,21 @@ pub extern "C" fn Servo_GetComputedKeyfr
raw_data: RawServoStyleSetBorrowed,
computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut)
{
use std::mem;
use style::properties::LonghandIdSet;
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let metrics = get_metrics_provider_for_product();
- let style = ComputedValues::as_arc(&style);
let element = GeckoElement(element);
let parent_element = element.inheritance_parent();
let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
- let parent_style = parent_data.as_ref().map(|d| d.styles.primary());
+ let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &***x);
let mut context = create_context(&data, &metrics, style, &parent_style);
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let default_values = data.default_computed_values();
for (index, keyframe) in keyframes.iter().enumerate() {
@@ -2926,23 +2964,22 @@ pub extern "C" fn Servo_GetComputedKeyfr
#[no_mangle]
pub extern "C" fn Servo_GetAnimationValues(declarations: RawServoDeclarationBlockBorrowed,
element: RawGeckoElementBorrowed,
style: ServoComputedValuesBorrowed,
raw_data: RawServoStyleSetBorrowed,
animation_values: RawGeckoServoAnimationValueListBorrowedMut) {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
- let style = ComputedValues::as_arc(&style);
let metrics = get_metrics_provider_for_product();
let element = GeckoElement(element);
let parent_element = element.inheritance_parent();
let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
- let parent_style = parent_data.as_ref().map(|d| d.styles.primary());
+ let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &***x);
let mut context = create_context(&data, &metrics, style, &parent_style);
let default_values = data.default_computed_values();
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
@@ -2955,23 +2992,22 @@ pub extern "C" fn Servo_GetAnimationValu
#[no_mangle]
pub extern "C" fn Servo_AnimationValue_Compute(element: RawGeckoElementBorrowed,
declarations: RawServoDeclarationBlockBorrowed,
style: ServoComputedValuesBorrowed,
raw_data: RawServoStyleSetBorrowed)
-> RawServoAnimationValueStrong {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
- let style = ComputedValues::as_arc(&style);
let metrics = get_metrics_provider_for_product();
let element = GeckoElement(element);
let parent_element = element.inheritance_parent();
let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
- let parent_style = parent_data.as_ref().map(|d| d.styles.primary());
+ let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &***x);
let mut context = create_context(&data, &metrics, style, &parent_style);
let default_values = data.default_computed_values();
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
// We only compute the first element in declarations.
@@ -3205,34 +3241,35 @@ pub extern "C" fn Servo_StyleSet_GetCoun
let guard = global_style_data.shared_lock.read();
rule.read_with(&guard).get()
}).unwrap_or(ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(
raw_data: RawServoStyleSetBorrowed,
- parent_style_or_null: ServoComputedValuesBorrowedOrNull,
- declarations: RawServoDeclarationBlockBorrowed
-) -> ServoComputedValuesStrong {
+ parent_style_context: ServoStyleContextBorrowedOrNull,
+ declarations: RawServoDeclarationBlockBorrowed,
+) -> ServoStyleContextStrong {
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let guards = StylesheetGuards::same(&guard);
- let parent_style = match ComputedValues::arc_from_borrowed(&parent_style_or_null) {
- Some(parent) => &parent.inner,
+ let parent_style = match parent_style_context {
+ Some(parent) => &**parent,
None => doc_data.default_computed_values(),
};
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
doc_data.stylist.compute_for_declarations(&guards,
parent_style,
- declarations.clone_arc()).into_strong()
+ declarations.clone_arc(),
+ parent_style_context).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(
raw_data: RawServoStyleSetBorrowed,
element: RawGeckoElementBorrowed,
local_name: *mut nsIAtom,
) -> bool {
@@ -3282,44 +3319,45 @@ pub extern "C" fn Servo_StyleSet_HasStat
has_dep
}
#[no_mangle]
pub extern "C" fn Servo_GetCustomPropertyValue(computed_values: ServoComputedValuesBorrowed,
name: *const nsAString,
value: *mut nsAString) -> bool {
- let custom_properties = match ComputedValues::as_arc(&computed_values).custom_properties() {
+
+ let custom_properties = match computed_values.custom_properties() {
Some(p) => p,
None => return false,
};
let name = unsafe { Atom::from((&*name)) };
let computed_value = match custom_properties.get_computed_value(&name) {
Some(v) => v,
None => return false,
};
computed_value.to_css(unsafe { value.as_mut().unwrap() }).unwrap();
true
}
#[no_mangle]
pub extern "C" fn Servo_GetCustomPropertiesCount(computed_values: ServoComputedValuesBorrowed) -> u32 {
- match ComputedValues::as_arc(&computed_values).custom_properties() {
+ match ComputedValuesInner::as_arc(&computed_values).custom_properties() {
Some(p) => p.len() as u32,
None => 0,
}
}
#[no_mangle]
pub extern "C" fn Servo_GetCustomPropertyNameAt(computed_values: ServoComputedValuesBorrowed,
index: u32,
name: *mut nsAString) -> bool {
- let custom_properties = match ComputedValues::as_arc(&computed_values).custom_properties() {
+ let custom_properties = match ComputedValuesInner::as_arc(&computed_values).custom_properties() {
Some(p) => p,
None => return false,
};
let property_name = match custom_properties.get_name_at(index) {
Some(n) => n,
None => return false,
};