Issue #2112 - Part 2: Stub out Servo functions

This commit is contained in:
FranklinDM 2024-03-24 20:28:40 +08:00 committed by roytam1
commit 88ac168f96
8 changed files with 77 additions and 1228 deletions

View file

@ -26,66 +26,28 @@ ServoRestyleManager::PostRestyleEvent(Element* aElement,
nsRestyleHint aRestyleHint,
nsChangeHint aMinChangeHint)
{
if (MOZ_UNLIKELY(IsDisconnected()) ||
MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
return;
}
if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) {
return; // Nothing to do.
}
// XXX This is a temporary hack to make style attribute change works.
// In the future, we should be able to use this hint directly.
if (aRestyleHint & eRestyle_StyleAttribute) {
aRestyleHint &= ~eRestyle_StyleAttribute;
aRestyleHint |= eRestyle_Self | eRestyle_Subtree;
}
// Note that unlike in Servo, we don't mark elements as dirty until we process
// the restyle hints in ProcessPendingRestyles.
if (aRestyleHint || aMinChangeHint) {
ServoElementSnapshot* snapshot = SnapshotForElement(aElement);
snapshot->AddExplicitRestyleHint(aRestyleHint);
snapshot->AddExplicitChangeHint(aMinChangeHint);
}
PostRestyleEventInternal(false);
}
void
ServoRestyleManager::PostRestyleEventForLazyConstruction()
{
PostRestyleEventInternal(true);
}
void
ServoRestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
nsRestyleHint aRestyleHint)
{
NS_WARNING("stylo: ServoRestyleManager::RebuildAllStyleData not implemented");
}
void
ServoRestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
nsRestyleHint aRestyleHint)
{
NS_WARNING("stylo: ServoRestyleManager::PostRebuildAllStyleDataEvent not implemented");
}
static void
MarkSelfAndDescendantsAsNotDirtyForServo(nsIContent* aContent)
{
aContent->UnsetIsDirtyForServo();
if (aContent->HasDirtyDescendantsForServo()) {
aContent->UnsetHasDirtyDescendantsForServo();
StyleChildrenIterator it(aContent);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
MarkSelfAndDescendantsAsNotDirtyForServo(n);
}
}
}
void
@ -94,408 +56,51 @@ ServoRestyleManager::RecreateStyleContexts(nsIContent* aContent,
ServoStyleSet* aStyleSet,
nsStyleChangeList& aChangeListToProcess)
{
MOZ_ASSERT(aContent->IsElement() || aContent->IsNodeOfType(nsINode::eTEXT));
nsIFrame* primaryFrame = aContent->GetPrimaryFrame();
if (!primaryFrame && !aContent->IsDirtyForServo()) {
// This happens when, for example, a display: none child of a
// HAS_DIRTY_DESCENDANTS content is reached as part of the traversal.
MarkSelfAndDescendantsAsNotDirtyForServo(aContent);
return;
}
// Work on text before.
if (!aContent->IsElement()) {
if (primaryFrame) {
RefPtr<nsStyleContext> oldStyleContext = primaryFrame->StyleContext();
RefPtr<nsStyleContext> newContext =
aStyleSet->ResolveStyleForText(aContent, aParentContext);
for (nsIFrame* f = primaryFrame; f;
f = GetNextContinuationWithSameStyle(f, oldStyleContext)) {
f->SetStyleContext(newContext);
}
}
aContent->UnsetIsDirtyForServo();
return;
}
Element* element = aContent->AsElement();
if (element->IsDirtyForServo()) {
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Get(aContent).Consume();
MOZ_ASSERT(computedValues);
nsChangeHint changeHint = nsChangeHint(0);
// Add an explicit change hint if appropriate.
ServoElementSnapshot* snapshot;
if (mModifiedElements.Get(element, &snapshot)) {
changeHint |= snapshot->ExplicitChangeHint();
}
// Add the stored change hint if there's a frame. If there isn't a frame,
// generate a ReconstructFrame change hint if the new display value
// (which we can get from the ComputedValues stored on the node) is not
// none.
if (primaryFrame) {
changeHint |= primaryFrame->StyleContext()->ConsumeStoredChangeHint();
} else {
const nsStyleDisplay* currentDisplay =
Servo_GetStyleDisplay(computedValues);
if (currentDisplay->mDisplay != StyleDisplay::None) {
changeHint |= nsChangeHint_ReconstructFrame;
}
}
// Add the new change hint to the list of elements to process if
// we need to do any work.
if (changeHint) {
aChangeListToProcess.AppendChange(primaryFrame, element, changeHint);
}
// The frame reconstruction step (if needed) will ask for the descendants'
// style correctly. If not needed, we're done too.
//
// Note that we must leave the old style on an existing frame that is
// about to be reframed, since some frame constructor code wants to
// inspect the old style to work out what to do.
if (changeHint & nsChangeHint_ReconstructFrame) {
// Since we might still have some dirty bits set on descendants,
// inconsistent with the clearing of HasDirtyDescendants we will do as
// we return from these recursive RecreateStyleContexts calls, we
// explicitly clear them here. Otherwise we will trigger assertions
// when we soon process the frame reconstruction.
MarkSelfAndDescendantsAsNotDirtyForServo(element);
return;
}
// If there is no frame, and we didn't generate a ReconstructFrame change
// hint, then we don't need to do any more work.
if (!primaryFrame) {
aContent->UnsetIsDirtyForServo();
return;
}
// 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
// GetNextContinuationWithSameStyle the pointer is not dereferenced, only
// compared), but better not playing with dangling pointers if not needed.
RefPtr<nsStyleContext> oldStyleContext = primaryFrame->StyleContext();
MOZ_ASSERT(oldStyleContext);
RefPtr<nsStyleContext> newContext =
aStyleSet->GetContext(computedValues.forget(), aParentContext, nullptr,
CSSPseudoElementType::NotPseudo);
// XXX This could not always work as expected: there are kinds of content
// with the first split and the last sharing style, but others not. We
// should handle those properly.
for (nsIFrame* f = primaryFrame; f;
f = GetNextContinuationWithSameStyle(f, oldStyleContext)) {
f->SetStyleContext(newContext);
}
// Update pseudo-elements state if appropriate.
const static CSSPseudoElementType pseudosToRestyle[] = {
CSSPseudoElementType::before,
CSSPseudoElementType::after,
};
for (CSSPseudoElementType pseudoType : pseudosToRestyle) {
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(pseudoType);
if (nsIFrame* pseudoFrame = FrameForPseudoElement(element, pseudoTag)) {
// TODO: we could maybe make this more performant via calling into
// Servo just once to know which pseudo-elements we've got to restyle?
RefPtr<nsStyleContext> pseudoContext =
aStyleSet->ProbePseudoElementStyle(element, pseudoType, newContext);
// If pseudoContext is null here, it means the frame is going away, so
// our change hint computation should have already indicated we need
// to reframe.
MOZ_ASSERT_IF(!pseudoContext,
changeHint & nsChangeHint_ReconstructFrame);
if (pseudoContext) {
pseudoFrame->SetStyleContext(pseudoContext);
// We only care restyling text nodes, since other type of nodes
// (images), are still not supported. If that eventually changes, we
// may have to write more code here... Or not, I don't think too
// many inherited properties can affect those other frames.
StyleChildrenIterator it(pseudoFrame->GetContent());
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (n->IsNodeOfType(nsINode::eTEXT)) {
RefPtr<nsStyleContext> childContext =
aStyleSet->ResolveStyleForText(n, pseudoContext);
MOZ_ASSERT(n->GetPrimaryFrame(),
"How? This node is created at FC time!");
n->GetPrimaryFrame()->SetStyleContext(childContext);
}
}
}
}
}
aContent->UnsetIsDirtyForServo();
}
if (aContent->HasDirtyDescendantsForServo()) {
MOZ_ASSERT(primaryFrame,
"Frame construction should be scheduled, and it takes the "
"correct style for the children, so no need to be here.");
StyleChildrenIterator it(aContent);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
if (n->IsElement() || n->IsNodeOfType(nsINode::eTEXT)) {
RecreateStyleContexts(n, primaryFrame->StyleContext(),
aStyleSet, aChangeListToProcess);
}
}
aContent->UnsetHasDirtyDescendantsForServo();
}
}
static void
MarkChildrenAsDirtyForServo(nsIContent* aContent)
{
StyleChildrenIterator it(aContent);
nsIContent* n = it.GetNextChild();
bool hadChildren = bool(n);
for (; n; n = it.GetNextChild()) {
n->SetIsDirtyForServo();
}
if (hadChildren) {
aContent->SetHasDirtyDescendantsForServo();
}
}
/* static */ nsIFrame*
ServoRestyleManager::FrameForPseudoElement(const nsIContent* aContent,
nsIAtom* aPseudoTagOrNull)
{
MOZ_ASSERT_IF(aPseudoTagOrNull, aContent->IsElement());
if (!aPseudoTagOrNull) {
return aContent->GetPrimaryFrame();
}
if (aPseudoTagOrNull == nsCSSPseudoElements::before) {
return nsLayoutUtils::GetBeforeFrame(aContent);
}
if (aPseudoTagOrNull == nsCSSPseudoElements::after) {
return nsLayoutUtils::GetAfterFrame(aContent);
}
MOZ_CRASH("Unkown pseudo-element given to "
"ServoRestyleManager::FrameForPseudoElement");
return nullptr;
}
/* static */ void
ServoRestyleManager::NoteRestyleHint(Element* aElement, nsRestyleHint aHint)
{
const nsRestyleHint HANDLED_RESTYLE_HINTS = eRestyle_Self |
eRestyle_Subtree |
eRestyle_LaterSiblings |
eRestyle_SomeDescendants;
// NB: For Servo, at least for now, restyling and running selector-matching
// against the subtree is necessary as part of restyling the element, so
// processing eRestyle_Self will perform at least as much work as
// eRestyle_Subtree.
if (aHint & (eRestyle_Self | eRestyle_Subtree)) {
aElement->SetIsDirtyForServo();
aElement->MarkAncestorsAsHavingDirtyDescendantsForServo();
// NB: Servo gives us a eRestyle_SomeDescendants when it expects us to run
// selector matching on all the descendants. There's a bug on Servo to align
// meanings here (#12710) to avoid this potential source of confusion.
} else if (aHint & eRestyle_SomeDescendants) {
MarkChildrenAsDirtyForServo(aElement);
aElement->MarkAncestorsAsHavingDirtyDescendantsForServo();
}
if (aHint & eRestyle_LaterSiblings) {
aElement->MarkAncestorsAsHavingDirtyDescendantsForServo();
for (nsIContent* cur = aElement->GetNextSibling(); cur;
cur = cur->GetNextSibling()) {
cur->SetIsDirtyForServo();
}
}
// TODO: Handle all other nsRestyleHint values.
if (aHint & ~HANDLED_RESTYLE_HINTS) {
NS_WARNING(nsPrintfCString("stylo: Unhandled restyle hint %s",
RestyleManagerBase::RestyleHintToString(aHint).get()).get());
}
}
void
ServoRestyleManager::ProcessPendingRestyles()
{
MOZ_ASSERT(PresContext()->Document(), "No document? Pshaw!");
MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");
if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
// PresShell::FlushPendingNotifications doesn't early-return in the case
// where the PreShell hasn't yet been initialized (and therefore we haven't
// yet done the initial style traversal of the DOM tree). We should arguably
// fix up the callers and assert against this case, but we just detect and
// handle it for now.
return;
}
if (!HasPendingRestyles()) {
return;
}
ServoStyleSet* styleSet = StyleSet();
nsIDocument* doc = PresContext()->Document();
Element* root = doc->GetRootElement();
if (root) {
// ProcessPendingRestyles can generate new restyles (e.g. from the
// frame constructor if it decides that a ReconstructFrame change must
// apply to the parent of the element that generated that hint). So
// we loop while mModifiedElements still has some restyles in it, clearing
// it after each RecreateStyleContexts call below.
while (!mModifiedElements.IsEmpty()) {
for (auto iter = mModifiedElements.Iter(); !iter.Done(); iter.Next()) {
ServoElementSnapshot* snapshot = iter.UserData();
Element* element = iter.Key();
// The element is no longer in the document, so don't bother computing
// a final restyle hint for it.
//
// XXXheycam RestyleTracker checks that the element's GetComposedDoc()
// matches the document we're restyling. Do we need to do that too?
if (!element->IsInComposedDoc()) {
continue;
}
// TODO: avoid the ComputeRestyleHint call if we already have the highest
// explicit restyle hint?
nsRestyleHint hint = styleSet->ComputeRestyleHint(element, snapshot);
hint |= snapshot->ExplicitRestyleHint();
if (hint) {
NoteRestyleHint(element, hint);
}
}
if (!root->IsDirtyForServo() && !root->HasDirtyDescendantsForServo()) {
mModifiedElements.Clear();
break;
}
mInStyleRefresh = true;
styleSet->StyleDocument(/* aLeaveDirtyBits = */ true);
// First do any queued-up frame creation. (see bugs 827239 and 997506).
//
// XXXEmilio I'm calling this to avoid random behavior changes, since we
// delay frame construction after styling we should re-check once our
// model is more stable whether we can skip this call.
//
// Note this has to be *after* restyling, because otherwise frame
// construction will find unstyled nodes, and that's not funny.
PresContext()->FrameConstructor()->CreateNeededFrames();
nsStyleChangeList changeList;
RecreateStyleContexts(root, nullptr, styleSet, changeList);
mModifiedElements.Clear();
ProcessRestyledFrames(changeList);
mInStyleRefresh = false;
}
}
MOZ_ASSERT(!doc->IsDirtyForServo());
doc->UnsetHasDirtyDescendantsForServo();
IncrementRestyleGeneration();
}
void
ServoRestyleManager::RestyleForInsertOrChange(nsINode* aContainer,
nsIContent* aChild)
{
//
// XXXbholley: We need the Gecko logic here to correctly restyle for things
// like :empty and positional selectors (though we may not need to post
// restyle events as agressively as the Gecko path does).
//
// Bug 1297899 tracks this work.
//
}
void
ServoRestyleManager::ContentInserted(nsINode* aContainer, nsIContent* aChild)
{
if (aContainer == aContainer->OwnerDoc()) {
// If we're getting this notification for the insertion of a root element,
// that means either:
// (a) We initialized the PresShell before the root element existed, or
// (b) The root element was removed and it or another root is being
// inserted.
//
// Either way the whole tree is dirty, so we should style the document.
MOZ_ASSERT(aChild == aChild->OwnerDoc()->GetRootElement());
MOZ_ASSERT(aChild->IsDirtyForServo());
StyleSet()->StyleDocument(/* aLeaveDirtyBits = */ false);
return;
}
if (!aContainer->HasServoData()) {
// This can happen with display:none. Bug 1297249 tracks more investigation
// and assertions here.
return;
}
// Style the new subtree because we will most likely need it during subsequent
// frame construction. Bug 1298281 tracks deferring this work in the lazy
// frame construction case.
StyleSet()->StyleNewSubtree(aChild);
RestyleForInsertOrChange(aContainer, aChild);
}
void
ServoRestyleManager::RestyleForAppend(nsIContent* aContainer,
nsIContent* aFirstNewContent)
{
//
// XXXbholley: We need the Gecko logic here to correctly restyle for things
// like :empty and positional selectors (though we may not need to post
// restyle events as agressively as the Gecko path does).
//
// Bug 1297899 tracks this work.
//
}
void
ServoRestyleManager::ContentAppended(nsIContent* aContainer,
nsIContent* aFirstNewContent)
{
if (!aContainer->HasServoData()) {
// This can happen with display:none. Bug 1297249 tracks more investigation
// and assertions here.
return;
}
// Style the new subtree because we will most likely need it during subsequent
// frame construction. Bug 1298281 tracks deferring this work in the lazy
// frame construction case.
if (aFirstNewContent->GetNextSibling()) {
aContainer->SetHasDirtyDescendantsForServo();
StyleSet()->StyleNewChildren(aContainer);
} else {
StyleSet()->StyleNewSubtree(aFirstNewContent);
}
RestyleForAppend(aContainer, aFirstNewContent);
}
void
@ -503,48 +108,12 @@ ServoRestyleManager::ContentRemoved(nsINode* aContainer,
nsIContent* aOldChild,
nsIContent* aFollowingSibling)
{
NS_WARNING("stylo: ServoRestyleManager::ContentRemoved not implemented");
}
void
ServoRestyleManager::ContentStateChanged(nsIContent* aContent,
EventStates aChangedBits)
{
if (!aContent->IsElement()) {
return;
}
Element* aElement = aContent->AsElement();
nsChangeHint changeHint;
nsRestyleHint restyleHint;
// NOTE: restyleHint here is effectively always 0, since that's what
// ServoStyleSet::HasStateDependentStyle returns. Servo computes on
// ProcessPendingRestyles using the ElementSnapshot, but in theory could
// compute it sequentially easily.
//
// Determine what's the best way to do it, and how much work do we save
// processing the restyle hint early (i.e., computing the style hint here
// sequentially, potentially saving the snapshot), vs lazily (snapshot
// approach).
//
// If we take the sequential approach we need to specialize Servo's restyle
// hints system a bit more, and mesure whether we save something storing the
// restyle hint in the table and deferring the dirtiness setting until
// ProcessPendingRestyles (that's a requirement if we store snapshots though),
// vs processing the restyle hint in-place, dirtying the nodes on
// PostRestyleEvent.
//
// If we definitely take the snapshot approach, we should take rid of
// HasStateDependentStyle, etc (though right now they're no-ops).
ContentStateChangedInternal(aElement, aChangedBits, &changeHint,
&restyleHint);
EventStates previousState = aElement->StyleState() ^ aChangedBits;
ServoElementSnapshot* snapshot = SnapshotForElement(aElement);
snapshot->AddState(previousState);
PostRestyleEvent(aElement, restyleHint, changeHint);
}
void
@ -553,8 +122,6 @@ ServoRestyleManager::AttributeWillChange(Element* aElement,
nsIAtom* aAttribute, int32_t aModType,
const nsAttrValue* aNewValue)
{
ServoElementSnapshot* snapshot = SnapshotForElement(aElement);
snapshot->AddAttrs(aElement);
}
void
@ -562,25 +129,18 @@ ServoRestyleManager::AttributeChanged(Element* aElement, int32_t aNameSpaceID,
nsIAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue)
{
MOZ_ASSERT(SnapshotForElement(aElement)->HasAttrs());
if (aAttribute == nsGkAtoms::style) {
PostRestyleEvent(aElement, eRestyle_StyleAttribute, nsChangeHint(0));
}
}
nsresult
ServoRestyleManager::ReparentStyleContext(nsIFrame* aFrame)
{
NS_WARNING("stylo: ServoRestyleManager::ReparentStyleContext not implemented");
return NS_OK;
}
ServoElementSnapshot*
ServoRestyleManager::SnapshotForElement(Element* aElement)
{
// NB: aElement is the argument for the construction of the snapshot in the
// not found case.
return mModifiedElements.LookupOrAdd(aElement, aElement);
return nullptr;
}
} // namespace mozilla

