mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 08:18:41 +09:00
Issue #2112 - Part 2: Stub out Servo functions
This commit is contained in:
parent
656ee639c5
commit
88ac168f96
8 changed files with 77 additions and 1228 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue