Bug 1324627 - Add a special, explicit path for lazy style resolution and use it for GetComputedStyle. r=heycam

MozReview-Commit-ID: ECnoeHYkpT
This commit is contained in:
Bobby Holley 2016-12-28 11:33:18 +08:00
Родитель 51a0af30f0
Коммит dccae432a9
5 изменённых файлов: 69 добавлений и 20 удалений

Просмотреть файл

@ -154,9 +154,7 @@ ServoRestyleManager::RecreateStyleContexts(Element* aElement,
bool recreateContext = primaryFrame && changeHint;
if (recreateContext) {
RefPtr<ServoComputedValues> computedValues
= Servo_ResolveStyle(aElement, aStyleSet->mRawSet.get(),
ConsumeStyleBehavior::Consume,
LazyComputeBehavior::Assert).Consume();
= Servo_ResolveStyle(aElement, ConsumeStyleBehavior::Consume).Consume();
// Hold the old style context alive, because it could become a dangling
// pointer during the replacement. In practice it's not a huge deal (on

Просмотреть файл

@ -161,12 +161,24 @@ SERVO_BINDING_FUNC(Servo_NoteExplicitHints, void, RawGeckoElementBorrowed elemen
nsRestyleHint restyle_hint, nsChangeHint change_hint)
SERVO_BINDING_FUNC(Servo_CheckChangeHint, nsChangeHint, RawGeckoElementBorrowed element)
SERVO_BINDING_FUNC(Servo_ResolveStyle, ServoComputedValuesStrong,
RawGeckoElementBorrowed element, RawServoStyleSetBorrowed set,
mozilla::ConsumeStyleBehavior consume, mozilla::LazyComputeBehavior compute)
RawGeckoElementBorrowed element, mozilla::ConsumeStyleBehavior consume)
SERVO_BINDING_FUNC(Servo_ResolvePseudoStyle, ServoComputedValuesStrong,
RawGeckoElementBorrowed element, nsIAtom* pseudo_tag,
bool is_probe, RawServoStyleSetBorrowed set)
// 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,
RawGeckoElementBorrowed element, nsIAtom* pseudo_tag,
mozilla::ConsumeStyleBehavior consume,
RawServoStyleSetBorrowed set)
// Restyle the given subtree.
SERVO_BINDING_FUNC(Servo_TraverseSubtree, void,
RawGeckoElementBorrowed root, RawServoStyleSetBorrowed set,

Просмотреть файл

@ -109,8 +109,15 @@ ServoStyleSet::GetContext(nsIContent* aContent,
{
MOZ_ASSERT(aContent->IsElement());
Element* element = aContent->AsElement();
RefPtr<ServoComputedValues> computedValues =
Servo_ResolveStyle(element, mRawSet.get(), aConsume, aMayCompute).Consume();
RefPtr<ServoComputedValues> computedValues;
if (aMayCompute == LazyComputeBehavior::Allow) {
computedValues =
Servo_ResolveStyleLazily(element, nullptr, aConsume, mRawSet.get()).Consume();
} else {
computedValues = Servo_ResolveStyle(element, aConsume).Consume();
}
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType);
}
@ -205,6 +212,21 @@ ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveTransientStyle(Element* aElement, CSSPseudoElementType aType)
{
nsIAtom* pseudoTag = nullptr;
if (aType != CSSPseudoElementType::NotPseudo) {
pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
}
RefPtr<ServoComputedValues> computedValues =
Servo_ResolveStyleLazily(aElement, pseudoTag, ConsumeStyleBehavior::DontConsume,
mRawSet.get()).Consume();
return GetContext(computedValues.forget(), nullptr, pseudoTag, aType);
}
// aFlags is an nsStyleSet flags bitfield
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,

Просмотреть файл

@ -80,6 +80,13 @@ public:
nsStyleContext* aParentContext,
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).
already_AddRefed<nsStyleContext>
ResolveTransientStyle(dom::Element* aElement,
mozilla::CSSPseudoElementType aPseudoType);
// aFlags is an nsStyleSet flags bitfield
already_AddRefed<nsStyleContext>
ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,

Просмотреть файл

@ -492,13 +492,6 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
// No frame has been created, or we have a pseudo, or we're looking
// for the default style, so resolve the style ourselves.
RefPtr<nsStyleContext> parentContext;
nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
// Don't resolve parent context for document fragments.
if (parent && parent->IsElement())
parentContext = GetStyleContextForElementNoFlush(parent->AsElement(),
nullptr, presShell,
aStyleType);
nsPresContext *presContext = presShell->GetPresContext();
if (!presContext)
@ -506,13 +499,35 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
StyleSetHandle styleSet = presShell->StyleSet();
RefPtr<nsStyleContext> sc;
auto type = CSSPseudoElementType::NotPseudo;
if (aPseudo) {
CSSPseudoElementType type = nsCSSPseudoElements::
GetPseudoType(aPseudo, CSSEnabledState::eIgnoreEnabledState);
if (type >= CSSPseudoElementType::Count) {
return nullptr;
}
}
// For Servo, compute the result directly without recursively building up
// a throwaway style context chain.
if (ServoStyleSet* servoSet = styleSet->GetAsServo()) {
if (aStyleType == eDefaultOnly) {
NS_ERROR("stylo: ServoStyleSets cannot supply UA-only styles yet");
return nullptr;
}
return servoSet->ResolveTransientStyle(aElement, type);
}
RefPtr<nsStyleContext> sc;
RefPtr<nsStyleContext> parentContext;
nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
// Don't resolve parent context for document fragments.
if (parent && parent->IsElement())
parentContext = GetStyleContextForElementNoFlush(parent->AsElement(),
nullptr, aPresShell,
aStyleType);
if (type != CSSPseudoElementType::NotPseudo) {
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
Element* pseudoElement =
frame && inDocWithShell ? frame->GetPseudoElement(type) : nullptr;
@ -524,11 +539,6 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
}
if (aStyleType == eDefaultOnly) {
if (styleSet->IsServo()) {
NS_ERROR("stylo: ServoStyleSets cannot supply UA-only styles yet");
return nullptr;
}
// We really only want the user and UA rules. Filter out the other ones.
nsTArray< nsCOMPtr<nsIStyleRule> > rules;
for (nsRuleNode* ruleNode = sc->RuleNode();