View file

@ -77,8 +77,7 @@ public:
bool HasPendingRestyles()
{
return !mModifiedElements.IsEmpty() ||
PresContext()->Document()->HasDirtyDescendantsForServo();
return false;
}
@ -119,10 +118,7 @@ private:
inline ServoStyleSet* StyleSet() const
{
MOZ_ASSERT(PresContext()->StyleSet()->IsServo(),
"ServoRestyleManager should only be used with a Servo-flavored "
"style backend");
return PresContext()->StyleSet()->AsServo();
return nullptr;
}
};

View file

@ -52,330 +52,219 @@ IMPL_STRONG_REF_TYPE_FOR(RawServoDeclarationBlock)
uint32_t
Gecko_ChildrenCount(RawGeckoNodeBorrowed aNode)
{
return aNode->GetChildCount();
return 0;
}
bool
Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)
{
return aNode->IsElement();
return false;
}
RawGeckoNodeBorrowedOrNull
Gecko_GetParentNode(RawGeckoNodeBorrowed aNode)
{
return aNode->GetFlattenedTreeParentNode();
return nullptr;
}
RawGeckoNodeBorrowedOrNull
Gecko_GetFirstChild(RawGeckoNodeBorrowed aNode)
{
return aNode->GetFirstChild();
return nullptr;
}
RawGeckoNodeBorrowedOrNull
Gecko_GetLastChild(RawGeckoNodeBorrowed aNode)
{
return aNode->GetLastChild();
return nullptr;
}
RawGeckoNodeBorrowedOrNull
Gecko_GetPrevSibling(RawGeckoNodeBorrowed aNode)
{
return aNode->GetPreviousSibling();
return nullptr;
}
RawGeckoNodeBorrowedOrNull
Gecko_GetNextSibling(RawGeckoNodeBorrowed aNode)
{
return aNode->GetNextSibling();
return nullptr;
}
RawGeckoElementBorrowedOrNull
Gecko_GetParentElement(RawGeckoElementBorrowed aElement)
{
nsINode* parentNode = aElement->GetFlattenedTreeParentNode();
return parentNode->IsElement() ? parentNode->AsElement() : nullptr;
return nullptr;
}
RawGeckoElementBorrowedOrNull
Gecko_GetFirstChildElement(RawGeckoElementBorrowed aElement)
{
return aElement->GetFirstElementChild();
return nullptr;
}
RawGeckoElementBorrowedOrNull Gecko_GetLastChildElement(RawGeckoElementBorrowed aElement)
{
return aElement->GetLastElementChild();
return nullptr;
}
RawGeckoElementBorrowedOrNull
Gecko_GetPrevSiblingElement(RawGeckoElementBorrowed aElement)
{
return aElement->GetPreviousElementSibling();
return nullptr;
}
RawGeckoElementBorrowedOrNull
Gecko_GetNextSiblingElement(RawGeckoElementBorrowed aElement)
{
return aElement->GetNextElementSibling();
return nullptr;
}
RawGeckoElementBorrowedOrNull
Gecko_GetDocumentElement(RawGeckoDocumentBorrowed aDoc)
{
return aDoc->GetDocumentElement();
return nullptr;
}
StyleChildrenIteratorOwnedOrNull
Gecko_MaybeCreateStyleChildrenIterator(RawGeckoNodeBorrowed aNode)
{
if (!aNode->IsElement()) {
return nullptr;
}
const Element* el = aNode->AsElement();
return StyleChildrenIterator::IsNeeded(el) ? new StyleChildrenIterator(el)
: nullptr;
return nullptr;
}
void
Gecko_DropStyleChildrenIterator(StyleChildrenIteratorOwned aIterator)
{
MOZ_ASSERT(aIterator);
delete aIterator;
}
RawGeckoNodeBorrowed
Gecko_GetNextStyleChild(StyleChildrenIteratorBorrowedMut aIterator)
{
MOZ_ASSERT(aIterator);
return aIterator->GetNextChild();
return nullptr;
}
EventStates::ServoType
Gecko_ElementState(RawGeckoElementBorrowed aElement)
{
return aElement->StyleState().ServoValue();
return 0;
}
bool
Gecko_IsHTMLElementInHTMLDocument(RawGeckoElementBorrowed aElement)
{
return aElement->IsHTMLElement() && aElement->OwnerDoc()->IsHTMLDocument();
return false;
}
bool
Gecko_IsLink(RawGeckoElementBorrowed aElement)
{
return nsCSSRuleProcessor::IsLink(aElement);
return false;
}
bool
Gecko_IsTextNode(RawGeckoNodeBorrowed aNode)
{
return aNode->NodeInfo()->NodeType() == nsIDOMNode::TEXT_NODE;
return false;
}
bool
Gecko_IsVisitedLink(RawGeckoElementBorrowed aElement)
{
return aElement->StyleState().HasState(NS_EVENT_STATE_VISITED);
return false;
}
bool
Gecko_IsUnvisitedLink(RawGeckoElementBorrowed aElement)
{
return aElement->StyleState().HasState(NS_EVENT_STATE_UNVISITED);
return false;
}
bool
Gecko_IsRootElement(RawGeckoElementBorrowed aElement)
{
return aElement->OwnerDoc()->GetRootElement() == aElement;
return false;
}
nsIAtom*
Gecko_LocalName(RawGeckoElementBorrowed aElement)
{
return aElement->NodeInfo()->NameAtom();
return nullptr;
}
nsIAtom*
Gecko_Namespace(RawGeckoElementBorrowed aElement)
{
int32_t id = aElement->NodeInfo()->NamespaceID();
return nsContentUtils::NameSpaceManager()->NameSpaceURIAtomForServo(id);
return nullptr;
}
nsIAtom*
Gecko_GetElementId(RawGeckoElementBorrowed aElement)
{
const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::id);
return attr ? attr->GetAtomValue() : nullptr;
return nullptr;
}
// Dirtiness tracking.
uint32_t
Gecko_GetNodeFlags(RawGeckoNodeBorrowed aNode)
{
return aNode->GetFlags();
return 0;
}
void
Gecko_SetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
{
const_cast<nsINode*>(aNode)->SetFlags(aFlags);
}
void
Gecko_UnsetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
{
const_cast<nsINode*>(aNode)->UnsetFlags(aFlags);
}
nsStyleContext*
Gecko_GetStyleContext(RawGeckoNodeBorrowed aNode, nsIAtom* aPseudoTagOrNull)
{
MOZ_ASSERT(aNode->IsContent());
nsIFrame* relevantFrame =
ServoRestyleManager::FrameForPseudoElement(aNode->AsContent(),
aPseudoTagOrNull);
if (!relevantFrame) {
return nullptr;
}
return relevantFrame->StyleContext();
return nullptr;
}
nsChangeHint
Gecko_CalcStyleDifference(nsStyleContext* aOldStyleContext,
ServoComputedValuesBorrowed aComputedValues)
{
MOZ_ASSERT(aOldStyleContext);
MOZ_ASSERT(aComputedValues);
// Pass the safe thing, which causes us to miss a potential optimization. See
// bug 1289863.
nsChangeHint forDescendants = nsChangeHint_Hints_NotHandledForDescendants;
// Eventually, we should compute things out of these flags like
// ElementRestyler::RestyleSelf does and pass the result to the caller to
// potentially halt traversal. See bug 1289868.
uint32_t equalStructs, samePointerStructs;
nsChangeHint result =
aOldStyleContext->CalcStyleDifference(aComputedValues,
forDescendants,
&equalStructs,
&samePointerStructs);
return result;
return nsChangeHint(0);
}
void
Gecko_StoreStyleDifference(RawGeckoNodeBorrowed aNode, nsChangeHint aChangeHintToStore)
{
#ifdef MOZ_STYLO
MOZ_ASSERT(aNode->IsElement());
MOZ_ASSERT(aNode->IsDirtyForServo(),
"Change hint stored in a not-dirty node");
const Element* aElement = aNode->AsElement();
nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
if (!primaryFrame) {
// If there's no primary frame, that means that either this content is
// undisplayed (so we only need to check at the restyling phase for the
// display value on the element), or is a display: contents element.
//
// In this second case, we should store it in the frame constructor display
// contents map. Note that while this operation looks hairy, this would be
// thread-safe because the content should be there already (we'd only need
// to read the map and modify our entry).
//
// That being said, we still don't support display: contents anyway, so it's
// probably not worth it to do all the roundtrip just yet until we have a
// more concrete plan.
return;
}
if ((aChangeHintToStore & nsChangeHint_ReconstructFrame) &&
aNode->IsInNativeAnonymousSubtree())
{
NS_WARNING("stylo: Removing forbidden frame reconstruction hint on native "
"anonymous content. Fix this in bug 1297857!");
aChangeHintToStore &= ~nsChangeHint_ReconstructFrame;
}
primaryFrame->StyleContext()->StoreChangeHint(aChangeHintToStore);
#else
MOZ_CRASH("stylo: Shouldn't call Gecko_StoreStyleDifference in "
"non-stylo build");
#endif
}
RawServoDeclarationBlockStrongBorrowedOrNull
Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
{
const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::style);
if (!attr || attr->Type() != nsAttrValue::eCSSDeclaration) {
return nullptr;
}
DeclarationBlock* decl = attr->GetCSSDeclarationValue();
if (!decl) {
return nullptr;
}
if (decl->IsGecko()) {
// XXX This can happen at least when script sets style attribute
// since we haven't implemented Element.style for stylo. But
// we may want to turn it into an assertion after that's done.
NS_WARNING("stylo: requesting a Gecko declaration block?");
return nullptr;
}
return reinterpret_cast<const RawServoDeclarationBlockStrong*>
(decl->AsServo()->RefRaw());
return nullptr;
}
void
Gecko_FillAllBackgroundLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
{
nsRuleNode::FillAllBackgroundLists(*aLayers, aMaxLen);
}
void
Gecko_FillAllMaskLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
{
nsRuleNode::FillAllMaskLists(*aLayers, aMaxLen);
}
template <typename Implementor>
static nsIAtom*
AtomAttrValue(Implementor* aElement, nsIAtom* aName)
{
const nsAttrValue* attr = aElement->GetParsedAttr(aName);
return attr ? attr->GetAtomValue() : nullptr;
return nullptr;
}
template <typename Implementor, typename MatchFn>
static bool
DoMatch(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
{
if (aNS) {
int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS,
aElement->IsInChromeDocument());
NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
return value && aMatch(value);
}
// No namespace means any namespace - we have to check them all. :-(
BorrowedAttrInfo attrInfo;
for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
if (attrInfo.mName->LocalName() != aName) {
continue;
}
if (aMatch(attrInfo.mValue)) {
return true;
}
}
return false;
}
@ -383,8 +272,7 @@ template <typename Implementor>
static bool
HasAttr(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName)
{
auto match = [](const nsAttrValue* aValue) { return true; };
return DoMatch(aElement, aNS, aName, match);
return false;
}
template <typename Implementor>
@ -392,10 +280,7 @@ static bool
AttrEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, nsIAtom* aStr,
bool aIgnoreCase)
{
auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
};
return DoMatch(aElement, aNS, aName, match);
return false;
}
template <typename Implementor>
@ -403,13 +288,7 @@ static bool
AttrDashEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
nsIAtom* aStr)
{
auto match = [aStr](const nsAttrValue* aValue) {
nsAutoString str;
aValue->ToString(str);
const nsDefaultStringComparator c;
return nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c);
};
return DoMatch(aElement, aNS, aName, match);
return false;
}
template <typename Implementor>
@ -417,13 +296,7 @@ static bool
AttrIncludes(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
nsIAtom* aStr)
{
auto match = [aStr](const nsAttrValue* aValue) {
nsAutoString str;
aValue->ToString(str);
const nsDefaultStringComparator c;
return nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c);
};
return DoMatch(aElement, aNS, aName, match);
return false;
}
template <typename Implementor>
@ -431,12 +304,7 @@ static bool
AttrHasSubstring(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
nsIAtom* aStr)
{
auto match = [aStr](const nsAttrValue* aValue) {
nsAutoString str;
aValue->ToString(str);
return FindInReadable(str, nsDependentAtomString(aStr));
};
return DoMatch(aElement, aNS, aName, match);
return false;
}
template <typename Implementor>
@ -444,12 +312,7 @@ static bool
AttrHasPrefix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
nsIAtom* aStr)
{
auto match = [aStr](const nsAttrValue* aValue) {
nsAutoString str;
aValue->ToString(str);
return StringBeginsWith(str, nsDependentAtomString(aStr));
};
return DoMatch(aElement, aNS, aName, match);
return false;
}
template <typename Implementor>
@ -457,12 +320,7 @@ static bool
AttrHasSuffix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
nsIAtom* aStr)
{
auto match = [aStr](const nsAttrValue* aValue) {
nsAutoString str;
aValue->ToString(str);
return StringEndsWith(str, nsDependentAtomString(aStr));
};
return DoMatch(aElement, aNS, aName, match);
return false;
}
/**
@ -482,54 +340,7 @@ template <typename Implementor>
static uint32_t
ClassOrClassList(Implementor* aElement, nsIAtom** aClass, nsIAtom*** aClassList)
{
const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::_class);
if (!attr) {
return 0;
}
// For class values with only whitespace, Gecko just stores a string. For the
// purposes of the style system, there is no class in this case.
if (attr->Type() == nsAttrValue::eString) {
MOZ_ASSERT(nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
attr->GetStringValue()).IsEmpty());
return 0;
}
// Single tokens are generally stored as an atom. Check that case.
if (attr->Type() == nsAttrValue::eAtom) {
*aClass = attr->GetAtomValue();
return 1;
}
// At this point we should have an atom array. It is likely, but not
// guaranteed, that we have two or more elements in the array.
MOZ_ASSERT(attr->Type() == nsAttrValue::eAtomArray);
nsTArray<nsCOMPtr<nsIAtom>>* atomArray = attr->GetAtomArrayValue();
uint32_t length = atomArray->Length();
// Special case: zero elements.
if (length == 0) {
return 0;
}
// Special case: one element.
if (length == 1) {
*aClass = atomArray->ElementAt(0);
return 1;
}
// General case: Two or more elements.
//
// Note: We could also expose this array as an array of nsCOMPtrs, since
// bindgen knows what those look like, and eliminate the reinterpret_cast.
// But it's not obvious that that would be preferable.
static_assert(sizeof(nsCOMPtr<nsIAtom>) == sizeof(nsIAtom*), "Bad simplification");
static_assert(alignof(nsCOMPtr<nsIAtom>) == alignof(nsIAtom*), "Bad simplification");
nsCOMPtr<nsIAtom>* elements = atomArray->Elements();
nsIAtom** rawElements = reinterpret_cast<nsIAtom**>(elements);
*aClassList = rawElements;
return atomArray->Length();
return 0;
}
#define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
@ -585,51 +396,35 @@ SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, ServoElementSnapshot*
nsIAtom*
Gecko_Atomize(const char* aString, uint32_t aLength)
{
return NS_Atomize(nsDependentCSubstring(aString, aLength)).take();
return nullptr;
}
void
Gecko_AddRefAtom(nsIAtom* aAtom)
{
NS_ADDREF(aAtom);
}
void
Gecko_ReleaseAtom(nsIAtom* aAtom)
{
NS_RELEASE(aAtom);
}
const uint16_t*
Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength)
{
static_assert(sizeof(char16_t) == sizeof(uint16_t), "Servo doesn't know what a char16_t is");
MOZ_ASSERT(aAtom);
*aLength = aAtom->GetLength();
// We need to manually cast from char16ptr_t to const char16_t* to handle the
// MOZ_USE_CHAR16_WRAPPER we use on WIndows.
return reinterpret_cast<const uint16_t*>(static_cast<const char16_t*>(aAtom->GetUTF16String()));
return nullptr;
}
bool
Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength)
{
// XXXbholley: We should be able to do this without converting, I just can't
// find the right thing to call.
nsDependentAtomString atomStr(aAtom);
NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
return atomStr.Equals(inStr);
return false;
}
bool
Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLength)
{
// XXXbholley: We should be able to do this without converting, I just can't
// find the right thing to call.
nsDependentAtomString atomStr(aAtom);
NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
return nsContentUtils::EqualsIgnoreASCIICase(atomStr, inStr);
return false;
}
void
@ -637,53 +432,35 @@ Gecko_Utf8SliceToString(nsString* aString,
const uint8_t* aBuffer,
size_t aBufferLen)
{
MOZ_ASSERT(aString);
MOZ_ASSERT(aBuffer);
aString->Truncate();
AppendUTF8toUTF16(Substring(reinterpret_cast<const char*>(aBuffer),
aBufferLen), *aString);
}
void
Gecko_FontFamilyList_Clear(FontFamilyList* aList) {
aList->Clear();
}
void
Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName)
{
// Servo doesn't record whether the name was quoted or unquoted, so just
// assume unquoted for now.
FontFamilyName family;
aName->ToString(family.mName);
aList->Append(family);
}
void
Gecko_FontFamilyList_AppendGeneric(FontFamilyList* aList, FontFamilyType aType)
{
aList->Append(FontFamilyName(aType));
}
void
Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src)
{
dst->fontlist = src->fontlist;
}
void
Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type)
{
// Builtin counter styles are static and use no-op refcounting, and thus are
// safe to use off-main-thread.
style_struct->SetCounterStyle(CounterStyleManager::GetBuiltinStyle(type));
}
void
Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src)
{
dst->SetCounterStyle(src->GetCounterStyle());
}
NS_IMPL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
@ -696,42 +473,22 @@ Gecko_SetMozBinding(nsStyleDisplay* aDisplay,
ThreadSafeURIHolder* aReferrer,
ThreadSafePrincipalHolder* aPrincipal)
{
MOZ_ASSERT(aDisplay);
MOZ_ASSERT(aURLString);
MOZ_ASSERT(aBaseURI);
MOZ_ASSERT(aReferrer);
MOZ_ASSERT(aPrincipal);
nsString url;
nsDependentCSubstring urlString(reinterpret_cast<const char*>(aURLString),
aURLStringLength);
AppendUTF8toUTF16(urlString, url);
RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
aDisplay->mBinding =
new css::URLValue(urlBuffer, do_AddRef(aBaseURI),
do_AddRef(aReferrer), do_AddRef(aPrincipal));
}
void
Gecko_CopyMozBindingFrom(nsStyleDisplay* aDest, const nsStyleDisplay* aSrc)
{
aDest->mBinding = aSrc->mBinding;
}
void
Gecko_SetNullImageValue(nsStyleImage* aImage)
{
MOZ_ASSERT(aImage);
aImage->SetNull();
}
void
Gecko_SetGradientImageValue(nsStyleImage* aImage, nsStyleGradient* aGradient)
{
MOZ_ASSERT(aImage);
aImage->SetGradientData(aGradient);
}
static already_AddRefed<nsStyleImageRequest>
@ -741,21 +498,7 @@ CreateStyleImageRequest(nsStyleImageRequest::Mode aModeFlags,
ThreadSafeURIHolder* aReferrer,
ThreadSafePrincipalHolder* aPrincipal)
{
MOZ_ASSERT(aURLString);
MOZ_ASSERT(aBaseURI);
MOZ_ASSERT(aReferrer);
MOZ_ASSERT(aPrincipal);
nsString url;
nsDependentCSubstring urlString(reinterpret_cast<const char*>(aURLString),
aURLStringLength);
AppendUTF8toUTF16(urlString, url);
RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
RefPtr<nsStyleImageRequest> req =
new nsStyleImageRequest(aModeFlags, urlBuffer, do_AddRef(aBaseURI),
do_AddRef(aReferrer), do_AddRef(aPrincipal));
return req.forget();
return nullptr;
}
void
@ -765,20 +508,11 @@ Gecko_SetUrlImageValue(nsStyleImage* aImage,
ThreadSafeURIHolder* aReferrer,
ThreadSafePrincipalHolder* aPrincipal)
{
RefPtr<nsStyleImageRequest> req =
CreateStyleImageRequest(nsStyleImageRequest::Mode::Track,
aURLString, aURLStringLength,
aBaseURI, aReferrer, aPrincipal);
aImage->SetImageRequest(req.forget());
}
void
Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
{
MOZ_ASSERT(aImage);
MOZ_ASSERT(aOther);
*aImage = *aOther;
}
nsStyleGradient*
@ -788,35 +522,12 @@ Gecko_CreateGradient(uint8_t aShape,
bool aLegacySyntax,
uint32_t aStopCount)
{
nsStyleGradient* result = new nsStyleGradient();
result->mShape = aShape;
result->mSize = aSize;
result->mRepeating = aRepeating;
result->mLegacySyntax = aLegacySyntax;
result->mAngle.SetNoneValue();
result->mBgPosX.SetNoneValue();
result->mBgPosY.SetNoneValue();
result->mRadiusX.SetNoneValue();
result->mRadiusY.SetNoneValue();
nsStyleGradientStop dummyStop;
dummyStop.mLocation.SetNoneValue();
dummyStop.mColor = NS_RGB(0, 0, 0);
dummyStop.mIsInterpolationHint = 0;
for (uint32_t i = 0; i < aStopCount; i++) {
result->mStops.AppendElement(dummyStop);
}
return result;
return nullptr;
}
void
Gecko_SetListStyleImageNone(nsStyleList* aList)
{
aList->mListStyleImage = nullptr;
}
void
@ -826,123 +537,73 @@ Gecko_SetListStyleImage(nsStyleList* aList,
ThreadSafeURIHolder* aReferrer,
ThreadSafePrincipalHolder* aPrincipal)
{
aList->mListStyleImage =
CreateStyleImageRequest(nsStyleImageRequest::Mode(0),
aURLString, aURLStringLength,
aBaseURI, aReferrer, aPrincipal);
}
void
Gecko_CopyListStyleImageFrom(nsStyleList* aList, const nsStyleList* aSource)
{
aList->mListStyleImage = aSource->mListStyleImage;
}
void
Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity, size_t aElemSize)
{
auto base =
reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
nsTArray_CopyWithMemutils>*>(aArray);
base->EnsureCapacity<nsTArrayInfallibleAllocator>(aCapacity, aElemSize);
}
void
Gecko_ClearPODTArray(void* aArray, size_t aElementSize, size_t aElementAlign)
{
auto base =
reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
nsTArray_CopyWithMemutils>*>(aArray);
base->template ShiftData<nsTArrayInfallibleAllocator>(0, base->Length(), 0,
aElementSize, aElementAlign);
}
void
Gecko_ClearStyleContents(nsStyleContent* aContent)
{
aContent->AllocateContents(0);
}
void
Gecko_CopyStyleContentsFrom(nsStyleContent* aContent, const nsStyleContent* aOther)
{
uint32_t count = aOther->ContentCount();
aContent->AllocateContents(count);
for (uint32_t i = 0; i < count; ++i) {
aContent->ContentAt(i) = aOther->ContentAt(i);
}
}
void
Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
nsStyleImageLayers::LayerType aLayerType)
{
size_t oldLength = aLayers->mLayers.Length();
aLayers->mLayers.EnsureLengthAtLeast(aLen);
for (size_t i = oldLength; i < aLen; ++i) {
aLayers->mLayers[i].Initialize(aLayerType);
}
}
void
Gecko_ResetStyleCoord(nsStyleUnit* aUnit, nsStyleUnion* aValue)
{
nsStyleCoord::Reset(*aUnit, *aValue);
}
void
Gecko_SetStyleCoordCalcValue(nsStyleUnit* aUnit, nsStyleUnion* aValue, nsStyleCoord::CalcValue aCalc)
{
// Calc units should be cleaned up first
MOZ_ASSERT(*aUnit != nsStyleUnit::eStyleUnit_Calc);
nsStyleCoord::Calc* calcRef = new nsStyleCoord::Calc();
calcRef->mLength = aCalc.mLength;
calcRef->mPercent = aCalc.mPercent;
calcRef->mHasPercent = aCalc.mHasPercent;
*aUnit = nsStyleUnit::eStyleUnit_Calc;
aValue->mPointer = calcRef;
calcRef->AddRef();
}
void
Gecko_CopyClipPathValueFrom(mozilla::StyleClipPath* aDst, const mozilla::StyleClipPath* aSrc)
{
MOZ_ASSERT(aDst);
MOZ_ASSERT(aSrc);
*aDst = *aSrc;
}
void
Gecko_DestroyClipPath(mozilla::StyleClipPath* aClip)
{
aClip->~StyleClipPath();
}
mozilla::StyleBasicShape*
Gecko_NewBasicShape(mozilla::StyleBasicShapeType aType)
{
RefPtr<StyleBasicShape> ptr = new mozilla::StyleBasicShape(aType);
return ptr.forget().take();
return nullptr;
}
void
Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len)
{
effects->mFilters.Clear();
effects->mFilters.SetLength(new_len);
}
void
Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest)
{
aDest->mFilters = aSrc->mFilters;
}
NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
@ -950,8 +611,7 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
nsCSSShadowArray*
Gecko_NewCSSShadowArray(uint32_t aLen)
{
RefPtr<nsCSSShadowArray> arr = new(aLen) nsCSSShadowArray(aLen);
return arr.forget().take();
return nullptr;
}
NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSShadowArray, CSSShadowArray);
@ -959,9 +619,7 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSShadowArray, CSSShadowArray);
nsStyleQuoteValues*
Gecko_NewStyleQuoteValues(uint32_t aLen)
{
RefPtr<nsStyleQuoteValues> values = new nsStyleQuoteValues;
values->mQuotePairs.SetLength(aLen);
return values.forget().take();
return nullptr;
}
NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleQuoteValues, QuoteValues);
@ -969,68 +627,48 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleQuoteValues, QuoteValues);
nsCSSValueSharedList*
Gecko_NewCSSValueSharedList(uint32_t aLen)
{
RefPtr<nsCSSValueSharedList> list = new nsCSSValueSharedList;
if (aLen == 0) {
return list.forget().take();
}
list->mHead = new nsCSSValueList;
nsCSSValueList* cur = list->mHead;
for (uint32_t i = 0; i < aLen - 1; i++) {
cur->mNext = new nsCSSValueList;
cur = cur->mNext;
}
return list.forget().take();
return nullptr;
}
void
Gecko_CSSValue_SetAbsoluteLength(nsCSSValueBorrowedMut aCSSValue, nscoord aLen)
{
aCSSValue->SetIntegerCoordValue(aLen);
}
void
Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut aCSSValue, float aNumber)
{
aCSSValue->SetFloatValue(aNumber, eCSSUnit_Number);
}
void
Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut aCSSValue, nsCSSKeyword aKeyword)
{
aCSSValue->SetIntValue(aKeyword, eCSSUnit_Enumerated);
}
void
Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut aCSSValue, float aPercent)
{
aCSSValue->SetFloatValue(aPercent, eCSSUnit_Number);
}
void
Gecko_CSSValue_SetAngle(nsCSSValueBorrowedMut aCSSValue, float aRadians)
{
aCSSValue->SetFloatValue(aRadians, eCSSUnit_Radian);
}
void
Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut aCSSValue, nsStyleCoord::CalcValue aCalc)
{
aCSSValue->SetCalcValue(&aCalc);
}
void
Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut aCSSValue, int32_t aLen)
{
nsCSSValue::Array* arr = nsCSSValue::Array::Create(aLen);
aCSSValue->SetArrayValue(arr, eCSSUnit_Function);
}
nsCSSValueBorrowedMut
Gecko_CSSValue_GetArrayItem(nsCSSValueBorrowedMut aCSSValue, int32_t aIndex)
{
return &aCSSValue->GetArrayValue()->Item(aIndex);
return nullptr;
}
NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
@ -1040,20 +678,17 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
void \
Gecko_Construct_nsStyle##name(nsStyle##name* ptr) \
{ \
new (ptr) nsStyle##name(StyleStructContext::ServoContext()); \
} \
\
void \
Gecko_CopyConstruct_nsStyle##name(nsStyle##name* ptr, \
const nsStyle##name* other) \
{ \
new (ptr) nsStyle##name(*other); \
} \
\
void \
Gecko_Destroy_nsStyle##name(nsStyle##name* ptr) \
{ \
ptr->~nsStyle##name(); \
}
#include "nsStyleStructList.h"

View file

@ -14,11 +14,7 @@ namespace mozilla {
/* static */ already_AddRefed<ServoDeclarationBlock>
ServoDeclarationBlock::FromCssText(const nsAString& aCssText)
{
NS_ConvertUTF16toUTF8 value(aCssText);
RefPtr<RawServoDeclarationBlock>
raw = Servo_ParseStyleAttribute(&value).Consume();
RefPtr<ServoDeclarationBlock> decl = new ServoDeclarationBlock(raw.forget());
return decl.forget();
return nullptr;
}
/**
@ -29,27 +25,10 @@ class MOZ_STACK_CLASS PropertyAtomHolder
public:
explicit PropertyAtomHolder(const nsAString& aProperty)
{
nsCSSPropertyID propID =
nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
if (propID == eCSSPropertyExtra_variable) {
mIsCustomProperty = true;
mAtom = NS_Atomize(
Substring(aProperty, CSS_CUSTOM_NAME_PREFIX_LENGTH)).take();
} else {
mIsCustomProperty = false;
if (propID != eCSSProperty_UNKNOWN) {
mAtom = nsCSSProps::AtomForProperty(propID);
} else {
mAtom = nullptr;
}
}
}
~PropertyAtomHolder()
{
if (mIsCustomProperty) {
NS_RELEASE(mAtom);
}
}
explicit operator bool() const { return !!mAtom; }
@ -65,46 +44,28 @@ void
ServoDeclarationBlock::GetPropertyValue(const nsAString& aProperty,
nsAString& aValue) const
{
if (PropertyAtomHolder holder{aProperty}) {
Servo_DeclarationBlock_GetPropertyValue(
mRaw, holder.Atom(), holder.IsCustomProperty(), &aValue);
}
}
void
ServoDeclarationBlock::GetPropertyValueByID(nsCSSPropertyID aPropID,
nsAString& aValue) const
{
nsIAtom* atom = nsCSSProps::AtomForProperty(aPropID);
Servo_DeclarationBlock_GetPropertyValue(mRaw, atom, false, &aValue);
}
bool
ServoDeclarationBlock::GetPropertyIsImportant(const nsAString& aProperty) const
{
if (PropertyAtomHolder holder{aProperty}) {
return Servo_DeclarationBlock_GetPropertyIsImportant(
mRaw, holder.Atom(), holder.IsCustomProperty());
}
return false;
}
void
ServoDeclarationBlock::RemoveProperty(const nsAString& aProperty)
{
AssertMutable();
if (PropertyAtomHolder holder{aProperty}) {
Servo_DeclarationBlock_RemoveProperty(mRaw, holder.Atom(),
holder.IsCustomProperty());
}
}
void
ServoDeclarationBlock::RemovePropertyByID(nsCSSPropertyID aPropID)
{
AssertMutable();
nsIAtom* atom = nsCSSProps::AtomForProperty(aPropID);
Servo_DeclarationBlock_RemoveProperty(mRaw, atom, false);
}
} // namespace mozilla

View file

@ -16,30 +16,11 @@ ServoElementSnapshot::ServoElementSnapshot(Element* aElement)
, mExplicitRestyleHint(nsRestyleHint(0))
, mExplicitChangeHint(nsChangeHint(0))
{
mIsHTMLElementInHTMLDocument =
aElement->IsHTMLElement() && aElement->IsInHTMLDocument();
mIsInChromeDocument =
nsContentUtils::IsChromeDoc(aElement->OwnerDoc());
}
void
ServoElementSnapshot::AddAttrs(Element* aElement)
{
MOZ_ASSERT(aElement);
if (HasAny(Flags::Attributes)) {
return;
}
uint32_t attrCount = aElement->GetAttrCount();
const nsAttrName* attrName;
for (uint32_t i = 0; i < attrCount; ++i) {
attrName = aElement->GetAttrNameAt(i);
const nsAttrValue* attrValue =
aElement->GetParsedAttr(attrName->LocalName(), attrName->NamespaceID());
mAttrs.AppendElement(ServoAttrSnapshot(*attrName, *attrValue));
}
mContains |= Flags::Attributes;
}
} // namespace mozilla

View file

@ -77,10 +77,6 @@ public:
*/
void AddState(EventStates aState)
{
if (!HasAny(Flags::State)) {
mState = aState.ServoValue();
mContains |= Flags::State;
}
}
/**
@ -90,12 +86,10 @@ public:
void AddExplicitChangeHint(nsChangeHint aMinChangeHint)
{
mExplicitChangeHint |= aMinChangeHint;
}
void AddExplicitRestyleHint(nsRestyleHint aRestyleHint)
{
mExplicitRestyleHint |= aRestyleHint;
}
nsRestyleHint ExplicitRestyleHint() { return mExplicitRestyleHint; }
@ -107,10 +101,7 @@ public:
*/
BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const
{
if (aIndex >= mAttrs.Length()) {
return BorrowedAttrInfo(nullptr, nullptr);
}
return BorrowedAttrInfo(&mAttrs[aIndex].mName, &mAttrs[aIndex].mValue);
return BorrowedAttrInfo(nullptr, nullptr);
}
const nsAttrValue* GetParsedAttr(nsIAtom* aLocalName) const
@ -121,33 +112,18 @@ public:
const nsAttrValue* GetParsedAttr(nsIAtom* aLocalName,
int32_t aNamespaceID) const
{
uint32_t i, len = mAttrs.Length();
if (aNamespaceID == kNameSpaceID_None) {
// This should be the common case so lets make an optimized loop
for (i = 0; i < len; ++i) {
if (mAttrs[i].mName.Equals(aLocalName)) {
return &mAttrs[i].mValue;
}
}
return nullptr;
}
for (i = 0; i < len; ++i) {
if (mAttrs[i].mName.Equals(aLocalName, aNamespaceID)) {
return &mAttrs[i].mValue;
}
}
return nullptr;
}
bool IsInChromeDocument() const
{
return mIsInChromeDocument;
return false;
}
bool HasAny(Flags aFlags) { return bool(mContains & aFlags); }
bool HasAny(Flags aFlags)
{
return false;
}
private:
// TODO: Profile, a 1 or 2 element AutoTArray could be worth it, given we know

