diff options
Diffstat (limited to 'layout/base')
70 files changed, 1219 insertions, 1875 deletions
diff --git a/layout/base/AccessibleCaret.cpp b/layout/base/AccessibleCaret.cpp index 165f385f5..27877c732 100644 --- a/layout/base/AccessibleCaret.cpp +++ b/layout/base/AccessibleCaret.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/AccessibleCaret.h b/layout/base/AccessibleCaret.h index 42e5bb386..342950010 100644 --- a/layout/base/AccessibleCaret.h +++ b/layout/base/AccessibleCaret.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/AccessibleCaretEventHub.cpp b/layout/base/AccessibleCaretEventHub.cpp index b897e4d77..d7e9d70b6 100644 --- a/layout/base/AccessibleCaretEventHub.cpp +++ b/layout/base/AccessibleCaretEventHub.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/AccessibleCaretEventHub.h b/layout/base/AccessibleCaretEventHub.h index 6681f8669..e2fb4c04a 100644 --- a/layout/base/AccessibleCaretEventHub.h +++ b/layout/base/AccessibleCaretEventHub.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/AccessibleCaretLogger.h b/layout/base/AccessibleCaretLogger.h index 9a0235643..76695f666 100644 --- a/layout/base/AccessibleCaretLogger.h +++ b/layout/base/AccessibleCaretLogger.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/AccessibleCaretManager.cpp b/layout/base/AccessibleCaretManager.cpp index ac3f36bea..4dd55009c 100644 --- a/layout/base/AccessibleCaretManager.cpp +++ b/layout/base/AccessibleCaretManager.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -23,9 +22,6 @@ #include "nsFrameSelection.h" #include "nsGenericHTMLElement.h" #include "nsIHapticFeedback.h" -#ifdef MOZ_WIDGET_ANDROID -#include "nsWindow.h" -#endif namespace mozilla { @@ -897,15 +893,6 @@ AccessibleCaretManager::SetSelectionDragState(bool aState) const if (fs) { fs->SetDragState(aState); } - - // Pin Fennecs DynamicToolbarAnimator in place before/after dragging, - // to avoid co-incident screen scrolling. - #ifdef MOZ_WIDGET_ANDROID - nsIDocument* doc = mPresShell->GetDocument(); - MOZ_ASSERT(doc); - nsIWidget* widget = nsContentUtils::WidgetForDocument(doc); - static_cast<nsWindow*>(widget)->SetSelectionDragState(aState); - #endif } void diff --git a/layout/base/AccessibleCaretManager.h b/layout/base/AccessibleCaretManager.h index 1cfe85d01..e8636b356 100644 --- a/layout/base/AccessibleCaretManager.h +++ b/layout/base/AccessibleCaretManager.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/ArenaRefPtr.h b/layout/base/ArenaRefPtr.h index bc8ecaa70..732ca01e8 100644 --- a/layout/base/ArenaRefPtr.h +++ b/layout/base/ArenaRefPtr.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/ArenaRefPtrInlines.h b/layout/base/ArenaRefPtrInlines.h index a85e98569..36cb8a9a5 100644 --- a/layout/base/ArenaRefPtrInlines.h +++ b/layout/base/ArenaRefPtrInlines.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 934d108e0..8695cd650 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -2502,7 +2502,6 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, aData->mVisibilityComputedRegion.SetEmpty(); // FIXME: Temporary workaround for bug 681192 and bug 724786. -#ifndef MOZ_WIDGET_ANDROID // Calculate exact position of the top-left of the active scrolled root. // This might not be 0,0 due to the snapping in ScaleToNearestPixels. gfxPoint animatedGeometryRootTopLeft = scaledOffset - ThebesPoint(matrix.GetTranslation()) + mParameters.mOffset; @@ -2515,9 +2514,6 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, } else if (didResetScrollPositionForLayerPixelAlignment) { aData->mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft; } -#else - Unused << didResetScrollPositionForLayerPixelAlignment; -#endif } #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING) diff --git a/layout/base/LayoutConstants.h b/layout/base/LayoutConstants.h index cd6e1c3f5..d624a1a19 100644 --- a/layout/base/LayoutConstants.h +++ b/layout/base/LayoutConstants.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/PositionedEventTargeting.cpp b/layout/base/PositionedEventTargeting.cpp index 668ff2938..731e951e5 100644 --- a/layout/base/PositionedEventTargeting.cpp +++ b/layout/base/PositionedEventTargeting.cpp @@ -620,8 +620,6 @@ FindFrameTargetedByInputEvent(WidgetGUIEvent* aEvent, PET_LOG("Final target is %p\n", target); // Uncomment this to dump the frame tree to help with debugging. - // Note that dumping the frame tree at the top of the function may flood - // logcat on Android devices and cause the PET_LOGs to get dropped. // aRootFrame->DumpFrameTree(); if (!target || !prefs->mRepositionEventCoords) { diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index a5a4e1237..9e80ef7bc 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -146,8 +146,10 @@ RestyleManager::RestyleElement(Element* aElement, } if (aMinHint & nsChangeHint_ReconstructFrame) { - FrameConstructor()->RecreateFramesForContent(aElement, false, - nsCSSFrameConstructor::REMOVE_FOR_RECONSTRUCTION, nullptr); + FrameConstructor()->RecreateFramesForContent( + aElement, + nsCSSFrameConstructor::InsertionKind::Sync, + nsCSSFrameConstructor::REMOVE_FOR_RECONSTRUCTION); } else if (aPrimaryFrame) { ComputeAndProcessStyleChange(aPrimaryFrame, aMinHint, aRestyleTracker, aRestyleHint, aRestyleHintData); @@ -241,14 +243,14 @@ RestyleManager::AnimationsWithDestroyedFrame::StopAnimationsWithoutFrame( // Forwarded nsIDocumentObserver method, to handle restyling (and // passing the notification to the frame). -nsresult +void RestyleManager::ContentStateChanged(nsIContent* aContent, EventStates aStateMask) { // XXXbz it would be good if this function only took Elements, but // we'd have to make ESM guarantee that usefully. if (!aContent->IsElement()) { - return NS_OK; + return; } Element* aElement = aContent->AsElement(); @@ -258,7 +260,6 @@ RestyleManager::ContentStateChanged(nsIContent* aContent, ContentStateChangedInternal(aElement, aStateMask, &changeHint, &restyleHint); PostRestyleEvent(aElement, restyleHint, changeHint); - return NS_OK; } // Forwarded nsIMutationObserver method, to handle restyling. @@ -1057,6 +1058,25 @@ ElementForStyleContext(nsIContent* aParentContent, return f->GetContent()->AsElement(); } + Element* frameElement = aFrame->GetContent()->AsElement(); + if (frameElement->IsNativeAnonymous() && + nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(aPseudoType)) { + // NAC-implemented pseudos use the closest non-NAC element as their + // element to inherit from. + // + // FIXME(heycam): In theory we shouldn't need to limit this only to + // JS-created pseudo-implementing NAC, as all pseudo-implementing + // should use the closest non-native anonymous ancestor element as + // its originating element. But removing that part of the condition + // reveals some bugs in style resultion with display:contents and + // XBL. See bug 1345809. + Element* originatingElement = + nsContentUtils::GetClosestNonNativeAnonymousAncestor(frameElement); + if (originatingElement) { + return originatingElement; + } + } + if (aParentContent) { return aParentContent->AsElement(); } @@ -1806,7 +1826,7 @@ ElementRestyler::ConditionallyRestyleUndisplayedNodes( } for (UndisplayedNode* undisplayed = aUndisplayed; undisplayed; - undisplayed = undisplayed->mNext) { + undisplayed = undisplayed->getNext()) { if (!undisplayed->mContent->IsElement()) { continue; @@ -2336,6 +2356,16 @@ ElementRestyler::ComputeRestyleResultFromFrame(nsIFrame* aSelf, return; } + // Each NAC element inherits from the first non-NAC ancestor, so child + // NAC may inherit from our parent instead of us. That means we can't + // cull traversal if our style context didn't change. + if (aSelf->GetContent() && aSelf->GetContent()->IsNativeAnonymous()) { + LOG_RESTYLE_CONTINUE("native anonymous content"); + aRestyleResult = RestyleResult::eContinue; + aCanStopWithStyleChange = false; + return; + } + // Style changes might have moved children between the two nsLetterFrames // (the one matching ::first-letter and the one containing the rest of the // content). Continue restyling to the children of the nsLetterFrame so @@ -3437,7 +3467,7 @@ ElementRestyler::RestyleUndisplayedNodes(nsRestyleHint aChildRestyleHint, if (undisplayed) { pusher.PushAncestorAndStyleScope(undisplayedParent); } - for (; undisplayed; undisplayed = undisplayed->mNext) { + for (; undisplayed; undisplayed = undisplayed->getNext()) { NS_ASSERTION(undisplayedParent || undisplayed->mContent == mPresContext->Document()->GetRootElement(), @@ -3454,7 +3484,7 @@ ElementRestyler::RestyleUndisplayedNodes(nsRestyleHint aChildRestyleHint, // not have a frame and would not otherwise be pushed as an ancestor. nsIContent* parent = undisplayed->mContent->GetParent(); TreeMatchContext::AutoAncestorPusher insertionPointPusher(mTreeMatchContext); - if (parent && nsContentUtils::IsContentInsertionPoint(parent)) { + if (parent && parent->IsActiveChildrenElement()) { insertionPointPusher.PushAncestorAndStyleScope(parent); } @@ -3593,14 +3623,14 @@ ElementRestyler::MustReframeForPseudo(CSSPseudoElementType aPseudoType, // Check for a ::before pseudo style and the absence of a ::before content, // but only if aFrame is null or is the first continuation/ib-split. if ((aFrame && !nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) || - nsLayoutUtils::GetBeforeFrameForContent(aGenConParentFrame, aContent)) { + nsLayoutUtils::GetBeforeFrame(aContent)) { return false; } } else { // Similarly for ::after, but check for being the last continuation/ // ib-split. if ((aFrame && nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame)) || - nsLayoutUtils::GetAfterFrameForContent(aGenConParentFrame, aContent)) { + nsLayoutUtils::GetAfterFrame(aContent)) { return false; } } @@ -3680,7 +3710,7 @@ ElementRestyler::RestyleContentChildren(nsIFrame* aParent, // nsPageFrame that does not have a content. nsIContent* parent = child->GetContent() ? child->GetContent()->GetParent() : nullptr; TreeMatchContext::AutoAncestorPusher insertionPointPusher(mTreeMatchContext); - if (parent && nsContentUtils::IsContentInsertionPoint(parent)) { + if (parent && parent->IsActiveChildrenElement()) { insertionPointPusher.PushAncestorAndStyleScope(parent); } diff --git a/layout/base/RestyleManager.h b/layout/base/RestyleManager.h index 4886d77bc..dd58f4bb4 100644 --- a/layout/base/RestyleManager.h +++ b/layout/base/RestyleManager.h @@ -59,8 +59,8 @@ public: // Forwarded nsIDocumentObserver method, to handle restyling (and // passing the notification to the frame). - nsresult ContentStateChanged(nsIContent* aContent, - EventStates aStateMask); + void ContentStateChanged(nsIContent* aContent, + EventStates aStateMask); // Forwarded nsIMutationObserver method, to handle restyling. void AttributeWillChange(Element* aElement, diff --git a/layout/base/RestyleManagerBase.cpp b/layout/base/RestyleManagerBase.cpp index e2145934b..192c0df99 100644 --- a/layout/base/RestyleManagerBase.cpp +++ b/layout/base/RestyleManagerBase.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -172,7 +171,7 @@ RestyleManagerBase::ChangeHintToString(nsChangeHint aHint) "NeutralChange", "InvalidateRenderingObservers", "ReflowChangesSizeOrPosition", "UpdateComputedBSize", "UpdateUsesOpacity", "UpdateBackgroundPosition", - "AddOrRemoveTransform", "CSSOverflowChange", + "AddOrRemoveTransform", "ScrollbarChange", }; static_assert(nsChangeHint_AllHints == (1 << ArrayLength(names)) - 1, "Name list doesn't match change hints."); @@ -1112,11 +1111,11 @@ if (!mDestroyedFrames) { nsPresContext* presContext = PresContext(); nsCSSFrameConstructor* frameConstructor = presContext->FrameConstructor(); - // Handle nsChangeHint_CSSOverflowChange, by either updating the + // Handle nsChangeHint_ScrollbarChange, by either updating the // scrollbars on the viewport, or upgrading the change hint to frame-reconstruct. for (nsStyleChangeData& data : aChangeList) { - if (data.mHint & nsChangeHint_CSSOverflowChange) { - data.mHint &= ~nsChangeHint_CSSOverflowChange; + if (data.mHint & nsChangeHint_ScrollbarChange) { + data.mHint &= ~nsChangeHint_ScrollbarChange; bool doReconstruct = true; // assume the worst // Only bother with this if we're html/body, since: @@ -1138,9 +1137,9 @@ if (!mDestroyedFrames) { // to reconstruct - we can just reflow, because no scrollframe is being // added/removed. nsIContent* prevOverrideNode = - presContext->GetViewportScrollbarStylesOverrideNode(); + presContext->GetViewportScrollStylesOverrideNode(); nsIContent* newOverrideNode = - presContext->UpdateViewportScrollbarStylesOverride(); + presContext->UpdateViewportScrollStylesOverride(); if (data.mContent == prevOverrideNode || data.mContent == newOverrideNode) { @@ -1267,8 +1266,10 @@ if (!mDestroyedFrames) { // We could also have problems with triggering of CSS transitions // on elements whose frames are reconstructed, since we depend on // the reconstruction happening synchronously. - frameConstructor->RecreateFramesForContent(content, false, - nsCSSFrameConstructor::REMOVE_FOR_RECONSTRUCTION, nullptr); + frameConstructor->RecreateFramesForContent( + content, + nsCSSFrameConstructor::InsertionKind::Sync, + nsCSSFrameConstructor::REMOVE_FOR_RECONSTRUCTION); } else { NS_ASSERTION(frame, "This shouldn't happen"); diff --git a/layout/base/RestyleManagerBase.h b/layout/base/RestyleManagerBase.h index d92c3d1f7..8b8bf4170 100644 --- a/layout/base/RestyleManagerBase.h +++ b/layout/base/RestyleManagerBase.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/RestyleManagerHandle.h b/layout/base/RestyleManagerHandle.h index 8be04d12c..5cc26e41e 100644 --- a/layout/base/RestyleManagerHandle.h +++ b/layout/base/RestyleManagerHandle.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -125,8 +124,8 @@ public: nsIContent* aChild); inline void RestyleForAppend(nsIContent* aContainer, nsIContent* aFirstNewContent); - inline nsresult ContentStateChanged(nsIContent* aContent, - EventStates aStateMask); + inline void ContentStateChanged(nsIContent* aContent, + EventStates aStateMask); inline void AttributeWillChange(dom::Element* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute, diff --git a/layout/base/RestyleManagerHandleInlines.h b/layout/base/RestyleManagerHandleInlines.h index cc374edd5..6c8276fce 100644 --- a/layout/base/RestyleManagerHandleInlines.h +++ b/layout/base/RestyleManagerHandleInlines.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -122,7 +121,7 @@ RestyleManagerHandle::Ptr::RestyleForAppend(nsIContent* aContainer, FORWARD(RestyleForAppend, (aContainer, aFirstNewContent)); } -nsresult +void RestyleManagerHandle::Ptr::ContentStateChanged(nsIContent* aContent, EventStates aStateMask) { diff --git a/layout/base/ScrollbarStyles.cpp b/layout/base/ScrollStyles.cpp index cc9f0c57d..328657d3d 100644 --- a/layout/base/ScrollbarStyles.cpp +++ b/layout/base/ScrollStyles.cpp @@ -3,12 +3,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "ScrollbarStyles.h" +#include "ScrollStyles.h" #include "nsStyleStruct.h" // for nsStyleDisplay and nsStyleBackground::Position namespace mozilla { - ScrollbarStyles::ScrollbarStyles(uint8_t aH, uint8_t aV, + ScrollStyles::ScrollStyles(uint8_t aH, uint8_t aV, const nsStyleDisplay* aDisplay) : mHorizontal(aH), mVertical(aV), mScrollBehavior(aDisplay->mScrollBehavior), @@ -19,7 +19,7 @@ namespace mozilla { mScrollSnapDestinationX(aDisplay->mScrollSnapDestination.mXPosition), mScrollSnapDestinationY(aDisplay->mScrollSnapDestination.mYPosition) {} - ScrollbarStyles::ScrollbarStyles(const nsStyleDisplay* aDisplay) + ScrollStyles::ScrollStyles(const nsStyleDisplay* aDisplay) : mHorizontal(aDisplay->mOverflowX), mVertical(aDisplay->mOverflowY), mScrollBehavior(aDisplay->mScrollBehavior), mScrollSnapTypeX(aDisplay->mScrollSnapTypeX), diff --git a/layout/base/ScrollbarStyles.h b/layout/base/ScrollStyles.h index e6f0c6dde..c5743ee6b 100644 --- a/layout/base/ScrollbarStyles.h +++ b/layout/base/ScrollStyles.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef ScrollbarStyles_h -#define ScrollbarStyles_h +#ifndef ScrollStyles_h +#define ScrollStyles_h #include <stdint.h> #include "nsStyleConsts.h" // for NS_STYLE_SCROLL_SNAP_* @@ -16,7 +16,7 @@ struct nsStyleDisplay; namespace mozilla { -struct ScrollbarStyles +struct ScrollStyles { // Always one of NS_STYLE_OVERFLOW_SCROLL, NS_STYLE_OVERFLOW_HIDDEN, // or NS_STYLE_OVERFLOW_AUTO. @@ -34,7 +34,7 @@ struct ScrollbarStyles nsStyleCoord::CalcValue mScrollSnapDestinationX; nsStyleCoord::CalcValue mScrollSnapDestinationY; - ScrollbarStyles(uint8_t aH, uint8_t aV) + ScrollStyles(uint8_t aH, uint8_t aV) : mHorizontal(aH), mVertical(aV), mScrollBehavior(NS_STYLE_SCROLL_BEHAVIOR_AUTO), mScrollSnapTypeX(NS_STYLE_SCROLL_SNAP_TYPE_NONE), @@ -50,10 +50,10 @@ struct ScrollbarStyles mScrollSnapDestinationY.mHasPercent = false; } - explicit ScrollbarStyles(const nsStyleDisplay* aDisplay); - ScrollbarStyles(uint8_t aH, uint8_t aV, const nsStyleDisplay* aDisplay); - ScrollbarStyles() {} - bool operator==(const ScrollbarStyles& aStyles) const { + explicit ScrollStyles(const nsStyleDisplay* aDisplay); + ScrollStyles(uint8_t aH, uint8_t aV, const nsStyleDisplay* aDisplay); + ScrollStyles() {} + bool operator==(const ScrollStyles& aStyles) const { return aStyles.mHorizontal == mHorizontal && aStyles.mVertical == mVertical && aStyles.mScrollBehavior == mScrollBehavior && aStyles.mScrollSnapTypeX == mScrollSnapTypeX && @@ -63,7 +63,7 @@ struct ScrollbarStyles aStyles.mScrollSnapDestinationX == mScrollSnapDestinationX && aStyles.mScrollSnapDestinationY == mScrollSnapDestinationY; } - bool operator!=(const ScrollbarStyles& aStyles) const { + bool operator!=(const ScrollStyles& aStyles) const { return !(*this == aStyles); } bool IsHiddenInBothDirections() const { diff --git a/layout/base/ServoRestyleManager.cpp b/layout/base/ServoRestyleManager.cpp index 82c81ea46..9ff3f4e88 100644 --- a/layout/base/ServoRestyleManager.cpp +++ b/layout/base/ServoRestyleManager.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -278,24 +277,17 @@ ServoRestyleManager::FrameForPseudoElement(const nsIContent* aContent, nsIAtom* aPseudoTagOrNull) { MOZ_ASSERT_IF(aPseudoTagOrNull, aContent->IsElement()); - nsIFrame* primaryFrame = aContent->GetPrimaryFrame(); if (!aPseudoTagOrNull) { - return primaryFrame; - } - - if (!primaryFrame) { - return nullptr; + return aContent->GetPrimaryFrame(); } - // NOTE: we probably need to special-case display: contents here. Gecko's - // RestyleManager passes the primary frame of the parent instead. if (aPseudoTagOrNull == nsCSSPseudoElements::before) { - return nsLayoutUtils::GetBeforeFrameForContent(primaryFrame, aContent); + return nsLayoutUtils::GetBeforeFrame(aContent); } if (aPseudoTagOrNull == nsCSSPseudoElements::after) { - return nsLayoutUtils::GetAfterFrameForContent(primaryFrame, aContent); + return nsLayoutUtils::GetAfterFrame(aContent); } MOZ_CRASH("Unkown pseudo-element given to " @@ -514,12 +506,12 @@ ServoRestyleManager::ContentRemoved(nsINode* aContainer, NS_WARNING("stylo: ServoRestyleManager::ContentRemoved not implemented"); } -nsresult +void ServoRestyleManager::ContentStateChanged(nsIContent* aContent, EventStates aChangedBits) { if (!aContent->IsElement()) { - return NS_OK; + return; } Element* aElement = aContent->AsElement(); @@ -553,7 +545,6 @@ ServoRestyleManager::ContentStateChanged(nsIContent* aContent, snapshot->AddState(previousState); PostRestyleEvent(aElement, restyleHint, changeHint); - return NS_OK; } void diff --git a/layout/base/ServoRestyleManager.h b/layout/base/ServoRestyleManager.h index 6856171c1..855b3cab1 100644 --- a/layout/base/ServoRestyleManager.h +++ b/layout/base/ServoRestyleManager.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -63,8 +62,7 @@ public: nsIContent* aChild); void RestyleForAppend(nsIContent* aContainer, nsIContent* aFirstNewContent); - nsresult ContentStateChanged(nsIContent* aContent, - EventStates aStateMask); + void ContentStateChanged(nsIContent* aContent, EventStates aStateMask); void AttributeWillChange(dom::Element* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute, diff --git a/layout/base/StaticPresData.cpp b/layout/base/StaticPresData.cpp index 73acd5440..74b0e17eb 100644 --- a/layout/base/StaticPresData.cpp +++ b/layout/base/StaticPresData.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/StaticPresData.h b/layout/base/StaticPresData.h index 62e174fd2..5e8b8d66b 100644 --- a/layout/base/StaticPresData.h +++ b/layout/base/StaticPresData.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/TouchManager.cpp b/layout/base/TouchManager.cpp index e7972d5af..4439a3a7b 100644 --- a/layout/base/TouchManager.cpp +++ b/layout/base/TouchManager.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/TouchManager.h b/layout/base/TouchManager.h index 7c0d51734..8a41a90ca 100644 --- a/layout/base/TouchManager.h +++ b/layout/base/TouchManager.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/UnitTransforms.h b/layout/base/UnitTransforms.h index e3a5af2d2..5320964dd 100644 --- a/layout/base/UnitTransforms.h +++ b/layout/base/UnitTransforms.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/Units.h b/layout/base/Units.h index 199a91902..4e33ae8a4 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/ZoomConstraintsClient.cpp b/layout/base/ZoomConstraintsClient.cpp index 2391a116d..67666676b 100644 --- a/layout/base/ZoomConstraintsClient.cpp +++ b/layout/base/ZoomConstraintsClient.cpp @@ -53,7 +53,7 @@ GetWidget(nsIPresShell* aShell) return nullptr; } if (nsIFrame* rootFrame = aShell->GetRootFrame()) { -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) +#if defined(MOZ_WIDGET_UIKIT) return rootFrame->GetNearestWidget(); #else if (nsView* view = rootFrame->GetView()) { diff --git a/layout/base/crashtests/1261351-iframe.html b/layout/base/crashtests/1261351-iframe.html index 82c1e25fa..a0484f332 100644 --- a/layout/base/crashtests/1261351-iframe.html +++ b/layout/base/crashtests/1261351-iframe.html @@ -3,23 +3,26 @@ 'use strict'; // -sp-context: content (function () { - let proto = Object.create(HTMLDivElement.prototype); - proto.template = `<style></style>`; - proto.createdCallback = function() { - let shadow = this.createShadowRoot(); - if (this.template) { - let te = document.createElement('template'); - te.innerHTML = this.template; - shadow.appendChild(document.importNode(te.content, true)); - } - }; + class UiComponentTest extends HTMLDivElement { + constructor() { + super(); + this.template = `<style></style>`; + } - let UiComponentTest = document.registerElement('ui-component-test', { - prototype: proto, - }); + connectedCallback() { + let shadow = this.createShadowRoot(); + if (this.template) { + let te = document.createElement('template'); + te.innerHTML = this.template; + shadow.appendChild(document.importNode(te.content, true)); + } + } + }; - let uic = new UiComponentTest(); - document.body.appendChild(uic); + customElements.define('ui-component-test', UiComponentTest, { extend: 'div'} ); + + let uic = new UiComponentTest(); + document.body.appendChild(uic); })(); </script> diff --git a/layout/base/crashtests/1404789-1.html b/layout/base/crashtests/1404789-1.html new file mode 100644 index 000000000..bd577ae24 --- /dev/null +++ b/layout/base/crashtests/1404789-1.html @@ -0,0 +1,16 @@ +<!doctype html> +<script> + // Test for content redistribution outside of the document. + // Passes if it doesn't assert. + let host = document.createElement('div'); + host.innerHTML = "<div id='foo'></div>"; + + let shadowRoot = host.createShadowRoot(); + shadowRoot.innerHTML = "<content select='#foo'></content>"; + + host.firstElementChild.removeAttribute('id'); + + // Move to the document, do the same. + document.documentElement.appendChild(host); + host.firstElementChild.setAttribute('id', 'foo'); +</script> diff --git a/layout/base/crashtests/1404789-2.html b/layout/base/crashtests/1404789-2.html new file mode 100644 index 000000000..667618141 --- /dev/null +++ b/layout/base/crashtests/1404789-2.html @@ -0,0 +1,2 @@ +<!doctype html> +<iframe style="display: none" src="1404789-1.html"></iframe> diff --git a/layout/base/crashtests/1419762.html b/layout/base/crashtests/1419762.html new file mode 100644 index 000000000..08a56106d --- /dev/null +++ b/layout/base/crashtests/1419762.html @@ -0,0 +1,15 @@ +<style id='style_1'> + :first-child { display: table-column-group; } +</style> +<script> + try { o1 = document.createElement('isindex') } catch(e) { } + try { o2 = document.createElement('input') } catch(e) { } + try { o3 = document.createElement('optgroup') } catch(e) { } + try { o4 = document.createElement('col') } catch(e) { } + try { document.documentElement.appendChild(o1) } catch(e) { } + try { o1.appendChild(o2) } catch(e) { } + try { o1.appendChild(o3) } catch(e) { } + try { document.documentElement.offsetTop; } catch (e) { } + try { document.documentElement.appendChild(o4) } catch(e) { } + try { document.styleSheets[0].insertRule('optgroup::first-line { list-style-type: japanese-formal; }', 0); } catch(e) { } +</script> diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 6ded4ff3f..1a3bf667b 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -294,7 +294,7 @@ load 469861-1.xhtml load 469861-2.xhtml load 470851-1.xhtml load 471594-1.xhtml -asserts-if(Android&&!asyncPan,1-2) load 473042.xhtml # bug 1034369 (may also cause a few assertions to be registered on the next test) +load 473042.xhtml # bug 1034369 (may also cause a few assertions to be registered on the next test) asserts(0-5) load 474075.html # bug 847368 load 477333-1.xhtml load 477731-1.html @@ -411,7 +411,7 @@ load 709536-1.xhtml load 722137.html load 725535.html load 727601.html -skip-if(Android) asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966, for android bug 760271 +asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966 asserts(0-2) load 736389-1.xhtml # sometimes the above assertions are delayed and is reported on this test instead load 736924-1.html load 749816-1.html @@ -447,7 +447,7 @@ load 866588.html load 876092.html load 876221.html load 897852.html -asserts(4-6) asserts-if(Android&&!asyncPan,2) load 898913.html # bug 847368 +asserts(4-6) load 898913.html # bug 847368 pref(layers.acceleration.enabled,false) pref(layers.force-active,true) load 919434.html load 926728.html load 930381.html @@ -483,3 +483,6 @@ load 1308793.svg load 1308848-1.html load 1308848-2.html asserts(0-1) load 1343606.html # bug 1343948 +load 1404789-1.html +load 1404789-2.html +load 1419762.html diff --git a/layout/base/gtest/TestAccessibleCaretEventHub.cpp b/layout/base/gtest/TestAccessibleCaretEventHub.cpp index 5216a52dc..cc3b332ee 100644 --- a/layout/base/gtest/TestAccessibleCaretEventHub.cpp +++ b/layout/base/gtest/TestAccessibleCaretEventHub.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/gtest/TestAccessibleCaretManager.cpp b/layout/base/gtest/TestAccessibleCaretManager.cpp index 78ec6eea9..acaea92a5 100644 --- a/layout/base/gtest/TestAccessibleCaretManager.cpp +++ b/layout/base/gtest/TestAccessibleCaretManager.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/gtest/moz.build b/layout/base/gtest/moz.build index 2e9100443..0dbc4c5e7 100644 --- a/layout/base/gtest/moz.build +++ b/layout/base/gtest/moz.build @@ -1,5 +1,4 @@ # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/moz.build b/layout/base/moz.build index f115280ce..86377e9db 100644 --- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -1,5 +1,4 @@ # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -96,7 +95,7 @@ EXPORTS += [ 'nsRefreshDriver.h', 'nsStyleChangeList.h', 'nsStyleSheetService.h', - 'ScrollbarStyles.h', + 'ScrollStyles.h', 'StackArena.h', 'Units.h', 'UnitTransforms.h', @@ -163,7 +162,7 @@ SOURCES += [ 'RestyleManager.cpp', 'RestyleManagerBase.cpp', 'RestyleTracker.cpp', - 'ScrollbarStyles.cpp', + 'ScrollStyles.cpp', 'ServoRestyleManager.cpp', 'StackArena.cpp', 'StaticPresData.cpp', @@ -194,11 +193,6 @@ LOCAL_INCLUDES += [ '/view', ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': - LOCAL_INCLUDES += [ - '/widget/android', - ] - FINAL_LIBRARY = 'xul' BROWSER_CHROME_MANIFESTS += ['tests/browser.ini'] diff --git a/layout/base/nsArenaMemoryStats.h b/layout/base/nsArenaMemoryStats.h index 2a872cfe8..ea4535e2c 100644 --- a/layout/base/nsArenaMemoryStats.h +++ b/layout/base/nsArenaMemoryStats.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index d28e60740..2cc5ec818 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -43,6 +43,7 @@ #include "nsContainerFrame.h" #include "nsNameSpaceManager.h" #include "nsIComboboxControlFrame.h" +#include "nsComboboxControlFrame.h" #include "nsIListControlFrame.h" #include "nsIDOMCharacterData.h" #include "nsPlaceholderFrame.h" @@ -691,10 +692,9 @@ nsAbsoluteItems::nsAbsoluteItems(nsContainerFrame* aContainingBlock) void nsAbsoluteItems::AddChild(nsIFrame* aChild) { - NS_ASSERTION(aChild->PresContext()->FrameManager()-> - GetPlaceholderFrameFor(aChild), - "Child without placeholder being added to nsAbsoluteItems?"); aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW); + NS_ASSERTION(aChild->GetPlaceholderFrame(), + "Child without placeholder being added to nsAbsoluteItems?"); nsFrameItems::AddChild(aChild); } @@ -1831,11 +1831,7 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat aPseudoElement == CSSPseudoElementType::after, "unexpected aPseudoElement"); - // XXXbz is this ever true? - if (!aParentContent->IsElement()) { - NS_ERROR("Bogus generated content parent"); - return; - } + MOZ_ASSERT(aParentContent->IsElement()); StyleSetHandle styleSet = mPresShell->StyleSet(); @@ -1863,7 +1859,15 @@ nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aStat nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget()); if (NS_FAILED(rv)) return; + + // Cleared when the pseudo is unbound from the tree, so no need to store a + // strong reference, nor a destructor. + nsIAtom* property = isBefore + ? nsGkAtoms::beforePseudoProperty : nsGkAtoms::afterPseudoProperty; + aParentContent->SetProperty(property, container.get()); + container->SetIsNativeAnonymousRoot(); + container->SetPseudoElementType(aPseudoElement); // If the parent is in a shadow tree, make sure we don't // bind with a document because shadow roots and its descendants @@ -2402,12 +2406,12 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle GetRootFrame()->SetStyleContextWithoutNotification(sc); } - // Make sure to call UpdateViewportScrollbarStylesOverride before + // Make sure to call UpdateViewportScrollStylesOverride before // SetUpDocElementContainingBlock, since it sets up our scrollbar state // properly. DebugOnly<nsIContent*> propagatedScrollFrom; if (nsPresContext* presContext = mPresShell->GetPresContext()) { - propagatedScrollFrom = presContext->UpdateViewportScrollbarStylesOverride(); + propagatedScrollFrom = presContext->UpdateViewportScrollStylesOverride(); } SetUpDocElementContainingBlock(aDocElement); @@ -3028,14 +3032,12 @@ nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell* aPresShell, placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow); - // The placeholder frame has a pointer back to the out-of-flow frame + // Associate the placeholder/out-of-flow with each other. placeholderFrame->SetOutOfFlowFrame(aFrame); + aFrame->SetProperty(nsIFrame::PlaceholderFrameProperty(), placeholderFrame); aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW); - // Add mapping from absolutely positioned frame to its placeholder frame - aPresShell->FrameManager()->RegisterPlaceholderFrame(placeholderFrame); - return placeholderFrame; } @@ -3076,7 +3078,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, // The drop-down list's frame is created explicitly. The combobox frame shares its content // with the drop-down list. nsFrameState flags = NS_BLOCK_FLOAT_MGR; - nsContainerFrame* comboboxFrame = + nsComboboxControlFrame* comboboxFrame = NS_NewComboboxControlFrame(mPresShell, styleContext, flags); // Save the history state so we don't restore during construction @@ -3091,10 +3093,6 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, aState.AddChild(comboboxFrame, aFrameItems, content, styleContext, aParentFrame); - nsIComboboxControlFrame* comboBox = do_QueryFrame(comboboxFrame); - NS_ASSERTION(comboBox, "NS_NewComboboxControlFrame returned frame that " - "doesn't implement nsIComboboxControlFrame"); - // Resolve pseudo element style for the dropdown list RefPtr<nsStyleContext> listStyle; listStyle = mPresShell->StyleSet()-> @@ -3109,7 +3107,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, listControlFrame->SetComboboxFrame(comboboxFrame); } // Notify combobox that it should use the listbox as it's popup - comboBox->SetDropDown(listFrame); + comboboxFrame->SetDropDown(listFrame); NS_ASSERTION(!listFrame->IsAbsPosContainingBlock(), "Ended up with positioned dropdown list somehow."); @@ -3130,10 +3128,29 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, // Create display and button frames from the combobox's anonymous content. // The anonymous content is appended to existing anonymous content for this // element (the scrollbars). - nsFrameItems childItems; - CreateAnonymousFrames(aState, content, comboboxFrame, - aItem.mPendingBinding, childItems); + + // nsComboboxControlFrame needs special frame creation behavior for its first + // piece of anonymous content, which means that we can't take the normal + // ProcessChildren path. + AutoTArray<nsIAnonymousContentCreator::ContentInfo, 2> newAnonymousItems; + DebugOnly<nsresult> rv = GetAnonymousContent(content, comboboxFrame, newAnonymousItems); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + MOZ_ASSERT(newAnonymousItems.Length() == 2); + + // Manually create a frame for the special NAC. + MOZ_ASSERT(newAnonymousItems[0].mContent == comboboxFrame->GetDisplayNode()); + newAnonymousItems.RemoveElementAt(0); + nsIFrame* customFrame = comboboxFrame->CreateFrameForDisplayNode(); + MOZ_ASSERT(customFrame); + customFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT); + childItems.AddChild(customFrame); + + // The other piece of NAC can take the normal path. + FrameConstructionItemList fcItems; + AddFCItemsForAnonymousContent(aState, comboboxFrame, newAnonymousItems, + fcItems); + ConstructFramesFromItemList(aState, fcItems, comboboxFrame, childItems); comboboxFrame->SetInitialChildList(kPrincipalList, childItems); @@ -3173,7 +3190,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, * But the select tag should really be fixed to use GFX scrollbars that can * be create with BuildScrollFrame. */ -nsresult +void nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState, nsContainerFrame* scrollFrame, nsContainerFrame* scrolledFrame, @@ -3219,7 +3236,6 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState, // Set the scrolled frame's initial child lists scrolledFrame->SetInitialChildList(kPrincipalList, childItems); - return NS_OK; } nsIFrame* @@ -3564,10 +3580,6 @@ nsCSSFrameConstructor::FindHTMLData(Element* aElement, return nullptr; } - if (aTag == nsGkAtoms::details && !HTMLDetailsElement::IsDetailsEnabled()) { - return nullptr; - } - static const FrameConstructionDataByTag sHTMLData[] = { SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData), SIMPLE_TAG_CHAIN(mozgeneratedcontentimage, @@ -3656,14 +3668,8 @@ nsCSSFrameConstructor::FindInputData(Element* aElement, nsCSSAnonBoxes::buttonContent) }, // TODO: this is temporary until a frame is written: bug 635240. SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame), -#if defined(MOZ_WIDGET_ANDROID) - // On Android/B2G, date/time input appears as a normal text box. - SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewTextControlFrame), - SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame), -#else SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewDateTimeControlFrame), SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewDateTimeControlFrame), -#endif // TODO: this is temporary until a frame is written: bug 888320 SIMPLE_INT_CREATE(NS_FORM_INPUT_MONTH, NS_NewTextControlFrame), // TODO: this is temporary until a frame is written: bug 888320 @@ -3810,7 +3816,7 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt // AutoDisplayContentsAncestorPusher above.) TreeMatchContext::AutoAncestorPusher insertionPointPusher(aState.mTreeMatchContext); - if (adcp.IsEmpty() && parent && nsContentUtils::IsContentInsertionPoint(parent)) { + if (adcp.IsEmpty() && parent && parent->IsActiveChildrenElement()) { if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { insertionPointPusher.PushAncestorAndStyleScope(parent); } else { @@ -4099,70 +4105,6 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt } } -// after the node has been constructed and initialized create any -// anonymous content a node needs. -nsresult -nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState, - nsIContent* aParent, - nsContainerFrame* aParentFrame, - PendingBinding* aPendingBinding, - nsFrameItems& aChildItems) -{ - AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> newAnonymousItems; - nsresult rv = GetAnonymousContent(aParent, aParentFrame, newAnonymousItems); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t count = newAnonymousItems.Length(); - if (count == 0) { - return NS_OK; - } - - nsFrameConstructorState::PendingBindingAutoPusher pusher(aState, - aPendingBinding); - TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext); - if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { - ancestorPusher.PushAncestorAndStyleScope(aParent->AsElement()); - } else { - ancestorPusher.PushStyleScope(aParent->AsElement()); - } - - nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame); - NS_ASSERTION(creator, - "How can that happen if we have nodes to construct frames for?"); - - InsertionPoint insertion(aParentFrame, aParent); - for (uint32_t i=0; i < count; i++) { - nsIContent* content = newAnonymousItems[i].mContent; - NS_ASSERTION(content, "null anonymous content?"); - NS_ASSERTION(!newAnonymousItems[i].mStyleContext, "Unexpected style context"); - NS_ASSERTION(newAnonymousItems[i].mChildren.IsEmpty(), - "This method is not currently used with frames that implement " - "nsIAnonymousContentCreator::CreateAnonymousContent to " - "output a list where the items have their own children"); - - nsIFrame* newFrame = creator->CreateFrameFor(content); - if (newFrame) { - NS_ASSERTION(content->GetPrimaryFrame(), - "Content must have a primary frame now"); - newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT); - aChildItems.AddChild(newFrame); - } else { - FrameConstructionItemList items; - { - // Skip parent display based style-fixup during our - // AddFrameConstructionItems() call: - TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper - parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext); - - AddFrameConstructionItems(aState, content, true, insertion, items); - } - ConstructFramesFromItemList(aState, items, aParentFrame, aChildItems); - } - } - - return NS_OK; -} - static void SetFlagsOnSubtree(nsIContent *aNode, uintptr_t aFlagsToSet) { @@ -4214,6 +4156,13 @@ ConnectAnonymousTreeDescendants(nsIContent* aParent, } } +void SetNativeAnonymousBitOnDescendants(nsIContent *aRoot) +{ + for (nsIContent* curr = aRoot; curr; curr = curr->GetNextNode(aRoot)) { + curr->SetFlags(NODE_IS_NATIVE_ANONYMOUS); + } +} + nsresult nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent, nsIFrame* aParentFrame, @@ -4235,16 +4184,32 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent, nsIContent* content = aContent[i].mContent; NS_ASSERTION(content, "null anonymous content?"); - // least-surprise CSS binding until we do the SVG specified - // cascading rules for <svg:use> - bug 265894 - if (aParentFrame->GetType() == nsGkAtoms::svgUseFrame) { + ConnectAnonymousTreeDescendants(content, aContent[i].mChildren); + + nsIAtom* parentFrameType = aParentFrame->GetType(); + if (parentFrameType == nsGkAtoms::svgUseFrame) { + // least-surprise CSS binding until we do the SVG specified + // cascading rules for <svg:use> - bug 265894 content->SetFlags(NODE_IS_ANONYMOUS_ROOT); } else { content->SetIsNativeAnonymousRoot(); + // Don't mark descendants of the custom content container + // as native anonymous. When canvas custom content is initially + // created and appended to the custom content container, in + // nsIDocument::InsertAnonymousContent, it is not considered native + // anonymous content. But if we end up reframing the root element, + // we will re-create the nsCanvasFrame, and we would end up in here, + // marking it as NAC. Existing uses of canvas custom content would + // break if it becomes NAC (since each element starts inheriting + // styles from its closest non-NAC ancestor, rather than from its + // parent). + if (!(parentFrameType == nsGkAtoms::canvasFrame && + content == static_cast<nsCanvasFrame*>(aParentFrame) + ->GetCustomContentContainer())) { + SetNativeAnonymousBitOnDescendants(content); + } } - ConnectAnonymousTreeDescendants(content, aContent[i].mChildren); - bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE); // If the parent is in a shadow tree, make sure we don't @@ -4269,11 +4234,9 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent, } if (ServoStyleSet* styleSet = mPresShell->StyleSet()->GetAsServo()) { - // Eagerly compute styles for the anonymous content tree, but only do so - // if the content doesn't have an explicit style context (if it does, we - // don't need the normal computed values). + // Eagerly compute styles for the anonymous content tree. for (auto& info : aContent) { - if (!info.mStyleContext) { + if (info.mContent->IsElement()) { styleSet->StyleNewSubtree(info.mContent); } } @@ -4579,11 +4542,25 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, // if there are any anonymous children for the scroll frame, create // frames for them. - // Pass a null pending binding: we don't care how constructors for any of - // this anonymous content order with anything else. It's never been - // consistent anyway. - CreateAnonymousFrames(aState, aContent, gfxScrollFrame, nullptr, - anonymousItems); + // + // We can't take the normal ProcessChildren path, because the NAC needs to + // be parented to the scrollframe, and everything else needs to be parented + // to the scrolledframe. + AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> scrollNAC; + DebugOnly<nsresult> rv = GetAnonymousContent(aContent, gfxScrollFrame, scrollNAC); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + if (scrollNAC.Length() > 0) { + TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext); + if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) { + ancestorPusher.PushAncestorAndStyleScope(aContent->AsElement()); + } else { + ancestorPusher.PushStyleScope(aContent->AsElement()); + } + + FrameConstructionItemList items; + AddFCItemsForAnonymousContent(aState, gfxScrollFrame, scrollNAC, items); + ConstructFramesFromItemList(aState, items, gfxScrollFrame, anonymousItems); + } aNewFrame = gfxScrollFrame; @@ -4683,7 +4660,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay, if (aElement->IsHTMLElement(nsGkAtoms::body)) { if (nsPresContext* presContext = mPresShell->GetPresContext()) { propagatedScrollToViewport = - presContext->UpdateViewportScrollbarStylesOverride() == aElement; + presContext->UpdateViewportScrollStylesOverride() == aElement; } } @@ -4719,7 +4696,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay, // scrollframe so that it paginates correctly, but we don't want to set // the bit on the block that tells it to clip at paint time. if (mPresShell->GetPresContext()-> - ElementWouldPropagateScrollbarStyles(aElement)) { + ElementWouldPropagateScrollStyles(aElement)) { suppressScrollFrame = false; } } @@ -5039,22 +5016,46 @@ nsCSSFrameConstructor::ResolveStyleContext(const InsertionPoint& aInsertion, already_AddRefed<nsStyleContext> nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext, nsIContent* aContent, - nsFrameConstructorState* aState) + nsFrameConstructorState* aState, + Element* aOriginatingElementOrNull) { StyleSetHandle styleSet = mPresShell->StyleSet(); aContent->OwnerDoc()->FlushPendingLinkUpdates(); RefPtr<nsStyleContext> result; if (aContent->IsElement()) { - if (aState) { - result = styleSet->ResolveStyleFor(aContent->AsElement(), - aParentStyleContext, - aState->mTreeMatchContext); + auto pseudoType = aContent->AsElement()->GetPseudoElementType(); + if (pseudoType == CSSPseudoElementType::NotPseudo) { + MOZ_ASSERT(!aOriginatingElementOrNull); + if (aState) { + result = styleSet->ResolveStyleFor(aContent->AsElement(), + aParentStyleContext, + aState->mTreeMatchContext); + } else { + result = styleSet->ResolveStyleFor(aContent->AsElement(), + aParentStyleContext); + } } else { - result = styleSet->ResolveStyleFor(aContent->AsElement(), - aParentStyleContext); + MOZ_ASSERT(aContent->IsInNativeAnonymousSubtree()); + if (!aOriginatingElementOrNull) { + // For pseudo-implementing NAC created by JS using the ChromeOnly + // document.createElement(..., { pseudo: ... }) API, we find the + // originating element by lookup the tree until we find a non-NAC + // ancestor. (These are the correct semantics for C++-generated pseudo- + // implementing NAC as well, but for those cases we already have a + // correct originating element passed in.) + MOZ_ASSERT(nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType)); + aOriginatingElementOrNull = + nsContentUtils::GetClosestNonNativeAnonymousAncestor(aContent->AsElement()); + } + MOZ_ASSERT(aOriginatingElementOrNull); + result = styleSet->ResolvePseudoElementStyle(aOriginatingElementOrNull, + pseudoType, + aParentStyleContext, + aContent->AsElement()); } } else { + MOZ_ASSERT(!aOriginatingElementOrNull); NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT), "shouldn't waste time creating style contexts for " "comments and processing instructions"); @@ -5790,7 +5791,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState // ::before and ::after); we always want to create "internal" anonymous // content. auto* details = HTMLDetailsElement::FromContentOrNull(parent); - if (details && details->IsDetailsEnabled() && !details->Open() && + if (details && !details->Open() && (!aContent->IsRootOfNativeAnonymousSubtree() || aContent->IsGeneratedContentContainerForBefore() || aContent->IsGeneratedContentContainerForAfter())) { @@ -5958,7 +5959,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState } FrameConstructionItem* item = nullptr; - if (details && details->IsDetailsEnabled() && details->Open()) { + if (details && details->Open()) { auto* summary = HTMLSummaryElement::FromContentOrNull(aContent); if (summary && summary->IsMainSummary()) { // If details is open, the main summary needs to be rendered as if it is @@ -6071,9 +6072,10 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState static void AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIContent* aContent) { - NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aOwnerFrame), - "property should only be set on first continuation/ib-sibling"); + // FIXME(emilio): Remove this property, and use the frame of the generated + // content itself to tear the content down? It should be quite simpler. + aOwnerFrame = nsLayoutUtils::FirstContinuationOrIBSplitSibling(aOwnerFrame); nsIFrame::ContentArray* value = aOwnerFrame->GetProperty(nsIFrame::GenConProperty()); if (!value) { @@ -6204,16 +6206,16 @@ IsRootBoxFrame(nsIFrame *aFrame) return (aFrame->GetType() == nsGkAtoms::rootFrame); } -nsresult +void nsCSSFrameConstructor::ReconstructDocElementHierarchy() { Element* rootElement = mDocument->GetRootElement(); if (!rootElement) { /* nothing to do */ - return NS_OK; + return; } - return RecreateFramesForContent(rootElement, false, REMOVE_FOR_RECONSTRUCTION, - nullptr); + RecreateFramesForContent(rootElement, InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); } nsContainerFrame* @@ -6318,129 +6320,24 @@ nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame) } /** - * This function will check whether aContainer has :after generated content. - * If so, appending to it should actually insert. The return value is the - * parent to use for newly-appended content. *aAfterFrame points to the :after - * frame before which appended content should go, if there is one. - */ -static nsContainerFrame* -AdjustAppendParentForAfterContent(nsFrameManager* aFrameManager, - nsIContent* aContainer, - nsContainerFrame* aParentFrame, - nsIContent* aChild, - nsIFrame** aAfterFrame) -{ - // If the parent frame has any pseudo-elements or aContainer is a - // display:contents node then we need to walk through the child - // frames to find the first one that is either a ::after frame for an - // ancestor of aChild or a frame that is for a node later in the - // document than aChild and return that in aAfterFrame. - if (aParentFrame->GetGenConPseudos() || - nsLayoutUtils::HasPseudoStyle(aContainer, aParentFrame->StyleContext(), - CSSPseudoElementType::after, - aParentFrame->PresContext()) || - aFrameManager->GetDisplayContentsStyleFor(aContainer)) { - nsIFrame* afterFrame = nullptr; - nsContainerFrame* parent = - static_cast<nsContainerFrame*>(aParentFrame->LastContinuation()); - bool done = false; - while (!done && parent) { - // Ensure that all normal flow children are on the principal child list. - parent->DrainSelfOverflowList(); - - nsIFrame* child = parent->GetChildList(nsIFrame::kPrincipalList).LastChild(); - if (child && child->IsPseudoFrame(aContainer) && - !child->IsGeneratedContentFrame()) { - // Drill down into non-generated pseudo frames of aContainer. - nsContainerFrame* childAsContainer = do_QueryFrame(child); - if (childAsContainer) { - parent = nsLayoutUtils::LastContinuationWithChild(childAsContainer); - continue; - } - } - - for (; child; child = child->GetPrevSibling()) { - nsIContent* c = child->GetContent(); - if (child->IsGeneratedContentFrame()) { - nsIContent* p = c->GetParent(); - if (c->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) { - if (!nsContentUtils::ContentIsDescendantOf(aChild, p) && - p != aContainer && - nsContentUtils::PositionIsBefore(p, aChild)) { - // ::after generated content for content earlier in the doc and not - // for an ancestor. "p != aContainer" may seem redundant but it - // checks if the ::after belongs to the XBL insertion point we're - // inserting aChild into (in which case ContentIsDescendantOf is - // false even though p == aContainer). - // See layout/reftests/bugs/482592-1a.xhtml for an example of that. - done = true; - break; - } - } else if (nsContentUtils::PositionIsBefore(p, aChild)) { - // Non-::after generated content for content earlier in the doc. - done = true; - break; - } - } else if (nsContentUtils::PositionIsBefore(c, aChild)) { - // Content is before aChild. - done = true; - break; - } - afterFrame = child; - } - - parent = static_cast<nsContainerFrame*>(parent->GetPrevContinuation()); - } - if (afterFrame) { - *aAfterFrame = afterFrame; - return afterFrame->GetParent(); - } - } - - *aAfterFrame = nullptr; - - if (IsFramePartOfIBSplit(aParentFrame)) { - // We might be in a situation where the last part of the {ib} split was - // empty. Since we have no ::after pseudo-element, we do in fact want to be - // appending to that last part, so advance to it if needed. Note that here - // aParentFrame is the result of a GetLastIBSplitSibling call, so must be - // either the last or next to last ib-split sibling. - nsContainerFrame* trailingInline = GetIBSplitSibling(aParentFrame); - if (trailingInline) { - aParentFrame = trailingInline; - } - - // Always make sure to look at the last continuation of the frame - // for the {ib} case, even if that continuation is empty. We - // don't do this for the non-ib-split-frame case, since in the - // other cases appending to the last nonempty continuation is fine - // and in fact not doing that can confuse code that doesn't know - // to pull kids from continuations other than its next one. - aParentFrame = - static_cast<nsContainerFrame*>(aParentFrame->LastContinuation()); - } - - return aParentFrame; -} - -/** * This function will get the previous sibling to use for an append operation. - * it takes a parent frame (must not be null) and its :after frame (may be - * null). + * + * It takes a parent frame (must not be null) and the next insertion sibling, if + * the parent content is display: contents or has ::after content (may be null). */ static nsIFrame* -FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame) +FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aNextSibling) { - if (aAfterFrame) { - NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent"); - NS_ASSERTION(aAfterFrame->GetPrevSibling() || - aParentFrame->PrincipalChildList().FirstChild() == aAfterFrame, - ":after frame must be on the principal child list here"); - return aAfterFrame->GetPrevSibling(); - } - aParentFrame->DrainSelfOverflowList(); + if (aNextSibling) { + MOZ_ASSERT(aNextSibling->GetParent() == aParentFrame, "Wrong parent"); + MOZ_ASSERT(aNextSibling->GetPrevSibling() || + aParentFrame->PrincipalChildList().FirstChild() == aNextSibling, + "next sibling must be on the principal child list here"); + return aNextSibling->GetPrevSibling(); + } + return aParentFrame->GetChildList(kPrincipalList).LastChild(); } @@ -6463,7 +6360,7 @@ GetInsertNextSibling(nsIFrame* aParentFrame, nsIFrame* aPrevSibling) * appending flowed frames to a parent's principal child list. It handles the * case where the parent is the trailing inline of an {ib} split. */ -nsresult +void nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState& aState, nsContainerFrame* aParentFrame, nsFrameItems& aFrameList, @@ -6548,13 +6445,11 @@ nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState& aStat return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings, aParentFrame, true); } - - return NS_OK; + return; } // Insert the frames after our aPrevSibling InsertFrames(aParentFrame, kPrincipalList, aPrevSibling, aFrameList); - return NS_OK; } #define UNSET_DISPLAY static_cast<StyleDisplay>(255) @@ -6656,111 +6551,147 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling, return true; } +// FIXME(emilio): If we ever kill IsValidSibling() we can simplify this quite a +// bit (no need to pass aTargetContent or aTargetContentDisplay, and the +// adjust() calls can be responsibility of the caller). +template<nsCSSFrameConstructor::SiblingDirection aDirection> nsIFrame* -nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent, - nsIContent* aTargetContent, - StyleDisplay& aTargetContentDisplay, - nsContainerFrame* aParentFrame, - bool aPrevSibling) -{ - nsIFrame* sibling = aContent->GetPrimaryFrame(); - if (!sibling && GetDisplayContentsStyleFor(aContent)) { - // A display:contents node - check if it has a ::before / ::after frame... - sibling = aPrevSibling ? - nsLayoutUtils::GetAfterFrameForContent(aParentFrame, aContent) : - nsLayoutUtils::GetBeforeFrameForContent(aParentFrame, aContent); - if (!sibling) { - // ... then recurse into children ... - const bool forward = !aPrevSibling; - FlattenedChildIterator iter(aContent, forward); - sibling = aPrevSibling ? - FindPreviousSibling(iter, aTargetContent, aTargetContentDisplay, aParentFrame) : - FindNextSibling(iter, aTargetContent, aTargetContentDisplay, aParentFrame); - } - if (!sibling) { - // ... then ::after / ::before on the opposite end. - sibling = aPrevSibling ? - nsLayoutUtils::GetBeforeFrameForContent(aParentFrame, aContent) : - nsLayoutUtils::GetAfterFrameForContent(aParentFrame, aContent); - } - if (!sibling) { - return nullptr; +nsCSSFrameConstructor::FindSiblingInternal( + FlattenedChildIterator aIter, + nsIContent* aTargetContent, + StyleDisplay& aTargetContentDisplay) +{ + auto adjust = [&](nsIFrame* aPotentialSiblingFrame) -> nsIFrame* { + return AdjustSiblingFrame( + aPotentialSiblingFrame, aTargetContent, aTargetContentDisplay, + aDirection); + }; + + auto nextDomSibling = [](FlattenedChildIterator& aIter) -> nsIContent* { + return aDirection == SiblingDirection::Forward + ? aIter.GetNextChild() : aIter.GetPreviousChild(); + }; + + auto getNearPseudo = [](const nsIContent* aContent) -> nsIFrame* { + return aDirection == SiblingDirection::Forward + ? nsLayoutUtils::GetBeforeFrame(aContent) + : nsLayoutUtils::GetAfterFrame(aContent); + }; + + auto getFarPseudo = [](const nsIContent* aContent) -> nsIFrame* { + return aDirection == SiblingDirection::Forward + ? nsLayoutUtils::GetAfterFrame(aContent) + : nsLayoutUtils::GetBeforeFrame(aContent); + }; + + while (nsIContent* sibling = nextDomSibling(aIter)) { + if (nsIFrame* primaryFrame = sibling->GetPrimaryFrame()) { + // XXX the GetContent() == sibling check is needed due to bug 135040. + // Remove it once that's fixed. + if (primaryFrame->GetContent() == sibling) { + if (nsIFrame* frame = adjust(primaryFrame)) { + return frame; + } + } + } + + if (GetDisplayContentsStyleFor(sibling)) { + if (nsIFrame* frame = adjust(getNearPseudo(sibling))) { + return frame; + } + + const bool startFromBeginning = aDirection == SiblingDirection::Forward; + FlattenedChildIterator iter(sibling, startFromBeginning); + nsIFrame* sibling = FindSiblingInternal<aDirection>( + iter, aTargetContent, aTargetContentDisplay); + if (sibling) { + return sibling; + } } - } else if (!sibling || sibling->GetContent() != aContent) { - // XXX the GetContent() != aContent check is needed due to bug 135040. - // Remove it once that's fixed. - return nullptr; } - // If the frame is out-of-flow, GetPrimaryFrame() will have returned the - // out-of-flow frame; we want the placeholder. - if (sibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { - nsIFrame* placeholderFrame = GetPlaceholderFrameFor(sibling); - NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame"); - sibling = placeholderFrame; + return adjust(getFarPseudo(aIter.Parent())); +} + +nsIFrame* +nsCSSFrameConstructor::AdjustSiblingFrame( + nsIFrame* aSibling, + nsIContent* aTargetContent, + mozilla::StyleDisplay& aTargetContentDisplay, + SiblingDirection aDirection) +{ + if (!aSibling) { + return nullptr; } - // The frame we have now should never be a continuation - NS_ASSERTION(!sibling->GetPrevContinuation(), "How did that happen?"); + if (aSibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { + aSibling = aSibling->GetPlaceholderFrame(); + MOZ_ASSERT(aSibling); + } - if (aPrevSibling) { - // The frame may be a ib-split frame (a split inline frame that - // contains a block). Get the last part of that split. - if (IsFramePartOfIBSplit(sibling)) { - sibling = GetLastIBSplitSibling(sibling, true); + MOZ_ASSERT(!aSibling->GetPrevContinuation(), "How?"); + if (aDirection == SiblingDirection::Backward) { + // The frame may be a ib-split frame (a split inline frame that contains a + // block). Get the last part of that split. + if (IsFramePartOfIBSplit(aSibling)) { + aSibling = GetLastIBSplitSibling(aSibling, true); } // The frame may have a continuation. If so, we want the last // non-overflow-container continuation as our previous sibling. - sibling = sibling->GetTailContinuation(); + aSibling = aSibling->GetTailContinuation(); } - if (aTargetContent && - !IsValidSibling(sibling, aTargetContent, aTargetContentDisplay)) { - sibling = nullptr; + if (!IsValidSibling(aSibling, aTargetContent, aTargetContentDisplay)) { + return nullptr; } - return sibling; + return aSibling; } nsIFrame* -nsCSSFrameConstructor::FindPreviousSibling(FlattenedChildIterator aIter, - nsIContent* aTargetContent, - StyleDisplay& aTargetContentDisplay, - nsContainerFrame* aParentFrame) +nsCSSFrameConstructor::FindPreviousSibling(const FlattenedChildIterator& aIter, + StyleDisplay& aTargetContentDisplay) { - // Note: not all content objects are associated with a frame (e.g., if it's - // `display: none') so keep looking until we find a previous frame. - while (nsIContent* sibling = aIter.GetPreviousChild()) { - MOZ_ASSERT(sibling != aTargetContent); - nsIFrame* prevSibling = - FindFrameForContentSibling(sibling, aTargetContent, aTargetContentDisplay, - aParentFrame, true); - if (prevSibling) { - // Found a previous sibling, we're done! - return prevSibling; - } - } + return FindSibling<SiblingDirection::Backward>(aIter, aTargetContentDisplay); +} - return nullptr; +nsIFrame* +nsCSSFrameConstructor::FindNextSibling(const FlattenedChildIterator& aIter, + StyleDisplay& aTargetContentDisplay) +{ + return FindSibling<SiblingDirection::Forward>(aIter, aTargetContentDisplay); } +template<nsCSSFrameConstructor::SiblingDirection aDirection> nsIFrame* -nsCSSFrameConstructor::FindNextSibling(FlattenedChildIterator aIter, - nsIContent* aTargetContent, - StyleDisplay& aTargetContentDisplay, - nsContainerFrame* aParentFrame) +nsCSSFrameConstructor::FindSibling(const FlattenedChildIterator& aIter, + StyleDisplay& aTargetContentDisplay) { - while (nsIContent* sibling = aIter.GetNextChild()) { - MOZ_ASSERT(sibling != aTargetContent); - nsIFrame* nextSibling = - FindFrameForContentSibling(sibling, aTargetContent, aTargetContentDisplay, - aParentFrame, false); + nsIContent* targetContent = aIter.Get(); + nsIFrame* sibling = + FindSiblingInternal<aDirection>(aIter, targetContent, aTargetContentDisplay); + if (sibling) { + return sibling; + } - if (nextSibling) { - // We found a next sibling, we're done! - return nextSibling; + // Our siblings (if any) do not have a frame to guide us. The frame for the + // target content should be inserted whereever a frame for the container would + // be inserted. This is needed when inserting into display: contents nodes. + const nsIContent* current = aIter.Parent(); + while (GetDisplayContentsStyleFor(current)) { + const nsIContent* parent = current->GetFlattenedTreeParent(); + MOZ_ASSERT(parent, "No display: contents on the root"); + + FlattenedChildIterator iter(parent); + iter.Seek(current); + sibling = FindSiblingInternal<aDirection>( + iter, targetContent, aTargetContentDisplay); + if (sibling) { + return sibling; } + + current = parent; } return nullptr; @@ -6826,8 +6757,7 @@ nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion, // Note that FindPreviousSibling is passed the iterator by value, so that // the later usage of the iterator starts from the same place. StyleDisplay childDisplay = UNSET_DISPLAY; - nsIFrame* prevSibling = - FindPreviousSibling(iter, iter.Get(), childDisplay, aInsertion->mParentFrame); + nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay); // Now, find the geometric parent so that we can handle // continuations properly. Use the prev sibling if we have it; @@ -6840,48 +6770,20 @@ nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion, iter.Seek(aEndSkipChild); iter.GetPreviousChild(); } - nsIFrame* nextSibling = - FindNextSibling(iter, iter.Get(), childDisplay, aInsertion->mParentFrame); - if (GetDisplayContentsStyleFor(aInsertion->mContainer)) { - if (!nextSibling) { - // Our siblings (if any) does not have a frame to guide us. - // The frame for aChild should be inserted whereever a frame for - // the container would be inserted. This is needed when inserting - // into nested display:contents nodes. - nsIContent* child = aInsertion->mContainer; - nsIContent* parent = child->GetParent(); - aInsertion->mParentFrame = - ::GetAdjustedParentFrame(aInsertion->mParentFrame, - aInsertion->mParentFrame->GetType(), - parent); - InsertionPoint fakeInsertion(aInsertion->mParentFrame, parent); - nsIFrame* result = GetInsertionPrevSibling(&fakeInsertion, child, aIsAppend, - aIsRangeInsertSafe, nullptr, nullptr); - MOZ_ASSERT(aInsertion->mParentFrame->GetContent() == - fakeInsertion.mParentFrame->GetContent()); - // fakeInsertion.mParentFrame may now be a continuation of the frame - // we started with in the ctor above. - aInsertion->mParentFrame = fakeInsertion.mParentFrame; - return result; - } - - prevSibling = nextSibling->GetPrevSibling(); - } - - if (nextSibling) { + if (nsIFrame* nextSibling = FindNextSibling(iter, childDisplay)) { aInsertion->mParentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); } else { // No previous or next sibling, so treat this like an appended frame. *aIsAppend = true; if (IsFramePartOfIBSplit(aInsertion->mParentFrame)) { // Since we're appending, we'll walk to the last anonymous frame - // that was created for the broken inline frame. But don't walk - // to the trailing inline if it's empty; stop at the block. + // that was created for the broken inline frame. We can walk to the + // trailing inline, since we know this is a real append, and not an + // insert (that would've been handled by `FindNextSibling`). aInsertion->mParentFrame = - GetLastIBSplitSibling(aInsertion->mParentFrame, false); + GetLastIBSplitSibling(aInsertion->mParentFrame, true); } - // Get continuation that parents the last child. This MUST be done - // before the AdjustAppendParentForAfterContent call. + // Get continuation that parents the last child. aInsertion->mParentFrame = nsLayoutUtils::LastContinuationWithChild(aInsertion->mParentFrame); // Deal with fieldsets @@ -6889,12 +6791,7 @@ nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion, ::GetAdjustedParentFrame(aInsertion->mParentFrame, aInsertion->mParentFrame->GetType(), aChild); - nsIFrame* appendAfterFrame; - aInsertion->mParentFrame = - ::AdjustAppendParentForAfterContent(this, aInsertion->mContainer, - aInsertion->mParentFrame, - aChild, &appendAfterFrame); - prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, appendAfterFrame); + prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, nullptr); } } @@ -7010,7 +6907,8 @@ nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aParentContent, } NS_ASSERTION(!aContent->GetPrimaryFrame(), "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"); - ContentInserted(aParentContent, aContent, nullptr, false); + const bool allowLazyConstruction = true; + ContentInserted(aParentContent, aContent, nullptr, allowLazyConstruction); } // For inserts aChild should be valid, for appends it should be null. @@ -7020,11 +6918,8 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation, nsIContent* aContainer, nsIContent* aChild) { - // XXXmats no lazy frames for display:contents direct descendants yet - // (Mozilla bug 979782). if (mPresShell->GetPresContext()->IsChrome() || !aContainer || - aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXULElement() || - GetDisplayContentsStyleFor(aContainer)) { + aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXULElement()) { return false; } @@ -7060,8 +6955,7 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation, // hit a node with a leaf frame. // // Also, it's fine if one of the nodes without primary frame is a display: - // contents node except if it's the direct ancestor of the children we're - // recreating frames for. + // contents node. bool noPrimaryFrame = false; bool needsFrameBitSet = false; #endif @@ -7293,8 +7187,9 @@ nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame, cur = cur->GetNextSibling()) { if (IsSpecialFramesetChild(cur)) { // Just reframe the parent, since framesets are weird like that. - RecreateFramesForContent(aParentFrame->GetContent(), false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aParentFrame->GetContent(), + InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); return true; } } @@ -7302,7 +7197,7 @@ nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame, return false; } -nsresult +void nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, nsIContent* aFirstNewContent, bool aAllowLazyConstruction) @@ -7345,8 +7240,8 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, if (tag == nsGkAtoms::treechildren || tag == nsGkAtoms::treeitem || tag == nsGkAtoms::treerow) - return NS_OK; + return; } #endif // MOZ_XUL @@ -7359,21 +7254,21 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, //XXXsmaug This is super unefficient! nsIContent* bindingParent = aContainer->GetBindingParent(); LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(bindingParent, false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(bindingParent, InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // See comment in ContentRangeInserted for why this is necessary. if (!GetContentInsertionFrameFor(aContainer) && !aContainer->IsActiveChildrenElement()) { - return NS_OK; + return; } if (aAllowLazyConstruction && MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) { - return NS_OK; + return; } LAYOUT_PHASE_TEMP_EXIT(); @@ -7383,13 +7278,13 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, nsContainerFrame*& parentFrame = insertion.mParentFrame; LAYOUT_PHASE_TEMP_REENTER(); if (!parentFrame) { - return NS_OK; + return; } LAYOUT_PHASE_TEMP_EXIT(); if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) { LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } LAYOUT_PHASE_TEMP_REENTER(); @@ -7397,21 +7292,22 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, // Nothing to do here; we shouldn't be constructing kids of leaves // Clear lazy bits so we don't try to construct again. ClearLazyBits(aFirstNewContent, nullptr); - return NS_OK; + return; } if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) { LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(parentFrame->GetContent(), + InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // If the frame we are manipulating is a ib-split frame (that is, one // that's been created as a result of a block-in-inline situation) then we // need to append to the last ib-split sibling, not to the frame itself. - bool parentIBSplit = IsFramePartOfIBSplit(parentFrame); + const bool parentIBSplit = IsFramePartOfIBSplit(parentFrame); if (parentIBSplit) { #ifdef DEBUG if (gNoisyContentUpdates) { @@ -7437,38 +7333,79 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, parentFrame->GetType() != nsGkAtoms::detailsFrame, "Parent frame should not be fieldset or details!"); - // Deal with possible :after generated content on the parent - nsIFrame* parentAfterFrame; - parentFrame = - ::AdjustAppendParentForAfterContent(this, insertion.mContainer, parentFrame, - aFirstNewContent, &parentAfterFrame); + // Deal with possible :after generated content on the parent, or display: + // contents. + nsIFrame* nextSibling = nullptr; + if (GetDisplayContentsStyleFor(insertion.mContainer) || + nsLayoutUtils::GetAfterFrame(insertion.mContainer)) { + FlattenedChildIterator iter(insertion.mContainer); + iter.Seek(insertion.mContainer->GetLastChild()); + StyleDisplay unused = UNSET_DISPLAY; + nextSibling = FindNextSibling(iter, unused); + } - // Create some new frames - nsFrameConstructorState state(mPresShell, - GetAbsoluteContainingBlock(parentFrame, FIXED_POS), - GetAbsoluteContainingBlock(parentFrame, ABS_POS), - GetFloatContainingBlock(parentFrame)); - state.mTreeMatchContext.InitAncestors(aContainer->AsElement()); + if (nextSibling) { + parentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); + } else if (parentIBSplit) { + // We might be in a situation where the last part of the {ib} split was + // empty. Since we have no ::after pseudo-element, we do in fact want to be + // appending to that last part, so advance to it if needed. Note that here + // aParentFrame is the result of a GetLastIBSplitSibling call, so must be + // either the last or next to last ib-split sibling. + if (nsContainerFrame* trailingInline = GetIBSplitSibling(parentFrame)) { + parentFrame = trailingInline; + } - // See if the containing block has :first-letter style applied. - bool haveFirstLetterStyle = false, haveFirstLineStyle = false; - nsContainerFrame* containingBlock = state.mFloatedItems.containingBlock; - if (containingBlock) { - haveFirstLetterStyle = HasFirstLetterStyle(containingBlock); - haveFirstLineStyle = - ShouldHaveFirstLineStyle(containingBlock->GetContent(), - containingBlock->StyleContext()); + // Always make sure to look at the last continuation of the frame + // for the {ib} case, even if that continuation is empty. We + // don't do this for the non-ib-split-frame case, since in the + // other cases appending to the last nonempty continuation is fine + // and in fact not doing that can confuse code that doesn't know + // to pull kids from continuations other than its next one. + parentFrame = + static_cast<nsContainerFrame*>(parentFrame->LastContinuation()); } + nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame); + + // See if the containing block has :first-letter style applied. + const bool haveFirstLetterStyle = + containingBlock && HasFirstLetterStyle(containingBlock); + + const bool haveFirstLineStyle = + containingBlock && + ShouldHaveFirstLineStyle(containingBlock->GetContent(), + containingBlock->StyleContext()); + if (haveFirstLetterStyle) { + nsWeakFrame wf(nextSibling); // Before we get going, remove the current letter frames - RemoveLetterFrames(state.mPresShell, containingBlock); + RemoveLetterFrames(mPresShell, containingBlock); + + // Reget nextSibling, since we may have killed it. + if (nextSibling && !wf) { + FlattenedChildIterator iter(insertion.mContainer); + iter.Seek(insertion.mContainer->GetLastChild()); + StyleDisplay unused = UNSET_DISPLAY; + nextSibling = FindNextSibling(iter, unused); + if (nextSibling) { + parentFrame = nextSibling->GetParent()->GetContentInsertionFrame(); + containingBlock = GetFloatContainingBlock(parentFrame); + } + } } + // Create some new frames + nsFrameConstructorState state(mPresShell, + GetAbsoluteContainingBlock(parentFrame, FIXED_POS), + GetAbsoluteContainingBlock(parentFrame, ABS_POS), + containingBlock); + state.mTreeMatchContext.InitAncestors(aContainer->AsElement()); + nsIAtom* frameType = parentFrame->GetType(); FlattenedChildIterator iter(aContainer); - bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild()); + const bool haveNoXBLChildren = !iter.XBLInvolved() || !iter.GetNextChild(); FrameConstructionItemList items; if (aFirstNewContent->GetPreviousSibling() && GetParentType(frameType) == eTypeBlock && @@ -7493,7 +7430,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, AddFrameConstructionItems(state, child, false, insertion, items); } - nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, parentAfterFrame); + nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, nextSibling); // Perform special check for diddling around with the frames in // a ib-split inline frame. @@ -7503,7 +7440,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, if (WipeContainingBlock(state, containingBlock, parentFrame, items, true, prevSibling)) { LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } LAYOUT_PHASE_TEMP_REENTER(); @@ -7516,8 +7453,11 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, !prevSibling->IsInlineOutside() || prevSibling->GetType() == nsGkAtoms::brFrame); // :after content can't be <br> so no need to check it - items.SetLineBoundaryAtEnd(!parentAfterFrame || - !parentAfterFrame->IsInlineOutside()); + // + // FIXME(emilio): A display: contents sibling could! Write a test-case and + // fix. + items.SetLineBoundaryAtEnd( + !nextSibling || !nextSibling->IsInlineOutside()); } // To suppress whitespace-only text frames, we have to verify that // our container's DOM child list matches its flattened tree child list. @@ -7590,7 +7530,7 @@ nsCSSFrameConstructor::ContentAppended(nsIContent* aContainer, } #endif - return NS_OK; + return; } #ifdef MOZ_XUL @@ -7633,17 +7573,17 @@ bool NotifyListBoxBody(nsPresContext* aPresContext, } #endif // MOZ_XUL -nsresult +void nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, nsIContent* aChild, nsILayoutHistoryState* aFrameState, bool aAllowLazyConstruction) { - return ContentRangeInserted(aContainer, - aChild, - aChild->GetNextSibling(), - aFrameState, - aAllowLazyConstruction); + ContentRangeInserted(aContainer, + aChild, + aChild->GetNextSibling(), + aFrameState, + aAllowLazyConstruction); } // ContentRangeInserted handles creating frames for a range of nodes that @@ -7664,7 +7604,7 @@ nsCSSFrameConstructor::ContentInserted(nsIContent* aContainer, // in the caption list, while skipping any nodes in the range being inserted // (because when we treat the caption frames the other nodes have had their // frames constructed but not yet inserted into the frame tree). -nsresult +void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, nsIContent* aStartChild, nsIContent* aEndChild, @@ -7721,7 +7661,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, // The insert case in NotifyListBoxBody // doesn't use "old next sibling". aStartChild, nullptr, nullptr, CONTENT_INSERTED)) { - return NS_OK; + return; } } else { // We don't handle a range insert to a listbox parent, issue single @@ -7730,7 +7670,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, IssueSingleInsertNofications(aContainer, aStartChild, aEndChild, aAllowLazyConstruction); LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } } #endif // MOZ_XUL @@ -7745,7 +7685,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, if (aStartChild != docElement) { // Not the root element; just bail out - return NS_OK; + return; } NS_PRECONDITION(nullptr == mRootElementFrame, @@ -7782,7 +7722,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, } #endif - return NS_OK; + return; } if (aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE) && @@ -7795,10 +7735,10 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, //XXXsmaug This is super unefficient! nsIContent* bindingParent = aContainer->GetBindingParent(); LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(bindingParent, false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(bindingParent, InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // Put 'parentFrame' inside a scope so we don't confuse it with @@ -7809,7 +7749,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, // a parent. While its uncommon to change the structure of the default content itself, a label, // for example, can be reframed by having its value attribute set or removed. if (!parentFrame && !aContainer->IsActiveChildrenElement()) { - return NS_OK; + return; } // Otherwise, we've got parent content. Find its frame. @@ -7818,7 +7758,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, if (aAllowLazyConstruction && MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) { - return NS_OK; + return; } } @@ -7838,7 +7778,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, } if (!insertion.mParentFrame) { - return NS_OK; + return; } bool isAppend, isRangeInsertSafe; @@ -7852,16 +7792,14 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, IssueSingleInsertNofications(aContainer, aStartChild, aEndChild, aAllowLazyConstruction); LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } - nsIContent* container = insertion.mParentFrame->GetContent(); - nsIAtom* frameType = insertion.mParentFrame->GetType(); LAYOUT_PHASE_TEMP_EXIT(); if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild, aEndChild)) { LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } LAYOUT_PHASE_TEMP_REENTER(); @@ -7878,10 +7816,11 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, // and if so, proceed. But we'd have to extend nsFieldSetFrame // to locate this legend in the inserted frames and extract it. LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(insertion.mParentFrame->GetContent(), false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(insertion.mParentFrame->GetContent(), + InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // We should only get here with details when doing a single insertion because @@ -7893,26 +7832,27 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, // expensive to recreate the entire details frame, but it's the simplest way // to handle the insertion. LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = - RecreateFramesForContent(insertion.mParentFrame->GetContent(), false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(insertion.mParentFrame->GetContent(), + InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // Don't construct kids of leaves if (insertion.mParentFrame->IsLeaf()) { // Clear lazy bits so we don't try to construct again. ClearLazyBits(aStartChild, aEndChild); - return NS_OK; + return; } if (insertion.mParentFrame->IsFrameOfType(nsIFrame::eMathML)) { LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(insertion.mParentFrame->GetContent(), false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(insertion.mParentFrame->GetContent(), + InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } nsFrameConstructorState state(mPresShell, @@ -7962,7 +7902,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, // the placeholder frame. if (insertion.mParentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { nsPlaceholderFrame* placeholderFrame = - GetPlaceholderFrameFor(insertion.mParentFrame); + insertion.mParentFrame->GetPlaceholderFrame(); NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?"); insertion.mParentFrame = placeholderFrame->GetParent(); } else { @@ -7989,30 +7929,13 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, IssueSingleInsertNofications(aContainer, aStartChild, aEndChild, aAllowLazyConstruction); LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } - container = insertion.mParentFrame->GetContent(); frameType = insertion.mParentFrame->GetType(); } } - if (!prevSibling) { - // We're inserting the new frames as the first child. See if the - // parent has a :before pseudo-element - nsIFrame* firstChild = insertion.mParentFrame->PrincipalChildList().FirstChild(); - - if (firstChild && - nsLayoutUtils::IsGeneratedContentFor(container, firstChild, - nsCSSPseudoElements::before)) { - // Insert the new frames after the last continuation of the :before - prevSibling = firstChild->GetTailContinuation(); - insertion.mParentFrame = prevSibling->GetParent()->GetContentInsertionFrame(); - // Don't change isAppend here; we'll can call AppendFrames as needed, and - // the change to our prevSibling doesn't affect that. - } - } - FrameConstructionItemList items; ParentType parentType = GetParentType(frameType); FlattenedChildIterator iter(aContainer); @@ -8057,7 +7980,7 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items, isAppend, prevSibling)) { LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; + return; } LAYOUT_PHASE_TEMP_REENTER(); @@ -8081,65 +8004,11 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, } } - // If the parent of our current prevSibling is different from the frame we'll - // actually use as the parent, then the calculated insertion point is now - // invalid and as it is unknown where to insert correctly we append instead - // (bug 341858). - // This can affect our prevSibling and isAppend, but should not have any - // effect on the WipeContainingBlock above, since this should only happen - // when neither parent is a ib-split frame and should not affect whitespace - // handling inside table-related frames (and in fact, can only happen when - // one of the parents is a table wrapper and one is an inner table or when the - // parent is a fieldset or fieldset content frame). So it won't affect the - // {ib} or XUL box cases in WipeContainingBlock(), and the table pseudo - // handling will only be affected by us maybe thinking we're not inserting - // at the beginning, whereas we really are. That would have made us reframe - // unnecessarily, but that's ok. - // XXXbz we should push our frame construction item code up higher, so we - // know what our items are by the time we start figuring out previous - // siblings - if (prevSibling && frameItems.NotEmpty() && - frameItems.FirstChild()->GetParent() != prevSibling->GetParent()) { -#ifdef DEBUG - nsIFrame* frame1 = frameItems.FirstChild()->GetParent(); - nsIFrame* frame2 = prevSibling->GetParent(); - NS_ASSERTION(!IsFramePartOfIBSplit(frame1) && - !IsFramePartOfIBSplit(frame2), - "Neither should be ib-split"); - NS_ASSERTION((frame1->GetType() == nsGkAtoms::tableFrame && - frame2->GetType() == nsGkAtoms::tableWrapperFrame) || - (frame1->GetType() == nsGkAtoms::tableWrapperFrame && - frame2->GetType() == nsGkAtoms::tableFrame) || - frame1->GetType() == nsGkAtoms::fieldSetFrame || - (frame1->GetParent() && - frame1->GetParent()->GetType() == nsGkAtoms::fieldSetFrame), - "Unexpected frame types"); -#endif - isAppend = true; - nsIFrame* appendAfterFrame; - insertion.mParentFrame = - ::AdjustAppendParentForAfterContent(this, container, - frameItems.FirstChild()->GetParent(), - aStartChild, &appendAfterFrame); - prevSibling = ::FindAppendPrevSibling(insertion.mParentFrame, appendAfterFrame); - } - - if (haveFirstLineStyle && insertion.mParentFrame == containingBlock) { + if (haveFirstLineStyle && insertion.mParentFrame == containingBlock && isAppend) { // It's possible that the new frame goes into a first-line // frame. Look at it and see... - if (isAppend) { - // Use append logic when appending - AppendFirstLineFrames(state, containingBlock->GetContent(), - containingBlock, frameItems); - } - else { - // Use more complicated insert logic when inserting - // XXXbz this method is a no-op, so it's easy for the args being passed - // here to make no sense without anyone noticing... If it ever stops - // being a no-op, vet them carefully! - InsertFirstLineFrames(state, container, containingBlock, &insertion.mParentFrame, - prevSibling, frameItems); - } + AppendFirstLineFrames(state, containingBlock->GetContent(), + containingBlock, frameItems); } // We might have captions; put them into the caption list of the @@ -8222,32 +8091,35 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer, #endif #ifdef ACCESSIBILITY - nsAccessibilityService* accService = nsIPresShell::AccService(); - if (accService) { + if (nsAccessibilityService* accService = nsIPresShell::AccService()) { accService->ContentRangeInserted(mPresShell, aContainer, aStartChild, aEndChild); } #endif - return NS_OK; + return; } -nsresult -nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, - nsIContent* aChild, - nsIContent* aOldNextSibling, - RemoveFlags aFlags, - bool* aDidReconstruct, - nsIContent** aDestroyedFramesFor) -{ +void +nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aOldNextSibling, + RemoveFlags aFlags, + bool* aDidReconstruct) +{ + MOZ_ASSERT(aChild); + MOZ_ASSERT(aDidReconstruct); AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC); NS_PRECONDITION(mUpdateCount != 0, "Should be in an update while destroying frames"); *aDidReconstruct = false; - if (aDestroyedFramesFor) { - *aDestroyedFramesFor = aChild; - } + + // Only recreate sync if we're already in frame construction, that is, + // recreate async for XBL DOM changes, and normal content removals. + const InsertionKind insertionKind = (aFlags == REMOVE_FOR_RECONSTRUCTION) + ? InsertionKind::Sync + : InsertionKind::Async; nsPresContext* presContext = mPresShell->GetPresContext(); MOZ_ASSERT(presContext, "Our presShell should have a valid presContext"); @@ -8261,7 +8133,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // source is a fullscreen element, and we have code elsewhere to update // scrollbars after fullscreen elements are removed -- specifically, it's // part of the fullscreen cleanup code called by Element::UnbindFromTree.) - presContext->UpdateViewportScrollbarStylesOverride(); + presContext->UpdateViewportScrollStylesOverride(); } // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and @@ -8280,7 +8152,6 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, } #endif - nsresult rv = NS_OK; nsIFrame* childFrame = aChild->GetPrimaryFrame(); if (!childFrame || childFrame->GetContent() != aChild) { // XXXbz the GetContent() != aChild check is needed due to bug 135040. @@ -8290,37 +8161,33 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild), "display:contents nodes shouldn't have a frame"); if (!childFrame && GetDisplayContentsStyleFor(aChild)) { - nsIFrame* ancestorFrame = nullptr; - nsIContent* ancestor = aContainer; - for (; ancestor; ancestor = ancestor->GetParent()) { - ancestorFrame = ancestor->GetPrimaryFrame(); - if (ancestorFrame) { - break; - } + nsIContent* ancestor = aChild->GetFlattenedTreeParent(); + MOZ_ASSERT(ancestor, "display: contents on the root?"); + while (!ancestor->GetPrimaryFrame()) { + ancestor = ancestor->GetFlattenedTreeParent(); + MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!"); } - if (ancestorFrame) { - nsIFrame* contentInsertion = ancestorFrame->GetContentInsertionFrame(); - if (ancestorFrame->GetGenConPseudos() || - (contentInsertion && contentInsertion->GetGenConPseudos())) { - *aDidReconstruct = true; - LAYOUT_PHASE_TEMP_EXIT(); - // XXXmats Can we recreate frames only for the ::after/::before content? - // XXX Perhaps even only those that belong to the aChild sub-tree? - RecreateFramesForContent(ancestor, false, aFlags, aDestroyedFramesFor); - LAYOUT_PHASE_TEMP_REENTER(); - return NS_OK; - } + + nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame(); + if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) { + *aDidReconstruct = true; + + // XXXmats Can we recreate frames only for the ::after/::before content? + // XXX Perhaps even only those that belong to the aChild sub-tree? + LAYOUT_PHASE_TEMP_EXIT(); + RecreateFramesForContent(ancestor, insertionKind, aFlags); + LAYOUT_PHASE_TEMP_REENTER(); + return; } FlattenedChildIterator iter(aChild); for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) { if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) { LAYOUT_PHASE_TEMP_EXIT(); - rv = ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct, aDestroyedFramesFor); + ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct); LAYOUT_PHASE_TEMP_REENTER(); - NS_ENSURE_SUCCESS(rv, rv); if (aFlags != REMOVE_DESTROY_FRAMES && *aDidReconstruct) { - return rv; + return; } } } @@ -8333,7 +8200,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, if (aFlags == REMOVE_DESTROY_FRAMES) { CaptureStateForFramesOf(aChild, mTempFrameTreeState); } - return NS_OK; + return; } #endif // MOZ_XUL @@ -8371,10 +8238,9 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, nsIContent* bindingParent = aContainer->GetBindingParent(); *aDidReconstruct = true; LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(bindingParent, false, - aFlags, aDestroyedFramesFor); + RecreateFramesForContent(bindingParent, insertionKind, aFlags); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } if (aFlags == REMOVE_DESTROY_FRAMES) { @@ -8386,15 +8252,11 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // See whether we need to remove more than just childFrame LAYOUT_PHASE_TEMP_EXIT(); - nsIContent* container; - if (MaybeRecreateContainerForFrameRemoval(childFrame, aFlags, &rv, &container)) { - LAYOUT_PHASE_TEMP_REENTER(); - MOZ_ASSERT(container); + if (MaybeRecreateContainerForFrameRemoval( + childFrame, insertionKind, aFlags)) { *aDidReconstruct = true; - if (aDestroyedFramesFor) { - *aDestroyedFramesFor = container; - } - return rv; + LAYOUT_PHASE_TEMP_REENTER(); + return; } LAYOUT_PHASE_TEMP_REENTER(); @@ -8407,10 +8269,10 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // Just reframe the parent, since framesets are weird like that. *aDidReconstruct = true; LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false, - aFlags, aDestroyedFramesFor); + RecreateFramesForContent(parentFrame->GetContent(), insertionKind, + aFlags); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // If we're a child of MathML, then we should reframe the MathML content. @@ -8421,10 +8283,9 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) { *aDidReconstruct = true; LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(possibleMathMLAncestor->GetContent(), - false, aFlags, aDestroyedFramesFor); + RecreateFramesForContent(parentFrame->GetContent(), insertionKind, aFlags); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // Undo XUL wrapping if it's no longer needed. @@ -8438,15 +8299,14 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, !AnyKidsNeedBlockParent(childFrame->GetNextSibling())) { *aDidReconstruct = true; LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(grandparentFrame->GetContent(), true, - aFlags, aDestroyedFramesFor); + RecreateFramesForContent(grandparentFrame->GetContent(), insertionKind, + aFlags); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } #ifdef ACCESSIBILITY - nsAccessibilityService* accService = nsIPresShell::AccService(); - if (accService) { + if (nsAccessibilityService* accService = nsIPresShell::AccService()) { accService->ContentRemoved(mPresShell, aChild); } #endif @@ -8455,7 +8315,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // :first-letter style applies. nsIFrame* inflowChild = childFrame; if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { - inflowChild = GetPlaceholderFrameFor(childFrame); + inflowChild = childFrame->GetPlaceholderFrame(); NS_ASSERTION(inflowChild, "No placeholder for out-of-flow?"); } nsContainerFrame* containingBlock = @@ -8485,7 +8345,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // XXXbz the GetContent() != aChild check is needed due to bug 135040. // Remove it once that's fixed. ClearUndisplayedContentIn(aChild, aContainer); - return NS_OK; + return; } parentFrame = childFrame->GetParent(); parentType = parentFrame->GetType(); @@ -8511,7 +8371,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // Notify the parent frame that it should delete the frame if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { - childFrame = GetPlaceholderFrameFor(childFrame); + childFrame = childFrame->GetPlaceholderFrame(); NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow."); parentFrame = childFrame->GetParent(); } @@ -8549,6 +8409,9 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, // and hence it's adjacent to a block end. // If aOldNextSibling is null, then the text node before the node being // removed is the last node, and we don't need to worry about it. + // + // FIXME(emilio): This should probably use the lazy frame construction + // bits if possible instead of reframing it in place. if (aOldNextSibling) { nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling(); if (prevSibling && prevSibling->GetPreviousSibling()) { @@ -8575,7 +8438,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer, #endif } - return rv; + return; } /** @@ -8637,12 +8500,11 @@ nsCSSFrameConstructor::EnsureFrameForTextNode(nsGenericDOMDataNode* aContent) return aContent->GetPrimaryFrame(); } -nsresult +void nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent, CharacterDataChangeInfo* aInfo) { AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC); - nsresult rv = NS_OK; if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) && !aContent->TextIsOnlyWhitespace()) || @@ -8654,10 +8516,10 @@ nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent, "Bit should never be set on generated content"); #endif LAYOUT_PHASE_TEMP_EXIT(); - nsresult rv = RecreateFramesForContent(aContent, false, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aContent, InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); LAYOUT_PHASE_TEMP_REENTER(); - return rv; + return; } // Find the child frame @@ -8705,8 +8567,6 @@ nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent, RecoverLetterFrames(block); } } - - return rv; } void @@ -9155,7 +9015,7 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame) // are within fixed frames, because that would cause duplicates on the new // page - bug 389619) for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) { - nsIFrame* prevPlaceholder = GetPlaceholderFrameFor(fixed); + nsIFrame* prevPlaceholder = fixed->GetPlaceholderFrame(); if (prevPlaceholder && nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) { // We want to use the same style as the primary style frame for @@ -9320,7 +9180,8 @@ nsCSSFrameConstructor::MaybeRecreateFramesForElement(Element* aElement) } } - RecreateFramesForContent(aElement, false, REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aElement, InsertionKind::Sync, + REMOVE_FOR_RECONSTRUCTION); return nullptr; } @@ -9363,19 +9224,16 @@ FindPreviousNonWhitespaceSibling(nsIFrame* aFrame) } bool -nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, - RemoveFlags aFlags, - nsresult* aResult, - nsIContent** aDestroyedFramesFor) +nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval( + nsIFrame* aFrame, + InsertionKind aInsertionKind, + RemoveFlags aFlags) { NS_PRECONDITION(aFrame, "Must have a frame"); NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root"); - NS_PRECONDITION(aResult, "Null out param?"); NS_PRECONDITION(aFrame == aFrame->FirstContinuation(), "aFrame not the result of GetPrimaryFrame()?"); - *aDestroyedFramesFor = nullptr; - if (IsFramePartOfIBSplit(aFrame)) { // The removal functions can't handle removal of an {ib} split directly; we // need to rebuild the containing block. @@ -9388,44 +9246,44 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, } #endif - *aResult = ReframeContainingBlock(aFrame, aFlags, aDestroyedFramesFor); + ReframeContainingBlock(aFrame, aInsertionKind, aFlags); return true; } nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame(); if (insertionFrame && insertionFrame->GetType() == nsGkAtoms::legendFrame && aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) { - // When we remove the legend for a fieldset, we should reframe - // the fieldset to ensure another legend is used, if there is one - *aResult = RecreateFramesForContent(aFrame->GetParent()->GetContent(), false, - aFlags, aDestroyedFramesFor); + RecreateFramesForContent(aFrame->GetParent()->GetContent(), aInsertionKind, + aFlags); return true; } - if (insertionFrame && - aFrame->GetParent()->GetType() == nsGkAtoms::detailsFrame) { + nsIFrame* inFlowFrame = + (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ? + aFrame->GetPlaceholderFrame() : aFrame; + MOZ_ASSERT(inFlowFrame, "How did that happen?"); + MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(), + "placeholder for primary frame has previous continuations?"); + nsIFrame* parent = inFlowFrame->GetParent(); + + if (parent && parent->GetType() == nsGkAtoms::detailsFrame) { HTMLSummaryElement* summary = - HTMLSummaryElement::FromContent(insertionFrame->GetContent()); + HTMLSummaryElement::FromContent(aFrame->GetContent()); + DetailsFrame* detailsFrame = static_cast<DetailsFrame*>(parent); - if (summary && summary->IsMainSummary()) { + // Unlike adding summary element cases, we need to check children of the + // parent details frame since at this moment the summary element has been + // already removed from the parent details element's child list. + if (summary && detailsFrame->HasMainSummaryFrame(aFrame)) { // When removing a summary, we should reframe the parent details frame to // ensure that another summary is used or the default summary is // generated. - *aResult = RecreateFramesForContent(aFrame->GetParent()->GetContent(), - false, REMOVE_FOR_RECONSTRUCTION, - aDestroyedFramesFor); + RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags); return true; } } // Now check for possibly needing to reconstruct due to a pseudo parent - nsIFrame* inFlowFrame = - (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ? - GetPlaceholderFrameFor(aFrame) : aFrame; - MOZ_ASSERT(inFlowFrame, "How did that happen?"); - MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(), - "placeholder for primary frame has previous continuations?"); - nsIFrame* parent = inFlowFrame->GetParent(); // For the case of ruby pseudo parent, effectively, only pseudo rb/rt frame // need to be checked here, since all other types of parent will be catched // by "Check ruby containers" section below. @@ -9443,10 +9301,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, // Similar if we're a table-caption. (inFlowFrame->IsTableCaption() && parent->GetChildList(nsIFrame::kCaptionList).FirstChild() == inFlowFrame)) { - // We're the first or last frame in the pseudo. Need to reframe. - // Good enough to recreate frames for |parent|'s content - *aResult = RecreateFramesForContent(parent->GetContent(), true, aFlags, - aDestroyedFramesFor); + RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags); return true; } } @@ -9475,8 +9330,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, #endif // Good enough to recreate frames for aFrame's parent's content; even if // aFrame's parent is a pseudo, that'll be the right content node. - *aResult = RecreateFramesForContent(parent->GetContent(), true, aFlags, - aDestroyedFramesFor); + RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags); return true; } } @@ -9492,8 +9346,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, // frames may be constructed or destroyed accordingly. // 2. The type of the first child of a ruby frame determines // whether a pseudo ruby base container should exist. - *aResult = RecreateFramesForContent(parent->GetContent(), true, aFlags, - aDestroyedFramesFor); + RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags); return true; } @@ -9516,8 +9369,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, } #endif // DEBUG // Recreate frames for the flex container (the removed frame's parent) - *aResult = RecreateFramesForContent(parent->GetContent(), true, aFlags, - aDestroyedFramesFor); + RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags); return true; } @@ -9535,8 +9387,8 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, } #endif // DEBUG // Recreate frames for the flex container (the removed frame's grandparent) - *aResult = RecreateFramesForContent(parent->GetParent()->GetContent(), true, - aFlags, aDestroyedFramesFor); + RecreateFramesForContent(parent->GetParent()->GetContent(), aInsertionKind, + aFlags); return true; } @@ -9544,7 +9396,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, if (aFrame->GetType() == nsGkAtoms::popupSetFrame) { nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell); if (rootBox && rootBox->GetPopupSetFrame() == aFrame) { - *aResult = ReconstructDocElementHierarchy(); + ReconstructDocElementHierarchy(); return true; } } @@ -9556,8 +9408,7 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, !inFlowFrame->GetNextSibling() && ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) || (parent->GetNextContinuation() && !parent->GetNextInFlow()))) { - *aResult = RecreateFramesForContent(parent->GetContent(), true, aFlags, - aDestroyedFramesFor); + RecreateFramesForContent(parent->GetContent(), aInsertionKind, aFlags); return true; } @@ -9593,24 +9444,26 @@ nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, } #endif - *aResult = ReframeContainingBlock(parent, aFlags, aDestroyedFramesFor); + ReframeContainingBlock(parent, aInsertionKind, aFlags); return true; } -nsresult -nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, - bool aAsyncInsert, - RemoveFlags aFlags, - nsIContent** aDestroyedFramesFor) +void +nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, + InsertionKind aInsertionKind, + RemoveFlags aFlags) { - NS_PRECONDITION(!aAsyncInsert || aContent->IsElement(), - "Can only insert elements async"); + MOZ_ASSERT(aInsertionKind != InsertionKind::Async || aContent->IsElement()); + MOZ_ASSERT(aContent); + // If there is no document, we don't want to recreate frames for it. (You // shouldn't generally be giving this method content without a document // anyway). // Rebuilding the frame tree can have bad effects, especially if it's the // frame tree for chrome (see bug 157322). - NS_ENSURE_TRUE(aContent->GetComposedDoc(), NS_ERROR_FAILURE); + if (NS_WARN_IF(!aContent->GetComposedDoc())) { + return; + } // Is the frame ib-split? If so, we need to reframe the containing // block *here*, rather than trying to remove and re-insert the @@ -9636,8 +9489,8 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, if (frame) { nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame); if (nonGeneratedAncestor->GetContent() != aContent) { - return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), aAsyncInsert, - aFlags, aDestroyedFramesFor); + return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), + aInsertionKind, aFlags); } if (frame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) { @@ -9657,8 +9510,8 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, if (ancestor->GetType() != nsGkAtoms::svgUseFrame) { NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(), "Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?"); - return RecreateFramesForContent(ancestor->GetContent(), aAsyncInsert, - aFlags, aDestroyedFramesFor); + return RecreateFramesForContent(ancestor->GetContent(), aInsertionKind, + aFlags); } } @@ -9669,20 +9522,13 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, // with native anonymous content from the editor. if (parent && parent->IsLeaf() && parentContent && parentContent != aContent) { - return RecreateFramesForContent(parentContent, aAsyncInsert, aFlags, - aDestroyedFramesFor); + return RecreateFramesForContent(parentContent, aInsertionKind, aFlags); } } - nsresult rv = NS_OK; - nsIContent* container; - if (frame && MaybeRecreateContainerForFrameRemoval(frame, aFlags, &rv, - &container)) { - MOZ_ASSERT(container); - if (aDestroyedFramesFor) { - *aDestroyedFramesFor = container; - } - return rv; + if (frame && + MaybeRecreateContainerForFrameRemoval(frame, aInsertionKind, aFlags)) { + return; } nsINode* containerNode = aContent->GetParentNode(); @@ -9694,47 +9540,44 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent, // Need the nsIContent parent, which might be null here, since we need to // pass it to ContentInserted and ContentRemoved. + // + // FIXME(emilio): Do we need a strong ref here? nsCOMPtr<nsIContent> container = aContent->GetParent(); // Remove the frames associated with the content object. bool didReconstruct; nsIContent* nextSibling = aContent->IsRootOfAnonymousSubtree() ? nullptr : aContent->GetNextSibling(); - const bool reconstruct = aFlags != REMOVE_DESTROY_FRAMES; - RemoveFlags flags = reconstruct ? REMOVE_FOR_RECONSTRUCTION : aFlags; - rv = ContentRemoved(container, aContent, nextSibling, flags, - &didReconstruct, aDestroyedFramesFor); - if (NS_FAILED(rv)) { - return rv; - } - if (reconstruct && !didReconstruct) { - // Now, recreate the frames associated with this content object. If - // ContentRemoved triggered reconstruction, then we don't need to do this - // because the frames will already have been built. - if (aAsyncInsert) { + ContentRemoved(container, aContent, nextSibling, aFlags, &didReconstruct); + if (!didReconstruct) { + if (aInsertionKind == InsertionKind::Async) { // XXXmats doesn't frame state need to be restored in this case too? - RestyleManager()->PostRestyleEvent( - aContent->AsElement(), nsRestyleHint(0), nsChangeHint_ReconstructFrame); + RestyleManager()->PostRestyleEvent(aContent->AsElement(), + nsRestyleHint(0), + nsChangeHint_ReconstructFrame); } else { - rv = ContentInserted(container, aContent, mTempFrameTreeState, false); + // Now, recreate the frames associated with this content object. If + // ContentRemoved triggered reconstruction, then we don't need to do this + // because the frames will already have been built. + ContentInserted(container, aContent, mTempFrameTreeState, false); } } } - - return rv; } void -nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent, - nsIContent** aDestroyedFramesFor) +nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent, + bool* aDidReconstruct) { MOZ_ASSERT(aContent && aContent->GetParentNode()); - bool didReconstruct; nsIContent* nextSibling = aContent->IsRootOfAnonymousSubtree() ? nullptr : aContent->GetNextSibling(); - ContentRemoved(aContent->GetParent(), aContent, nextSibling, - REMOVE_DESTROY_FRAMES, &didReconstruct, aDestroyedFramesFor); + ContentRemoved(aContent->GetParent(), + aContent, + nextSibling, + REMOVE_DESTROY_FRAMES, + aDidReconstruct); } ////////////////////////////////////////////////////////////////////// @@ -10666,13 +10509,6 @@ nsCSSFrameConstructor::AddFCItemsForAnonymousContent( { for (uint32_t i = 0; i < aAnonymousItems.Length(); ++i) { nsIContent* content = aAnonymousItems[i].mContent; -#ifdef DEBUG - nsIAnonymousContentCreator* creator = do_QueryFrame(aFrame); - NS_ASSERTION(!creator || !creator->CreateFrameFor(content), - "If you need to use CreateFrameFor, you need to call " - "CreateAnonymousFrames manually and not follow the standard " - "ProcessChildren() codepath for this frame"); -#endif // Gecko-styled nodes should have no pending restyle flags. MOZ_ASSERT_IF(!content->IsStyledByServo(), !content->IsElement() || @@ -10690,24 +10526,111 @@ nsCSSFrameConstructor::AddFCItemsForAnonymousContent( RefPtr<nsStyleContext> styleContext; TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext); - if (aAnonymousItems[i].mStyleContext) { - // If we have an explicit style context, that means that the anonymous - // content creator had its own plan for the style, and doesn't need the - // computed style obtained by cascading this content as a normal node. - // This happens when a native anonymous node is used to implement a - // pseudo-element. Allowing Servo to traverse these nodes would be wasted - // work, so assert that we didn't do that. - MOZ_ASSERT_IF(content->IsStyledByServo(), !content->HasServoData()); - styleContext = aAnonymousItems[i].mStyleContext.forget(); - } else { - // If we don't have an explicit style context, that means we need the - // ordinary computed values. Make sure we eagerly cascaded them when the - // anonymous nodes were created. - MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(), - content->HasServoData()); - styleContext = ResolveStyleContext(aFrame, content, &aState); + + // Make sure we eagerly performed the servo cascade when the anonymous + // nodes were created. + MOZ_ASSERT_IF(content->IsStyledByServo() && content->IsElement(), + content->AsElement()->HasServoData()); + + // Determine whether this NAC is pseudo-implementing. + nsIAtom* pseudo = nullptr; + if (content->IsElement()) { + auto pseudoType = content->AsElement()->GetPseudoElementType(); + if (pseudoType != CSSPseudoElementType::NotPseudo) { + pseudo = nsCSSPseudoElements::GetPseudoAtom(pseudoType); + } + } + + // Determine the appropriate parent style for this NAC, and if the NAC + // implements a pseudo-element, the appropriate originating element + // (that is to say, the element to the left of the ::pseudo-element in + // the selector). This is all rather tricky, and merits some discussion. + // + // First, it's important to note that author stylesheets generally do not + // apply to elements in native-anonymous subtrees. The exceptions to + // this are web-exposed pseudo-elements, where authors can style the + // pseudo-implementing NAC if the originating element is not itself in a NAC + // subtree. + // + // For this reason, it's very important that we avoid using a style parent + // that is inside a NAC subtree together with an originating element that + // is not inside a NAC subtree, since that would allow authors to + // explicitly inherit styles from internal elements, potentially making + // the NAC hierarchy observable. To ensure this, and generally simplify + // things, we always set the originating element to the style parent. + // + // As a consequence of the above, all web-exposed pseudo-elements (which, + // by definition, must have a content-accessible originating element) must + // also inherit style from that same content-accessible element. To avoid + // unintuitive behavior differences between NAC elements that do and don't + // correspond to web-exposed pseudo-elements, we follow this protocol for + // all NAC, pseudo-implementing or not. + // + // However, things get tricky with the <video> element, where we have a + // bunch of XBL-generated anonymous content descending from a native- + // anonymous XULElement. The XBL elements inherit style from their + // flattened tree parent, because that's how XBL works. But then we need + // to figure out what to do when one of those anonymous XBL elements + // (like an <input> element) generates its own (possibly pseudo-element- + // implementing) NAC. + // + // In this case, we inherit style from the XBL-generated NAC-creating + // element, rather than the <video> element. There are a number of good + // reasons for this. First, inheriting from the great-grandparent while + // the parent inherits from the grandparent would be bizarre at best. + // Second, exposing pseudo-elements from elements within our particular + // XBL implementation would allow content styles to (un)intentionally + // alter the video controls, which would be very bad. Third, our UA + // stylesheets have selectors like: + // + // input[type=range][orient=horizontal]::-moz-range-track + // + // and we need to make sure that the originating element is the <input>, + // not the <video>, because that's where the |orient| attribute lives. + // + // The upshot of all of this is that, to find the style parent (and + // originating element, if applicable), we walk up our parent chain to the + // first element that is not itself NAC (distinct from whether it happens + // to be in a NAC subtree). + // + // The one exception to all of this is scrollbar content, which we parent + // directly to the scrollframe. This is because the special-snowflake + // construction of scroll frames doesn't result in the placeholder frame + // being constructed until later, which means that GetInFlowParent() doesn't + // work right in the case of out-of-flow scrollframes. + // + // To implement all this, we need to pass the correct parent style context + // here because SetPrimaryFrame() may not have been called on the content + // yet and thus ResolveStyleContext can't find it otherwise. + // + // We don't need to worry about display:contents here, because such + // elements don't get a frame and thus can't generate NAC. But we do need + // to worry about anonymous boxes, which CorrectStyleParentFrame handles + // for us. + nsIFrame* inheritFrame = aFrame; + if (!content->IsNativeScrollbarContent()) { + while (inheritFrame->GetContent()->IsNativeAnonymous()) { + inheritFrame = inheritFrame->GetInFlowParent(); + } } + nsIFrame* styleParentFrame = + nsFrame::CorrectStyleParentFrame(inheritFrame, pseudo); + // The only way we can not have a style parent now is if inheritFrame is the + // canvas frame and we're the NAC parent for all the things added via + // nsIDocument::InsertAnonymousContent. + MOZ_ASSERT_IF(!styleParentFrame, + inheritFrame->GetType() == nsGkAtoms::canvasFrame); + // And that anonymous div has no pseudo. + MOZ_ASSERT_IF(!styleParentFrame, !pseudo); + + Element* originating = + pseudo ? styleParentFrame->GetContent()->AsElement() : nullptr; + nsStyleContext* parentStyle = + styleParentFrame ? styleParentFrame->StyleContext() : nullptr; + styleContext = + ResolveStyleContext(parentStyle, content, &aState, originating); + nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr; if (!aAnonymousItems[i].mChildren.IsEmpty()) { anonChildren = &aAnonymousItems[i].mChildren; @@ -11034,151 +10957,6 @@ nsCSSFrameConstructor::AppendFirstLineFrames( lineFrame, aFrameItems); } -// Special routine to handle inserting a new frame into a block -// frame's child list. Takes care of placing the new frame into the -// right place when first-line style is present. -nsresult -nsCSSFrameConstructor::InsertFirstLineFrames( - nsFrameConstructorState& aState, - nsIContent* aContent, - nsIFrame* aBlockFrame, - nsContainerFrame** aParentFrame, - nsIFrame* aPrevSibling, - nsFrameItems& aFrameItems) -{ - nsresult rv = NS_OK; - // XXXbz If you make this method actually do something, check to - // make sure that the caller is passing what you expect. In - // particular, which content is aContent? And audit the rest of - // this code too; it makes bogus assumptions and may not build. -#if 0 - nsIFrame* parentFrame = *aParentFrame; - nsIFrame* newFrame = aFrameItems.childList; - bool isInline = IsInlineOutside(newFrame); - - if (!aPrevSibling) { - // Insertion will become the first frame. Two cases: we either - // already have a first-line frame or we don't. - nsIFrame* firstBlockKid = aBlockFrame->PrincipalChildList().FirstChild(); - if (firstBlockKid->GetType() == nsGkAtoms::lineFrame) { - // We already have a first-line frame - nsIFrame* lineFrame = firstBlockKid; - - if (isInline) { - // Easy case: the new inline frame will go into the lineFrame. - ReparentFrame(this, lineFrame, newFrame); - InsertFrames(lineFrame, kPrincipalList, nullptr, newFrame); - - // Since the frame is going into the lineFrame, don't let it - // go into the block too. - aFrameItems.childList = nullptr; - aFrameItems.lastChild = nullptr; - } - else { - // Harder case: We are about to insert a block level element - // before the first-line frame. - // XXX need a method to steal away frames from the line-frame - } - } - else { - // We do not have a first-line frame - if (isInline) { - // We now need a first-line frame to contain the inline frame. - nsIFrame* lineFrame = NS_NewFirstLineFrame(firstLineStyle); - - if (NS_SUCCEEDED(rv)) { - // Lookup first-line style context - nsStyleContext* parentStyle = - nsFrame::CorrectStyleParentFrame(aBlockFrame, - nsCSSPseudoElements::firstLine)-> - StyleContext(); - RefPtr<nsStyleContext> firstLineStyle = - GetFirstLineStyle(aContent, parentStyle); - - // Initialize the line frame - InitAndRestoreFrame(aState, aContent, aBlockFrame, lineFrame); - - // Make sure the caller inserts the lineFrame into the - // blocks list of children. - aFrameItems.childList = lineFrame; - aFrameItems.lastChild = lineFrame; - - // Give the inline frames to the lineFrame <b>after</b> - // reparenting them - NS_ASSERTION(lineFrame->StyleContext() == firstLineStyle, - "Bogus style context on line frame"); - ReparentFrame(aPresContext, lineFrame, newFrame); - lineFrame->SetInitialChildList(kPrincipalList, newFrame); - } - } - else { - // Easy case: the regular insertion logic can insert the new - // frame because it's a block frame. - } - } - } - else { - // Insertion will not be the first frame. - nsIFrame* prevSiblingParent = aPrevSibling->GetParent(); - if (prevSiblingParent == aBlockFrame) { - // Easy case: The prev-siblings parent is the block - // frame. Therefore the prev-sibling is not currently in a - // line-frame. Therefore the new frame which is going after it, - // regardless of type, is not going into a line-frame. - } - else { - // If the prevSiblingParent is not the block-frame then it must - // be a line-frame (if it were a letter-frame, that logic would - // already have adjusted the prev-sibling to be the - // letter-frame). - if (isInline) { - // Easy case: the insertion can go where the caller thinks it - // should go (which is into prevSiblingParent). - } - else { - // Block elements don't end up in line-frames, therefore - // change the insertion point to aBlockFrame. However, there - // might be more inline elements following aPrevSibling that - // need to be pulled out of the line-frame and become children - // of the block. - nsIFrame* nextSibling = aPrevSibling->GetNextSibling(); - nsIFrame* nextLineFrame = prevSiblingParent->GetNextInFlow(); - if (nextSibling || nextLineFrame) { - // Oy. We have work to do. Create a list of the new frames - // that are going into the block by stripping them away from - // the line-frame(s). - if (nextSibling) { - nsLineFrame* lineFrame = (nsLineFrame*) prevSiblingParent; - nsFrameList tail = lineFrame->StealFramesAfter(aPrevSibling); - // XXX do something with 'tail' - } - - nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame; - for (;;) { - nextLineFrame = nextLineFrame->GetNextInFlow(); - if (!nextLineFrame) { - break; - } - nsIFrame* kids = nextLineFrame->PrincipalChildList().FirstChild(); - } - } - else { - // We got lucky: aPrevSibling was the last inline frame in - // the line-frame. - ReparentFrame(this, aBlockFrame, newFrame); - InsertFrames(aBlockFrame, kPrincipalList, - prevSiblingParent, newFrame); - aFrameItems.childList = nullptr; - aFrameItems.lastChild = nullptr; - } - } - } - } - -#endif - return rv; -} - //---------------------------------------------------------------------- // First-letter support @@ -11500,7 +11278,7 @@ FindFirstLetterFrame(nsIFrame* aFrame, nsIFrame::ChildListID aListID) return nullptr; } -nsresult +void nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames( nsIPresShell* aPresShell, nsIFrame* aBlockFrame) @@ -11512,7 +11290,7 @@ nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames( floatFrame = ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kPushedFloatsList); if (!floatFrame) { - return NS_OK; + return; } } @@ -11520,19 +11298,19 @@ nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames( // destroyed when we destroy the letter frame). nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild(); if (!textFrame) { - return NS_OK; + return; } // Discover the placeholder frame for the letter frame - nsPlaceholderFrame* placeholderFrame = GetPlaceholderFrameFor(floatFrame); + nsPlaceholderFrame* placeholderFrame = floatFrame->GetPlaceholderFrame(); if (!placeholderFrame) { // Somethings really wrong - return NS_OK; + return; } nsContainerFrame* parentFrame = placeholderFrame->GetParent(); if (!parentFrame) { // Somethings really wrong - return NS_OK; + return; } // Create a new text frame with the right style context that maps @@ -11541,7 +11319,7 @@ nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames( nsStyleContext* parentSC = parentFrame->StyleContext(); nsIContent* textContent = textFrame->GetContent(); if (!textContent) { - return NS_OK; + return; } RefPtr<nsStyleContext> newSC = aPresShell->StyleSet()-> ResolveStyleForText(textContent, parentSC); @@ -11586,11 +11364,9 @@ nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames( if (offsetsNeedFixing) { prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING); } - - return NS_OK; } -nsresult +void nsCSSFrameConstructor::RemoveFirstLetterFrames(nsIPresShell* aPresShell, nsContainerFrame* aFrame, nsContainerFrame* aBlockFrame, @@ -11663,11 +11439,9 @@ nsCSSFrameConstructor::RemoveFirstLetterFrames(nsIPresShell* aPresShell, prevSibling = kid; kid = kid->GetNextSibling(); } - - return NS_OK; } -nsresult +void nsCSSFrameConstructor::RemoveLetterFrames(nsIPresShell* aPresShell, nsContainerFrame* aBlockFrame) { @@ -11676,20 +11450,16 @@ nsCSSFrameConstructor::RemoveLetterFrames(nsIPresShell* aPresShell, nsContainerFrame* continuation = aBlockFrame; bool stopLooking = false; - nsresult rv; do { - rv = RemoveFloatingFirstLetterFrames(aPresShell, continuation); - if (NS_SUCCEEDED(rv)) { - rv = RemoveFirstLetterFrames(aPresShell, - continuation, aBlockFrame, &stopLooking); - } + RemoveFloatingFirstLetterFrames(aPresShell, continuation); + RemoveFirstLetterFrames(aPresShell, continuation, aBlockFrame, + &stopLooking); if (stopLooking) { break; } continuation = static_cast<nsContainerFrame*>(continuation->GetNextContinuation()); } while (continuation); - return rv; } // Fixup the letter frame situation for the given block @@ -11732,7 +11502,7 @@ nsCSSFrameConstructor::RecoverLetterFrames(nsContainerFrame* aBlockFrame) // listbox Widget Routines -nsresult +void nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame, nsIFrame* aPrevFrame, nsIContent* aChild, @@ -11740,8 +11510,6 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame, bool aIsAppend) { #ifdef MOZ_XUL - nsresult rv = NS_OK; - // Construct a new frame if (nullptr != aParentFrame) { nsFrameItems frameItems; @@ -11762,7 +11530,7 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame, if (StyleDisplay::None == display->mDisplay) { *aNewFrame = nullptr; - return NS_OK; + return; } BeginUpdate(); @@ -11781,9 +11549,9 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame, if (newFrame) { // Notify the parent frame if (aIsAppend) - rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems); + ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems); else - rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems); + ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems); } EndUpdate(); @@ -11798,10 +11566,6 @@ nsCSSFrameConstructor::CreateListBoxContent(nsContainerFrame* aParentFrame, } #endif } - - return rv; -#else - return NS_ERROR_FAILURE; #endif } @@ -12224,8 +11988,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, if (aFrame->IsXULBoxFrame() && !(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) && aItems.AnyItemsNeedBlockParent()) { - RecreateFramesForContent(aFrame->GetContent(), true, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } @@ -12244,8 +12008,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, const bool isWebkitBox = IsFlexContainerForLegacyBox(aFrame, frameType); if (aPrevSibling && IsAnonymousFlexOrGridItem(aPrevSibling) && iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) { - RecreateFramesForContent(aFrame->GetContent(), true, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } @@ -12256,8 +12020,9 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, iter.SetToEnd(); iter.Prev(); if (iter.item().NeedsAnonFlexOrGridItem(aState, isWebkitBox)) { - RecreateFramesForContent(aFrame->GetContent(), true, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aFrame->GetContent(), + InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } } @@ -12287,8 +12052,9 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, isWebkitBox)) { // We hit something that _doesn't_ need an anonymous flex item! // Rebuild the flex container to bust it out. - RecreateFramesForContent(containerFrame->GetContent(), true, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(containerFrame->GetContent(), + InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } @@ -12312,8 +12078,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, // We want to optimize it better, and avoid reframing as much as // possible. But given the cases above, and the fact that a ruby // usually won't be very large, it should be fine to reframe it. - RecreateFramesForContent(aFrame->GetContent(), true, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } @@ -12479,8 +12245,8 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, if (!aItems.AllWantParentType(parentType)) { // Reframing aFrame->GetContent() is good enough, since the content of // table pseudo-frames is the ancestor content. - RecreateFramesForContent(aFrame->GetContent(), true, - REMOVE_FOR_RECONSTRUCTION, nullptr); + RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } } @@ -12568,15 +12334,15 @@ nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState, static_cast<void*>(blockContent)); } #endif - RecreateFramesForContent(blockContent, true, REMOVE_FOR_RECONSTRUCTION, - nullptr); + RecreateFramesForContent(blockContent, InsertionKind::Async, + REMOVE_FOR_RECONSTRUCTION); return true; } -nsresult -nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame, - RemoveFlags aFlags, - nsIContent** aDestroyedFramesFor) +void +nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame, + InsertionKind aInsertionKind, + RemoveFlags aFlags) { #ifdef DEBUG @@ -12596,7 +12362,7 @@ nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame, // don't ReframeContainingBlock, this will result in a crash // if we remove a tree that's in reflow - see bug 121368 for testcase NS_ERROR("Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a Reflow!!!"); - return NS_OK; + return; } // Get the first "normal" ancestor of the target frame. @@ -12612,23 +12378,25 @@ nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame, // so GetFloatContainingBlock(aFrame) has been removed // And get the containingBlock's content - nsCOMPtr<nsIContent> blockContent = containingBlock->GetContent(); - if (blockContent) { + if (nsIContent* blockContent = containingBlock->GetContent()) { #ifdef DEBUG if (gNoisyContentUpdates) { printf(" ==> blockContent=%p\n", static_cast<void*>(blockContent)); } #endif - return RecreateFramesForContent(blockContent, true, aFlags, aDestroyedFramesFor); + RecreateFramesForContent(blockContent->AsElement(), aInsertionKind, + REMOVE_FOR_RECONSTRUCTION); + return; } } // If we get here, we're screwed! - return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(), - true, aFlags, nullptr); + RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(), + aInsertionKind, + REMOVE_FOR_RECONSTRUCTION); } -nsresult +void nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame) { { @@ -12662,8 +12430,6 @@ nsCSSFrameConstructor::GenerateChildFrames(nsContainerFrame* aFrame) // call XBL constructors after the frames are created mPresShell->GetDocument()->BindingManager()->ProcessAttachedQueue(); - - return NS_OK; } ////////////////////////////////////////////////////////// diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 7d1b8d42f..abdfbf7ce 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -22,7 +22,7 @@ #include "nsCounterManager.h" #include "nsIAnonymousContentCreator.h" #include "nsFrameManager.h" -#include "ScrollbarStyles.h" +#include "ScrollStyles.h" struct nsFrameItems; class nsStyleContext; @@ -48,7 +48,7 @@ class FlattenedChildIterator; } // namespace dom } // namespace mozilla -class nsCSSFrameConstructor : public nsFrameManager +class nsCSSFrameConstructor final : public nsFrameManager { public: typedef mozilla::CSSPseudoElementType CSSPseudoElementType; @@ -60,7 +60,7 @@ public: nsCSSFrameConstructor(nsIDocument* aDocument, nsIPresShell* aPresShell); ~nsCSSFrameConstructor(void) { - NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?"); + MOZ_ASSERT(mUpdateCount == 0, "Dying in the middle of our own update?"); } // get the alternate text for a content node @@ -78,7 +78,7 @@ public: nsIFrame* ConstructRootFrame(); - nsresult ReconstructDocElementHierarchy(); + void ReconstructDocElementHierarchy(); // Create frames for content nodes that are marked as needing frames. This // should be called before ProcessPendingRestyles. @@ -97,8 +97,8 @@ private: // aChild is the child being inserted for inserts, and the first // child being appended for appends. bool MaybeConstructLazily(Operation aOperation, - nsIContent* aContainer, - nsIContent* aChild); + nsIContent* aContainer, + nsIContent* aChild); // Issues a single ContentInserted for each child of aContainer in the range // [aStartChild, aEndChild). @@ -152,8 +152,8 @@ private: // Returns true if parent was recreated due to frameset child, false otherwise. bool MaybeRecreateForFrameset(nsIFrame* aParentFrame, - nsIContent* aStartChild, - nsIContent* aEndChild); + nsIContent* aStartChild, + nsIContent* aEndChild); public: /** @@ -202,16 +202,16 @@ public: // If aAllowLazyConstruction is true then frame construction of the new // children can be done lazily. - nsresult ContentAppended(nsIContent* aContainer, - nsIContent* aFirstNewContent, - bool aAllowLazyConstruction); + void ContentAppended(nsIContent* aContainer, + nsIContent* aFirstNewContent, + bool aAllowLazyConstruction); // If aAllowLazyConstruction is true then frame construction of the new child // can be done lazily. - nsresult ContentInserted(nsIContent* aContainer, - nsIContent* aChild, - nsILayoutHistoryState* aFrameState, - bool aAllowLazyConstruction); + void ContentInserted(nsIContent* aContainer, + nsIContent* aChild, + nsILayoutHistoryState* aFrameState, + bool aAllowLazyConstruction); // Like ContentInserted but handles inserting the children of aContainer in // the range [aStartChild, aEndChild). aStartChild must be non-null. @@ -219,12 +219,17 @@ public: // aStartChild. If aAllowLazyConstruction is true then frame construction of // the new children can be done lazily. It is only allowed to be true when // inserting a single node. - nsresult ContentRangeInserted(nsIContent* aContainer, - nsIContent* aStartChild, - nsIContent* aEndChild, - nsILayoutHistoryState* aFrameState, - bool aAllowLazyConstruction); + void ContentRangeInserted(nsIContent* aContainer, + nsIContent* aStartChild, + nsIContent* aEndChild, + nsILayoutHistoryState* aFrameState, + bool aAllowLazyConstruction); +public: + // FIXME(emilio): How important is it to keep the frame tree state around for + // REMOVE_DESTROY_FRAMES? + // + // Seems like otherwise we could just remove it. enum RemoveFlags { REMOVE_CONTENT, REMOVE_FOR_RECONSTRUCTION, REMOVE_DESTROY_FRAMES }; /** @@ -243,15 +248,14 @@ public: * only when aFlags == REMOVE_DESTROY_FRAMES, otherwise it will only be * captured if we reconstructed frames for an ancestor. */ - nsresult ContentRemoved(nsIContent* aContainer, - nsIContent* aChild, - nsIContent* aOldNextSibling, - RemoveFlags aFlags, - bool* aDidReconstruct, - nsIContent** aDestroyedFramesFor = nullptr); + void ContentRemoved(nsIContent* aContainer, + nsIContent* aChild, + nsIContent* aOldNextSibling, + RemoveFlags aFlags, + bool* aDidReconstruct); - nsresult CharacterDataChanged(nsIContent* aContent, - CharacterDataChangeInfo* aInfo); + void CharacterDataChanged(nsIContent* aContent, + CharacterDataChangeInfo* aInfo); // If aContent is a text node that has been optimized away due to being // whitespace next to a block boundary (or for some other reason), stop @@ -260,8 +264,8 @@ public: // Returns the frame for aContent if there is one. nsIFrame* EnsureFrameForTextNode(nsGenericDOMDataNode* aContent); - // generate the child frames and process bindings - nsresult GenerateChildFrames(nsContainerFrame* aFrame); + // Generate the child frames and process bindings + void GenerateChildFrames(nsContainerFrame* aFrame); // Should be called when a frame is going to be destroyed and // WillDestroyFrameTree hasn't been called yet. @@ -280,14 +284,10 @@ public: /** * Destroy the frames for aContent. Note that this may destroy frames - * for an ancestor instead - aDestroyedFramesFor contains the content node - * where frames were actually destroyed (which should be used in the - * ContentInserted call to recreate frames). The frame tree state - * is captured before the frames are destroyed and can be retrieved using - * GetLastCapturedLayoutHistoryState(). + * for an ancestor instead - aDidReconstruct contains whether a reconstruct + * was posted for any ancestor. */ - void DestroyFramesFor(nsIContent* aContent, - nsIContent** aDestroyedFramesFor); + void DestroyFramesFor(nsIContent* aContent, bool* aDidReconstruct); // Request to create a continuing frame. This method never returns null. nsIFrame* CreateContinuingFrame(nsPresContext* aPresContext, @@ -303,11 +303,11 @@ public: */ InsertionPoint GetInsertionPoint(nsIContent* aContainer, nsIContent* aChild); - nsresult CreateListBoxContent(nsContainerFrame* aParentFrame, - nsIFrame* aPrevFrame, - nsIContent* aChild, - nsIFrame** aResult, - bool aIsAppend); + void CreateListBoxContent(nsContainerFrame* aParentFrame, + nsIFrame* aPrevFrame, + nsIContent* aChild, + nsIFrame** aResult, + bool aIsAppend); // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame(); // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; } @@ -322,15 +322,6 @@ public: nsContainerFrame* GetDocElementContainingBlock() { return mDocElementContainingBlock; } - /** - * Return the layout history state that was captured in the last - * ContentRemoved / RecreateFramesForContent call. - */ - nsILayoutHistoryState* GetLastCapturedLayoutHistoryState() - { - return mTempFrameTreeState; - } - private: struct FrameConstructionItem; class FrameConstructionItemList; @@ -364,7 +355,8 @@ private: already_AddRefed<nsStyleContext> ResolveStyleContext(nsStyleContext* aParentStyleContext, nsIContent* aContent, - nsFrameConstructorState* aState); + nsFrameConstructorState* aState, + Element* aOriginatingElementOrNull = nullptr); // Add the frame construction items for the given aContent and aParentFrame // to the list. This might add more than one item in some rare cases. @@ -418,14 +410,14 @@ private: * @param [out] aNewContent the content node we create * @param [out] aNewFrame the new frame we create */ - nsresult CreateAttributeContent(nsIContent* aParentContent, - nsIFrame* aParentFrame, - int32_t aAttrNamespace, - nsIAtom* aAttrName, - nsStyleContext* aStyleContext, - nsCOMArray<nsIContent>& aGeneratedContent, - nsIContent** aNewContent, - nsIFrame** aNewFrame); + void CreateAttributeContent(nsIContent* aParentContent, + nsIFrame* aParentFrame, + int32_t aAttrNamespace, + nsIAtom* aAttrName, + nsStyleContext* aStyleContext, + nsCOMArray<nsIContent>& aGeneratedContent, + nsIContent** aNewContent, + nsIFrame** aNewFrame); /** * Create a text node containing the given string. If aText is non-null @@ -463,11 +455,11 @@ private: // aParentFrame. aPrevSibling must be the frame after which aFrameList is to // be placed on aParentFrame's principal child list. It may be null if // aFrameList is being added at the beginning of the child list. - nsresult AppendFramesToParent(nsFrameConstructorState& aState, - nsContainerFrame* aParentFrame, - nsFrameItems& aFrameList, - nsIFrame* aPrevSibling, - bool aIsRecursiveCall = false); + void AppendFramesToParent(nsFrameConstructorState& aState, + nsContainerFrame* aParentFrame, + nsFrameItems& aFrameList, + nsIFrame* aPrevSibling, + bool aIsRecursiveCall = false); // BEGIN TABLE SECTION /** @@ -1440,12 +1432,6 @@ private: nsFrameItems& aFrameItems); static bool AtLineBoundary(FCItemIterator& aIter); - nsresult CreateAnonymousFrames(nsFrameConstructorState& aState, - nsIContent* aParent, - nsContainerFrame* aParentFrame, - PendingBinding* aPendingBinding, - nsFrameItems& aChildItems); - nsresult GetAnonymousContent(nsIContent* aParent, nsIFrame* aParentFrame, nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent); @@ -1697,7 +1683,7 @@ private: // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false // aBuildCombobox indicates if we are building a combobox that has a dropdown // popup widget or not. - nsresult + void InitializeSelectFrame(nsFrameConstructorState& aState, nsContainerFrame* aScrollFrame, nsContainerFrame* aScrolledFrame, @@ -1718,34 +1704,36 @@ private: nsStyleContext* MaybeRecreateFramesForElement(Element* aElement); /** + * Whether insertion should be done synchronously or asynchronously. + * + * Generally, insertion is synchronous if we're reconstructing something from + * frame construction/reconstruction, and async if we're removing stuff, like + * from ContentRemoved. + */ + enum class InsertionKind + { + Sync, + Async, + }; + + /** * Recreate frames for aContent. * @param aContent the content to recreate frames for - * @param aAsyncInsert if true then a restyle event will be posted to handle - * the required ContentInserted call instead of doing it immediately. * @param aFlags normally you want to pass REMOVE_FOR_RECONSTRUCTION here - * @param aDestroyedFramesFor if non-null, it will contain the content that - * was actually reframed - it may be different than aContent. */ - nsresult - RecreateFramesForContent(nsIContent* aContent, - bool aAsyncInsert, - RemoveFlags aFlags, - nsIContent** aDestroyedFramesFor); + void RecreateFramesForContent(nsIContent* aContent, + InsertionKind aInsertionKind, + RemoveFlags aFlags); // If removal of aFrame from the frame tree requires reconstruction of some // containing block (either of aFrame or of its parent) due to {ib} splits or // table pseudo-frames, recreate the relevant frame subtree. The return value - // indicates whether this happened. If this method returns true, *aResult is - // the return value of ReframeContainingBlock or RecreateFramesForContent. If - // this method returns false, the value of *aResult is not affected. aFrame - // and aResult must not be null. aFrame must be the result of a + // indicates whether this happened. aFrame must be the result of a // GetPrimaryFrame() call on a content node (which means its parent is also - // not null). If this method returns true, aDestroyedFramesFor contains the - // content that was reframed. - bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, - RemoveFlags aFlags, - nsresult* aResult, - nsIContent** aDestroyedFramesFor); + // not null). + bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame, + InsertionKind aInsertionKind, + RemoveFlags aFlags); nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell* aPresShell, nsPresContext* aPresContext, @@ -1869,9 +1857,9 @@ private: bool aIsAppend, nsIFrame* aPrevSibling); - nsresult ReframeContainingBlock(nsIFrame* aFrame, - RemoveFlags aFlags, - nsIContent** aReframeContent); + void ReframeContainingBlock(nsIFrame* aFrame, + InsertionKind aInsertionKind, + RemoveFlags aFlags); //---------------------------------------- @@ -1925,18 +1913,18 @@ private: void RecoverLetterFrames(nsContainerFrame* aBlockFrame); // - nsresult RemoveLetterFrames(nsIPresShell* aPresShell, - nsContainerFrame* aBlockFrame); + void RemoveLetterFrames(nsIPresShell* aPresShell, + nsContainerFrame* aBlockFrame); // Recursive helper for RemoveLetterFrames - nsresult RemoveFirstLetterFrames(nsIPresShell* aPresShell, - nsContainerFrame* aFrame, - nsContainerFrame* aBlockFrame, - bool* aStopLooking); + void RemoveFirstLetterFrames(nsIPresShell* aPresShell, + nsContainerFrame* aFrame, + nsContainerFrame* aBlockFrame, + bool* aStopLooking); // Special remove method for those pesky floating first-letter frames - nsresult RemoveFloatingFirstLetterFrames(nsIPresShell* aPresShell, - nsIFrame* aBlockFrame); + void RemoveFloatingFirstLetterFrames(nsIPresShell* aPresShell, + nsIFrame* aBlockFrame); // Capture state for the frame tree rooted at the frame associated with the // content object, aContent @@ -1967,71 +1955,53 @@ private: nsContainerFrame* aBlockFrame, nsFrameItems& aFrameItems); - nsresult InsertFirstLineFrames(nsFrameConstructorState& aState, - nsIContent* aContent, - nsIFrame* aBlockFrame, - nsContainerFrame** aParentFrame, - nsIFrame* aPrevSibling, - nsFrameItems& aFrameItems); + // The direction in which we should look for siblings. + enum class SiblingDirection + { + Forward, + Backward, + }; /** - * Find the right frame to use for aContent when looking for sibling - * frames for aTargetContent. If aPrevSibling is true, this - * will look for last continuations, etc, as necessary. This calls - * IsValidSibling as needed; if that returns false it returns null. + * Find the frame for the content immediately next to the one aIter points to, + * in the direction SiblingDirection indicates, following continuations if + * necessary. * - * @param aContent the content to search for frames - * @param aTargetContent the content we're finding a sibling frame for - * @param aTargetContentDisplay the CSS display enum for aTargetContent if - * already known, UNSET_DISPLAY otherwise. It will be filled in - * if needed. - * @param aParentFrame the nearest ancestor frame, used internally for - * finding ::after / ::before frames - * @param aPrevSibling true if we're searching in reverse DOM order - */ - nsIFrame* FindFrameForContentSibling(nsIContent* aContent, - nsIContent* aTargetContent, - mozilla::StyleDisplay& aTargetContentDisplay, - nsContainerFrame* aParentFrame, - bool aPrevSibling); - - /** - * Find the frame for the content immediately preceding the one aIter - * points to, following continuations if necessary. aIter is passed by - * value on purpose, so as not to modify the caller's iterator. + * aIter is passed by const reference on purpose, so as not to modify the + * caller's iterator. * * @param aIter should be positioned such that aIter.GetPreviousChild() * is the first content to search for frames - * @param aTargetContent the content we're finding a sibling frame for - * @param aTargetContentDisplay the CSS display enum for aTargetContent if - * already known, UNSET_DISPLAY otherwise. It will be filled in - * if needed. - * @param aParentFrame the nearest ancestor frame, used inernally for - * finding ::after / ::before frames - */ - nsIFrame* FindPreviousSibling(mozilla::dom::FlattenedChildIterator aIter, - nsIContent* aTargetContent, - mozilla::StyleDisplay& aTargetContentDisplay, - nsContainerFrame* aParentFrame); - - /** - * Find the frame for the content node immediately following the one aIter - * points to, following continuations if necessary. aIter is passed by value - * on purpose, so as not to modify the caller's iterator. - * - * @param aIter should be positioned such that aIter.GetNextChild() - * is the first content to search for frames - * @param aTargetContent the content we're finding a sibling frame for - * @param aTargetContentDisplay the CSS display enum for aTargetContent if - * already known, UNSET_DISPLAY otherwise. It will be filled in - * if needed. - * @param aParentFrame the nearest ancestor frame, used inernally for - * finding ::after / ::before frames + * @param aTargetContentDisplay the CSS display enum for the content aIter + * points to if already known, UNSET_DISPLAY otherwise. It will be + * filled in if needed. */ - nsIFrame* FindNextSibling(mozilla::dom::FlattenedChildIterator aIter, - nsIContent* aTargetContent, - mozilla::StyleDisplay& aTargetContentDisplay, - nsContainerFrame* aParentFrame); + template<SiblingDirection> + nsIFrame* FindSibling(const mozilla::dom::FlattenedChildIterator& aIter, + mozilla::StyleDisplay& aTargetContentDisplay); + + // Helper for the implementation of FindSibling. + template<SiblingDirection> + nsIFrame* FindSiblingInternal( + mozilla::dom::FlattenedChildIterator, + nsIContent* aTargetContent, + mozilla::StyleDisplay& aTargetContentDisplay); + + // An alias of FindSibling<SiblingDirection::Forward>. + nsIFrame* FindNextSibling(const mozilla::dom::FlattenedChildIterator& aIter, + mozilla::StyleDisplay& aTargetContentDisplay); + // An alias of FindSibling<SiblingDirection::Backwards>. + nsIFrame* FindPreviousSibling(const mozilla::dom::FlattenedChildIterator& aIter, + mozilla::StyleDisplay& aTargetContentDisplay); + + // Given a potential first-continuation sibling frame for aTargetContent, + // verify that it is an actual valid sibling for it, and return the + // appropriate continuation the new frame for aTargetContent should be + // inserted next to. + nsIFrame* AdjustSiblingFrame(nsIFrame* aSibling, + nsIContent* aTargetContent, + mozilla::StyleDisplay& aTargetContentDisplay, + SiblingDirection aDirection); // Find the right previous sibling for an insertion. This also updates the // parent frame to point to the correct continuation of the parent frame to diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index eca22f3ba..2194a01f3 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsCaret.h b/layout/base/nsCaret.h index 703b33529..66ad0d8cf 100644 --- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index eb2709de6..4f176896b 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -225,7 +225,7 @@ enum nsChangeHint { * scrollframe, this is instead equivalent to nsChangeHint_AllReflowHints * (because the viewport always has an associated scrollframe). */ - nsChangeHint_CSSOverflowChange = 1 << 28, + nsChangeHint_ScrollbarChange = 1 << 28, // IMPORTANT NOTE: When adding new hints, consider whether you need // to add them to NS_HintsNotHandledForDescendantsIn() below. Please @@ -316,7 +316,7 @@ inline nsChangeHint operator^=(nsChangeHint& aLeft, nsChangeHint aRight) nsChangeHint_UpdatePostTransformOverflow | \ nsChangeHint_UpdateParentOverflow | \ nsChangeHint_ChildrenOnlyTransform | \ - nsChangeHint_CSSOverflowChange | \ + nsChangeHint_ScrollbarChange | \ nsChangeHint_RecomputePosition | \ nsChangeHint_UpdateContainingBlock | \ nsChangeHint_AddOrRemoveTransform | \ diff --git a/layout/base/nsDisplayItemTypes.h b/layout/base/nsDisplayItemTypes.h index e899245d0..7ea53e5f1 100644 --- a/layout/base/nsDisplayItemTypes.h +++ b/layout/base/nsDisplayItemTypes.h @@ -1,6 +1,5 @@ // IWYU pragma: private, include "nsDisplayList.h" /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 73e991246..e2a41aa28 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 9eac132fa..2b4efd86e 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index df0f1266d..a0af38c28 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -4327,7 +4326,7 @@ nsDocumentViewer::ShouldAttachToTopLevel() if (nsIWidget::UsePuppetWidgets()) return true; -#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_UIKIT) // On windows, in the parent process we also attach, but just to // chrome items nsWindowType winType = mParentWidget->WindowType(); diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index 97b022da8..be8cd7147 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -38,47 +38,17 @@ #include "nsIStatefulFrame.h" #include "nsContainerFrame.h" - #ifdef DEBUG - //#define DEBUG_UNDISPLAYED_MAP - //#define DEBUG_DISPLAY_CONTENTS_MAP - #else - #undef DEBUG_UNDISPLAYED_MAP - #undef DEBUG_DISPLAY_CONTENTS_MAP - #endif +// #define DEBUG_UNDISPLAYED_MAP +// #define DEBUG_DISPLAY_CONTENTS_MAP using namespace mozilla; using namespace mozilla::dom; //---------------------------------------------------------------------- -struct PlaceholderMapEntry : public PLDHashEntryHdr { - // key (the out of flow frame) can be obtained through placeholder frame - nsPlaceholderFrame *placeholderFrame; -}; - -static bool -PlaceholderMapMatchEntry(const PLDHashEntryHdr *hdr, const void *key) -{ - const PlaceholderMapEntry *entry = - static_cast<const PlaceholderMapEntry*>(hdr); - NS_ASSERTION(entry->placeholderFrame->GetOutOfFlowFrame() != - (void*)0xdddddddd, - "Dead placeholder in placeholder map"); - return entry->placeholderFrame->GetOutOfFlowFrame() == key; -} - -static const PLDHashTableOps PlaceholderMapOps = { - PLDHashTable::HashVoidPtrKeyStub, - PlaceholderMapMatchEntry, - PLDHashTable::MoveEntryStub, - PLDHashTable::ClearEntryStub, - nullptr -}; - nsFrameManagerBase::nsFrameManagerBase() : mPresShell(nullptr) , mRootFrame(nullptr) - , mPlaceholderMap(&PlaceholderMapOps, sizeof(PlaceholderMapEntry)) , mUndisplayedMap(nullptr) , mDisplayContentsMap(nullptr) , mIsDestroyingFrames(false) @@ -87,40 +57,49 @@ nsFrameManagerBase::nsFrameManagerBase() //---------------------------------------------------------------------- -// XXXldb This seems too complicated for what I think it's doing, and it -// should also be using PLDHashTable rather than plhash to use less memory. +/** + * The undisplayed map is a class that maps a parent content node to the + * undisplayed content children, and their style contexts. + * + * The linked list of nodes holds strong references to the style contexts and + * the content. + */ +class nsFrameManagerBase::UndisplayedMap : + private nsClassHashtable<nsPtrHashKey<nsIContent>, + LinkedList<UndisplayedNode>> +{ + typedef nsClassHashtable<nsPtrHashKey<nsIContent>, LinkedList<UndisplayedNode>> base_type; -class nsFrameManagerBase::UndisplayedMap { public: - explicit UndisplayedMap(uint32_t aNumBuckets = 16); - ~UndisplayedMap(void); + UndisplayedMap(); + ~UndisplayedMap(); UndisplayedNode* GetFirstNode(nsIContent* aParentContent); - nsresult AddNodeFor(nsIContent* aParentContent, - nsIContent* aChild, nsStyleContext* aStyle); + void AddNodeFor(nsIContent* aParentContent, + nsIContent* aChild, + nsStyleContext* aStyle); - void RemoveNodeFor(nsIContent* aParentContent, - UndisplayedNode* aNode); + void RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode); void RemoveNodesFor(nsIContent* aParentContent); - UndisplayedNode* UnlinkNodesFor(nsIContent* aParentContent); + + nsAutoPtr<LinkedList<UndisplayedNode>> + UnlinkNodesFor(nsIContent* aParentContent); // Removes all entries from the hash table - void Clear(void); + void Clear(); protected: + LinkedList<UndisplayedNode>* GetListFor(nsIContent* aParentContent); + LinkedList<UndisplayedNode>* GetOrCreateListFor(nsIContent* aParentContent); + void AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent); /** - * Gets the entry for the provided parent content. If the content - * is a <xbl:children> element, |**aParentContent| is set to - * the parent of the children element. + * Get the applicable parent for the map lookup. This is almost always the + * provided argument, except if it's a <xbl:children> element, in which case + * it's the parent of the children element. */ - PLHashEntry** GetEntryFor(nsIContent** aParentContent); - void AppendNodeFor(UndisplayedNode* aNode, - nsIContent* aParentContent); - - PLHashTable* mTable; - PLHashEntry** mLastLookup; + nsIContent* GetApplicableParent(nsIContent* aParent); }; //---------------------------------------------------------------------- @@ -138,14 +117,10 @@ nsFrameManager::Destroy() // Destroy the frame hierarchy. mPresShell->SetIgnoreFrameDestruction(true); - // Unregister all placeholders before tearing down the frame tree - nsFrameManager::ClearPlaceholderFrameMap(); - if (mRootFrame) { mRootFrame->Destroy(); mRootFrame = nullptr; } - delete mUndisplayedMap; mUndisplayedMap = nullptr; delete mDisplayContentsMap; @@ -156,58 +131,9 @@ nsFrameManager::Destroy() //---------------------------------------------------------------------- -// Placeholder frame functions -nsPlaceholderFrame* -nsFrameManager::GetPlaceholderFrameFor(const nsIFrame* aFrame) -{ - NS_PRECONDITION(aFrame, "null param unexpected"); - - auto entry = static_cast<PlaceholderMapEntry*> - (const_cast<PLDHashTable*>(&mPlaceholderMap)->Search(aFrame)); - if (entry) { - return entry->placeholderFrame; - } - - return nullptr; -} - -void -nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame) -{ - MOZ_ASSERT(aPlaceholderFrame, "null param unexpected"); - MOZ_ASSERT(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(), - "unexpected frame type"); - auto entry = static_cast<PlaceholderMapEntry*> - (mPlaceholderMap.Add(aPlaceholderFrame->GetOutOfFlowFrame())); - MOZ_ASSERT(!entry->placeholderFrame, - "Registering a placeholder for a frame that already has a placeholder!"); - entry->placeholderFrame = aPlaceholderFrame; -} - -void -nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame) -{ - NS_PRECONDITION(aPlaceholderFrame, "null param unexpected"); - NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(), - "unexpected frame type"); - - mPlaceholderMap.Remove(aPlaceholderFrame->GetOutOfFlowFrame()); -} - -void -nsFrameManager::ClearPlaceholderFrameMap() -{ - for (auto iter = mPlaceholderMap.Iter(); !iter.Done(); iter.Next()) { - auto entry = static_cast<PlaceholderMapEntry*>(iter.Get()); - entry->placeholderFrame->SetOutOfFlowFrame(nullptr); - } - mPlaceholderMap.Clear(); -} - -//---------------------------------------------------------------------- - /* static */ nsStyleContext* -nsFrameManager::GetStyleContextInMap(UndisplayedMap* aMap, nsIContent* aContent) +nsFrameManager::GetStyleContextInMap(UndisplayedMap* aMap, + const nsIContent* aContent) { if (!aContent) { return nullptr; @@ -215,7 +141,7 @@ nsFrameManager::GetStyleContextInMap(UndisplayedMap* aMap, nsIContent* aContent) nsIContent* parent = aContent->GetParentElementCrossingShadowRoot(); MOZ_ASSERT(parent || !aContent->GetParent(), "no non-elements"); for (UndisplayedNode* node = aMap->GetFirstNode(parent); - node; node = node->mNext) { + node; node = node->getNext()) { if (node->mContent == aContent) return node->mStyle; } @@ -241,16 +167,16 @@ nsFrameManager::SetStyleContextInMap(UndisplayedMap* aMap, nsIContent* aContent, nsStyleContext* aStyleContext) { - NS_PRECONDITION(!aStyleContext->GetPseudo(), - "Should only have actual elements here"); + MOZ_ASSERT(!aStyleContext->GetPseudo(), + "Should only have actual elements here"); #if defined(DEBUG_UNDISPLAYED_MAP) || defined(DEBUG_DISPLAY_BOX_CONTENTS_MAP) static int i = 0; printf("SetStyleContextInMap(%d): p=%p \n", i++, (void *)aContent); #endif - NS_ASSERTION(!GetStyleContextInMap(aMap, aContent), - "Already have an entry for aContent"); + MOZ_ASSERT(!GetStyleContextInMap(aMap, aContent), + "Already have an entry for aContent"); nsIContent* parent = aContent->GetParentElementCrossingShadowRoot(); MOZ_ASSERT(parent || !aContent->GetParent(), "no non-elements"); @@ -287,7 +213,7 @@ nsFrameManager::ChangeStyleContextInMap(UndisplayedMap* aMap, #endif for (UndisplayedNode* node = aMap->GetFirstNode(aContent->GetParent()); - node; node = node->mNext) { + node; node = node->getNext()) { if (node->mContent == aContent) { node->mStyle = aStyleContext; return; @@ -306,25 +232,25 @@ nsFrameManager::ClearUndisplayedContentIn(nsIContent* aContent, printf("ClearUndisplayedContent(%d): content=%p parent=%p --> ", i++, (void *)aContent, (void*)aParentContent); #endif - if (mUndisplayedMap) { - UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aParentContent); - while (node) { - if (node->mContent == aContent) { - mUndisplayedMap->RemoveNodeFor(aParentContent, node); + if (!mUndisplayedMap) { + return; + } + + for (UndisplayedNode* node = mUndisplayedMap->GetFirstNode(aParentContent); + node; node = node->getNext()) { + if (node->mContent == aContent) { + mUndisplayedMap->RemoveNodeFor(aParentContent, node); #ifdef DEBUG_UNDISPLAYED_MAP - printf( "REMOVED!\n"); + printf( "REMOVED!\n"); #endif -#ifdef DEBUG - // make sure that there are no more entries for the same content - nsStyleContext *context = GetUndisplayedContent(aContent); - NS_ASSERTION(context == nullptr, "Found more undisplayed content data after removal"); -#endif - return; - } - node = node->mNext; + // make sure that there are no more entries for the same content + MOZ_ASSERT(!GetUndisplayedContent(aContent), + "Found more undisplayed content data after removal"); + return; } } + #ifdef DEBUG_UNDISPLAYED_MAP printf( "not found.\n"); #endif @@ -380,26 +306,25 @@ nsFrameManager::ClearDisplayContentsIn(nsIContent* aContent, static int i = 0; printf("ClearDisplayContents(%d): content=%p parent=%p --> ", i++, (void *)aContent, (void*)aParentContent); #endif - - if (mDisplayContentsMap) { - UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aParentContent); - while (node) { - if (node->mContent == aContent) { - mDisplayContentsMap->RemoveNodeFor(aParentContent, node); + + if (!mDisplayContentsMap) { + return; + } + + for (UndisplayedNode* node = mDisplayContentsMap->GetFirstNode(aParentContent); + node; node = node->getNext()) { + if (node->mContent == aContent) { + mDisplayContentsMap->RemoveNodeFor(aParentContent, node); #ifdef DEBUG_DISPLAY_CONTENTS_MAP - printf( "REMOVED!\n"); -#endif -#ifdef DEBUG - // make sure that there are no more entries for the same content - nsStyleContext* context = GetDisplayContentsStyleFor(aContent); - NS_ASSERTION(context == nullptr, "Found more entries for aContent after removal"); + printf( "REMOVED!\n"); #endif - ClearAllDisplayContentsIn(aContent); - ClearAllUndisplayedContentIn(aContent); - return; - } - node = node->mNext; + // make sure that there are no more entries for the same content + MOZ_ASSERT(!GetDisplayContentsStyleFor(aContent), + "Found more entries for aContent after removal"); + ClearAllDisplayContentsIn(aContent); + ClearAllUndisplayedContentIn(aContent); + return; } } #ifdef DEBUG_DISPLAY_CONTENTS_MAP @@ -416,14 +341,14 @@ nsFrameManager::ClearAllDisplayContentsIn(nsIContent* aParentContent) #endif if (mDisplayContentsMap) { - UndisplayedNode* cur = mDisplayContentsMap->UnlinkNodesFor(aParentContent); - while (cur) { - UndisplayedNode* next = cur->mNext; - cur->mNext = nullptr; - ClearAllDisplayContentsIn(cur->mContent); - ClearAllUndisplayedContentIn(cur->mContent); - delete cur; - cur = next; + nsAutoPtr<LinkedList<UndisplayedNode>> list = + mDisplayContentsMap->UnlinkNodesFor(aParentContent); + if (list) { + while (UndisplayedNode* node = list->popFirst()) { + ClearAllDisplayContentsIn(node->mContent); + ClearAllUndisplayedContentIn(node->mContent); + delete node; + } } } @@ -495,7 +420,7 @@ nsFrameManager::RemoveFrame(ChildListID aListID, aOldFrame->GetType() == nsGkAtoms::textFrame, "Must remove first continuation."); NS_ASSERTION(!(aOldFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW && - GetPlaceholderFrameFor(aOldFrame)), + aOldFrame->GetPlaceholderFrame()), "Must call RemoveFrame on placeholder for out-of-flows."); nsContainerFrame* parentFrame = aOldFrame->GetParent(); if (parentFrame->IsAbsoluteContainer() && @@ -654,182 +579,132 @@ nsFrameManager::RestoreFrameState(nsIFrame* aFrame, //---------------------------------------------------------------------- -static PLHashNumber -HashKey(void* key) -{ - return NS_PTR_TO_INT32(key); -} - -static int -CompareKeys(void* key1, void* key2) -{ - return key1 == key2; -} - -//---------------------------------------------------------------------- - -nsFrameManagerBase::UndisplayedMap::UndisplayedMap(uint32_t aNumBuckets) +nsFrameManagerBase::UndisplayedMap::UndisplayedMap() { MOZ_COUNT_CTOR(nsFrameManagerBase::UndisplayedMap); - mTable = PL_NewHashTable(aNumBuckets, (PLHashFunction)HashKey, - (PLHashComparator)CompareKeys, - (PLHashComparator)nullptr, - nullptr, nullptr); - mLastLookup = nullptr; } nsFrameManagerBase::UndisplayedMap::~UndisplayedMap(void) { MOZ_COUNT_DTOR(nsFrameManagerBase::UndisplayedMap); Clear(); - PL_HashTableDestroy(mTable); } -PLHashEntry** -nsFrameManagerBase::UndisplayedMap::GetEntryFor(nsIContent** aParentContent) +void +nsFrameManagerBase::UndisplayedMap::Clear() { - nsIContent* parentContent = *aParentContent; - - if (mLastLookup && (parentContent == (*mLastLookup)->key)) { - return mLastLookup; + for (auto iter = Iter(); !iter.Done(); iter.Next()) { + auto* list = iter.UserData(); + while (auto* node = list->popFirst()) { + delete node; + } + iter.Remove(); } +} +nsIContent* +nsFrameManagerBase::UndisplayedMap::GetApplicableParent(nsIContent* aParent) +{ // In the case of XBL default content, <xbl:children> elements do not get a // frame causing a mismatch between the content tree and the frame tree. // |GetEntryFor| is sometimes called with the content tree parent (which may // be a <xbl:children> element) but the parent in the frame tree would be the // insertion parent (parent of the <xbl:children> element). Here the children // elements are normalized to the insertion parent to correct for the mismatch. - if (parentContent && nsContentUtils::IsContentInsertionPoint(parentContent)) { - parentContent = parentContent->GetParent(); - // Change the caller's pointer for the parent content to be the insertion parent. - *aParentContent = parentContent; + if (aParent && aParent->IsActiveChildrenElement()) { + return aParent->GetParent(); } - PLHashNumber hashCode = NS_PTR_TO_INT32(parentContent); - PLHashEntry** entry = PL_HashTableRawLookup(mTable, hashCode, parentContent); - if (*entry) { - mLastLookup = entry; - } - return entry; + return aParent; } -UndisplayedNode* -nsFrameManagerBase::UndisplayedMap::GetFirstNode(nsIContent* aParentContent) +LinkedList<UndisplayedNode>* +nsFrameManagerBase::UndisplayedMap::GetListFor(nsIContent* aParent) { - PLHashEntry** entry = GetEntryFor(&aParentContent); - if (*entry) { - return (UndisplayedNode*)((*entry)->value); + aParent = GetApplicableParent(aParent); + + LinkedList<UndisplayedNode>* list; + if (Get(aParent, &list)) { + return list; } + return nullptr; } +LinkedList<UndisplayedNode>* +nsFrameManagerBase::UndisplayedMap::GetOrCreateListFor(nsIContent* aParent) +{ + aParent = GetApplicableParent(aParent); + return LookupOrAdd(aParent); +} + + +UndisplayedNode* +nsFrameManagerBase::UndisplayedMap::GetFirstNode(nsIContent* aParentContent) +{ + auto* list = GetListFor(aParentContent); + return list ? list->getFirst() : nullptr; +} + void nsFrameManagerBase::UndisplayedMap::AppendNodeFor(UndisplayedNode* aNode, nsIContent* aParentContent) { - PLHashEntry** entry = GetEntryFor(&aParentContent); - if (*entry) { - UndisplayedNode* node = (UndisplayedNode*)((*entry)->value); - while (node->mNext) { - if (node->mContent == aNode->mContent) { - // We actually need to check this in optimized builds because - // there are some callers that do this. See bug 118014, bug - // 136704, etc. - NS_NOTREACHED("node in map twice"); - delete aNode; - return; - } - node = node->mNext; - } - node->mNext = aNode; - } - else { - PLHashNumber hashCode = NS_PTR_TO_INT32(aParentContent); - PL_HashTableRawAdd(mTable, entry, hashCode, aParentContent, aNode); - mLastLookup = nullptr; // hashtable may have shifted bucket out from under us + LinkedList<UndisplayedNode>* list = GetOrCreateListFor(aParentContent); + +#ifdef DEBUG + for (UndisplayedNode* node = list->getFirst(); node; node = node->getNext()) { + // NOTE: In the original code there was a work around for this case, I want + // to check it still happens before hacking around it the same way. + MOZ_ASSERT(node->mContent != aNode->mContent, + "Duplicated content in undisplayed list!"); } +#endif + + list->insertBack(aNode); } -nsresult +void nsFrameManagerBase::UndisplayedMap::AddNodeFor(nsIContent* aParentContent, - nsIContent* aChild, + nsIContent* aChild, nsStyleContext* aStyle) { UndisplayedNode* node = new UndisplayedNode(aChild, aStyle); - AppendNodeFor(node, aParentContent); - return NS_OK; } void nsFrameManagerBase::UndisplayedMap::RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode) { - PLHashEntry** entry = GetEntryFor(&aParentContent); - NS_ASSERTION(*entry, "content not in map"); - if (*entry) { - if ((UndisplayedNode*)((*entry)->value) == aNode) { // first node - if (aNode->mNext) { - (*entry)->value = aNode->mNext; - aNode->mNext = nullptr; - } - else { - PL_HashTableRawRemove(mTable, entry, *entry); - mLastLookup = nullptr; // hashtable may have shifted bucket out from under us - } - } - else { - UndisplayedNode* node = (UndisplayedNode*)((*entry)->value); - while (node->mNext) { - if (node->mNext == aNode) { - node->mNext = aNode->mNext; - aNode->mNext = nullptr; - break; - } - node = node->mNext; - } - } - } +#ifdef DEBUG + auto list = GetListFor(aParentContent); + MOZ_ASSERT(list, "content not in map"); + aNode->removeFrom(*list); +#else + aNode->remove(); +#endif delete aNode; } -UndisplayedNode* +nsAutoPtr<LinkedList<UndisplayedNode>> nsFrameManagerBase::UndisplayedMap::UnlinkNodesFor(nsIContent* aParentContent) { - PLHashEntry** entry = GetEntryFor(&aParentContent); - NS_ASSERTION(entry, "content not in map"); - if (*entry) { - UndisplayedNode* node = (UndisplayedNode*)((*entry)->value); - NS_ASSERTION(node, "null node for non-null entry in UndisplayedMap"); - PL_HashTableRawRemove(mTable, entry, *entry); - mLastLookup = nullptr; // hashtable may have shifted bucket out from under us - return node; - } - return nullptr; + nsAutoPtr<LinkedList<UndisplayedNode>> list; + RemoveAndForget(GetApplicableParent(aParentContent), list); + return list; } void nsFrameManagerBase::UndisplayedMap::RemoveNodesFor(nsIContent* aParentContent) { - delete UnlinkNodesFor(aParentContent); -} - -static int -RemoveUndisplayedEntry(PLHashEntry* he, int i, void* arg) -{ - UndisplayedNode* node = (UndisplayedNode*)(he->value); - delete node; - // Remove and free this entry and continue enumerating - return HT_ENUMERATE_REMOVE | HT_ENUMERATE_NEXT; -} - -void -nsFrameManagerBase::UndisplayedMap::Clear(void) -{ - mLastLookup = nullptr; - PL_HashTableEnumerateEntries(mTable, RemoveUndisplayedEntry, 0); + nsAutoPtr<LinkedList<UndisplayedNode>> list = UnlinkNodesFor(aParentContent); + if (list) { + while (auto* node = list->popFirst()) { + delete node; + } + } } uint32_t nsFrameManagerBase::sGlobalGenerationNumber; diff --git a/layout/base/nsFrameManager.h b/layout/base/nsFrameManager.h index 1b9148314..ae7477d3d 100644 --- a/layout/base/nsFrameManager.h +++ b/layout/base/nsFrameManager.h @@ -33,40 +33,25 @@ namespace mozilla { * Node in a linked list, containing the style for an element that * does not have a frame but whose parent does have a frame. */ -struct UndisplayedNode { +struct UndisplayedNode : public LinkedListElement<UndisplayedNode> +{ UndisplayedNode(nsIContent* aContent, nsStyleContext* aStyle) - : mContent(aContent), - mStyle(aStyle), - mNext(nullptr) + : mContent(aContent) + , mStyle(aStyle) { MOZ_COUNT_CTOR(mozilla::UndisplayedNode); } - ~UndisplayedNode() - { - MOZ_COUNT_DTOR(mozilla::UndisplayedNode); - - // Delete mNext iteratively to avoid blowing up the stack (bug 460461). - UndisplayedNode* cur = mNext; - while (cur) { - UndisplayedNode* next = cur->mNext; - cur->mNext = nullptr; - delete cur; - cur = next; - } - } + ~UndisplayedNode() { MOZ_COUNT_DTOR(mozilla::UndisplayedNode); } - nsCOMPtr<nsIContent> mContent; - RefPtr<nsStyleContext> mStyle; - UndisplayedNode* mNext; + nsCOMPtr<nsIContent> mContent; + RefPtr<nsStyleContext> mStyle; }; } // namespace mozilla /** - * Frame manager interface. The frame manager serves two purposes: - * <li>provides a service for mapping from content to frame and from - * out-of-flow frame to placeholder frame. + * Frame manager interface. The frame manager serves one purpose: * <li>handles structural modifications to the frame model. If the frame model * lock can be acquired, then the changes are processed immediately; otherwise, * they're queued and processed later. @@ -94,15 +79,8 @@ public: */ void Destroy(); - // Placeholder frame functions - nsPlaceholderFrame* GetPlaceholderFrameFor(const nsIFrame* aFrame); - void RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame); - void UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame); - - void ClearPlaceholderFrameMap(); - // Mapping undisplayed content - nsStyleContext* GetUndisplayedContent(nsIContent* aContent) + nsStyleContext* GetUndisplayedContent(const nsIContent* aContent) { if (!mUndisplayedMap) { return nullptr; @@ -127,7 +105,7 @@ public: /** * Return the registered display:contents style context for aContent, if any. */ - nsStyleContext* GetDisplayContentsStyleFor(nsIContent* aContent) + nsStyleContext* GetDisplayContentsStyleFor(const nsIContent* aContent) { if (!mDisplayContentsMap) { return nullptr; @@ -207,7 +185,7 @@ public: nsILayoutHistoryState* aState); protected: static nsStyleContext* GetStyleContextInMap(UndisplayedMap* aMap, - nsIContent* aContent); + const nsIContent* aContent); static mozilla::UndisplayedNode* GetAllUndisplayedNodesInMapFor(UndisplayedMap* aMap, nsIContent* aParentContent); diff --git a/layout/base/nsFrameManagerBase.h b/layout/base/nsFrameManagerBase.h index 757dce7e5..bb192b64f 100644 --- a/layout/base/nsFrameManagerBase.h +++ b/layout/base/nsFrameManagerBase.h @@ -53,7 +53,6 @@ protected: // weak link, because the pres shell owns us nsIPresShell* MOZ_NON_OWNING_REF mPresShell; nsIFrame* mRootFrame; - PLDHashTable mPlaceholderMap; UndisplayedMap* mUndisplayedMap; UndisplayedMap* mDisplayContentsMap; bool mIsDestroyingFrames; // The frame manager is destroying some frame(s). diff --git a/layout/base/nsFrameTraversal.cpp b/layout/base/nsFrameTraversal.cpp index ab07d07df..0c6a655a2 100644 --- a/layout/base/nsFrameTraversal.cpp +++ b/layout/base/nsFrameTraversal.cpp @@ -83,6 +83,10 @@ protected: virtual nsIFrame* GetNextSiblingInner(nsIFrame* aFrame); virtual nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame); + /** + * Return the placeholder frame for aFrame if it has one, otherwise return + * aFrame itself. + */ nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame); bool IsPopupFrame(nsIFrame* aFrame); @@ -487,18 +491,11 @@ nsFrameIterator::GetPrevSiblingInner(nsIFrame* aFrame) { nsIFrame* nsFrameIterator::GetPlaceholderFrame(nsIFrame* aFrame) { - nsIFrame* result = aFrame; - nsIPresShell *presShell = mPresContext->GetPresShell(); - if (presShell) { - nsIFrame* placeholder = presShell->GetPlaceholderFrameFor(aFrame); - if (placeholder) - result = placeholder; + if (MOZ_LIKELY(!aFrame || !aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW))) { + return aFrame; } - - if (result != aFrame) - result = GetPlaceholderFrame(result); - - return result; + nsIFrame* placeholder = aFrame->GetPlaceholderFrame(); + return placeholder ? placeholder : aFrame; } bool diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 865f5534c..cf19867ef 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -486,12 +486,6 @@ public: virtual nsCanvasFrame* GetCanvasFrame() const = 0; /** - * Gets the placeholder frame associated with the specified frame. This is - * a helper frame that forwards the request to the frame manager. - */ - virtual nsIFrame* GetPlaceholderFrameFor(nsIFrame* aFrame) const = 0; - - /** * Tell the pres shell that a frame needs to be marked dirty and needs * Reflow. It's OK if this is an ancestor of the frame needing reflow as * long as the ancestor chain between them doesn't cross a reflow root. @@ -545,20 +539,12 @@ public: virtual void NotifyCounterStylesAreDirty() = 0; /** - * Destroy the frames for aContent. Note that this may destroy frames - * for an ancestor instead - aDestroyedFramesFor contains the content node - * where frames were actually destroyed (which should be used in the - * CreateFramesFor call). The frame tree state will be captured before - * the frames are destroyed in the frame constructor. - */ - virtual void DestroyFramesFor(nsIContent* aContent, - nsIContent** aDestroyedFramesFor) = 0; - /** - * Create new frames for aContent. It will use the last captured layout - * history state captured in the frame constructor to restore the state - * in the new frame tree. + * Destroy the frames for aElement, and reconstruct them asynchronously if + * needed. + * + * Note that this may destroy frames for an ancestor instead. */ - virtual void CreateFramesFor(nsIContent* aContent) = 0; + virtual void DestroyFramesForAndRestyle(mozilla::dom::Element* aElement) = 0; /** * Recreates the frames for a node @@ -977,7 +963,7 @@ public: /** * Reconstruct frames for all elements in the document */ - virtual nsresult ReconstructFrames() = 0; + virtual void ReconstructFrames() = 0; /** * Notify that a content node's state has changed @@ -1725,10 +1711,6 @@ public: void SyncWindowProperties(nsView* aView); -#ifdef ANDROID - virtual nsIDocument* GetTouchEventTargetDocument() = 0; -#endif - protected: friend class nsRefreshDriver; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 9b204d734..ccdc5503f 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -912,11 +911,6 @@ ApplyRectMultiplier(nsRect aRect, float aMultiplier) bool nsLayoutUtils::UsesAsyncScrolling(nsIFrame* aFrame) { -#ifdef MOZ_WIDGET_ANDROID - // We always have async scrolling for android - return true; -#endif - return AsyncPanZoomEnabled(aFrame); } @@ -1519,90 +1513,38 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame) return id; } -/*static*/ nsIFrame* -nsLayoutUtils::GetBeforeFrameForContent(nsIFrame* aFrame, - const nsIContent* aContent) -{ - // We need to call GetGenConPseudos() on the first continuation/ib-split. - // Find it, for symmetry with GetAfterFrameForContent. - nsContainerFrame* genConParentFrame = - FirstContinuationOrIBSplitSibling(aFrame)->GetContentInsertionFrame(); - if (!genConParentFrame) { - return nullptr; - } - nsTArray<nsIContent*>* prop = genConParentFrame->GetGenConPseudos(); - if (prop) { - const nsTArray<nsIContent*>& pseudos(*prop); - for (uint32_t i = 0; i < pseudos.Length(); ++i) { - if (pseudos[i]->GetParent() == aContent && - pseudos[i]->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) { - return pseudos[i]->GetPrimaryFrame(); - } - } - } - // If the first child frame is a pseudo-frame, then try that. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case. - nsIFrame* childFrame = genConParentFrame->PrincipalChildList().FirstChild(); - if (childFrame && - childFrame->IsPseudoFrame(aContent) && - !childFrame->IsGeneratedContentFrame()) { - return GetBeforeFrameForContent(childFrame, aContent); - } - return nullptr; +static Element* +GetPseudo(const nsIContent* aContent, nsIAtom* aPseudoProperty) +{ + MOZ_ASSERT(aPseudoProperty == nsGkAtoms::beforePseudoProperty || + aPseudoProperty == nsGkAtoms::afterPseudoProperty); + return static_cast<Element*>(aContent->GetProperty(aPseudoProperty)); } -/*static*/ nsIFrame* -nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame) +/*static*/ Element* +nsLayoutUtils::GetBeforePseudo(const nsIContent* aContent) { - return GetBeforeFrameForContent(aFrame, aFrame->GetContent()); + return GetPseudo(aContent, nsGkAtoms::beforePseudoProperty); } /*static*/ nsIFrame* -nsLayoutUtils::GetAfterFrameForContent(nsIFrame* aFrame, - const nsIContent* aContent) -{ - // We need to call GetGenConPseudos() on the first continuation, - // but callers are likely to pass the last. - nsContainerFrame* genConParentFrame = - FirstContinuationOrIBSplitSibling(aFrame)->GetContentInsertionFrame(); - if (!genConParentFrame) { - return nullptr; - } - nsTArray<nsIContent*>* prop = genConParentFrame->GetGenConPseudos(); - if (prop) { - const nsTArray<nsIContent*>& pseudos(*prop); - for (uint32_t i = 0; i < pseudos.Length(); ++i) { - if (pseudos[i]->GetParent() == aContent && - pseudos[i]->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter) { - return pseudos[i]->GetPrimaryFrame(); - } - } - } - // If the last child frame is a pseudo-frame, then try that. - // Note that the frame we create for the generated content is also a - // pseudo-frame and so don't drill down in that case. - genConParentFrame = aFrame->GetContentInsertionFrame(); - if (!genConParentFrame) { - return nullptr; - } - nsIFrame* lastParentContinuation = - LastContinuationWithChild(static_cast<nsContainerFrame*>( - LastContinuationOrIBSplitSibling(genConParentFrame))); - nsIFrame* childFrame = - lastParentContinuation->GetChildList(nsIFrame::kPrincipalList).LastChild(); - if (childFrame && - childFrame->IsPseudoFrame(aContent) && - !childFrame->IsGeneratedContentFrame()) { - return GetAfterFrameForContent(childFrame->FirstContinuation(), aContent); - } - return nullptr; +nsLayoutUtils::GetBeforeFrame(const nsIContent* aContent) +{ + Element* pseudo = GetBeforePseudo(aContent); + return pseudo ? pseudo->GetPrimaryFrame() : nullptr; +} + +/*static*/ Element* +nsLayoutUtils::GetAfterPseudo(const nsIContent* aContent) +{ + return GetPseudo(aContent, nsGkAtoms::afterPseudoProperty); } /*static*/ nsIFrame* -nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame) +nsLayoutUtils::GetAfterFrame(const nsIContent* aContent) { - return GetAfterFrameForContent(aFrame, aFrame->GetContent()); + Element* pseudo = GetAfterPseudo(aContent); + return pseudo ? pseudo->GetPrimaryFrame() : nullptr; } // static @@ -1673,33 +1615,6 @@ nsLayoutUtils::GetFloatFromPlaceholder(nsIFrame* aFrame) { } // static -bool -nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent, - nsIFrame* aFrame, - nsIAtom* aPseudoElement) -{ - NS_PRECONDITION(aFrame, "Must have a frame"); - NS_PRECONDITION(aPseudoElement, "Must have a pseudo name"); - - if (!aFrame->IsGeneratedContentFrame()) { - return false; - } - nsIFrame* parent = aFrame->GetParent(); - NS_ASSERTION(parent, "Generated content can't be root frame"); - if (parent->IsGeneratedContentFrame()) { - // Not the root of the generated content - return false; - } - - if (aContent && parent->GetContent() != aContent) { - return false; - } - - return (aFrame->GetContent()->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) == - (aPseudoElement == nsCSSPseudoElements::before); -} - -// static nsIFrame* nsLayoutUtils::GetCrossDocParentFrame(const nsIFrame* aFrame, nsPoint* aExtraOffset) @@ -2108,7 +2023,7 @@ nsLayoutUtils::GetNearestScrollableFrameForDirection(nsIFrame* aFrame, for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) { nsIScrollableFrame* scrollableFrame = do_QueryFrame(f); if (scrollableFrame) { - ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); + ScrollStyles ss = scrollableFrame->GetScrollStyles(); uint32_t directions = scrollableFrame->GetPerceivedScrollingDirections(); if (aDirection == eVertical ? (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN && @@ -2135,7 +2050,7 @@ nsLayoutUtils::GetNearestScrollableFrame(nsIFrame* aFrame, uint32_t aFlags) return scrollableFrame; } } else { - ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles(); + ScrollStyles ss = scrollableFrame->GetScrollStyles(); if ((aFlags & SCROLLABLE_INCLUDE_HIDDEN) || ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN) { @@ -4427,8 +4342,7 @@ nsLayoutUtils::GetParentOrPlaceholderFor(nsIFrame* aFrame) { if ((aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) && !aFrame->GetPrevInFlow()) { - return aFrame->PresContext()->PresShell()->FrameManager()-> - GetPlaceholderFrameFor(aFrame); + return aFrame->GetProperty(nsIFrame::PlaceholderFrameProperty()); } return aFrame->GetParent(); } @@ -8185,7 +8099,7 @@ UpdateCompositionBoundsForRCDRSF(ParentLayerRect& aCompBounds, return false; } -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) +#if defined(MOZ_WIDGET_UIKIT) nsIWidget* widget = rootFrame->GetNearestWidget(); #else nsView* view = rootFrame->GetView(); @@ -8341,11 +8255,11 @@ nsLayoutUtils::CalculateScrollableRectForFrame(nsIScrollableFrame* aScrollableFr contentBounds = aScrollableFrame->GetScrollRange(); nsPoint scrollPosition = aScrollableFrame->GetScrollPosition(); - if (aScrollableFrame->GetScrollbarStyles().mVertical == NS_STYLE_OVERFLOW_HIDDEN) { + if (aScrollableFrame->GetScrollStyles().mVertical == NS_STYLE_OVERFLOW_HIDDEN) { contentBounds.y = scrollPosition.y; contentBounds.height = 0; } - if (aScrollableFrame->GetScrollbarStyles().mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) { + if (aScrollableFrame->GetScrollStyles().mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) { contentBounds.x = scrollPosition.x; contentBounds.width = 0; } diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index f4471ce74..21407511a 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -278,50 +278,26 @@ public: static mozilla::layout::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame); /** - * GetBeforeFrameForContent returns the ::before frame for aContent, if - * one exists. This is typically O(1). The frame passed in must be - * the first-in-flow. - * - * @param aGenConParentFrame an ancestor of the ::before frame - * @param aContent the content whose ::before is wanted - * @return the ::before frame or nullptr if there isn't one + * Returns the ::before pseudo-element for aContent, if any. */ - static nsIFrame* GetBeforeFrameForContent(nsIFrame* aGenConParentFrame, - const nsIContent* aContent); + static mozilla::dom::Element* GetBeforePseudo(const nsIContent* aContent); /** - * GetBeforeFrame returns the outermost ::before frame of the given frame, if - * one exists. This is typically O(1). The frame passed in must be - * the first-in-flow. - * - * @param aFrame the frame whose ::before is wanted - * @return the :before frame or nullptr if there isn't one + * Returns the frame corresponding to the ::before pseudo-element for + * aContent, if any. */ - static nsIFrame* GetBeforeFrame(nsIFrame* aFrame); + static nsIFrame* GetBeforeFrame(const nsIContent* aContent); /** - * GetAfterFrameForContent returns the ::after frame for aContent, if one - * exists. This will walk the in-flow chain of aGenConParentFrame to the - * last-in-flow if needed. This function is typically O(N) in the number - * of child frames, following in-flows, etc. - * - * @param aGenConParentFrame an ancestor of the ::after frame - * @param aContent the content whose ::after is wanted - * @return the ::after frame or nullptr if there isn't one + * Returns the ::after pseudo-element for aContent, if any. */ - static nsIFrame* GetAfterFrameForContent(nsIFrame* aGenConParentFrame, - const nsIContent* aContent); + static mozilla::dom::Element* GetAfterPseudo(const nsIContent* aContent); /** - * GetAfterFrame returns the outermost ::after frame of the given frame, if one - * exists. This will walk the in-flow chain to the last-in-flow if - * needed. This function is typically O(N) in the number of child - * frames, following in-flows, etc. - * - * @param aFrame the frame whose ::after is wanted - * @return the :after frame or nullptr if there isn't one + * Returns the frame corresponding to the ::after pseudo-element for aContent, + * if any. */ - static nsIFrame* GetAfterFrame(nsIFrame* aFrame); + static nsIFrame* GetAfterFrame(const nsIContent* aContent); /** * Given a frame, search up the frame tree until we find an @@ -379,23 +355,6 @@ public: */ static nsIFrame* GetRealPrimaryFrameFor(const nsIContent* aContent); - /** - * IsGeneratedContentFor returns true if aFrame is the outermost - * frame for generated content of type aPseudoElement for aContent. - * aFrame *might not* have the aPseudoElement pseudo-style! For example - * it might be a table wrapper frame and the inner table frame might - * have the pseudo-style. - * - * @param aContent the content node we're looking at. If this is - * null, then we just assume that aFrame has the right content - * pointer. - * @param aFrame the frame we're looking at - * @param aPseudoElement the pseudo type we're interested in - * @return whether aFrame is the generated aPseudoElement frame for aContent - */ - static bool IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, - nsIAtom* aPseudoElement); - #ifdef DEBUG // TODO: remove, see bug 598468. static bool gPreventAssertInCompareTreePosition; diff --git a/layout/base/nsPresArena.cpp b/layout/base/nsPresArena.cpp index 2b1f072df..8e7fb9374 100644 --- a/layout/base/nsPresArena.cpp +++ b/layout/base/nsPresArena.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/nsPresArena.h b/layout/base/nsPresArena.h index 32407541e..00a54d68d 100644 --- a/layout/base/nsPresArena.h +++ b/layout/base/nsPresArena.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. diff --git a/layout/base/nsPresArenaObjectList.h b/layout/base/nsPresArenaObjectList.h index c226aa3b4..82ab98244 100644 --- a/layout/base/nsPresArenaObjectList.h +++ b/layout/base/nsPresArenaObjectList.h @@ -1,4 +1,3 @@ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 1d90b967a..f7be42b5f 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1346,7 +1346,7 @@ nsPresContext::ScreenSizeInchesForFontInflation(bool* aChanged) } static bool -CheckOverflow(const nsStyleDisplay* aDisplay, ScrollbarStyles* aStyles) +CheckOverflow(const nsStyleDisplay* aDisplay, ScrollStyles* aStyles) { if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE && aDisplay->mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_AUTO && @@ -1362,17 +1362,17 @@ CheckOverflow(const nsStyleDisplay* aDisplay, ScrollbarStyles* aStyles) } if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP) { - *aStyles = ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, + *aStyles = ScrollStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN, aDisplay); } else { - *aStyles = ScrollbarStyles(aDisplay); + *aStyles = ScrollStyles(aDisplay); } return true; } static nsIContent* -GetPropagatedScrollbarStylesForViewport(nsPresContext* aPresContext, - ScrollbarStyles *aStyles) +GetPropagatedScrollStylesForViewport(nsPresContext* aPresContext, + ScrollStyles *aStyles) { nsIDocument* document = aPresContext->Document(); Element* docElement = document->GetRootElement(); @@ -1424,16 +1424,16 @@ GetPropagatedScrollbarStylesForViewport(nsPresContext* aPresContext, } nsIContent* -nsPresContext::UpdateViewportScrollbarStylesOverride() +nsPresContext::UpdateViewportScrollStylesOverride() { // Start off with our default styles, and then update them as needed. - mViewportStyleScrollbar = ScrollbarStyles(NS_STYLE_OVERFLOW_AUTO, + mViewportStyleScrollbar = ScrollStyles(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO); mViewportScrollbarOverrideNode = nullptr; // Don't propagate the scrollbar state in printing or print preview. if (!IsPaginated()) { mViewportScrollbarOverrideNode = - GetPropagatedScrollbarStylesForViewport(this, &mViewportStyleScrollbar); + GetPropagatedScrollStylesForViewport(this, &mViewportStyleScrollbar); } nsIDocument* document = Document(); @@ -1445,7 +1445,7 @@ nsPresContext::UpdateViewportScrollbarStylesOverride() // affected across fullscreen change. if (fullscreenElement != document->GetRootElement() && fullscreenElement != mViewportScrollbarOverrideNode) { - mViewportStyleScrollbar = ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, + mViewportStyleScrollbar = ScrollStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN); } } @@ -1454,7 +1454,7 @@ nsPresContext::UpdateViewportScrollbarStylesOverride() } bool -nsPresContext::ElementWouldPropagateScrollbarStyles(Element* aElement) +nsPresContext::ElementWouldPropagateScrollStyles(Element* aElement) { MOZ_ASSERT(IsPaginated(), "Should only be called on paginated contexts"); if (aElement->GetParent() && !aElement->IsHTMLElement(nsGkAtoms::body)) { @@ -1462,13 +1462,13 @@ nsPresContext::ElementWouldPropagateScrollbarStyles(Element* aElement) return false; } - // Go ahead and just call GetPropagatedScrollbarStylesForViewport, but update - // a dummy ScrollbarStyles we don't care about. It'll do a bit of extra work, + // Go ahead and just call GetPropagatedScrollStylesForViewport, but update + // a dummy ScrollStyles we don't care about. It'll do a bit of extra work, // but saves us having to have more complicated code or more code duplication; // in practice we will make this call quite rarely, because we checked for all // the common cases above. - ScrollbarStyles dummy(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO); - return GetPropagatedScrollbarStylesForViewport(this, &dummy) == aElement; + ScrollStyles dummy(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO); + return GetPropagatedScrollStylesForViewport(this, &dummy) == aElement; } void diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index a2b9bb533..10908a604 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -35,7 +35,7 @@ #include "mozilla/AppUnits.h" #include "prclist.h" #include "nsThreadUtils.h" -#include "ScrollbarStyles.h" +#include "ScrollStyles.h" #include "nsIMessageManager.h" #include "mozilla/RestyleLogging.h" #include "Units.h" @@ -140,7 +140,7 @@ class nsPresContext : public nsIObserver, public mozilla::SupportsWeakPtr<nsPresContext> { public: typedef mozilla::LangGroupFontPrefs LangGroupFontPrefs; - typedef mozilla::ScrollbarStyles ScrollbarStyles; + typedef mozilla::ScrollStyles ScrollStyles; typedef mozilla::StaticPresData StaticPresData; NS_DECL_CYCLE_COLLECTING_ISUPPORTS @@ -716,19 +716,19 @@ public: * @return if scroll was propagated from some content node, the content node * it was propagated from. */ - nsIContent* UpdateViewportScrollbarStylesOverride(); + nsIContent* UpdateViewportScrollStylesOverride(); /** * Returns the cached result from the last call to - * UpdateViewportScrollbarStylesOverride() -- i.e. return the node + * UpdateViewportScrollStylesOverride() -- i.e. return the node * whose scrollbar styles we have propagated to the viewport (or nullptr if * there is no such node). */ - nsIContent* GetViewportScrollbarStylesOverrideNode() const { + nsIContent* GetViewportScrollStylesOverrideNode() const { return mViewportScrollbarOverrideNode; } - const ScrollbarStyles& GetViewportScrollbarStylesOverride() const + const ScrollStyles& GetViewportScrollStylesOverride() const { return mViewportStyleScrollbar; } @@ -737,7 +737,7 @@ public: * Check whether the given element would propagate its scrollbar styles to the * viewport in non-paginated mode. Must only be called if IsPaginated(). */ - bool ElementWouldPropagateScrollbarStyles(mozilla::dom::Element* aElement); + bool ElementWouldPropagateScrollStyles(mozilla::dom::Element* aElement); /** * Set and get methods for controlling the background drawing @@ -1312,13 +1312,13 @@ protected: // This is a non-owning pointer. May be null. If non-null, it's guaranteed // to be pointing to a node that's still alive, because we'll reset it in - // UpdateViewportScrollbarStylesOverride() as part of the cleanup code + // UpdateViewportScrollStylesOverride() as part of the cleanup code // when this node is removed from the document. (For <body> and the root node, // this call happens in nsCSSFrameConstructor::ContentRemoved(). For // fullscreen elements, it happens in the fullscreen-specific cleanup // invoked by Element::UnbindFromTree().) nsIContent* MOZ_NON_OWNING_REF mViewportScrollbarOverrideNode; - ScrollbarStyles mViewportStyleScrollbar; + ScrollStyles mViewportStyleScrollbar; uint8_t mFocusRingWidth; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 0544a69a4..9ba4ff462 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -198,10 +197,6 @@ #include "mozilla/StyleSheetInlines.h" #include "mozilla/dom/ImageTracker.h" -#ifdef ANDROID -#include "nsIDocShellTreeOwner.h" -#endif - #ifdef MOZ_TASK_TRACER #include "GeckoTaskTracer.h" using namespace mozilla::tasktracer; @@ -2832,10 +2827,9 @@ PresShell::CancelAllPendingReflows() } void -PresShell::DestroyFramesFor(nsIContent* aContent, - nsIContent** aDestroyedFramesFor) +PresShell::DestroyFramesForAndRestyle(Element* aElement) { - MOZ_ASSERT(aContent); + MOZ_ASSERT(aElement); NS_ENSURE_TRUE_VOID(mPresContext); if (!mDidInitialize) { return; @@ -2847,43 +2841,20 @@ PresShell::DestroyFramesFor(nsIContent* aContent, ++mChangeNestCount; nsCSSFrameConstructor* fc = FrameConstructor(); + bool didReconstruct; fc->BeginUpdate(); - fc->DestroyFramesFor(aContent, aDestroyedFramesFor); + fc->DestroyFramesFor(aElement, &didReconstruct); fc->EndUpdate(); - --mChangeNestCount; -} - -void -PresShell::CreateFramesFor(nsIContent* aContent) -{ - NS_ENSURE_TRUE_VOID(mPresContext); - if (!mDidInitialize) { - // Nothing to do here. In fact, if we proceed and aContent is the - // root we will crash. - return; - } - - // Don't call RecreateFramesForContent since that is not exported and we want - // to keep the number of entrypoints down. - - NS_ASSERTION(mViewManager, "Should have view manager"); - MOZ_ASSERT(aContent); - - // Have to make sure that the content notifications are flushed before we - // start messing with the frame model; otherwise we can get content doubling. - mDocument->FlushPendingNotifications(Flush_ContentAndNotify); + auto changeHint = didReconstruct + ? nsChangeHint(0) + : nsChangeHint_ReconstructFrame; - nsAutoScriptBlocker scriptBlocker; - - // Mark ourselves as not safe to flush while we're doing frame construction. - ++mChangeNestCount; - - nsCSSFrameConstructor* fc = FrameConstructor(); - nsILayoutHistoryState* layoutState = fc->GetLastCapturedLayoutHistoryState(); - fc->BeginUpdate(); - fc->ContentInserted(aContent->GetParent(), aContent, layoutState, false); - fc->EndUpdate(); + // NOTE(emilio): eRestyle_Subtree is needed to force also a full subtree + // restyle for the content (in Stylo, where the existence of frames != the + // existence of styles). + mPresContext->RestyleManager()->PostRestyleEvent( + aElement, eRestyle_Subtree, changeHint); --mChangeNestCount; } @@ -3360,7 +3331,7 @@ static void ScrollToShowRect(nsIScrollableFrame* aFrameAsScrollable, aHorizontal.mWhenToScroll == nsIPresShell::SCROLL_IF_NOT_VISIBLE) { lineSize = aFrameAsScrollable->GetLineScrollAmount(); } - ScrollbarStyles ss = aFrameAsScrollable->GetScrollbarStyles(); + ScrollStyles ss = aFrameAsScrollable->GetScrollStyles(); nsRect allowedRange(scrollPt, nsSize(0, 0)); bool needToScroll = false; uint32_t directions = aFrameAsScrollable->GetPerceivedScrollingDirections(); @@ -3417,7 +3388,7 @@ static void ScrollToShowRect(nsIScrollableFrame* aFrameAsScrollable, // a current smooth scroll operation. if (needToScroll) { nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT; - bool autoBehaviorIsSmooth = (aFrameAsScrollable->GetScrollbarStyles().mScrollBehavior + bool autoBehaviorIsSmooth = (aFrameAsScrollable->GetScrollStyles().mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH); bool smoothScroll = (aFlags & nsIPresShell::SCROLL_SMOOTH) || ((aFlags & nsIPresShell::SCROLL_SMOOTH_AUTO) && autoBehaviorIsSmooth); @@ -4448,14 +4419,14 @@ PresShell::NotifyCounterStylesAreDirty() mFrameConstructor->EndUpdate(); } -nsresult -PresShell::ReconstructFrames(void) +void +PresShell::ReconstructFrames() { NS_PRECONDITION(!mFrameConstructor->GetRootFrame() || mDidInitialize, "Must not have root frame before initial reflow"); if (!mDidInitialize || mIsDestroying) { // Nothing to do here - return NS_OK; + return; } nsCOMPtr<nsIPresShell> kungFuDeathGrip(this); @@ -4465,16 +4436,14 @@ PresShell::ReconstructFrames(void) mDocument->FlushPendingNotifications(Flush_ContentAndNotify); if (mIsDestroying) { - return NS_OK; + return; } nsAutoCauseReflowNotifier crNotifier(this); mFrameConstructor->BeginUpdate(); - nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy(); + mFrameConstructor->ReconstructDocElementHierarchy(); VERIFY_STYLE_TREE; mFrameConstructor->EndUpdate(); - - return rv; } void @@ -4602,12 +4571,6 @@ PresShell::StyleRuleRemoved(StyleSheet* aStyleSheet) RecordStyleSheetChange(aStyleSheet); } -nsIFrame* -PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame) const -{ - return mFrameConstructor->GetPlaceholderFrameFor(aFrame); -} - nsresult PresShell::RenderDocument(const nsRect& aRect, uint32_t aFlags, nscolor aBackgroundColor, @@ -4759,9 +4722,11 @@ PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder, frame->GetOffsets(frameStartOffset, frameEndOffset); int32_t hilightStart = - atStart ? std::max(aRange->StartOffset(), frameStartOffset) : frameStartOffset; + atStart ? std::max(static_cast<int32_t>(aRange->StartOffset()), + frameStartOffset) : frameStartOffset; int32_t hilightEnd = - atEnd ? std::min(aRange->EndOffset(), frameEndOffset) : frameEndOffset; + atEnd ? std::min(static_cast<int32_t>(aRange->EndOffset()), + frameEndOffset) : frameEndOffset; if (hilightStart < hilightEnd) { // determine the location of the start and end edges of the range. nsPoint startPoint, endPoint; @@ -7318,12 +7283,6 @@ PresShell::HandleEvent(nsIFrame* aFrame, // if the mouse is being captured then retarget the mouse event at the // document that is being captured. retargetEventDoc = capturingContent->GetComposedDoc(); -#ifdef ANDROID - } else if ((aEvent->mClass == eTouchEventClass) || - (aEvent->mClass == eMouseEventClass) || - (aEvent->mClass == eWheelEventClass)) { - retargetEventDoc = GetTouchEventTargetDocument(); -#endif } if (retargetEventDoc) { @@ -7877,38 +7836,6 @@ PresShell::HandleEvent(nsIFrame* aFrame, return rv; } -#ifdef ANDROID -nsIDocument* -PresShell::GetTouchEventTargetDocument() -{ - nsPresContext* context = GetPresContext(); - if (!context || !context->IsRoot()) { - return nullptr; - } - - nsCOMPtr<nsIDocShellTreeItem> shellAsTreeItem = context->GetDocShell(); - if (!shellAsTreeItem) { - return nullptr; - } - - nsCOMPtr<nsIDocShellTreeOwner> owner; - shellAsTreeItem->GetTreeOwner(getter_AddRefs(owner)); - if (!owner) { - return nullptr; - } - - // now get the primary content shell (active tab) - nsCOMPtr<nsIDocShellTreeItem> item; - owner->GetPrimaryContentShell(getter_AddRefs(item)); - nsCOMPtr<nsIDocShell> childDocShell = do_QueryInterface(item); - if (!childDocShell) { - return nullptr; - } - - return childDocShell->GetDocument(); -} -#endif - #ifdef DEBUG void PresShell::ShowEventTargetDebug() diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index f20370d73..fbbcfc7ec 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=2 sw=2 et tw=78: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -130,7 +129,6 @@ public: virtual nsIPageSequenceFrame* GetPageSequenceFrame() const override; virtual nsCanvasFrame* GetCanvasFrame() const override; - virtual nsIFrame* GetPlaceholderFrameFor(nsIFrame* aFrame) const override; virtual void FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty, nsFrameState aBitToAdd, ReflowRootHandling aRootHandling = @@ -140,9 +138,7 @@ public: virtual bool IsSafeToFlush() const override; virtual void FlushPendingNotifications(mozFlushType aType) override; virtual void FlushPendingNotifications(mozilla::ChangesToFlush aType) override; - virtual void DestroyFramesFor(nsIContent* aContent, - nsIContent** aDestroyedFramesFor) override; - virtual void CreateFramesFor(nsIContent* aContent) override; + virtual void DestroyFramesForAndRestyle(mozilla::dom::Element* aElement) override; /** * Recreates the frames for a node @@ -200,7 +196,7 @@ public: virtual void NotifyCounterStylesAreDirty() override; - virtual nsresult ReconstructFrames(void) override; + virtual void ReconstructFrames(void) override; virtual void Freeze() override; virtual void Thaw() override; virtual void FireOrClearDelayedEvents(bool aFireEvents) override; @@ -759,9 +755,6 @@ protected: virtual void SysColorChanged() override { mPresContext->SysColorChanged(); } virtual void ThemeChanged() override { mPresContext->ThemeChanged(); } virtual void BackingScaleFactorChanged() override { mPresContext->UIResolutionChanged(); } -#ifdef ANDROID - virtual nsIDocument* GetTouchEventTargetDocument() override; -#endif virtual void PausePainting() override; virtual void ResumePainting() override; diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index c0d09d2a0..02838d764 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index 4e839e764..e1dd5b6a9 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsStyleSheetService.cpp b/layout/base/nsStyleSheetService.cpp index 676e46a50..722a82ed4 100644 --- a/layout/base/nsStyleSheetService.cpp +++ b/layout/base/nsStyleSheetService.cpp @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/nsStyleSheetService.h b/layout/base/nsStyleSheetService.h index 982e1a05a..1d27bf25d 100644 --- a/layout/base/nsStyleSheetService.h +++ b/layout/base/nsStyleSheetService.h @@ -1,5 +1,4 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ diff --git a/layout/base/tests/chrome/chrome.ini b/layout/base/tests/chrome/chrome.ini index 2f6ca0ba8..56454d311 100644 --- a/layout/base/tests/chrome/chrome.ini +++ b/layout/base/tests/chrome/chrome.ini @@ -1,5 +1,4 @@ [DEFAULT] -skip-if = os == 'android' support-files = animated.gif blue-32x32.png diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini index 405697977..fc616b1ef 100644 --- a/layout/base/tests/mochitest.ini +++ b/layout/base/tests/mochitest.ini @@ -1,6 +1,4 @@ [DEFAULT] -# Android: SLOW_DIRECTORY; -skip-if = toolkit == 'android' support-files = Ahem.ttf border_radius_hit_testing_iframe.html @@ -224,23 +222,18 @@ support-files = file_bug607529.html skip-if = e10s # bug 1020135, nested oop iframes not supported support-files = bug921928_event_target_iframe_apps_oop.html [test_mozPaintCount.html] -skip-if = toolkit == 'android' [test_scroll_event_ordering.html] [test_scroll_selection_into_view.html] support-files=scroll_selection_into_view_window.html [test_scroll_snapping.html] -skip-if = buildapp == 'android' # bug 1041833 [test_scroll_snapping_scrollbars.html] -skip-if = buildapp == 'android' # bug 1041833 [test_bug583889.html] support-files = bug583889_inner1.html bug583889_inner2.html [test_bug582771.html] [test_bug968148.html] support-files = bug968148_inner.html [test_bug603550.html] -skip-if = toolkit == 'android' #TIMED_OUT [test_bug629838.html] -skip-if = toolkit == 'android' [test_bug646757.html] [test_bug718809.html] [test_bug725426.html] @@ -270,13 +263,12 @@ support-files = # because of bug 469208. [test_bug332655-1.html] -skip-if = toolkit == 'android' [test_bug332655-2.html] [test_bug499538-1.html] [test_bug749186.html] [test_bug644768.html] [test_flush_on_paint.html] -skip-if = true || (toolkit == 'android') || (toolkit == "cocoa") # Bug 688128, bug 539356 +skip-if = true || (toolkit == "cocoa") # Bug 688128, bug 539356 [test_getBoxQuads_convertPointRectQuad.html] [test_bug687297.html] support-files = @@ -294,7 +286,7 @@ support-files = bug1080361_inner.html [test_bug1093686.html] support-files = bug1093686_inner.html [test_bug1120705.html] -skip-if = buildapp == 'android' || os == 'mac' || toolkit == 'gtk2' || toolkit == 'gtk3' # android does not have clickable scrollbars, mac does not have scrollbar down and up buttons, gtk may or may not have scrollbar buttons depending on theme +skip-if = os == 'mac' || toolkit == 'gtk2' || toolkit == 'gtk3' # mac does not have scrollbar down and up buttons, gtk may or may not have scrollbar buttons depending on theme [test_bug1153130.html] support-files = bug1153130_inner.html [test_bug1162990.html] diff --git a/layout/base/tests/selection-utils.js b/layout/base/tests/selection-utils.js index a14ff0d81..ed902e1cf 100644 --- a/layout/base/tests/selection-utils.js +++ b/layout/base/tests/selection-utils.js @@ -1,5 +1,4 @@ // -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- -// vim: set ts=2 sw=2 et tw=78: function clearSelection(w) { var sel = (w ? w : window).getSelection(); diff --git a/layout/base/tests/test_reftests_with_caret.html b/layout/base/tests/test_reftests_with_caret.html index d9b5d4a6c..062c605b9 100644 --- a/layout/base/tests/test_reftests_with_caret.html +++ b/layout/base/tests/test_reftests_with_caret.html @@ -189,20 +189,15 @@ var tests = [ function() {SpecialPowers.pushPrefEnv({'clear': [['layout.accessiblecaret.enabled']]}, nextTest);} , ]; -if (navigator.appVersion.indexOf("Android") == -1 && - SpecialPowers.Services.appinfo.name != "B2G") { - tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]); - tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]); - tests.push([ 'bug923376.html' , 'bug923376-ref.html' ]); - tests.push(function() {SpecialPowers.pushPrefEnv({'set': [['layout.css.overflow-clip-box.enabled', true]]}, nextTest);}); - tests.push([ 'bug966992-1.html' , 'bug966992-1-ref.html' ]); - tests.push([ 'bug966992-2.html' , 'bug966992-2-ref.html' ]); - tests.push([ 'bug966992-3.html' , 'bug966992-3-ref.html' ]); - tests.push(function() {SpecialPowers.pushPrefEnv({'clear': [['layout.css.overflow-clip-box.enabled']]}, nextTest);}); - tests.push([ 'bug1258308-1.html' , 'bug1258308-1-ref.html' ]); // maybe VK_END doesn't work on Android? -} else { - is(SpecialPowers.getIntPref("layout.spellcheckDefault"), 0, "Spellcheck should be turned off for this platform or this if..else check removed"); -} +tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]); +tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]); +tests.push([ 'bug923376.html' , 'bug923376-ref.html' ]); +tests.push(function() {SpecialPowers.pushPrefEnv({'set': [['layout.css.overflow-clip-box.enabled', true]]}, nextTest);}); +tests.push([ 'bug966992-1.html' , 'bug966992-1-ref.html' ]); +tests.push([ 'bug966992-2.html' , 'bug966992-2-ref.html' ]); +tests.push([ 'bug966992-3.html' , 'bug966992-3-ref.html' ]); +tests.push(function() {SpecialPowers.pushPrefEnv({'clear': [['layout.css.overflow-clip-box.enabled']]}, nextTest);}); +tests.push([ 'bug1258308-1.html' , 'bug1258308-1-ref.html' ]); if (navigator.platform.indexOf("Linux") >= 0 && SpecialPowers.Services.appinfo.name != "B2G") { |