View file

@ -51,24 +51,17 @@ ServoStyleSet::GetAuthorStyleDisabled() const
nsresult
ServoStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled)
{
MOZ_CRASH("stylo: not implemented");
return NS_OK;
}
void
ServoStyleSet::BeginUpdate()
{
++mBatching;
}
nsresult
ServoStyleSet::EndUpdate()
{
MOZ_ASSERT(mBatching > 0);
if (--mBatching > 0) {
return NS_OK;
}
// ... do something ...
return NS_OK;
}
@ -76,8 +69,7 @@ already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext)
{
return GetContext(aElement, aParentContext, nullptr,
CSSPseudoElementType::NotPseudo);
return nullptr;
}
already_AddRefed<nsStyleContext>
@ -86,10 +78,7 @@ ServoStyleSet::GetContext(nsIContent* aContent,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType)
{
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Get(aContent).Consume();
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType);
return nullptr;
}
already_AddRefed<nsStyleContext>
@ -98,14 +87,7 @@ ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType)
{
// XXXbholley: nsStyleSet does visited handling here.
// XXXbholley: Figure out the correct thing to pass here. Does this fixup
// duplicate something that servo already does?
bool skipFixup = false;
return NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
aPseudoType, Move(aComputedValues), skipFixup);
return nullptr;
}
already_AddRefed<nsStyleContext>
@ -113,47 +95,20 @@ ServoStyleSet::ResolveStyleFor(Element* aElement,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext)
{
// aTreeMatchContext is used to speed up selector matching,
// but if the element already has a ServoComputedValues computed in
// advance, then we shouldn't need to use it.
return ResolveStyleFor(aElement, aParentContext);
return nullptr;
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
nsStyleContext* aParentContext)
{
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->StyleSource().AsServoComputedValues();
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(parentComputedValues).Consume();
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::mozText, CSSPseudoElementType::AnonBox);
return nullptr;
}
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleForOtherNonElement(nsStyleContext* aParentContext)
{
// The parent context can be null if the non-element share a style context
// with the root of an anonymous subtree.
const ServoComputedValues* parent =
aParentContext ? aParentContext->StyleSource().AsServoComputedValues() : nullptr;
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(parent).Consume();
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::mozOtherNonElement,
CSSPseudoElementType::AnonBox);
return nullptr;
}
already_AddRefed<nsStyleContext>
@ -162,20 +117,7 @@ ServoStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
nsStyleContext* aParentContext,
Element* aPseudoElement)
{
if (aPseudoElement) {
NS_ERROR("stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
}
MOZ_ASSERT(aParentContext);
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_GetForPseudoElement(
aParentContext->StyleSource().AsServoComputedValues(),
aParentElement, pseudoTag, mRawSet.get(), /* is_probe = */ false).Consume();
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
return nullptr;
}
// aFlags is an nsStyleSet flags bitfield
@ -184,31 +126,7 @@ ServoStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
nsStyleContext* aParentContext,
uint32_t aFlags)
{
MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag));
MOZ_ASSERT(aFlags == 0 ||
aFlags == nsStyleSet::eSkipParentDisplayBasedStyleFixup);
bool skipFixup = aFlags & nsStyleSet::eSkipParentDisplayBasedStyleFixup;
const ServoComputedValues* parentStyle =
aParentContext ? aParentContext->StyleSource().AsServoComputedValues()
: nullptr;
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_GetForAnonymousBox(parentStyle, aPseudoTag,
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();
}
#endif
return NS_NewStyleContext(aParentContext, mPresContext, aPseudoTag,
CSSPseudoElementType::AnonBox,
computedValues.forget(), skipFixup);
return nullptr;
}
// manage the set of style sheets in the style set
@ -216,16 +134,6 @@ nsresult
ServoStyleSet::AppendStyleSheet(SheetType aType,
ServoStyleSheet* aSheet)
{
MOZ_ASSERT(aSheet);
MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
mSheets[aType].RemoveElement(aSheet);
mSheets[aType].AppendElement(aSheet);
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet->RawSheet());
return NS_OK;
}
@ -233,16 +141,6 @@ nsresult
ServoStyleSet::PrependStyleSheet(SheetType aType,
ServoStyleSheet* aSheet)
{
MOZ_ASSERT(aSheet);
MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
mSheets[aType].RemoveElement(aSheet);
mSheets[aType].InsertElementAt(0, aSheet);
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_PrependStyleSheet(mRawSet.get(), aSheet->RawSheet());
return NS_OK;
}
@ -250,15 +148,6 @@ nsresult
ServoStyleSet::RemoveStyleSheet(SheetType aType,
ServoStyleSheet* aSheet)
{
MOZ_ASSERT(aSheet);
MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
mSheets[aType].RemoveElement(aSheet);
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), aSheet->RawSheet());
return NS_OK;
}
@ -266,22 +155,6 @@ nsresult
ServoStyleSet::ReplaceSheets(SheetType aType,
const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets)
{
// Gecko uses a two-dimensional array keyed by sheet type, whereas Servo
// stores a flattened list. This makes ReplaceSheets a pretty clunky thing
// to express. If the need ever arises, we can easily make this more efficent,
// probably by aligning the representations better between engines.
for (ServoStyleSheet* sheet : mSheets[aType]) {
Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), sheet->RawSheet());
}
mSheets[aType].Clear();
mSheets[aType].AppendElements(aNewSheets);
for (ServoStyleSheet* sheet : mSheets[aType]) {
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet->RawSheet());
}
return NS_OK;
}
@ -290,68 +163,32 @@ ServoStyleSet::InsertStyleSheetBefore(SheetType aType,
ServoStyleSheet* aNewSheet,
ServoStyleSheet* aReferenceSheet)
{
MOZ_ASSERT(aNewSheet);
MOZ_ASSERT(aReferenceSheet);
MOZ_ASSERT(aNewSheet->IsApplicable());
mSheets[aType].RemoveElement(aNewSheet);
size_t idx = mSheets[aType].IndexOf(aReferenceSheet);
if (idx == mSheets[aType].NoIndex) {
return NS_ERROR_INVALID_ARG;
}
mSheets[aType].InsertElementAt(idx, aNewSheet);
// Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aNewSheet->RawSheet(),
aReferenceSheet->RawSheet());
return NS_OK;
}
int32_t
ServoStyleSet::SheetCount(SheetType aType) const
{
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
return mSheets[aType].Length();
return 0;
}
ServoStyleSheet*
ServoStyleSet::StyleSheetAt(SheetType aType,
int32_t aIndex) const
{
MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
return mSheets[aType][aIndex];
return nullptr;
}
nsresult
ServoStyleSet::RemoveDocStyleSheet(ServoStyleSheet* aSheet)
{
return RemoveStyleSheet(SheetType::Doc, aSheet);
return NS_OK;
}
nsresult
ServoStyleSet::AddDocStyleSheet(ServoStyleSheet* aSheet,
nsIDocument* aDocument)
{
RefPtr<StyleSheet> strong(aSheet);
mSheets[SheetType::Doc].RemoveElement(aSheet);
size_t index =
aDocument->FindDocStyleSheetInsertionPoint(mSheets[SheetType::Doc], *aSheet);
mSheets[SheetType::Doc].InsertElementAt(index, aSheet);
// Maintain a mirrored list of sheets on the servo side.
ServoStyleSheet* followingSheet =
mSheets[SheetType::Doc].SafeElementAt(index + 1);
if (followingSheet) {
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aSheet->RawSheet(),
followingSheet->RawSheet());
} else {
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet->RawSheet());
}
return NS_OK;
}
@ -360,35 +197,7 @@ ServoStyleSet::ProbePseudoElementStyle(Element* aParentElement,
CSSPseudoElementType aType,
nsStyleContext* aParentContext)
{
MOZ_ASSERT(aParentContext);
MOZ_ASSERT(aType < CSSPseudoElementType::Count);
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_GetForPseudoElement(
aParentContext->StyleSource().AsServoComputedValues(),
aParentElement, pseudoTag, mRawSet.get(), /* is_probe = */ true).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.
if (computedValues &&
(pseudoTag == nsCSSPseudoElements::before ||
pseudoTag == nsCSSPseudoElements::after)) {
const nsStyleDisplay *display = Servo_GetStyleDisplay(computedValues);
const nsStyleContent *content = Servo_GetStyleContent(computedValues);
// XXXldb What is contentCount for |content: ""|?
if (display->mDisplay == StyleDisplay::None ||
content->ContentCount() == 0) {
return nullptr;
}
}
return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType);
return nullptr;
}
already_AddRefed<nsStyleContext>
@ -398,17 +207,13 @@ ServoStyleSet::ProbePseudoElementStyle(Element* aParentElement,
TreeMatchContext& aTreeMatchContext,
Element* aPseudoElement)
{
if (aPseudoElement) {
NS_ERROR("stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
}
return ProbePseudoElementStyle(aParentElement, aType, aParentContext);
return nullptr;
}
nsRestyleHint
ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
EventStates aStateMask)
{
NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
return nsRestyleHint(0);
}
@ -418,7 +223,6 @@ ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
dom::Element* aPseudoElement,
EventStates aStateMask)
{
NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
return nsRestyleHint(0);
}
@ -426,54 +230,25 @@ nsRestyleHint
ServoStyleSet::ComputeRestyleHint(dom::Element* aElement,
ServoElementSnapshot* aSnapshot)
{
return Servo_ComputeRestyleHint(aElement, aSnapshot, mRawSet.get());
return nsRestyleHint(0);
}
static void
ClearDirtyBits(nsIContent* aContent)
{
bool traverseDescendants = aContent->HasDirtyDescendantsForServo();
aContent->UnsetIsDirtyAndHasDirtyDescendantsForServo();
if (!traverseDescendants) {
return;
}
StyleChildrenIterator it(aContent);
for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
ClearDirtyBits(n);
}
}
void
ServoStyleSet::StyleDocument(bool aLeaveDirtyBits)
{
// Grab the root.
nsIDocument* doc = mPresContext->Document();
nsIContent* root = doc->GetRootElement();
MOZ_ASSERT(root);
// Restyle the document, clearing the dirty bits if requested.
Servo_RestyleSubtree(root, mRawSet.get());
if (!aLeaveDirtyBits) {
ClearDirtyBits(root);
doc->UnsetHasDirtyDescendantsForServo();
}
}
void
ServoStyleSet::StyleNewSubtree(nsIContent* aContent)
{
MOZ_ASSERT(aContent->IsDirtyForServo());
if (aContent->IsElement() || aContent->IsNodeOfType(nsINode::eTEXT)) {
Servo_RestyleSubtree(aContent, mRawSet.get());
}
ClearDirtyBits(aContent);
}
void
ServoStyleSet::StyleNewChildren(nsIContent* aParent)
{
MOZ_ASSERT(aParent->HasDirtyDescendantsForServo());
Servo_RestyleSubtree(aParent, mRawSet.get());
ClearDirtyBits(aParent);
}

View file

@ -23,44 +23,29 @@ ServoStyleSheet::ServoStyleSheet(css::SheetParsingMode aParsingMode,
ServoStyleSheet::~ServoStyleSheet()
{
DropSheet();
}
bool
ServoStyleSheet::HasRules() const
{
return mSheet && Servo_StyleSheet_HasRules(mSheet);
return false;
}
void
ServoStyleSheet::SetAssociatedDocument(nsIDocument* aDocument,
DocumentAssociationMode aAssociationMode)
{
MOZ_ASSERT_IF(!aDocument, aAssociationMode == NotOwnedByDocument);
// XXXheycam: Traverse to child ServoStyleSheets to set this, like
// CSSStyleSheet::SetAssociatedDocument does.
mDocument = aDocument;
mDocumentAssociationMode = aAssociationMode;
}
ServoStyleSheet*
ServoStyleSheet::GetParentSheet() const
{
// XXXheycam: When we implement support for child sheets, we'll have
// to fix SetAssociatedDocument to propagate the associated document down
// to the children.
MOZ_CRASH("stylo: not implemented");
return nullptr;
}
void
ServoStyleSheet::AppendStyleSheet(ServoStyleSheet* aSheet)
{
// XXXheycam: When we implement support for child sheets, we'll have
// to fix SetOwningDocument to propagate the owning document down
// to the children.
MOZ_CRASH("stylo: not implemented");
}
nsresult
@ -70,40 +55,23 @@ ServoStyleSheet::ParseSheet(const nsAString& aInput,
nsIPrincipal* aSheetPrincipal,
uint32_t aLineNumber)
{
DropSheet();
RefPtr<ThreadSafeURIHolder> base = new ThreadSafeURIHolder(aBaseURI);
RefPtr<ThreadSafeURIHolder> referrer = new ThreadSafeURIHolder(aSheetURI);
RefPtr<ThreadSafePrincipalHolder> principal =
new ThreadSafePrincipalHolder(aSheetPrincipal);
nsCString baseString;
nsresult rv = aBaseURI->GetSpec(baseString);
NS_ENSURE_SUCCESS(rv, rv);
NS_ConvertUTF16toUTF8 input(aInput);
mSheet = Servo_StyleSheet_FromUTF8Bytes(&input, mParsingMode, &baseString,
base, referrer, principal).Consume();
return NS_OK;
}
void
ServoStyleSheet::LoadFailed()
{
mSheet = Servo_StyleSheet_Empty(mParsingMode).Consume();
}
void
ServoStyleSheet::DropSheet()
{
mSheet = nullptr;
}
size_t
ServoStyleSheet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
MOZ_CRASH("stylo: not implemented");
return 0;
}
#ifdef DEBUG
@ -129,7 +97,6 @@ ServoStyleSheet::GetDOMOwnerRule() const
CSSRuleList*
ServoStyleSheet::GetCssRulesInternal(ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return nullptr;
}
@ -137,14 +104,12 @@ uint32_t
ServoStyleSheet::InsertRuleInternal(const nsAString& aRule,
uint32_t aIndex, ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return 0;
}
void
ServoStyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
} // namespace mozilla