layout/base/nsCSSFrameConstructor.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/base/nsCSSFrameConstructor.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,11393 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +// vim:cindent:ts=2:et:sw=2:
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/*
    1.11 + * construction of a frame tree that is nearly isomorphic to the content
    1.12 + * tree and updating of that tree in response to dynamic changes
    1.13 + */
    1.14 +
    1.15 +#include "nsCSSFrameConstructor.h"
    1.16 +
    1.17 +#include "mozilla/AutoRestore.h"
    1.18 +#include "mozilla/DebugOnly.h"
    1.19 +#include "mozilla/dom/HTMLSelectElement.h"
    1.20 +#include "mozilla/EventStates.h"
    1.21 +#include "mozilla/Likely.h"
    1.22 +#include "mozilla/LinkedList.h"
    1.23 +#include "nsAbsoluteContainingBlock.h"
    1.24 +#include "nsIAtom.h"
    1.25 +#include "nsIFrameInlines.h"
    1.26 +#include "nsGkAtoms.h"
    1.27 +#include "nsPresContext.h"
    1.28 +#include "nsIDocument.h"
    1.29 +#include "nsTableFrame.h"
    1.30 +#include "nsTableColFrame.h"
    1.31 +#include "nsIDOMHTMLDocument.h"
    1.32 +#include "nsHTMLParts.h"
    1.33 +#include "nsIPresShell.h"
    1.34 +#include "nsUnicharUtils.h"
    1.35 +#include "nsStyleSet.h"
    1.36 +#include "nsViewManager.h"
    1.37 +#include "nsStyleConsts.h"
    1.38 +#include "nsIDOMXULElement.h"
    1.39 +#include "nsContainerFrame.h"
    1.40 +#include "nsNameSpaceManager.h"
    1.41 +#include "nsIComboboxControlFrame.h"
    1.42 +#include "nsIListControlFrame.h"
    1.43 +#include "nsIDOMCharacterData.h"
    1.44 +#include "nsPlaceholderFrame.h"
    1.45 +#include "nsTableRowGroupFrame.h"
    1.46 +#include "nsIFormControl.h"
    1.47 +#include "nsCSSAnonBoxes.h"
    1.48 +#include "nsTextFragment.h"
    1.49 +#include "nsIAnonymousContentCreator.h"
    1.50 +#include "nsBindingManager.h"
    1.51 +#include "nsXBLBinding.h"
    1.52 +#include "nsContentUtils.h"
    1.53 +#include "nsIScriptError.h"
    1.54 +#ifdef XP_MACOSX
    1.55 +#include "nsIDocShell.h"
    1.56 +#endif
    1.57 +#include "ChildIterator.h"
    1.58 +#include "nsError.h"
    1.59 +#include "nsLayoutUtils.h"
    1.60 +#include "nsAutoPtr.h"
    1.61 +#include "nsBoxFrame.h"
    1.62 +#include "nsBoxLayout.h"
    1.63 +#include "nsFlexContainerFrame.h"
    1.64 +#include "nsGridContainerFrame.h"
    1.65 +#include "nsImageFrame.h"
    1.66 +#include "nsIObjectLoadingContent.h"
    1.67 +#include "nsTArray.h"
    1.68 +#include "nsGenericDOMDataNode.h"
    1.69 +#include "mozilla/dom/Element.h"
    1.70 +#include "nsAutoLayoutPhase.h"
    1.71 +#include "nsStyleStructInlines.h"
    1.72 +#include "nsPageContentFrame.h"
    1.73 +#include "RestyleManager.h"
    1.74 +#include "StickyScrollContainer.h"
    1.75 +#include "nsFieldSetFrame.h"
    1.76 +
    1.77 +#ifdef MOZ_XUL
    1.78 +#include "nsIRootBox.h"
    1.79 +#endif
    1.80 +#ifdef ACCESSIBILITY
    1.81 +#include "nsAccessibilityService.h"
    1.82 +#endif
    1.83 +
    1.84 +#include "nsBlockFrame.h"
    1.85 +
    1.86 +#include "nsIScrollableFrame.h"
    1.87 +
    1.88 +#include "nsXBLService.h"
    1.89 +
    1.90 +#undef NOISY_FIRST_LETTER
    1.91 +
    1.92 +#include "nsMathMLParts.h"
    1.93 +#include "mozilla/dom/SVGTests.h"
    1.94 +#include "nsSVGUtils.h"
    1.95 +
    1.96 +#include "nsRefreshDriver.h"
    1.97 +#include "nsRuleProcessorData.h"
    1.98 +#include "nsTextNode.h"
    1.99 +
   1.100 +using namespace mozilla;
   1.101 +using namespace mozilla::dom;
   1.102 +
   1.103 +// An alias for convenience.
   1.104 +static const nsIFrame::ChildListID kPrincipalList = nsIFrame::kPrincipalList;
   1.105 +
   1.106 +nsIFrame*
   1.107 +NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.108 +
   1.109 +nsIFrame*
   1.110 +NS_NewHTMLVideoFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.111 +
   1.112 +nsIFrame*
   1.113 +NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.114 +nsIFrame*
   1.115 +NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.116 +nsIFrame*
   1.117 +NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.118 +nsIFrame*
   1.119 +NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.120 +nsIFrame*
   1.121 +NS_NewSVGGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.122 +nsIFrame*
   1.123 +NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.124 +nsIFrame*
   1.125 +NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.126 +nsIFrame*
   1.127 +NS_NewSVGAFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.128 +nsIFrame*
   1.129 +NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.130 +nsIFrame*
   1.131 +NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.132 +nsIFrame*
   1.133 +NS_NewSVGContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.134 +nsIFrame*
   1.135 +NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.136 +nsIFrame*
   1.137 +NS_NewSVGViewFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.138 +extern nsIFrame*
   1.139 +NS_NewSVGLinearGradientFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
   1.140 +extern nsIFrame*
   1.141 +NS_NewSVGRadialGradientFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
   1.142 +extern nsIFrame*
   1.143 +NS_NewSVGStopFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
   1.144 +nsIFrame*
   1.145 +NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.146 +nsIFrame*
   1.147 +NS_NewSVGMarkerAnonChildFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.148 +extern nsIFrame*
   1.149 +NS_NewSVGImageFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
   1.150 +nsIFrame*
   1.151 +NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.152 +nsIFrame*
   1.153 +NS_NewSVGFilterFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
   1.154 +nsIFrame*
   1.155 +NS_NewSVGPatternFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.156 +nsIFrame*
   1.157 +NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.158 +nsIFrame*
   1.159 +NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.160 +nsIFrame*
   1.161 +NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.162 +nsIFrame*
   1.163 +NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.164 +nsIFrame*
   1.165 +NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.166 +
   1.167 +#include "nsINodeInfo.h"
   1.168 +#include "prenv.h"
   1.169 +#include "nsNodeInfoManager.h"
   1.170 +#include "nsContentCreatorFunctions.h"
   1.171 +
   1.172 +#ifdef DEBUG
   1.173 +// Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
   1.174 +// more of the following flags (comma separated) for handy debug
   1.175 +// output.
   1.176 +static bool gNoisyContentUpdates = false;
   1.177 +static bool gReallyNoisyContentUpdates = false;
   1.178 +static bool gNoisyInlineConstruction = false;
   1.179 +
   1.180 +struct FrameCtorDebugFlags {
   1.181 +  const char* name;
   1.182 +  bool* on;
   1.183 +};
   1.184 +
   1.185 +static FrameCtorDebugFlags gFlags[] = {
   1.186 +  { "content-updates",              &gNoisyContentUpdates },
   1.187 +  { "really-noisy-content-updates", &gReallyNoisyContentUpdates },
   1.188 +  { "noisy-inline",                 &gNoisyInlineConstruction }
   1.189 +};
   1.190 +
   1.191 +#define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
   1.192 +#endif
   1.193 +
   1.194 +
   1.195 +#ifdef MOZ_XUL
   1.196 +#include "nsMenuFrame.h"
   1.197 +#include "nsPopupSetFrame.h"
   1.198 +#include "nsTreeColFrame.h"
   1.199 +#include "nsIBoxObject.h"
   1.200 +#include "nsPIListBoxObject.h"
   1.201 +#include "nsListBoxBodyFrame.h"
   1.202 +#include "nsListItemFrame.h"
   1.203 +#include "nsXULLabelFrame.h"
   1.204 +
   1.205 +//------------------------------------------------------------------
   1.206 +
   1.207 +nsIFrame*
   1.208 +NS_NewAutoRepeatBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.209 +
   1.210 +nsIFrame*
   1.211 +NS_NewRootBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.212 +
   1.213 +nsIFrame*
   1.214 +NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.215 +
   1.216 +nsIFrame*
   1.217 +NS_NewThumbFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.218 +
   1.219 +nsIFrame*
   1.220 +NS_NewDeckFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.221 +
   1.222 +nsIFrame*
   1.223 +NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.224 +
   1.225 +nsIFrame*
   1.226 +NS_NewStackFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.227 +
   1.228 +nsIFrame*
   1.229 +NS_NewProgressMeterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.230 +
   1.231 +nsIFrame*
   1.232 +NS_NewRangeFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.233 +
   1.234 +nsIFrame*
   1.235 +NS_NewImageBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.236 +
   1.237 +nsIFrame*
   1.238 +NS_NewTextBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.239 +
   1.240 +nsIFrame*
   1.241 +NS_NewGroupBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.242 +
   1.243 +nsIFrame*
   1.244 +NS_NewButtonBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.245 +
   1.246 +nsIFrame*
   1.247 +NS_NewSplitterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.248 +
   1.249 +nsIFrame*
   1.250 +NS_NewMenuPopupFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.251 +
   1.252 +nsIFrame*
   1.253 +NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.254 +
   1.255 +nsIFrame*
   1.256 +NS_NewMenuFrame (nsIPresShell* aPresShell, nsStyleContext* aContext, uint32_t aFlags);
   1.257 +
   1.258 +nsIFrame*
   1.259 +NS_NewMenuBarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.260 +
   1.261 +nsIFrame*
   1.262 +NS_NewTreeBodyFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.263 +
   1.264 +// grid
   1.265 +nsresult
   1.266 +NS_NewGridLayout2 ( nsIPresShell* aPresShell, nsBoxLayout** aNewLayout );
   1.267 +nsIFrame*
   1.268 +NS_NewGridRowLeafFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.269 +nsIFrame*
   1.270 +NS_NewGridRowGroupFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.271 +
   1.272 +// end grid
   1.273 +
   1.274 +nsIFrame*
   1.275 +NS_NewTitleBarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.276 +
   1.277 +nsIFrame*
   1.278 +NS_NewResizerFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.279 +
   1.280 +
   1.281 +#endif
   1.282 +
   1.283 +nsIFrame*
   1.284 +NS_NewHTMLScrollFrame (nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot);
   1.285 +
   1.286 +nsIFrame*
   1.287 +NS_NewXULScrollFrame (nsIPresShell* aPresShell, nsStyleContext* aContext,
   1.288 +                      bool aIsRoot, bool aClipAllDescendants);
   1.289 +
   1.290 +nsIFrame*
   1.291 +NS_NewSliderFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.292 +
   1.293 +nsIFrame*
   1.294 +NS_NewScrollbarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.295 +
   1.296 +nsIFrame*
   1.297 +NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
   1.298 +
   1.299 +
   1.300 +#ifdef NOISY_FINDFRAME
   1.301 +static int32_t FFWC_totalCount=0;
   1.302 +static int32_t FFWC_doLoop=0;
   1.303 +static int32_t FFWC_doSibling=0;
   1.304 +static int32_t FFWC_recursions=0;
   1.305 +static int32_t FFWC_nextInFlows=0;
   1.306 +#endif
   1.307 +
   1.308 +// Returns true if aFrame is an anonymous flex item
   1.309 +static inline bool
   1.310 +IsAnonymousFlexItem(const nsIFrame* aFrame)
   1.311 +{
   1.312 +  const nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
   1.313 +  return pseudoType == nsCSSAnonBoxes::anonymousFlexItem;
   1.314 +}
   1.315 +
   1.316 +static inline nsIFrame*
   1.317 +GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
   1.318 +{
   1.319 +  // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
   1.320 +  nsIFrame* firstChild = aFieldsetFrame->GetFirstPrincipalChild();
   1.321 +  nsIFrame* inner = firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
   1.322 +  return inner ? inner->GetContentInsertionFrame() : nullptr;
   1.323 +}
   1.324 +
   1.325 +#define FCDATA_DECL(_flags, _func)                          \
   1.326 +  { _flags, { (FrameCreationFunc)_func }, nullptr, nullptr }
   1.327 +#define FCDATA_WITH_WRAPPING_BLOCK(_flags, _func, _anon_box)  \
   1.328 +  { _flags | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS,        \
   1.329 +      { (FrameCreationFunc)_func }, nullptr, &_anon_box }
   1.330 +
   1.331 +//----------------------------------------------------------------------
   1.332 +
   1.333 +/**
   1.334 + * True if aFrame is an actual inline frame in the sense of non-replaced
   1.335 + * display:inline CSS boxes.  In other words, it can be affected by {ib}
   1.336 + * splitting and can contain first-letter frames.  Basically, this is either an
   1.337 + * inline frame (positioned or otherwise) or an line frame (this last because
   1.338 + * it can contain first-letter and because inserting blocks in the middle of it
   1.339 + * needs to terminate it).
   1.340 + */
   1.341 +static bool
   1.342 +IsInlineFrame(const nsIFrame* aFrame)
   1.343 +{
   1.344 +  return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
   1.345 +}
   1.346 +
   1.347 +/**
   1.348 + * True if aFrame is an instance of an SVG frame class or is an inline/block
   1.349 + * frame being used for SVG text.
   1.350 + */
   1.351 +static bool
   1.352 +IsFrameForSVG(const nsIFrame* aFrame)
   1.353 +{
   1.354 +  return aFrame->IsFrameOfType(nsIFrame::eSVG) ||
   1.355 +         aFrame->IsSVGText();
   1.356 +}
   1.357 +
   1.358 +/**
   1.359 + * Returns true iff aFrame explicitly prevents its descendants from floating
   1.360 + * (at least, down to the level of descendants which themselves are
   1.361 + * float-containing blocks -- those will manage the floating status of any
   1.362 + * lower-level descendents inside them, of course).
   1.363 + */
   1.364 +static bool
   1.365 +ShouldSuppressFloatingOfDescendants(nsIFrame* aFrame)
   1.366 +{
   1.367 +  return aFrame->IsFrameOfType(nsIFrame::eMathML) ||
   1.368 +    aFrame->IsBoxFrame() ||
   1.369 +    aFrame->GetType() == nsGkAtoms::flexContainerFrame ||
   1.370 +    aFrame->GetType() == nsGkAtoms::gridContainerFrame;
   1.371 +}
   1.372 +
   1.373 +/**
   1.374 + * If any children require a block parent, return the first such child.
   1.375 + * Otherwise return null.
   1.376 + */
   1.377 +static nsIContent*
   1.378 +AnyKidsNeedBlockParent(nsIFrame *aFrameList)
   1.379 +{
   1.380 +  for (nsIFrame *k = aFrameList; k; k = k->GetNextSibling()) {
   1.381 +    // Line participants, such as text and inline frames, can't be
   1.382 +    // directly inside a XUL box; they must be wrapped in an
   1.383 +    // intermediate block.
   1.384 +    if (k->IsFrameOfType(nsIFrame::eLineParticipant)) {
   1.385 +      return k->GetContent();
   1.386 +    }
   1.387 +  }
   1.388 +  return nullptr;
   1.389 +}
   1.390 +
   1.391 +// Reparent a frame into a wrapper frame that is a child of its old parent.
   1.392 +static void
   1.393 +ReparentFrame(RestyleManager* aRestyleManager,
   1.394 +              nsIFrame* aNewParentFrame,
   1.395 +              nsIFrame* aFrame)
   1.396 +{
   1.397 +  aFrame->SetParent(aNewParentFrame);
   1.398 +  aRestyleManager->ReparentStyleContext(aFrame);
   1.399 +}
   1.400 +
   1.401 +static void
   1.402 +ReparentFrames(nsCSSFrameConstructor* aFrameConstructor,
   1.403 +               nsIFrame* aNewParentFrame,
   1.404 +               const nsFrameList& aFrameList)
   1.405 +{
   1.406 +  RestyleManager* restyleManager = aFrameConstructor->RestyleManager();
   1.407 +  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
   1.408 +    ReparentFrame(restyleManager, aNewParentFrame, e.get());
   1.409 +  }
   1.410 +}
   1.411 +
   1.412 +//----------------------------------------------------------------------
   1.413 +//
   1.414 +// When inline frames get weird and have block frames in them, we
   1.415 +// annotate them to help us respond to incremental content changes
   1.416 +// more easily.
   1.417 +
   1.418 +static inline bool
   1.419 +IsFramePartOfIBSplit(nsIFrame* aFrame)
   1.420 +{
   1.421 +  return (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) != 0;
   1.422 +}
   1.423 +
   1.424 +static nsIFrame* GetIBSplitSibling(nsIFrame* aFrame)
   1.425 +{
   1.426 +  NS_PRECONDITION(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
   1.427 +
   1.428 +  // We only store the "ib-split sibling" annotation with the first
   1.429 +  // frame in the continuation chain. Walk back to find that frame now.
   1.430 +  return static_cast<nsIFrame*>
   1.431 +    (aFrame->FirstContinuation()->
   1.432 +       Properties().Get(nsIFrame::IBSplitSibling()));
   1.433 +}
   1.434 +
   1.435 +static nsIFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
   1.436 +{
   1.437 +  NS_PRECONDITION(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
   1.438 +
   1.439 +  // We only store the ib-split sibling annotation with the first
   1.440 +  // frame in the continuation chain. Walk back to find that frame now.
   1.441 +  return static_cast<nsIFrame*>
   1.442 +    (aFrame->FirstContinuation()->
   1.443 +       Properties().Get(nsIFrame::IBSplitPrevSibling()));
   1.444 +}
   1.445 +
   1.446 +static nsIFrame*
   1.447 +GetLastIBSplitSibling(nsIFrame* aFrame, bool aReturnEmptyTrailingInline)
   1.448 +{
   1.449 +  for (nsIFrame *frame = aFrame, *next; ; frame = next) {
   1.450 +    next = GetIBSplitSibling(frame);
   1.451 +    if (!next ||
   1.452 +        (!aReturnEmptyTrailingInline && !next->GetFirstPrincipalChild() &&
   1.453 +         !GetIBSplitSibling(next))) {
   1.454 +      NS_ASSERTION(!next || !frame->IsInlineOutside(),
   1.455 +                   "Should have a block here!");
   1.456 +      return frame;
   1.457 +    }
   1.458 +  }
   1.459 +  NS_NOTREACHED("unreachable code");
   1.460 +  return nullptr;
   1.461 +}
   1.462 +
   1.463 +static void
   1.464 +SetFrameIsIBSplit(nsIFrame* aFrame, nsIFrame* aIBSplitSibling)
   1.465 +{
   1.466 +  NS_PRECONDITION(aFrame, "bad args!");
   1.467 +
   1.468 +  // We should be the only continuation
   1.469 +  NS_ASSERTION(!aFrame->GetPrevContinuation(),
   1.470 +               "assigning ib-split sibling to other than first continuation!");
   1.471 +  NS_ASSERTION(!aFrame->GetNextContinuation() ||
   1.472 +               IsFramePartOfIBSplit(aFrame->GetNextContinuation()),
   1.473 +               "should have no non-ib-split continuations here");
   1.474 +
   1.475 +  // Mark the frame as ib-split.
   1.476 +  aFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
   1.477 +
   1.478 +  if (aIBSplitSibling) {
   1.479 +    NS_ASSERTION(!aIBSplitSibling->GetPrevContinuation(),
   1.480 +                 "assigning something other than the first continuation as the "
   1.481 +                 "ib-split sibling");
   1.482 +
   1.483 +    // Store the ib-split sibling (if we were given one) with the
   1.484 +    // first frame in the flow.
   1.485 +    FramePropertyTable* props = aFrame->PresContext()->PropertyTable();
   1.486 +    props->Set(aFrame, nsIFrame::IBSplitSibling(), aIBSplitSibling);
   1.487 +    props->Set(aIBSplitSibling, nsIFrame::IBSplitPrevSibling(), aFrame);
   1.488 +  }
   1.489 +}
   1.490 +
   1.491 +static nsIFrame*
   1.492 +GetIBContainingBlockFor(nsIFrame* aFrame)
   1.493 +{
   1.494 +  NS_PRECONDITION(IsFramePartOfIBSplit(aFrame),
   1.495 +                  "GetIBContainingBlockFor() should only be called on known IB frames");
   1.496 +
   1.497 +  // Get the first "normal" ancestor of the target frame.
   1.498 +  nsIFrame* parentFrame;
   1.499 +  do {
   1.500 +    parentFrame = aFrame->GetParent();
   1.501 +
   1.502 +    if (! parentFrame) {
   1.503 +      NS_ERROR("no unsplit block frame in IB hierarchy");
   1.504 +      return aFrame;
   1.505 +    }
   1.506 +
   1.507 +    // Note that we ignore non-ib-split frames which have a pseudo on their
   1.508 +    // style context -- they're not the frames we're looking for!  In
   1.509 +    // particular, they may be hiding a real parent that _is_ in an ib-split.
   1.510 +    if (!IsFramePartOfIBSplit(parentFrame) &&
   1.511 +        !parentFrame->StyleContext()->GetPseudo())
   1.512 +      break;
   1.513 +
   1.514 +    aFrame = parentFrame;
   1.515 +  } while (1);
   1.516 +
   1.517 +  // post-conditions
   1.518 +  NS_ASSERTION(parentFrame, "no normal ancestor found for ib-split frame "
   1.519 +                            "in GetIBContainingBlockFor");
   1.520 +  NS_ASSERTION(parentFrame != aFrame, "parentFrame is actually the child frame - bogus reslt");
   1.521 +
   1.522 +  return parentFrame;
   1.523 +}
   1.524 +
   1.525 +//----------------------------------------------------------------------
   1.526 +
   1.527 +// Block/inline frame construction logic. We maintain a few invariants here:
   1.528 +//
   1.529 +// 1. Block frames contain block and inline frames.
   1.530 +//
   1.531 +// 2. Inline frames only contain inline frames. If an inline parent has a block
   1.532 +// child then the block child is migrated upward until it lands in a block
   1.533 +// parent (the inline frames containing block is where it will end up).
   1.534 +
   1.535 +// After this function returns, aLink is pointing to the first link at or
   1.536 +// after its starting position for which the next frame is a block.  If there
   1.537 +// is no such link, it points to the end of the list.
   1.538 +static void
   1.539 +FindFirstBlock(nsFrameList::FrameLinkEnumerator& aLink)
   1.540 +{
   1.541 +  for ( ; !aLink.AtEnd(); aLink.Next()) {
   1.542 +    if (!aLink.NextFrame()->IsInlineOutside()) {
   1.543 +      return;
   1.544 +    }
   1.545 +  }
   1.546 +}
   1.547 +
   1.548 +// This function returns a frame link enumerator pointing to the first link in
   1.549 +// the list for which the next frame is not block.  If there is no such link,
   1.550 +// it points to the end of the list.
   1.551 +static nsFrameList::FrameLinkEnumerator
   1.552 +FindFirstNonBlock(const nsFrameList& aList)
   1.553 +{
   1.554 +  nsFrameList::FrameLinkEnumerator link(aList);
   1.555 +  for (; !link.AtEnd(); link.Next()) {
   1.556 +    if (link.NextFrame()->IsInlineOutside()) {
   1.557 +      break;
   1.558 +    }
   1.559 +  }
   1.560 +  return link;
   1.561 +}
   1.562 +
   1.563 +inline void
   1.564 +SetInitialSingleChild(nsIFrame* aParent, nsIFrame* aFrame)
   1.565 +{
   1.566 +  NS_PRECONDITION(!aFrame->GetNextSibling(), "Should be using a frame list");
   1.567 +  nsFrameList temp(aFrame, aFrame);
   1.568 +  aParent->SetInitialChildList(kPrincipalList, temp);
   1.569 +}
   1.570 +
   1.571 +// -----------------------------------------------------------
   1.572 +
   1.573 +// Structure used when constructing formatting object trees.
   1.574 +struct nsFrameItems : public nsFrameList
   1.575 +{
   1.576 +  // Appends the frame to the end of the list
   1.577 +  void AddChild(nsIFrame* aChild);
   1.578 +};
   1.579 +
   1.580 +void
   1.581 +nsFrameItems::AddChild(nsIFrame* aChild)
   1.582 +{
   1.583 +  NS_PRECONDITION(aChild, "nsFrameItems::AddChild");
   1.584 +
   1.585 +  // It'd be really nice if we could just AppendFrames(kPrincipalList, aChild) here,
   1.586 +  // but some of our callers put frames that have different
   1.587 +  // parents (caption, I'm looking at you) on the same framelist, and
   1.588 +  // nsFrameList asserts if you try to do that.
   1.589 +  if (IsEmpty()) {
   1.590 +    SetFrames(aChild);
   1.591 +  }
   1.592 +  else {
   1.593 +    NS_ASSERTION(aChild != mLastChild,
   1.594 +                 "Same frame being added to frame list twice?");
   1.595 +    mLastChild->SetNextSibling(aChild);
   1.596 +    mLastChild = nsLayoutUtils::GetLastSibling(aChild);
   1.597 +  }
   1.598 +}
   1.599 +
   1.600 +// -----------------------------------------------------------
   1.601 +
   1.602 +// Structure used when constructing formatting object trees. Contains
   1.603 +// state information needed for absolutely positioned elements
   1.604 +struct nsAbsoluteItems : nsFrameItems {
   1.605 +  // containing block for absolutely positioned elements
   1.606 +  nsIFrame* containingBlock;
   1.607 +
   1.608 +  nsAbsoluteItems(nsIFrame* aContainingBlock);
   1.609 +#ifdef DEBUG
   1.610 +  // XXXbz Does this need a debug-only assignment operator that nulls out the
   1.611 +  // childList in the nsAbsoluteItems we're copying?  Introducing a difference
   1.612 +  // between debug and non-debug behavior seems bad, so I guess not...
   1.613 +  ~nsAbsoluteItems() {
   1.614 +    NS_ASSERTION(!FirstChild(),
   1.615 +                 "Dangling child list.  Someone forgot to insert it?");
   1.616 +  }
   1.617 +#endif
   1.618 +
   1.619 +  // Appends the frame to the end of the list
   1.620 +  void AddChild(nsIFrame* aChild);
   1.621 +};
   1.622 +
   1.623 +nsAbsoluteItems::nsAbsoluteItems(nsIFrame* aContainingBlock)
   1.624 +  : containingBlock(aContainingBlock)
   1.625 +{
   1.626 +}
   1.627 +
   1.628 +// Additional behavior is that it sets the frame's NS_FRAME_OUT_OF_FLOW flag
   1.629 +void
   1.630 +nsAbsoluteItems::AddChild(nsIFrame* aChild)
   1.631 +{
   1.632 +  NS_ASSERTION(aChild->PresContext()->FrameManager()->
   1.633 +               GetPlaceholderFrameFor(aChild),
   1.634 +               "Child without placeholder being added to nsAbsoluteItems?");
   1.635 +  aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW);
   1.636 +  nsFrameItems::AddChild(aChild);
   1.637 +}
   1.638 +
   1.639 +// -----------------------------------------------------------
   1.640 +
   1.641 +// Structure for saving the existing state when pushing/poping containing
   1.642 +// blocks. The destructor restores the state to its previous state
   1.643 +class MOZ_STACK_CLASS nsFrameConstructorSaveState {
   1.644 +public:
   1.645 +  typedef nsIFrame::ChildListID ChildListID;
   1.646 +  nsFrameConstructorSaveState();
   1.647 +  ~nsFrameConstructorSaveState();
   1.648 +
   1.649 +private:
   1.650 +  nsAbsoluteItems* mItems;      // pointer to struct whose data we save/restore
   1.651 +  nsAbsoluteItems  mSavedItems; // copy of original data
   1.652 +
   1.653 +  // The name of the child list in which our frames would belong
   1.654 +  ChildListID mChildListID;
   1.655 +  nsFrameConstructorState* mState;
   1.656 +
   1.657 +  // State used only when we're saving the abs-pos state for a transformed
   1.658 +  // element.
   1.659 +  nsAbsoluteItems mSavedFixedItems;
   1.660 +
   1.661 +  bool mSavedFixedPosIsAbsPos;
   1.662 +
   1.663 +  friend class nsFrameConstructorState;
   1.664 +};
   1.665 +
   1.666 +// Structure used to keep track of a list of bindings we need to call
   1.667 +// AddToAttachedQueue on.  These should be in post-order depth-first
   1.668 +// flattened tree traversal order.
   1.669 +struct PendingBinding : public LinkedListElement<PendingBinding>
   1.670 +{
   1.671 +#ifdef NS_BUILD_REFCNT_LOGGING
   1.672 +  PendingBinding() {
   1.673 +    MOZ_COUNT_CTOR(PendingBinding);
   1.674 +  }
   1.675 +  ~PendingBinding() {
   1.676 +    MOZ_COUNT_DTOR(PendingBinding);
   1.677 +  }
   1.678 +#endif
   1.679 +
   1.680 +  nsRefPtr<nsXBLBinding> mBinding;
   1.681 +};
   1.682 +
   1.683 +// Structure used for maintaining state information during the
   1.684 +// frame construction process
   1.685 +class MOZ_STACK_CLASS nsFrameConstructorState {
   1.686 +public:
   1.687 +  typedef nsIFrame::ChildListID ChildListID;
   1.688 +
   1.689 +  nsPresContext            *mPresContext;
   1.690 +  nsIPresShell             *mPresShell;
   1.691 +  nsFrameManager           *mFrameManager;
   1.692 +
   1.693 +#ifdef MOZ_XUL
   1.694 +  // Frames destined for the kPopupList.
   1.695 +  nsAbsoluteItems           mPopupItems;
   1.696 +#endif
   1.697 +
   1.698 +  // Containing block information for out-of-flow frames.
   1.699 +  nsAbsoluteItems           mFixedItems;
   1.700 +  nsAbsoluteItems           mAbsoluteItems;
   1.701 +  nsAbsoluteItems           mFloatedItems;
   1.702 +
   1.703 +  nsCOMPtr<nsILayoutHistoryState> mFrameState;
   1.704 +  // These bits will be added to the state bits of any frame we construct
   1.705 +  // using this state.
   1.706 +  nsFrameState              mAdditionalStateBits;
   1.707 +
   1.708 +  // When working with the -moz-transform property, we want to hook
   1.709 +  // the abs-pos and fixed-pos lists together, since transformed
   1.710 +  // elements are fixed-pos containing blocks.  This flag determines
   1.711 +  // whether or not we want to wire the fixed-pos and abs-pos lists
   1.712 +  // together.
   1.713 +  bool                      mFixedPosIsAbsPos;
   1.714 +
   1.715 +  // A boolean to indicate whether we have a "pending" popupgroup.  That is, we
   1.716 +  // have already created the FrameConstructionItem for the root popupgroup but
   1.717 +  // we have not yet created the relevant frame.
   1.718 +  bool                      mHavePendingPopupgroup;
   1.719 +
   1.720 +  // If false (which is the default) then call SetPrimaryFrame() as needed
   1.721 +  // during frame construction.  If true, don't make any SetPrimaryFrame()
   1.722 +  // calls, except for generated content which doesn't have a primary frame
   1.723 +  // yet.  The mCreatingExtraFrames == true mode is meant to be used for
   1.724 +  // construction of random "extra" frames for elements via normal frame
   1.725 +  // construction APIs (e.g. replication of things across pages in paginated
   1.726 +  // mode).
   1.727 +  bool                      mCreatingExtraFrames;
   1.728 +
   1.729 +  nsCOMArray<nsIContent>    mGeneratedTextNodesWithInitializer;
   1.730 +
   1.731 +  TreeMatchContext          mTreeMatchContext;
   1.732 +
   1.733 +  // Constructor
   1.734 +  // Use the passed-in history state.
   1.735 +  nsFrameConstructorState(nsIPresShell*          aPresShell,
   1.736 +                          nsIFrame*              aFixedContainingBlock,
   1.737 +                          nsIFrame*              aAbsoluteContainingBlock,
   1.738 +                          nsIFrame*              aFloatContainingBlock,
   1.739 +                          nsILayoutHistoryState* aHistoryState);
   1.740 +  // Get the history state from the pres context's pres shell.
   1.741 +  nsFrameConstructorState(nsIPresShell*          aPresShell,
   1.742 +                          nsIFrame*              aFixedContainingBlock,
   1.743 +                          nsIFrame*              aAbsoluteContainingBlock,
   1.744 +                          nsIFrame*              aFloatContainingBlock);
   1.745 +
   1.746 +  ~nsFrameConstructorState();
   1.747 +
   1.748 +  // Function to push the existing absolute containing block state and
   1.749 +  // create a new scope. Code that uses this function should get matching
   1.750 +  // logic in GetAbsoluteContainingBlock.
   1.751 +  // Also makes aNewAbsoluteContainingBlock the containing block for
   1.752 +  // fixed-pos elements if necessary.
   1.753 +  // aPositionedFrame is the frame whose style actually makes
   1.754 +  // aNewAbsoluteContainingBlock a containing block. E.g. for a scrollable element
   1.755 +  // aPositionedFrame is the element's primary frame and
   1.756 +  // aNewAbsoluteContainingBlock is the scrolled frame.
   1.757 +  void PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
   1.758 +                                   nsIFrame* aPositionedFrame,
   1.759 +                                   nsFrameConstructorSaveState& aSaveState);
   1.760 +
   1.761 +  // Function to push the existing float containing block state and
   1.762 +  // create a new scope. Code that uses this function should get matching
   1.763 +  // logic in GetFloatContainingBlock.
   1.764 +  // Pushing a null float containing block forbids any frames from being
   1.765 +  // floated until a new float containing block is pushed.
   1.766 +  // XXX we should get rid of null float containing blocks and teach the
   1.767 +  // various frame classes to deal with floats instead.
   1.768 +  void PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
   1.769 +                                nsFrameConstructorSaveState& aSaveState);
   1.770 +
   1.771 +  // Function to return the proper geometric parent for a frame with display
   1.772 +  // struct given by aStyleDisplay and parent's frame given by
   1.773 +  // aContentParentFrame.
   1.774 +  nsIFrame* GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
   1.775 +                               nsIFrame* aContentParentFrame) const;
   1.776 +
   1.777 +  /**
   1.778 +   * Function to add a new frame to the right frame list.  This MUST be called
   1.779 +   * on frames before their children have been processed if the frames might
   1.780 +   * conceivably be out-of-flow; otherwise cleanup in error cases won't work
   1.781 +   * right.  Also, this MUST be called on frames after they have been
   1.782 +   * initialized.
   1.783 +   * @param aNewFrame the frame to add
   1.784 +   * @param aFrameItems the list to add in-flow frames to
   1.785 +   * @param aContent the content pointer for aNewFrame
   1.786 +   * @param aStyleContext the style context resolved for aContent
   1.787 +   * @param aParentFrame the parent frame for the content if it were in-flow
   1.788 +   * @param aCanBePositioned pass false if the frame isn't allowed to be
   1.789 +   *        positioned
   1.790 +   * @param aCanBeFloated pass false if the frame isn't allowed to be
   1.791 +   *        floated
   1.792 +   * @param aIsOutOfFlowPopup pass true if the frame is an out-of-flow popup
   1.793 +   *        (XUL-only)
   1.794 +   */
   1.795 +  void AddChild(nsIFrame* aNewFrame,
   1.796 +                nsFrameItems& aFrameItems,
   1.797 +                nsIContent* aContent,
   1.798 +                nsStyleContext* aStyleContext,
   1.799 +                nsIFrame* aParentFrame,
   1.800 +                bool aCanBePositioned = true,
   1.801 +                bool aCanBeFloated = true,
   1.802 +                bool aIsOutOfFlowPopup = false,
   1.803 +                bool aInsertAfter = false,
   1.804 +                nsIFrame* aInsertAfterFrame = nullptr);
   1.805 +
   1.806 +  /**
   1.807 +   * Function to return the fixed-pos element list.  Normally this will just hand back the
   1.808 +   * fixed-pos element list, but in case we're dealing with a transformed element that's
   1.809 +   * acting as an abs-pos and fixed-pos container, we'll hand back the abs-pos list.  Callers should
   1.810 +   * use this function if they want to get the list acting as the fixed-pos item parent.
   1.811 +   */
   1.812 +  nsAbsoluteItems& GetFixedItems()
   1.813 +  {
   1.814 +    return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
   1.815 +  }
   1.816 +  const nsAbsoluteItems& GetFixedItems() const
   1.817 +  {
   1.818 +    return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
   1.819 +  }
   1.820 +
   1.821 +
   1.822 +  /**
   1.823 +   * class to automatically push and pop a pending binding in the frame
   1.824 +   * constructor state.  See nsCSSFrameConstructor::FrameConstructionItem
   1.825 +   * mPendingBinding documentation.
   1.826 +   */
   1.827 +  class PendingBindingAutoPusher;
   1.828 +  friend class PendingBindingAutoPusher;
   1.829 +  class MOZ_STACK_CLASS PendingBindingAutoPusher {
   1.830 +  public:
   1.831 +    PendingBindingAutoPusher(nsFrameConstructorState& aState,
   1.832 +                             PendingBinding* aPendingBinding) :
   1.833 +      mState(aState),
   1.834 +      mPendingBinding(aState.mCurrentPendingBindingInsertionPoint)
   1.835 +        {
   1.836 +          if (aPendingBinding) {
   1.837 +            aState.mCurrentPendingBindingInsertionPoint = aPendingBinding;
   1.838 +          }
   1.839 +        }
   1.840 +
   1.841 +    ~PendingBindingAutoPusher()
   1.842 +      {
   1.843 +        mState.mCurrentPendingBindingInsertionPoint = mPendingBinding;
   1.844 +      }
   1.845 +
   1.846 +  private:
   1.847 +    nsFrameConstructorState& mState;
   1.848 +    PendingBinding* mPendingBinding;
   1.849 +  };
   1.850 +
   1.851 +  /**
   1.852 +   * Add a new pending binding to the list
   1.853 +   */
   1.854 +  void AddPendingBinding(PendingBinding* aPendingBinding) {
   1.855 +    if (mCurrentPendingBindingInsertionPoint) {
   1.856 +      mCurrentPendingBindingInsertionPoint->setPrevious(aPendingBinding);
   1.857 +    } else {
   1.858 +      mPendingBindings.insertBack(aPendingBinding);
   1.859 +    }
   1.860 +  }
   1.861 +
   1.862 +protected:
   1.863 +  friend class nsFrameConstructorSaveState;
   1.864 +
   1.865 +  /**
   1.866 +   * ProcessFrameInsertions takes the frames in aFrameItems and adds them as
   1.867 +   * kids to the aChildListID child list of |aFrameItems.containingBlock|.
   1.868 +   */
   1.869 +  void ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
   1.870 +                              ChildListID aChildListID);
   1.871 +
   1.872 +  // Our list of all pending bindings.  When we're done, we need to call
   1.873 +  // AddToAttachedQueue on all of them, in order.
   1.874 +  LinkedList<PendingBinding> mPendingBindings;
   1.875 +
   1.876 +  PendingBinding* mCurrentPendingBindingInsertionPoint;
   1.877 +};
   1.878 +
   1.879 +nsFrameConstructorState::nsFrameConstructorState(nsIPresShell*          aPresShell,
   1.880 +                                                 nsIFrame*              aFixedContainingBlock,
   1.881 +                                                 nsIFrame*              aAbsoluteContainingBlock,
   1.882 +                                                 nsIFrame*              aFloatContainingBlock,
   1.883 +                                                 nsILayoutHistoryState* aHistoryState)
   1.884 +  : mPresContext(aPresShell->GetPresContext()),
   1.885 +    mPresShell(aPresShell),
   1.886 +    mFrameManager(aPresShell->FrameManager()),
   1.887 +#ifdef MOZ_XUL
   1.888 +    mPopupItems(nullptr),
   1.889 +#endif
   1.890 +    mFixedItems(aFixedContainingBlock),
   1.891 +    mAbsoluteItems(aAbsoluteContainingBlock),
   1.892 +    mFloatedItems(aFloatContainingBlock),
   1.893 +    // See PushAbsoluteContaningBlock below
   1.894 +    mFrameState(aHistoryState),
   1.895 +    mAdditionalStateBits(nsFrameState(0)),
   1.896 +    // If the fixed-pos containing block is equal to the abs-pos containing
   1.897 +    // block, use the abs-pos containing block's abs-pos list for fixed-pos
   1.898 +	// frames.
   1.899 +    mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
   1.900 +    mHavePendingPopupgroup(false),
   1.901 +    mCreatingExtraFrames(false),
   1.902 +    mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited,
   1.903 +                      aPresShell->GetDocument()),
   1.904 +    mCurrentPendingBindingInsertionPoint(nullptr)
   1.905 +{
   1.906 +#ifdef MOZ_XUL
   1.907 +  nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
   1.908 +  if (rootBox) {
   1.909 +    mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
   1.910 +  }
   1.911 +#endif
   1.912 +  MOZ_COUNT_CTOR(nsFrameConstructorState);
   1.913 +}
   1.914 +
   1.915 +nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
   1.916 +                                                 nsIFrame*     aFixedContainingBlock,
   1.917 +                                                 nsIFrame*     aAbsoluteContainingBlock,
   1.918 +                                                 nsIFrame*     aFloatContainingBlock)
   1.919 +  : mPresContext(aPresShell->GetPresContext()),
   1.920 +    mPresShell(aPresShell),
   1.921 +    mFrameManager(aPresShell->FrameManager()),
   1.922 +#ifdef MOZ_XUL
   1.923 +    mPopupItems(nullptr),
   1.924 +#endif
   1.925 +    mFixedItems(aFixedContainingBlock),
   1.926 +    mAbsoluteItems(aAbsoluteContainingBlock),
   1.927 +    mFloatedItems(aFloatContainingBlock),
   1.928 +    // See PushAbsoluteContaningBlock below
   1.929 +    mAdditionalStateBits(nsFrameState(0)),
   1.930 +    // If the fixed-pos containing block is equal to the abs-pos containing
   1.931 +    // block, use the abs-pos containing block's abs-pos list for fixed-pos
   1.932 +	// frames.
   1.933 +    mFixedPosIsAbsPos(aFixedContainingBlock == aAbsoluteContainingBlock),
   1.934 +    mHavePendingPopupgroup(false),
   1.935 +    mCreatingExtraFrames(false),
   1.936 +    mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited,
   1.937 +                      aPresShell->GetDocument()),
   1.938 +    mCurrentPendingBindingInsertionPoint(nullptr)
   1.939 +{
   1.940 +#ifdef MOZ_XUL
   1.941 +  nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
   1.942 +  if (rootBox) {
   1.943 +    mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
   1.944 +  }
   1.945 +#endif
   1.946 +  MOZ_COUNT_CTOR(nsFrameConstructorState);
   1.947 +  mFrameState = aPresShell->GetDocument()->GetLayoutHistoryState();
   1.948 +}
   1.949 +
   1.950 +nsFrameConstructorState::~nsFrameConstructorState()
   1.951 +{
   1.952 +  // Frame order comparison functions only work properly when the placeholders
   1.953 +  // have been inserted into the frame tree. So for example if we have a new float
   1.954 +  // containing the placeholder for a new abs-pos frame, and we process the abs-pos
   1.955 +  // insertion first, then we won't be able to find the right place to insert in
   1.956 +  // in the abs-pos list. So put floats in first, because they can contain placeholders
   1.957 +  // for abs-pos and fixed-pos items whose containing blocks are outside the floats.
   1.958 +  // Then put abs-pos frames in, because they can contain placeholders for fixed-pos
   1.959 +  // items whose containing block is outside the abs-pos frames.
   1.960 +  MOZ_COUNT_DTOR(nsFrameConstructorState);
   1.961 +  ProcessFrameInsertions(mFloatedItems, nsIFrame::kFloatList);
   1.962 +  ProcessFrameInsertions(mAbsoluteItems, nsIFrame::kAbsoluteList);
   1.963 +  ProcessFrameInsertions(mFixedItems, nsIFrame::kFixedList);
   1.964 +#ifdef MOZ_XUL
   1.965 +  ProcessFrameInsertions(mPopupItems, nsIFrame::kPopupList);
   1.966 +#endif
   1.967 +  for (int32_t i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
   1.968 +    mGeneratedTextNodesWithInitializer[i]->
   1.969 +      DeleteProperty(nsGkAtoms::genConInitializerProperty);
   1.970 +  }
   1.971 +  if (!mPendingBindings.isEmpty()) {
   1.972 +    nsBindingManager* bindingManager = mPresShell->GetDocument()->BindingManager();
   1.973 +    do {
   1.974 +      nsAutoPtr<PendingBinding> pendingBinding;
   1.975 +      pendingBinding = mPendingBindings.popFirst();
   1.976 +      bindingManager->AddToAttachedQueue(pendingBinding->mBinding);
   1.977 +    } while (!mPendingBindings.isEmpty());
   1.978 +    mCurrentPendingBindingInsertionPoint = nullptr;
   1.979 +  }
   1.980 +}
   1.981 +
   1.982 +static nsIFrame*
   1.983 +AdjustAbsoluteContainingBlock(nsIFrame* aContainingBlockIn)
   1.984 +{
   1.985 +  if (!aContainingBlockIn) {
   1.986 +    return nullptr;
   1.987 +  }
   1.988 +
   1.989 +  // Always use the container's first continuation. (Inline frames can have
   1.990 +  // non-fluid bidi continuations...)
   1.991 +  return aContainingBlockIn->FirstContinuation();
   1.992 +}
   1.993 +
   1.994 +void
   1.995 +nsFrameConstructorState::PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
   1.996 +                                                     nsIFrame* aPositionedFrame,
   1.997 +                                                     nsFrameConstructorSaveState& aSaveState)
   1.998 +{
   1.999 +  aSaveState.mItems = &mAbsoluteItems;
  1.1000 +  aSaveState.mSavedItems = mAbsoluteItems;
  1.1001 +  aSaveState.mChildListID = nsIFrame::kAbsoluteList;
  1.1002 +  aSaveState.mState = this;
  1.1003 +  aSaveState.mSavedFixedPosIsAbsPos = mFixedPosIsAbsPos;
  1.1004 +
  1.1005 +  if (mFixedPosIsAbsPos) {
  1.1006 +    // Since we're going to replace mAbsoluteItems, we need to save it into
  1.1007 +    // mFixedItems now (and save the current value of mFixedItems).
  1.1008 +    aSaveState.mSavedFixedItems = mFixedItems;
  1.1009 +    mFixedItems = mAbsoluteItems;
  1.1010 +  }
  1.1011 +
  1.1012 +  mAbsoluteItems =
  1.1013 +    nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
  1.1014 +
  1.1015 +  /* See if we're wiring the fixed-pos and abs-pos lists together.  This happens iff
  1.1016 +   * we're a transformed element.
  1.1017 +   */
  1.1018 +  mFixedPosIsAbsPos = aPositionedFrame &&
  1.1019 +      (aPositionedFrame->StyleDisplay()->HasTransform(aPositionedFrame) ||
  1.1020 +       aPositionedFrame->StyleDisplay()->HasPerspectiveStyle());
  1.1021 +
  1.1022 +  if (aNewAbsoluteContainingBlock) {
  1.1023 +    aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
  1.1024 +  }
  1.1025 +}
  1.1026 +
  1.1027 +void
  1.1028 +nsFrameConstructorState::PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
  1.1029 +                                                  nsFrameConstructorSaveState& aSaveState)
  1.1030 +{
  1.1031 +  NS_PRECONDITION(!aNewFloatContainingBlock ||
  1.1032 +                  aNewFloatContainingBlock->IsFloatContainingBlock(),
  1.1033 +                  "Please push a real float containing block!");
  1.1034 +  NS_ASSERTION(!aNewFloatContainingBlock ||
  1.1035 +               !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock),
  1.1036 +               "We should not push a frame that is supposed to _suppress_ "
  1.1037 +               "floats as a float containing block!");
  1.1038 +  aSaveState.mItems = &mFloatedItems;
  1.1039 +  aSaveState.mSavedItems = mFloatedItems;
  1.1040 +  aSaveState.mChildListID = nsIFrame::kFloatList;
  1.1041 +  aSaveState.mState = this;
  1.1042 +  mFloatedItems = nsAbsoluteItems(aNewFloatContainingBlock);
  1.1043 +}
  1.1044 +
  1.1045 +nsIFrame*
  1.1046 +nsFrameConstructorState::GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
  1.1047 +                                            nsIFrame* aContentParentFrame) const
  1.1048 +{
  1.1049 +  NS_PRECONDITION(aStyleDisplay, "Must have display struct!");
  1.1050 +
  1.1051 +  // If there is no container for a fixed, absolute, or floating root
  1.1052 +  // frame, we will ignore the positioning.  This hack is originally
  1.1053 +  // brought to you by the letter T: tables, since other roots don't
  1.1054 +  // even call into this code.  See bug 178855.
  1.1055 +  //
  1.1056 +  // XXX Disabling positioning in this case is a hack.  If one was so inclined,
  1.1057 +  // one could support this either by (1) inserting a dummy block between the
  1.1058 +  // table and the canvas or (2) teaching the canvas how to reflow positioned
  1.1059 +  // elements. (1) has the usual problems when multiple frames share the same
  1.1060 +  // content (notice all the special cases in this file dealing with inner
  1.1061 +  // tables and outer tables which share the same content). (2) requires some
  1.1062 +  // work and possible factoring.
  1.1063 +  //
  1.1064 +  // XXXbz couldn't we just force position to "static" on roots and
  1.1065 +  // float to "none"?  That's OK per CSS 2.1, as far as I can tell.
  1.1066 +
  1.1067 +  if (aContentParentFrame && aContentParentFrame->IsSVGText()) {
  1.1068 +    return aContentParentFrame;
  1.1069 +  }
  1.1070 +
  1.1071 +  if (aStyleDisplay->IsFloatingStyle() && mFloatedItems.containingBlock) {
  1.1072 +    NS_ASSERTION(!aStyleDisplay->IsAbsolutelyPositionedStyle(),
  1.1073 +                 "Absolutely positioned _and_ floating?");
  1.1074 +    return mFloatedItems.containingBlock;
  1.1075 +  }
  1.1076 +
  1.1077 +  if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
  1.1078 +      mAbsoluteItems.containingBlock) {
  1.1079 +    return mAbsoluteItems.containingBlock;
  1.1080 +  }
  1.1081 +
  1.1082 +  if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
  1.1083 +      GetFixedItems().containingBlock) {
  1.1084 +    return GetFixedItems().containingBlock;
  1.1085 +  }
  1.1086 +
  1.1087 +  return aContentParentFrame;
  1.1088 +}
  1.1089 +
  1.1090 +void
  1.1091 +nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
  1.1092 +                                  nsFrameItems& aFrameItems,
  1.1093 +                                  nsIContent* aContent,
  1.1094 +                                  nsStyleContext* aStyleContext,
  1.1095 +                                  nsIFrame* aParentFrame,
  1.1096 +                                  bool aCanBePositioned,
  1.1097 +                                  bool aCanBeFloated,
  1.1098 +                                  bool aIsOutOfFlowPopup,
  1.1099 +                                  bool aInsertAfter,
  1.1100 +                                  nsIFrame* aInsertAfterFrame)
  1.1101 +{
  1.1102 +  NS_PRECONDITION(!aNewFrame->GetNextSibling(), "Shouldn't happen");
  1.1103 +
  1.1104 +  const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
  1.1105 +
  1.1106 +  // The comments in GetGeometricParent regarding root table frames
  1.1107 +  // all apply here, unfortunately.
  1.1108 +
  1.1109 +  bool needPlaceholder = false;
  1.1110 +  nsFrameState placeholderType;
  1.1111 +  nsFrameItems* frameItems = &aFrameItems;
  1.1112 +#ifdef MOZ_XUL
  1.1113 +  if (MOZ_UNLIKELY(aIsOutOfFlowPopup)) {
  1.1114 +      NS_ASSERTION(aNewFrame->GetParent() == mPopupItems.containingBlock,
  1.1115 +                   "Popup whose parent is not the popup containing block?");
  1.1116 +      NS_ASSERTION(mPopupItems.containingBlock, "Must have a popup set frame!");
  1.1117 +      needPlaceholder = true;
  1.1118 +      frameItems = &mPopupItems;
  1.1119 +      placeholderType = PLACEHOLDER_FOR_POPUP;
  1.1120 +  }
  1.1121 +  else
  1.1122 +#endif // MOZ_XUL
  1.1123 +  if (aCanBeFloated && aNewFrame->IsFloating() &&
  1.1124 +      mFloatedItems.containingBlock) {
  1.1125 +    NS_ASSERTION(aNewFrame->GetParent() == mFloatedItems.containingBlock,
  1.1126 +                 "Float whose parent is not the float containing block?");
  1.1127 +    needPlaceholder = true;
  1.1128 +    frameItems = &mFloatedItems;
  1.1129 +    placeholderType = PLACEHOLDER_FOR_FLOAT;
  1.1130 +  }
  1.1131 +  else if (aCanBePositioned) {
  1.1132 +    if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
  1.1133 +        mAbsoluteItems.containingBlock) {
  1.1134 +      NS_ASSERTION(aNewFrame->GetParent() == mAbsoluteItems.containingBlock,
  1.1135 +                   "Abs pos whose parent is not the abs pos containing block?");
  1.1136 +      needPlaceholder = true;
  1.1137 +      frameItems = &mAbsoluteItems;
  1.1138 +      placeholderType = PLACEHOLDER_FOR_ABSPOS;
  1.1139 +    }
  1.1140 +    if (disp->mPosition == NS_STYLE_POSITION_FIXED &&
  1.1141 +        GetFixedItems().containingBlock) {
  1.1142 +      NS_ASSERTION(aNewFrame->GetParent() == GetFixedItems().containingBlock,
  1.1143 +                   "Fixed pos whose parent is not the fixed pos containing block?");
  1.1144 +      needPlaceholder = true;
  1.1145 +      frameItems = &GetFixedItems();
  1.1146 +      placeholderType = PLACEHOLDER_FOR_FIXEDPOS;
  1.1147 +    }
  1.1148 +  }
  1.1149 +
  1.1150 +  if (needPlaceholder) {
  1.1151 +    NS_ASSERTION(frameItems != &aFrameItems,
  1.1152 +                 "Putting frame in-flow _and_ want a placeholder?");
  1.1153 +    nsIFrame* placeholderFrame =
  1.1154 +      nsCSSFrameConstructor::CreatePlaceholderFrameFor(mPresShell,
  1.1155 +                                                       aContent,
  1.1156 +                                                       aNewFrame,
  1.1157 +                                                       aStyleContext,
  1.1158 +                                                       aParentFrame,
  1.1159 +                                                       nullptr,
  1.1160 +                                                       placeholderType);
  1.1161 +
  1.1162 +    placeholderFrame->AddStateBits(mAdditionalStateBits);
  1.1163 +    // Add the placeholder frame to the flow
  1.1164 +    aFrameItems.AddChild(placeholderFrame);
  1.1165 +  }
  1.1166 +#ifdef DEBUG
  1.1167 +  else {
  1.1168 +    NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,
  1.1169 +                 "In-flow frame has wrong parent");
  1.1170 +  }
  1.1171 +#endif
  1.1172 +
  1.1173 +  if (aInsertAfter) {
  1.1174 +    frameItems->InsertFrame(nullptr, aInsertAfterFrame, aNewFrame);
  1.1175 +  } else {
  1.1176 +    frameItems->AddChild(aNewFrame);
  1.1177 +  }
  1.1178 +}
  1.1179 +
  1.1180 +void
  1.1181 +nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
  1.1182 +                                                ChildListID aChildListID)
  1.1183 +{
  1.1184 +#define NS_NONXUL_LIST_TEST (&aFrameItems == &mFloatedItems &&            \
  1.1185 +                             aChildListID == nsIFrame::kFloatList)    ||  \
  1.1186 +                            (&aFrameItems == &mAbsoluteItems &&           \
  1.1187 +                             aChildListID == nsIFrame::kAbsoluteList) ||  \
  1.1188 +                            (&aFrameItems == &mFixedItems &&              \
  1.1189 +                             aChildListID == nsIFrame::kFixedList)
  1.1190 +#ifdef MOZ_XUL
  1.1191 +  NS_PRECONDITION(NS_NONXUL_LIST_TEST ||
  1.1192 +                  (&aFrameItems == &mPopupItems &&
  1.1193 +                   aChildListID == nsIFrame::kPopupList),
  1.1194 +                  "Unexpected aFrameItems/aChildListID combination");
  1.1195 +#else
  1.1196 +  NS_PRECONDITION(NS_NONXUL_LIST_TEST,
  1.1197 +                  "Unexpected aFrameItems/aChildListID combination");
  1.1198 +#endif
  1.1199 +
  1.1200 +  if (aFrameItems.IsEmpty()) {
  1.1201 +    return;
  1.1202 +  }
  1.1203 +
  1.1204 +  nsIFrame* containingBlock = aFrameItems.containingBlock;
  1.1205 +
  1.1206 +  NS_ASSERTION(containingBlock,
  1.1207 +               "Child list without containing block?");
  1.1208 +
  1.1209 +  if (aChildListID == nsIFrame::kFixedList) {
  1.1210 +    // Put this frame on the transformed-frame's abs-pos list instead, if
  1.1211 +    // it has abs-pos children instead of fixed-pos children.
  1.1212 +    aChildListID = containingBlock->GetAbsoluteListID();
  1.1213 +  }
  1.1214 +
  1.1215 +  // Insert the frames hanging out in aItems.  We can use SetInitialChildList()
  1.1216 +  // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
  1.1217 +  // is set) and doesn't have any frames in the aChildListID child list yet.
  1.1218 +  const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
  1.1219 +  DebugOnly<nsresult> rv = NS_OK;
  1.1220 +  if (childList.IsEmpty() &&
  1.1221 +      (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
  1.1222 +    // If we're injecting absolutely positioned frames, inject them on the
  1.1223 +    // absolute containing block
  1.1224 +    if (aChildListID == containingBlock->GetAbsoluteListID()) {
  1.1225 +      rv = containingBlock->GetAbsoluteContainingBlock()->
  1.1226 +           SetInitialChildList(containingBlock, aChildListID, aFrameItems);
  1.1227 +    } else {
  1.1228 +      rv = containingBlock->SetInitialChildList(aChildListID, aFrameItems);
  1.1229 +    }
  1.1230 +  } else {
  1.1231 +    // Note that whether the frame construction context is doing an append or
  1.1232 +    // not is not helpful here, since it could be appending to some frame in
  1.1233 +    // the middle of the document, which means we're not necessarily
  1.1234 +    // appending to the children of the containing block.
  1.1235 +    //
  1.1236 +    // We need to make sure the 'append to the end of document' case is fast.
  1.1237 +    // So first test the last child of the containing block
  1.1238 +    nsIFrame* lastChild = childList.LastChild();
  1.1239 +
  1.1240 +    // CompareTreePosition uses placeholder hierarchy for out of flow frames,
  1.1241 +    // so this will make out-of-flows respect the ordering of placeholders,
  1.1242 +    // which is great because it takes care of anonymous content.
  1.1243 +    nsIFrame* firstNewFrame = aFrameItems.FirstChild();
  1.1244 +
  1.1245 +    // Cache the ancestor chain so that we can reuse it if needed.
  1.1246 +    nsAutoTArray<nsIFrame*, 20> firstNewFrameAncestors;
  1.1247 +    nsIFrame* notCommonAncestor = nullptr;
  1.1248 +    if (lastChild) {
  1.1249 +      notCommonAncestor = nsLayoutUtils::FillAncestors(firstNewFrame,
  1.1250 +                                                       containingBlock,
  1.1251 +                                                       &firstNewFrameAncestors);
  1.1252 +    }
  1.1253 +
  1.1254 +    if (!lastChild ||
  1.1255 +        nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame,
  1.1256 +                                           firstNewFrameAncestors,
  1.1257 +                                           notCommonAncestor ?
  1.1258 +                                             containingBlock : nullptr) < 0) {
  1.1259 +      // no lastChild, or lastChild comes before the new children, so just append
  1.1260 +      rv = mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
  1.1261 +    } else {
  1.1262 +      // Try the other children. First collect them to an array so that a
  1.1263 +      // reasonable fast binary search can be used to find the insertion point.
  1.1264 +      nsAutoTArray<nsIFrame*, 128> children;
  1.1265 +      for (nsIFrame* f = childList.FirstChild(); f != lastChild;
  1.1266 +           f = f->GetNextSibling()) {
  1.1267 +        children.AppendElement(f);
  1.1268 +      }
  1.1269 +
  1.1270 +      nsIFrame* insertionPoint = nullptr;
  1.1271 +      int32_t imin = 0;
  1.1272 +      int32_t max = children.Length();
  1.1273 +      while (max > imin) {
  1.1274 +        int32_t imid = imin + ((max - imin) / 2);
  1.1275 +        nsIFrame* f = children[imid];
  1.1276 +        int32_t compare =
  1.1277 +          nsLayoutUtils::CompareTreePosition(f, firstNewFrame, firstNewFrameAncestors,
  1.1278 +                                             notCommonAncestor ? containingBlock : nullptr);
  1.1279 +        if (compare > 0) {
  1.1280 +          // f is after the new frame.
  1.1281 +          max = imid;
  1.1282 +          insertionPoint = imid > 0 ? children[imid - 1] : nullptr;
  1.1283 +        } else if (compare < 0) {
  1.1284 +          // f is before the new frame.
  1.1285 +          imin = imid + 1;
  1.1286 +          insertionPoint = f;
  1.1287 +        } else {
  1.1288 +          // This is for the old behavior. Should be removed once it is
  1.1289 +          // guaranteed that CompareTreePosition can't return 0!
  1.1290 +          // See bug 928645.
  1.1291 +          NS_WARNING("Something odd happening???");
  1.1292 +          insertionPoint = nullptr;
  1.1293 +          for (uint32_t i = 0; i < children.Length(); ++i) {
  1.1294 +            nsIFrame* f = children[i];
  1.1295 +            if (nsLayoutUtils::CompareTreePosition(f, firstNewFrame,
  1.1296 +                                                   firstNewFrameAncestors,
  1.1297 +                                                   notCommonAncestor ?
  1.1298 +                                                     containingBlock : nullptr) > 0) {
  1.1299 +              break;
  1.1300 +            }
  1.1301 +            insertionPoint = f;
  1.1302 +          }
  1.1303 +          break;
  1.1304 +        }
  1.1305 +      }
  1.1306 +      rv = mFrameManager->InsertFrames(containingBlock, aChildListID,
  1.1307 +                                       insertionPoint, aFrameItems);
  1.1308 +    }
  1.1309 +  }
  1.1310 +
  1.1311 +  NS_POSTCONDITION(aFrameItems.IsEmpty(), "How did that happen?");
  1.1312 +
  1.1313 +  // XXXbz And if NS_FAILED(rv), what?  I guess we need to clean up the list
  1.1314 +  // and deal with all the placeholders... but what if the placeholders aren't
  1.1315 +  // in the document yet?  Could that happen?
  1.1316 +  NS_ASSERTION(NS_SUCCEEDED(rv), "Frames getting lost!");
  1.1317 +}
  1.1318 +
  1.1319 +
  1.1320 +nsFrameConstructorSaveState::nsFrameConstructorSaveState()
  1.1321 +  : mItems(nullptr),
  1.1322 +    mSavedItems(nullptr),
  1.1323 +    mChildListID(kPrincipalList),
  1.1324 +    mState(nullptr),
  1.1325 +    mSavedFixedItems(nullptr),
  1.1326 +    mSavedFixedPosIsAbsPos(false)
  1.1327 +{
  1.1328 +}
  1.1329 +
  1.1330 +nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
  1.1331 +{
  1.1332 +  // Restore the state
  1.1333 +  if (mItems) {
  1.1334 +    NS_ASSERTION(mState, "Can't have mItems set without having a state!");
  1.1335 +    mState->ProcessFrameInsertions(*mItems, mChildListID);
  1.1336 +    *mItems = mSavedItems;
  1.1337 +#ifdef DEBUG
  1.1338 +    // We've transferred the child list, so drop the pointer we held to it.
  1.1339 +    // Note that this only matters for the assert in ~nsAbsoluteItems.
  1.1340 +    mSavedItems.Clear();
  1.1341 +#endif
  1.1342 +    if (mItems == &mState->mAbsoluteItems) {
  1.1343 +      mState->mFixedPosIsAbsPos = mSavedFixedPosIsAbsPos;
  1.1344 +      if (mSavedFixedPosIsAbsPos) {
  1.1345 +        // mAbsoluteItems was moved to mFixedItems, so move mFixedItems back
  1.1346 +        // and repair the old mFixedItems now.
  1.1347 +        mState->mAbsoluteItems = mState->mFixedItems;
  1.1348 +        mState->mFixedItems = mSavedFixedItems;
  1.1349 +#ifdef DEBUG
  1.1350 +        mSavedFixedItems.Clear();
  1.1351 +#endif
  1.1352 +      }
  1.1353 +    }
  1.1354 +    NS_ASSERTION(!mItems->LastChild() || !mItems->LastChild()->GetNextSibling(),
  1.1355 +                 "Something corrupted our list");
  1.1356 +  }
  1.1357 +}
  1.1358 +
  1.1359 +static
  1.1360 +bool IsBorderCollapse(nsIFrame* aFrame)
  1.1361 +{
  1.1362 +  for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
  1.1363 +    if (nsGkAtoms::tableFrame == frame->GetType()) {
  1.1364 +      return ((nsTableFrame*)frame)->IsBorderCollapse();
  1.1365 +    }
  1.1366 +  }
  1.1367 +  NS_ASSERTION(false, "program error");
  1.1368 +  return false;
  1.1369 +}
  1.1370 +
  1.1371 +/**
  1.1372 + * Moves aFrameList from aOldParent to aNewParent.  This updates the parent
  1.1373 + * pointer of the frames in the list, and reparents their views as needed.
  1.1374 + * nsFrame::SetParent sets the NS_FRAME_HAS_VIEW bit on aNewParent and its
  1.1375 + * ancestors as needed. Then it sets the list as the initial child list
  1.1376 + * on aNewParent, unless aNewParent either already has kids or has been
  1.1377 + * reflowed; in that case it appends the new frames.  Note that this
  1.1378 + * method differs from ReparentFrames in that it doesn't change the kids'
  1.1379 + * style contexts.
  1.1380 + */
  1.1381 +// XXXbz Since this is only used for {ib} splits, could we just copy the view
  1.1382 +// bits from aOldParent to aNewParent and then use the
  1.1383 +// nsFrameList::ApplySetParent?  That would still leave us doing two passes
  1.1384 +// over the list, of course; if we really wanted to we could factor out the
  1.1385 +// relevant part of ReparentFrameViewList, I suppose...  Or just get rid of
  1.1386 +// views, which would make most of this function go away.
  1.1387 +static void
  1.1388 +MoveChildrenTo(nsPresContext* aPresContext,
  1.1389 +               nsIFrame* aOldParent,
  1.1390 +               nsIFrame* aNewParent,
  1.1391 +               nsFrameList& aFrameList)
  1.1392 +{
  1.1393 +  bool sameGrandParent = aOldParent->GetParent() == aNewParent->GetParent();
  1.1394 +
  1.1395 +  if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) {
  1.1396 +    // Move the frames into the new view
  1.1397 +    nsContainerFrame::ReparentFrameViewList(aFrameList, aOldParent, aNewParent);
  1.1398 +  }
  1.1399 +
  1.1400 +  for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
  1.1401 +    e.get()->SetParent(aNewParent);
  1.1402 +  }
  1.1403 +
  1.1404 +  if (aNewParent->PrincipalChildList().IsEmpty() &&
  1.1405 +      (aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
  1.1406 +    aNewParent->SetInitialChildList(kPrincipalList, aFrameList);
  1.1407 +  } else {
  1.1408 +    aNewParent->AppendFrames(kPrincipalList, aFrameList);
  1.1409 +  }
  1.1410 +}
  1.1411 +
  1.1412 +//----------------------------------------------------------------------
  1.1413 +
  1.1414 +nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument,
  1.1415 +                                             nsIPresShell *aPresShell,
  1.1416 +                                             nsStyleSet* aStyleSet)
  1.1417 +  : nsFrameManager(aPresShell, aStyleSet)
  1.1418 +  , mDocument(aDocument)
  1.1419 +  , mRootElementFrame(nullptr)
  1.1420 +  , mRootElementStyleFrame(nullptr)
  1.1421 +  , mFixedContainingBlock(nullptr)
  1.1422 +  , mDocElementContainingBlock(nullptr)
  1.1423 +  , mGfxScrollFrame(nullptr)
  1.1424 +  , mPageSequenceFrame(nullptr)
  1.1425 +  , mCurrentDepth(0)
  1.1426 +  , mUpdateCount(0)
  1.1427 +  , mQuotesDirty(false)
  1.1428 +  , mCountersDirty(false)
  1.1429 +  , mIsDestroyingFrameTree(false)
  1.1430 +  , mHasRootAbsPosContainingBlock(false)
  1.1431 +  , mAlwaysCreateFramesForIgnorableWhitespace(false)
  1.1432 +{
  1.1433 +#ifdef DEBUG
  1.1434 +  static bool gFirstTime = true;
  1.1435 +  if (gFirstTime) {
  1.1436 +    gFirstTime = false;
  1.1437 +    char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
  1.1438 +    if (flags) {
  1.1439 +      bool error = false;
  1.1440 +      for (;;) {
  1.1441 +        char* comma = PL_strchr(flags, ',');
  1.1442 +        if (comma)
  1.1443 +          *comma = '\0';
  1.1444 +
  1.1445 +        bool found = false;
  1.1446 +        FrameCtorDebugFlags* flag = gFlags;
  1.1447 +        FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
  1.1448 +        while (flag < limit) {
  1.1449 +          if (PL_strcasecmp(flag->name, flags) == 0) {
  1.1450 +            *(flag->on) = true;
  1.1451 +            printf("nsCSSFrameConstructor: setting %s debug flag on\n", flag->name);
  1.1452 +            found = true;
  1.1453 +            break;
  1.1454 +          }
  1.1455 +          ++flag;
  1.1456 +        }
  1.1457 +
  1.1458 +        if (! found)
  1.1459 +          error = true;
  1.1460 +
  1.1461 +        if (! comma)
  1.1462 +          break;
  1.1463 +
  1.1464 +        *comma = ',';
  1.1465 +        flags = comma + 1;
  1.1466 +      }
  1.1467 +
  1.1468 +      if (error) {
  1.1469 +        printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
  1.1470 +        FrameCtorDebugFlags* flag = gFlags;
  1.1471 +        FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
  1.1472 +        while (flag < limit) {
  1.1473 +          printf("  %s\n", flag->name);
  1.1474 +          ++flag;
  1.1475 +        }
  1.1476 +        printf("Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of flag\n");
  1.1477 +        printf("names (no whitespace)\n");
  1.1478 +      }
  1.1479 +    }
  1.1480 +  }
  1.1481 +#endif
  1.1482 +}
  1.1483 +
  1.1484 +void
  1.1485 +nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame)
  1.1486 +{
  1.1487 +  NS_PRECONDITION(mUpdateCount != 0,
  1.1488 +                  "Should be in an update while destroying frames");
  1.1489 +
  1.1490 +  if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
  1.1491 +    if (mQuoteList.DestroyNodesFor(aFrame))
  1.1492 +      QuotesDirty();
  1.1493 +  }
  1.1494 +
  1.1495 +  if (mCounterManager.DestroyNodesFor(aFrame)) {
  1.1496 +    // Technically we don't need to update anything if we destroyed only
  1.1497 +    // USE nodes.  However, this is unlikely to happen in the real world
  1.1498 +    // since USE nodes generally go along with INCREMENT nodes.
  1.1499 +    CountersDirty();
  1.1500 +  }
  1.1501 +
  1.1502 +  RestyleManager()->NotifyDestroyingFrame(aFrame);
  1.1503 +
  1.1504 +  nsFrameManager::NotifyDestroyingFrame(aFrame);
  1.1505 +}
  1.1506 +
  1.1507 +struct nsGenConInitializer {
  1.1508 +  nsAutoPtr<nsGenConNode> mNode;
  1.1509 +  nsGenConList*           mList;
  1.1510 +  void (nsCSSFrameConstructor::*mDirtyAll)();
  1.1511 +
  1.1512 +  nsGenConInitializer(nsGenConNode* aNode, nsGenConList* aList,
  1.1513 +                      void (nsCSSFrameConstructor::*aDirtyAll)())
  1.1514 +    : mNode(aNode), mList(aList), mDirtyAll(aDirtyAll) {}
  1.1515 +};
  1.1516 +
  1.1517 +already_AddRefed<nsIContent>
  1.1518 +nsCSSFrameConstructor::CreateGenConTextNode(nsFrameConstructorState& aState,
  1.1519 +                                            const nsString& aString,
  1.1520 +                                            nsCOMPtr<nsIDOMCharacterData>* aText,
  1.1521 +                                            nsGenConInitializer* aInitializer)
  1.1522 +{
  1.1523 +  nsRefPtr<nsTextNode> content = new nsTextNode(mDocument->NodeInfoManager());
  1.1524 +  content->SetText(aString, false);
  1.1525 +  if (aText) {
  1.1526 +    *aText = content;
  1.1527 +  }
  1.1528 +  if (aInitializer) {
  1.1529 +    content->SetProperty(nsGkAtoms::genConInitializerProperty, aInitializer,
  1.1530 +                         nsINode::DeleteProperty<nsGenConInitializer>);
  1.1531 +    aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
  1.1532 +  }
  1.1533 +  return content.forget();
  1.1534 +}
  1.1535 +
  1.1536 +already_AddRefed<nsIContent>
  1.1537 +nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
  1.1538 +                                              nsIContent*     aParentContent,
  1.1539 +                                              nsStyleContext* aStyleContext,
  1.1540 +                                              uint32_t        aContentIndex)
  1.1541 +{
  1.1542 +  // Get the content value
  1.1543 +  const nsStyleContentData &data =
  1.1544 +    aStyleContext->StyleContent()->ContentAt(aContentIndex);
  1.1545 +  nsStyleContentType type = data.mType;
  1.1546 +
  1.1547 +  if (eStyleContentType_Image == type) {
  1.1548 +    if (!data.mContent.mImage) {
  1.1549 +      // CSS had something specified that couldn't be converted to an
  1.1550 +      // image object
  1.1551 +      return nullptr;
  1.1552 +    }
  1.1553 +
  1.1554 +    // Create an image content object and pass it the image request.
  1.1555 +    // XXX Check if it's an image type we can handle...
  1.1556 +
  1.1557 +    nsCOMPtr<nsINodeInfo> nodeInfo;
  1.1558 +    nodeInfo = mDocument->NodeInfoManager()->
  1.1559 +      GetNodeInfo(nsGkAtoms::mozgeneratedcontentimage, nullptr,
  1.1560 +                  kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
  1.1561 +
  1.1562 +    nsCOMPtr<nsIContent> content;
  1.1563 +    NS_NewGenConImageContent(getter_AddRefs(content), nodeInfo.forget(),
  1.1564 +                             data.mContent.mImage);
  1.1565 +    return content.forget();
  1.1566 +  }
  1.1567 +
  1.1568 +  switch (type) {
  1.1569 +  case eStyleContentType_String:
  1.1570 +    return CreateGenConTextNode(aState,
  1.1571 +                                nsDependentString(data.mContent.mString),
  1.1572 +                                nullptr, nullptr);
  1.1573 +
  1.1574 +  case eStyleContentType_Attr:
  1.1575 +    {
  1.1576 +      nsCOMPtr<nsIAtom> attrName;
  1.1577 +      int32_t attrNameSpace = kNameSpaceID_None;
  1.1578 +      nsAutoString contentString(data.mContent.mString);
  1.1579 +
  1.1580 +      int32_t barIndex = contentString.FindChar('|'); // CSS namespace delimiter
  1.1581 +      if (-1 != barIndex) {
  1.1582 +        nsAutoString  nameSpaceVal;
  1.1583 +        contentString.Left(nameSpaceVal, barIndex);
  1.1584 +        nsresult error;
  1.1585 +        attrNameSpace = nameSpaceVal.ToInteger(&error);
  1.1586 +        contentString.Cut(0, barIndex + 1);
  1.1587 +        if (contentString.Length()) {
  1.1588 +          if (mDocument->IsHTML() && aParentContent->IsHTML()) {
  1.1589 +            ToLowerCase(contentString);
  1.1590 +          }
  1.1591 +          attrName = do_GetAtom(contentString);
  1.1592 +        }
  1.1593 +      }
  1.1594 +      else {
  1.1595 +        if (mDocument->IsHTML() && aParentContent->IsHTML()) {
  1.1596 +          ToLowerCase(contentString);
  1.1597 +        }
  1.1598 +        attrName = do_GetAtom(contentString);
  1.1599 +      }
  1.1600 +
  1.1601 +      if (!attrName) {
  1.1602 +        return nullptr;
  1.1603 +      }
  1.1604 +
  1.1605 +      nsCOMPtr<nsIContent> content;
  1.1606 +      NS_NewAttributeContent(mDocument->NodeInfoManager(),
  1.1607 +                             attrNameSpace, attrName, getter_AddRefs(content));
  1.1608 +      return content.forget();
  1.1609 +    }
  1.1610 +
  1.1611 +  case eStyleContentType_Counter:
  1.1612 +  case eStyleContentType_Counters:
  1.1613 +    {
  1.1614 +      nsCSSValue::Array* counters = data.mContent.mCounters;
  1.1615 +      nsCounterList* counterList = mCounterManager.CounterListFor(
  1.1616 +          nsDependentString(counters->Item(0).GetStringBufferValue()));
  1.1617 +      if (!counterList)
  1.1618 +        return nullptr;
  1.1619 +
  1.1620 +      nsCounterUseNode* node =
  1.1621 +        new nsCounterUseNode(counters, aContentIndex,
  1.1622 +                             type == eStyleContentType_Counters);
  1.1623 +
  1.1624 +      nsGenConInitializer* initializer =
  1.1625 +        new nsGenConInitializer(node, counterList,
  1.1626 +                                &nsCSSFrameConstructor::CountersDirty);
  1.1627 +      return CreateGenConTextNode(aState, EmptyString(), &node->mText,
  1.1628 +                                  initializer);
  1.1629 +    }
  1.1630 +
  1.1631 +  case eStyleContentType_Image:
  1.1632 +    NS_NOTREACHED("handled by if above");
  1.1633 +    return nullptr;
  1.1634 +
  1.1635 +  case eStyleContentType_OpenQuote:
  1.1636 +  case eStyleContentType_CloseQuote:
  1.1637 +  case eStyleContentType_NoOpenQuote:
  1.1638 +  case eStyleContentType_NoCloseQuote:
  1.1639 +    {
  1.1640 +      nsQuoteNode* node =
  1.1641 +        new nsQuoteNode(type, aContentIndex);
  1.1642 +
  1.1643 +      nsGenConInitializer* initializer =
  1.1644 +        new nsGenConInitializer(node, &mQuoteList,
  1.1645 +                                &nsCSSFrameConstructor::QuotesDirty);
  1.1646 +      return CreateGenConTextNode(aState, EmptyString(), &node->mText,
  1.1647 +                                  initializer);
  1.1648 +    }
  1.1649 +
  1.1650 +  case eStyleContentType_AltContent:
  1.1651 +    {
  1.1652 +      // Use the "alt" attribute; if that fails and the node is an HTML
  1.1653 +      // <input>, try the value attribute and then fall back to some default
  1.1654 +      // localized text we have.
  1.1655 +      // XXX what if the 'alt' attribute is added later, how will we
  1.1656 +      // detect that and do the right thing here?
  1.1657 +      if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::alt)) {
  1.1658 +        nsCOMPtr<nsIContent> content;
  1.1659 +        NS_NewAttributeContent(mDocument->NodeInfoManager(),
  1.1660 +                               kNameSpaceID_None, nsGkAtoms::alt, getter_AddRefs(content));
  1.1661 +        return content.forget();
  1.1662 +      }
  1.1663 +
  1.1664 +      if (aParentContent->IsHTML() &&
  1.1665 +          aParentContent->NodeInfo()->Equals(nsGkAtoms::input)) {
  1.1666 +        if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
  1.1667 +          nsCOMPtr<nsIContent> content;
  1.1668 +          NS_NewAttributeContent(mDocument->NodeInfoManager(),
  1.1669 +                                 kNameSpaceID_None, nsGkAtoms::value, getter_AddRefs(content));
  1.1670 +          return content.forget();
  1.1671 +        }
  1.1672 +
  1.1673 +        nsXPIDLString temp;
  1.1674 +        nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
  1.1675 +                                           "Submit", temp);
  1.1676 +        return CreateGenConTextNode(aState, temp, nullptr, nullptr);
  1.1677 +      }
  1.1678 +
  1.1679 +      break;
  1.1680 +    }
  1.1681 +
  1.1682 +  case eStyleContentType_Uninitialized:
  1.1683 +    NS_NOTREACHED("uninitialized content type");
  1.1684 +    return nullptr;
  1.1685 +  } // switch
  1.1686 +
  1.1687 +  return nullptr;
  1.1688 +}
  1.1689 +
  1.1690 +/*
  1.1691 + * aParentFrame - the frame that should be the parent of the generated
  1.1692 + *   content.  This is the frame for the corresponding content node,
  1.1693 + *   which must not be a leaf frame.
  1.1694 + *
  1.1695 + * Any items created are added to aItems.
  1.1696 + *
  1.1697 + * We create an XML element (tag _moz_generated_content_before or
  1.1698 + * _moz_generated_content_after) representing the pseudoelement. We
  1.1699 + * create a DOM node for each 'content' item and make those nodes the
  1.1700 + * children of the XML element. Then we create a frame subtree for
  1.1701 + * the XML element as if it were a regular child of
  1.1702 + * aParentFrame/aParentContent, giving the XML element the ::before or
  1.1703 + * ::after style.
  1.1704 + */
  1.1705 +void
  1.1706 +nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
  1.1707 +                                                  nsIFrame*        aParentFrame,
  1.1708 +                                                  nsIContent*      aParentContent,
  1.1709 +                                                  nsStyleContext*  aStyleContext,
  1.1710 +                                                  nsCSSPseudoElements::Type aPseudoElement,
  1.1711 +                                                  FrameConstructionItemList& aItems)
  1.1712 +{
  1.1713 +  // XXXbz is this ever true?
  1.1714 +  if (!aParentContent->IsElement()) {
  1.1715 +    NS_ERROR("Bogus generated content parent");
  1.1716 +    return;
  1.1717 +  }
  1.1718 +
  1.1719 +  nsStyleSet *styleSet = mPresShell->StyleSet();
  1.1720 +
  1.1721 +  // Probe for the existence of the pseudo-element
  1.1722 +  nsRefPtr<nsStyleContext> pseudoStyleContext;
  1.1723 +  pseudoStyleContext =
  1.1724 +    styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
  1.1725 +                                      aPseudoElement,
  1.1726 +                                      aStyleContext,
  1.1727 +                                      aState.mTreeMatchContext);
  1.1728 +  if (!pseudoStyleContext)
  1.1729 +    return;
  1.1730 +  // |ProbePseudoStyleFor| checked the 'display' property and the
  1.1731 +  // |ContentCount()| of the 'content' property for us.
  1.1732 +  nsCOMPtr<nsINodeInfo> nodeInfo;
  1.1733 +  nsIAtom* elemName = aPseudoElement == nsCSSPseudoElements::ePseudo_before ?
  1.1734 +    nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
  1.1735 +  nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nullptr,
  1.1736 +                                                       kNameSpaceID_None,
  1.1737 +                                                       nsIDOMNode::ELEMENT_NODE);
  1.1738 +  nsCOMPtr<Element> container;
  1.1739 +  nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
  1.1740 +  if (NS_FAILED(rv))
  1.1741 +    return;
  1.1742 +  container->SetIsNativeAnonymousRoot();
  1.1743 +
  1.1744 +  rv = container->BindToTree(mDocument, aParentContent, aParentContent, true);
  1.1745 +  if (NS_FAILED(rv)) {
  1.1746 +    container->UnbindFromTree();
  1.1747 +    return;
  1.1748 +  }
  1.1749 +
  1.1750 +  uint32_t contentCount = pseudoStyleContext->StyleContent()->ContentCount();
  1.1751 +  for (uint32_t contentIndex = 0; contentIndex < contentCount; contentIndex++) {
  1.1752 +    nsCOMPtr<nsIContent> content =
  1.1753 +      CreateGeneratedContent(aState, aParentContent, pseudoStyleContext,
  1.1754 +                             contentIndex);
  1.1755 +    if (content) {
  1.1756 +      container->AppendChildTo(content, false);
  1.1757 +    }
  1.1758 +  }
  1.1759 +
  1.1760 +  AddFrameConstructionItemsInternal(aState, container, aParentFrame, elemName,
  1.1761 +                                    kNameSpaceID_None, true,
  1.1762 +                                    pseudoStyleContext,
  1.1763 +                                    ITEM_IS_GENERATED_CONTENT, nullptr,
  1.1764 +                                    aItems);
  1.1765 +}
  1.1766 +
  1.1767 +/****************************************************
  1.1768 + **  BEGIN TABLE SECTION
  1.1769 + ****************************************************/
  1.1770 +
  1.1771 +// The term pseudo frame is being used instead of anonymous frame, since anonymous
  1.1772 +// frame has been used elsewhere to refer to frames that have generated content
  1.1773 +
  1.1774 +// Return whether the given frame is a table pseudo-frame.  Note that
  1.1775 +// cell-content and table-outer frames have pseudo-types, but are always
  1.1776 +// created, even for non-anonymous cells and tables respectively.  So for those
  1.1777 +// we have to examine the cell or table frame to see whether it's a pseudo
  1.1778 +// frame.  In particular, a lone table caption will have an outer table as its
  1.1779 +// parent, but will also trigger construction of an empty inner table, which
  1.1780 +// will be the one we can examine to see whether the outer was a pseudo-frame.
  1.1781 +static bool
  1.1782 +IsTablePseudo(nsIFrame* aFrame)
  1.1783 +{
  1.1784 +  nsIAtom* pseudoType = aFrame->StyleContext()->GetPseudo();
  1.1785 +  return pseudoType &&
  1.1786 +    (pseudoType == nsCSSAnonBoxes::table ||
  1.1787 +     pseudoType == nsCSSAnonBoxes::inlineTable ||
  1.1788 +     pseudoType == nsCSSAnonBoxes::tableColGroup ||
  1.1789 +     pseudoType == nsCSSAnonBoxes::tableRowGroup ||
  1.1790 +     pseudoType == nsCSSAnonBoxes::tableRow ||
  1.1791 +     pseudoType == nsCSSAnonBoxes::tableCell ||
  1.1792 +     (pseudoType == nsCSSAnonBoxes::cellContent &&
  1.1793 +      aFrame->GetParent()->StyleContext()->GetPseudo() ==
  1.1794 +        nsCSSAnonBoxes::tableCell) ||
  1.1795 +     (pseudoType == nsCSSAnonBoxes::tableOuter &&
  1.1796 +      (aFrame->GetFirstPrincipalChild()->StyleContext()->GetPseudo() ==
  1.1797 +         nsCSSAnonBoxes::table ||
  1.1798 +       aFrame->GetFirstPrincipalChild()->StyleContext()->GetPseudo() ==
  1.1799 +         nsCSSAnonBoxes::inlineTable)));
  1.1800 +}
  1.1801 +
  1.1802 +/* static */
  1.1803 +nsCSSFrameConstructor::ParentType
  1.1804 +nsCSSFrameConstructor::GetParentType(nsIAtom* aFrameType)
  1.1805 +{
  1.1806 +  if (aFrameType == nsGkAtoms::tableFrame) {
  1.1807 +    return eTypeTable;
  1.1808 +  }
  1.1809 +  if (aFrameType == nsGkAtoms::tableRowGroupFrame) {
  1.1810 +    return eTypeRowGroup;
  1.1811 +  }
  1.1812 +  if (aFrameType == nsGkAtoms::tableRowFrame) {
  1.1813 +    return eTypeRow;
  1.1814 +  }
  1.1815 +  if (aFrameType == nsGkAtoms::tableColGroupFrame) {
  1.1816 +    return eTypeColGroup;
  1.1817 +  }
  1.1818 +
  1.1819 +  return eTypeBlock;
  1.1820 +}
  1.1821 +
  1.1822 +static nsIFrame*
  1.1823 +AdjustCaptionParentFrame(nsIFrame* aParentFrame)
  1.1824 +{
  1.1825 +  if (nsGkAtoms::tableFrame == aParentFrame->GetType()) {
  1.1826 +    return aParentFrame->GetParent();;
  1.1827 +  }
  1.1828 +  return aParentFrame;
  1.1829 +}
  1.1830 +
  1.1831 +/**
  1.1832 + * If the parent frame is a |tableFrame| and the child is a
  1.1833 + * |captionFrame|, then we want to insert the frames beneath the
  1.1834 + * |tableFrame|'s parent frame. Returns |true| if the parent frame
  1.1835 + * needed to be fixed up.
  1.1836 + */
  1.1837 +static bool
  1.1838 +GetCaptionAdjustedParent(nsIFrame*        aParentFrame,
  1.1839 +                         const nsIFrame*  aChildFrame,
  1.1840 +                         nsIFrame**       aAdjParentFrame)
  1.1841 +{
  1.1842 +  *aAdjParentFrame = aParentFrame;
  1.1843 +  bool haveCaption = false;
  1.1844 +
  1.1845 +  if (nsGkAtoms::tableCaptionFrame == aChildFrame->GetType()) {
  1.1846 +    haveCaption = true;
  1.1847 +    *aAdjParentFrame = AdjustCaptionParentFrame(aParentFrame);
  1.1848 +  }
  1.1849 +  return haveCaption;
  1.1850 +}
  1.1851 +
  1.1852 +void
  1.1853 +nsCSSFrameConstructor::AdjustParentFrame(nsIFrame* &                  aParentFrame,
  1.1854 +                                         const FrameConstructionData* aFCData,
  1.1855 +                                         nsStyleContext*              aStyleContext)
  1.1856 +{
  1.1857 +  NS_PRECONDITION(aStyleContext, "Must have child's style context");
  1.1858 +  NS_PRECONDITION(aFCData, "Must have frame construction data");
  1.1859 +
  1.1860 +  bool tablePart = ((aFCData->mBits & FCDATA_IS_TABLE_PART) != 0);
  1.1861 +
  1.1862 +  if (tablePart && aStyleContext->StyleDisplay()->mDisplay ==
  1.1863 +      NS_STYLE_DISPLAY_TABLE_CAPTION) {
  1.1864 +    aParentFrame = AdjustCaptionParentFrame(aParentFrame);
  1.1865 +  }
  1.1866 +}
  1.1867 +
  1.1868 +// Pull all the captions present in aItems out  into aCaptions
  1.1869 +static void
  1.1870 +PullOutCaptionFrames(nsFrameItems& aItems, nsFrameItems& aCaptions)
  1.1871 +{
  1.1872 +  nsIFrame *child = aItems.FirstChild();
  1.1873 +  while (child) {
  1.1874 +    nsIFrame *nextSibling = child->GetNextSibling();
  1.1875 +    if (nsGkAtoms::tableCaptionFrame == child->GetType()) {
  1.1876 +      aItems.RemoveFrame(child);
  1.1877 +      aCaptions.AddChild(child);
  1.1878 +    }
  1.1879 +    child = nextSibling;
  1.1880 +  }
  1.1881 +}
  1.1882 +
  1.1883 +
  1.1884 +// Construct the outer, inner table frames and the children frames for the table.
  1.1885 +// XXX Page break frames for pseudo table frames are not constructed to avoid the risk
  1.1886 +// associated with revising the pseudo frame mechanism. The long term solution
  1.1887 +// of having frames handle page-break-before/after will solve the problem.
  1.1888 +nsIFrame*
  1.1889 +nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
  1.1890 +                                      FrameConstructionItem&   aItem,
  1.1891 +                                      nsIFrame*                aParentFrame,
  1.1892 +                                      const nsStyleDisplay*    aDisplay,
  1.1893 +                                      nsFrameItems&            aFrameItems)
  1.1894 +{
  1.1895 +  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE ||
  1.1896 +                  aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE,
  1.1897 +                  "Unexpected call");
  1.1898 +
  1.1899 +  nsIContent* const content = aItem.mContent;
  1.1900 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.1901 +  const uint32_t nameSpaceID = aItem.mNameSpaceID;
  1.1902 +
  1.1903 +  // create the pseudo SC for the outer table as a child of the inner SC
  1.1904 +  nsRefPtr<nsStyleContext> outerStyleContext;
  1.1905 +  outerStyleContext = mPresShell->StyleSet()->
  1.1906 +    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableOuter, styleContext);
  1.1907 +
  1.1908 +  // Create the outer table frame which holds the caption and inner table frame
  1.1909 +  nsIFrame* newFrame;
  1.1910 +  if (kNameSpaceID_MathML == nameSpaceID)
  1.1911 +    newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerStyleContext);
  1.1912 +  else
  1.1913 +    newFrame = NS_NewTableOuterFrame(mPresShell, outerStyleContext);
  1.1914 +
  1.1915 +  nsIFrame* geometricParent =
  1.1916 +    aState.GetGeometricParent(outerStyleContext->StyleDisplay(),
  1.1917 +                              aParentFrame);
  1.1918 +
  1.1919 +  // Init the table outer frame
  1.1920 +  InitAndRestoreFrame(aState, content, geometricParent, newFrame);
  1.1921 +
  1.1922 +  // Create the inner table frame
  1.1923 +  nsIFrame* innerFrame;
  1.1924 +  if (kNameSpaceID_MathML == nameSpaceID)
  1.1925 +    innerFrame = NS_NewMathMLmtableFrame(mPresShell, styleContext);
  1.1926 +  else
  1.1927 +    innerFrame = NS_NewTableFrame(mPresShell, styleContext);
  1.1928 +
  1.1929 +  InitAndRestoreFrame(aState, content, newFrame, innerFrame);
  1.1930 +
  1.1931 +  // Put the newly created frames into the right child list
  1.1932 +  SetInitialSingleChild(newFrame, innerFrame);
  1.1933 +
  1.1934 +  aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
  1.1935 +
  1.1936 +  if (!mRootElementFrame) {
  1.1937 +    // The frame we're constructing will be the root element frame.
  1.1938 +    // Set mRootElementFrame before processing children.
  1.1939 +    mRootElementFrame = newFrame;
  1.1940 +  }
  1.1941 +
  1.1942 +  nsFrameItems childItems;
  1.1943 +
  1.1944 +  // Process children
  1.1945 +  nsFrameConstructorSaveState absoluteSaveState;
  1.1946 +  const nsStyleDisplay* display = outerStyleContext->StyleDisplay();
  1.1947 +
  1.1948 +  // Mark the table frame as an absolute container if needed
  1.1949 +  newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.1950 +  if (display->IsPositioned(newFrame)) {
  1.1951 +    aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
  1.1952 +  }
  1.1953 +  NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
  1.1954 +               "nsIAnonymousContentCreator::CreateAnonymousContent "
  1.1955 +               "implementations for table frames are not currently expected "
  1.1956 +               "to output a list where the items have their own children");
  1.1957 +  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
  1.1958 +    ConstructFramesFromItemList(aState, aItem.mChildItems,
  1.1959 +                                innerFrame, childItems);
  1.1960 +  } else {
  1.1961 +    ProcessChildren(aState, content, styleContext, innerFrame,
  1.1962 +                    true, childItems, false, aItem.mPendingBinding);
  1.1963 +  }
  1.1964 +
  1.1965 +  nsFrameItems captionItems;
  1.1966 +  PullOutCaptionFrames(childItems, captionItems);
  1.1967 +
  1.1968 +  // Set the inner table frame's initial primary list
  1.1969 +  innerFrame->SetInitialChildList(kPrincipalList, childItems);
  1.1970 +
  1.1971 +  // Set the outer table frame's secondary childlist lists
  1.1972 +  if (captionItems.NotEmpty()) {
  1.1973 +    newFrame->SetInitialChildList(nsIFrame::kCaptionList, captionItems);
  1.1974 +  }
  1.1975 +
  1.1976 +  return newFrame;
  1.1977 +}
  1.1978 +
  1.1979 +static void
  1.1980 +MakeTablePartAbsoluteContainingBlockIfNeeded(nsFrameConstructorState&     aState,
  1.1981 +                                             const nsStyleDisplay*        aDisplay,
  1.1982 +                                             nsFrameConstructorSaveState& aAbsSaveState,
  1.1983 +                                             nsIFrame*                    aFrame)
  1.1984 +{
  1.1985 +  // If we're positioned, then we need to become an absolute containing block
  1.1986 +  // for any absolutely positioned children and register for post-reflow fixup.
  1.1987 +  //
  1.1988 +  // Note that usually if a frame type can be an absolute containing block, we
  1.1989 +  // always set NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN, whether it actually is or not.
  1.1990 +  // However, in this case flag serves the additional purpose of indicating that
  1.1991 +  // the frame was registered with its table frame. This allows us to avoid the
  1.1992 +  // overhead of unregistering the frame in most cases.
  1.1993 +  if (aDisplay->IsPositioned(aFrame)) {
  1.1994 +    aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.1995 +    aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
  1.1996 +    nsTableFrame::RegisterPositionedTablePart(aFrame);
  1.1997 +  }
  1.1998 +}
  1.1999 +
  1.2000 +nsIFrame*
  1.2001 +nsCSSFrameConstructor::ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
  1.2002 +                                                   FrameConstructionItem&   aItem,
  1.2003 +                                                   nsIFrame*                aParentFrame,
  1.2004 +                                                   const nsStyleDisplay*    aDisplay,
  1.2005 +                                                   nsFrameItems&            aFrameItems)
  1.2006 +{
  1.2007 +  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW ||
  1.2008 +                  aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW_GROUP ||
  1.2009 +                  aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP ||
  1.2010 +                  aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
  1.2011 +                  "Unexpected call");
  1.2012 +  MOZ_ASSERT(aItem.mStyleContext->StyleDisplay() == aDisplay,
  1.2013 +             "Display style doesn't match style context");
  1.2014 +  nsIContent* const content = aItem.mContent;
  1.2015 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.2016 +  const uint32_t nameSpaceID = aItem.mNameSpaceID;
  1.2017 +
  1.2018 +  nsIFrame* newFrame;
  1.2019 +  if (aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW) {
  1.2020 +    if (kNameSpaceID_MathML == nameSpaceID)
  1.2021 +      newFrame = NS_NewMathMLmtrFrame(mPresShell, styleContext);
  1.2022 +    else
  1.2023 +      newFrame = NS_NewTableRowFrame(mPresShell, styleContext);
  1.2024 +  } else {
  1.2025 +    newFrame = NS_NewTableRowGroupFrame(mPresShell, styleContext);
  1.2026 +  }
  1.2027 +
  1.2028 +  InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
  1.2029 +
  1.2030 +  nsFrameConstructorSaveState absoluteSaveState;
  1.2031 +  MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
  1.2032 +                                               absoluteSaveState,
  1.2033 +                                               newFrame);
  1.2034 +
  1.2035 +  nsFrameItems childItems;
  1.2036 +  NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
  1.2037 +               "nsIAnonymousContentCreator::CreateAnonymousContent "
  1.2038 +               "implementations for table frames are not currently expected "
  1.2039 +               "to output a list where the items have their own children");
  1.2040 +  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
  1.2041 +    ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
  1.2042 +                                childItems);
  1.2043 +  } else {
  1.2044 +    ProcessChildren(aState, content, styleContext, newFrame,
  1.2045 +                    true, childItems, false, aItem.mPendingBinding);
  1.2046 +  }
  1.2047 +
  1.2048 +  newFrame->SetInitialChildList(kPrincipalList, childItems);
  1.2049 +  aFrameItems.AddChild(newFrame);
  1.2050 +  return newFrame;
  1.2051 +}
  1.2052 +
  1.2053 +nsIFrame*
  1.2054 +nsCSSFrameConstructor::ConstructTableCol(nsFrameConstructorState& aState,
  1.2055 +                                         FrameConstructionItem&   aItem,
  1.2056 +                                         nsIFrame*                aParentFrame,
  1.2057 +                                         const nsStyleDisplay*    aStyleDisplay,
  1.2058 +                                         nsFrameItems&            aFrameItems)
  1.2059 +{
  1.2060 +  nsIContent* const content = aItem.mContent;
  1.2061 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.2062 +
  1.2063 +  nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, styleContext);
  1.2064 +  InitAndRestoreFrame(aState, content, aParentFrame, colFrame);
  1.2065 +
  1.2066 +  NS_ASSERTION(colFrame->StyleContext() == styleContext,
  1.2067 +               "Unexpected style context");
  1.2068 +
  1.2069 +  aFrameItems.AddChild(colFrame);
  1.2070 +
  1.2071 +  // construct additional col frames if the col frame has a span > 1
  1.2072 +  int32_t span = colFrame->GetSpan();
  1.2073 +  for (int32_t spanX = 1; spanX < span; spanX++) {
  1.2074 +    nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, styleContext);
  1.2075 +    InitAndRestoreFrame(aState, content, aParentFrame, newCol, false);
  1.2076 +    aFrameItems.LastChild()->SetNextContinuation(newCol);
  1.2077 +    newCol->SetPrevContinuation(aFrameItems.LastChild());
  1.2078 +    aFrameItems.AddChild(newCol);
  1.2079 +    newCol->SetColType(eColAnonymousCol);
  1.2080 +  }
  1.2081 +
  1.2082 +  return colFrame;
  1.2083 +}
  1.2084 +
  1.2085 +nsIFrame*
  1.2086 +nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
  1.2087 +                                          FrameConstructionItem&   aItem,
  1.2088 +                                          nsIFrame*                aParentFrame,
  1.2089 +                                          const nsStyleDisplay*    aDisplay,
  1.2090 +                                          nsFrameItems&            aFrameItems)
  1.2091 +{
  1.2092 +  NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL,
  1.2093 +                  "Unexpected call");
  1.2094 +
  1.2095 +  nsIContent* const content = aItem.mContent;
  1.2096 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.2097 +  const uint32_t nameSpaceID = aItem.mNameSpaceID;
  1.2098 +
  1.2099 +  bool borderCollapse = IsBorderCollapse(aParentFrame);
  1.2100 +  nsIFrame* newFrame;
  1.2101 +  // <mtable> is border separate in mathml.css and the MathML code doesn't implement
  1.2102 +  // border collapse. For those users who style <mtable> with border collapse,
  1.2103 +  // give them the default non-MathML table frames that understand border collapse.
  1.2104 +  // This won't break us because MathML table frames are all subclasses of the default
  1.2105 +  // table code, and so we can freely mix <mtable> with <mtr> or <tr>, <mtd> or <td>.
  1.2106 +  // What will happen is just that non-MathML frames won't understand MathML attributes
  1.2107 +  // and will therefore miss the special handling that the MathML code does.
  1.2108 +  if (kNameSpaceID_MathML == nameSpaceID && !borderCollapse)
  1.2109 +    newFrame = NS_NewMathMLmtdFrame(mPresShell, styleContext);
  1.2110 +  else
  1.2111 +    // Warning: If you change this and add a wrapper frame around table cell
  1.2112 +    // frames, make sure Bug 368554 doesn't regress!
  1.2113 +    // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
  1.2114 +    newFrame = NS_NewTableCellFrame(mPresShell, styleContext, borderCollapse);
  1.2115 +
  1.2116 +  // Initialize the table cell frame
  1.2117 +  InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
  1.2118 +
  1.2119 +  // Resolve pseudo style and initialize the body cell frame
  1.2120 +  nsRefPtr<nsStyleContext> innerPseudoStyle;
  1.2121 +  innerPseudoStyle = mPresShell->StyleSet()->
  1.2122 +    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::cellContent, styleContext);
  1.2123 +
  1.2124 +  // Create a block frame that will format the cell's content
  1.2125 +  bool isBlock;
  1.2126 +  nsIFrame* cellInnerFrame;
  1.2127 +  if (kNameSpaceID_MathML == nameSpaceID) {
  1.2128 +    cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
  1.2129 +    isBlock = false;
  1.2130 +  } else {
  1.2131 +    cellInnerFrame = NS_NewBlockFormattingContext(mPresShell, innerPseudoStyle);
  1.2132 +    isBlock = true;
  1.2133 +  }
  1.2134 +
  1.2135 +  InitAndRestoreFrame(aState, content, newFrame, cellInnerFrame);
  1.2136 +
  1.2137 +  nsFrameConstructorSaveState absoluteSaveState;
  1.2138 +  MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
  1.2139 +                                               absoluteSaveState,
  1.2140 +                                               newFrame);
  1.2141 +
  1.2142 +  nsFrameItems childItems;
  1.2143 +  NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
  1.2144 +               "nsIAnonymousContentCreator::CreateAnonymousContent "
  1.2145 +               "implementations for table frames are not currently expected "
  1.2146 +               "to output a list where the items have their own children");
  1.2147 +  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
  1.2148 +    // Need to push ourselves as a float containing block.
  1.2149 +    // XXXbz it might be nice to work on getting the parent
  1.2150 +    // FrameConstructionItem down into ProcessChildren and just making use of
  1.2151 +    // the push there, but that's a bit of work.
  1.2152 +    nsFrameConstructorSaveState floatSaveState;
  1.2153 +    if (!isBlock) { /* MathML case */
  1.2154 +      aState.PushFloatContainingBlock(nullptr, floatSaveState);
  1.2155 +    } else {
  1.2156 +      aState.PushFloatContainingBlock(cellInnerFrame, floatSaveState);
  1.2157 +    }
  1.2158 +
  1.2159 +    ConstructFramesFromItemList(aState, aItem.mChildItems, cellInnerFrame,
  1.2160 +                                childItems);
  1.2161 +  } else {
  1.2162 +    // Process the child content
  1.2163 +    ProcessChildren(aState, content, styleContext, cellInnerFrame,
  1.2164 +                    true, childItems, isBlock, aItem.mPendingBinding);
  1.2165 +  }
  1.2166 +
  1.2167 +  cellInnerFrame->SetInitialChildList(kPrincipalList, childItems);
  1.2168 +  SetInitialSingleChild(newFrame, cellInnerFrame);
  1.2169 +  aFrameItems.AddChild(newFrame);
  1.2170 +  return newFrame;
  1.2171 +}
  1.2172 +
  1.2173 +static inline bool
  1.2174 +NeedFrameFor(const nsFrameConstructorState& aState,
  1.2175 +             nsIFrame*   aParentFrame,
  1.2176 +             nsIContent* aChildContent)
  1.2177 +{
  1.2178 +  // XXX the GetContent() != aChildContent check is needed due to bug 135040.
  1.2179 +  // Remove it once that's fixed.
  1.2180 +  NS_PRECONDITION(!aChildContent->GetPrimaryFrame() ||
  1.2181 +                  aState.mCreatingExtraFrames ||
  1.2182 +                  aChildContent->GetPrimaryFrame()->GetContent() != aChildContent,
  1.2183 +                  "Why did we get called?");
  1.2184 +
  1.2185 +  // don't create a whitespace frame if aParentFrame doesn't want it.
  1.2186 +  // always create frames for children in generated content. counter(),
  1.2187 +  // quotes, and attr() content can easily change dynamically and we don't
  1.2188 +  // want to be reconstructing frames. It's not even clear that these
  1.2189 +  // should be considered ignorable just because they evaluate to
  1.2190 +  // whitespace.
  1.2191 +
  1.2192 +  // We could handle all this in CreateNeededTablePseudos or some other place
  1.2193 +  // after we build our frame construction items, but that would involve
  1.2194 +  // creating frame construction items for whitespace kids of
  1.2195 +  // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them
  1.2196 +  // all anyway, and involve an extra walk down the frame construction item
  1.2197 +  // list.
  1.2198 +  if (!aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) ||
  1.2199 +      aParentFrame->IsGeneratedContentFrame() ||
  1.2200 +      !aChildContent->IsNodeOfType(nsINode::eTEXT)) {
  1.2201 +    return true;
  1.2202 +  }
  1.2203 +
  1.2204 +  aChildContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
  1.2205 +                          NS_REFRAME_IF_WHITESPACE);
  1.2206 +  return !aChildContent->TextIsOnlyWhitespace();
  1.2207 +}
  1.2208 +
  1.2209 +/***********************************************
  1.2210 + * END TABLE SECTION
  1.2211 + ***********************************************/
  1.2212 +
  1.2213 +static bool CheckOverflow(nsPresContext* aPresContext,
  1.2214 +                            const nsStyleDisplay* aDisplay)
  1.2215 +{
  1.2216 +  if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
  1.2217 +    return false;
  1.2218 +
  1.2219 +  if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
  1.2220 +    aPresContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_HIDDEN,
  1.2221 +                                              NS_STYLE_OVERFLOW_HIDDEN);
  1.2222 +  else
  1.2223 +    aPresContext->SetViewportOverflowOverride(aDisplay->mOverflowX,
  1.2224 +                                              aDisplay->mOverflowY);
  1.2225 +  return true;
  1.2226 +}
  1.2227 +
  1.2228 +/**
  1.2229 + * This checks the root element and the HTML BODY, if any, for an "overflow" property
  1.2230 + * that should be applied to the viewport. If one is found then we return the
  1.2231 + * element that we took the overflow from (which should then be treated as
  1.2232 + * "overflow:visible"), and we store the overflow style in the prescontext.
  1.2233 + * @return if scroll was propagated from some content node, the content node it
  1.2234 + *         was propagated from.
  1.2235 + */
  1.2236 +nsIContent*
  1.2237 +nsCSSFrameConstructor::PropagateScrollToViewport()
  1.2238 +{
  1.2239 +  // Set default
  1.2240 +  nsPresContext* presContext = mPresShell->GetPresContext();
  1.2241 +  presContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_AUTO,
  1.2242 +                                           NS_STYLE_OVERFLOW_AUTO);
  1.2243 +
  1.2244 +  // We never mess with the viewport scroll state
  1.2245 +  // when printing or in print preview
  1.2246 +  if (presContext->IsPaginated()) {
  1.2247 +    return nullptr;
  1.2248 +  }
  1.2249 +
  1.2250 +  Element* docElement = mDocument->GetRootElement();
  1.2251 +
  1.2252 +  // Check the style on the document root element
  1.2253 +  nsStyleSet *styleSet = mPresShell->StyleSet();
  1.2254 +  nsRefPtr<nsStyleContext> rootStyle;
  1.2255 +  rootStyle = styleSet->ResolveStyleFor(docElement, nullptr);
  1.2256 +  if (CheckOverflow(presContext, rootStyle->StyleDisplay())) {
  1.2257 +    // tell caller we stole the overflow style from the root element
  1.2258 +    return docElement;
  1.2259 +  }
  1.2260 +
  1.2261 +  // Don't look in the BODY for non-HTML documents or HTML documents
  1.2262 +  // with non-HTML roots
  1.2263 +  // XXX this should be earlier; we shouldn't even look at the document root
  1.2264 +  // for non-HTML documents. Fix this once we support explicit CSS styling
  1.2265 +  // of the viewport
  1.2266 +  // XXX what about XHTML?
  1.2267 +  nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
  1.2268 +  if (!htmlDoc || !docElement->IsHTML()) {
  1.2269 +    return nullptr;
  1.2270 +  }
  1.2271 +
  1.2272 +  nsCOMPtr<nsIDOMHTMLElement> body;
  1.2273 +  htmlDoc->GetBody(getter_AddRefs(body));
  1.2274 +  nsCOMPtr<nsIContent> bodyElement = do_QueryInterface(body);
  1.2275 +
  1.2276 +  if (!bodyElement ||
  1.2277 +      !bodyElement->NodeInfo()->Equals(nsGkAtoms::body)) {
  1.2278 +    // The body is not a <body> tag, it's a <frameset>.
  1.2279 +    return nullptr;
  1.2280 +  }
  1.2281 +
  1.2282 +  nsRefPtr<nsStyleContext> bodyStyle;
  1.2283 +  bodyStyle = styleSet->ResolveStyleFor(bodyElement->AsElement(), rootStyle);
  1.2284 +
  1.2285 +  if (CheckOverflow(presContext, bodyStyle->StyleDisplay())) {
  1.2286 +    // tell caller we stole the overflow style from the body element
  1.2287 +    return bodyElement;
  1.2288 +  }
  1.2289 +
  1.2290 +  return nullptr;
  1.2291 +}
  1.2292 +
  1.2293 +nsIFrame*
  1.2294 +nsCSSFrameConstructor::ConstructDocElementFrame(Element*                 aDocElement,
  1.2295 +                                                nsILayoutHistoryState*   aFrameState)
  1.2296 +{
  1.2297 +  NS_PRECONDITION(mFixedContainingBlock,
  1.2298 +                  "No viewport?  Someone forgot to call ConstructRootFrame!");
  1.2299 +  NS_PRECONDITION(mFixedContainingBlock == GetRootFrame(),
  1.2300 +                  "Unexpected mFixedContainingBlock");
  1.2301 +  NS_PRECONDITION(!mDocElementContainingBlock,
  1.2302 +                  "Shouldn't have a doc element containing block here");
  1.2303 +
  1.2304 +  // Make sure to call PropagateScrollToViewport before
  1.2305 +  // SetUpDocElementContainingBlock, since it sets up our scrollbar state
  1.2306 +  // properly.
  1.2307 +#ifdef DEBUG
  1.2308 +  nsIContent* propagatedScrollFrom =
  1.2309 +#endif
  1.2310 +    PropagateScrollToViewport();
  1.2311 +
  1.2312 +  SetUpDocElementContainingBlock(aDocElement);
  1.2313 +
  1.2314 +  NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now");
  1.2315 +
  1.2316 +  nsFrameConstructorState state(mPresShell, mFixedContainingBlock, nullptr,
  1.2317 +                                nullptr, aFrameState);
  1.2318 +  // Initialize the ancestor filter with null for now; we'll push
  1.2319 +  // aDocElement once we finish resolving style for it.
  1.2320 +  state.mTreeMatchContext.InitAncestors(nullptr);
  1.2321 +
  1.2322 +  // XXXbz why, exactly?
  1.2323 +  if (!mTempFrameTreeState)
  1.2324 +    state.mPresShell->CaptureHistoryState(getter_AddRefs(mTempFrameTreeState));
  1.2325 +
  1.2326 +  // Make sure that we'll handle restyles for this document element in
  1.2327 +  // the future.  We need this, because the document element might
  1.2328 +  // have stale restyle bits from a previous frame constructor for
  1.2329 +  // this document.  Unlike in AddFrameConstructionItems, it's safe to
  1.2330 +  // unset all element restyle flags, since we don't have any
  1.2331 +  // siblings.
  1.2332 +  aDocElement->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
  1.2333 +
  1.2334 +  // --------- CREATE AREA OR BOX FRAME -------
  1.2335 +  nsRefPtr<nsStyleContext> styleContext;
  1.2336 +  styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
  1.2337 +                                                         nullptr);
  1.2338 +
  1.2339 +  const nsStyleDisplay* display = styleContext->StyleDisplay();
  1.2340 +
  1.2341 +  // Ensure that our XBL bindings are installed.
  1.2342 +  if (display->mBinding) {
  1.2343 +    // Get the XBL loader.
  1.2344 +    nsresult rv;
  1.2345 +    bool resolveStyle;
  1.2346 +
  1.2347 +    nsXBLService* xblService = nsXBLService::GetInstance();
  1.2348 +    if (!xblService) {
  1.2349 +      return nullptr;
  1.2350 +    }
  1.2351 +
  1.2352 +    nsRefPtr<nsXBLBinding> binding;
  1.2353 +    rv = xblService->LoadBindings(aDocElement, display->mBinding->GetURI(),
  1.2354 +                                  display->mBinding->mOriginPrincipal,
  1.2355 +                                  getter_AddRefs(binding), &resolveStyle);
  1.2356 +    if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
  1.2357 +      return nullptr; // Binding will load asynchronously.
  1.2358 +
  1.2359 +    if (binding) {
  1.2360 +      // For backwards compat, keep firing the root's constructor
  1.2361 +      // after all of its kids' constructors.  So tell the binding
  1.2362 +      // manager about it right now.
  1.2363 +      mDocument->BindingManager()->AddToAttachedQueue(binding);
  1.2364 +    }
  1.2365 +
  1.2366 +    if (resolveStyle) {
  1.2367 +      styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
  1.2368 +                                                             nullptr);
  1.2369 +      display = styleContext->StyleDisplay();
  1.2370 +    }
  1.2371 +  }
  1.2372 +
  1.2373 +  // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
  1.2374 +
  1.2375 +#ifdef DEBUG
  1.2376 +  NS_ASSERTION(!display->IsScrollableOverflow() ||
  1.2377 +               state.mPresContext->IsPaginated() ||
  1.2378 +               propagatedScrollFrom == aDocElement,
  1.2379 +               "Scrollbars should have been propagated to the viewport");
  1.2380 +#endif
  1.2381 +
  1.2382 +  if (MOZ_UNLIKELY(display->mDisplay == NS_STYLE_DISPLAY_NONE)) {
  1.2383 +    SetUndisplayedContent(aDocElement, styleContext);
  1.2384 +    return nullptr;
  1.2385 +  }
  1.2386 +
  1.2387 +  TreeMatchContext::AutoAncestorPusher ancestorPusher(state.mTreeMatchContext);
  1.2388 +  ancestorPusher.PushAncestorAndStyleScope(aDocElement);
  1.2389 +
  1.2390 +  // Make sure to start any background image loads for the root element now.
  1.2391 +  styleContext->StartBackgroundImageLoads();
  1.2392 +
  1.2393 +  nsFrameConstructorSaveState absoluteSaveState;
  1.2394 +  if (mHasRootAbsPosContainingBlock) {
  1.2395 +    // Push the absolute containing block now so we can absolutely position
  1.2396 +    // the root element
  1.2397 +    mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.2398 +    state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
  1.2399 +                                      mDocElementContainingBlock,
  1.2400 +                                      absoluteSaveState);
  1.2401 +  }
  1.2402 +
  1.2403 +  // The rules from CSS 2.1, section 9.2.4, have already been applied
  1.2404 +  // by the style system, so we can assume that display->mDisplay is
  1.2405 +  // either NONE, BLOCK, or TABLE.
  1.2406 +
  1.2407 +  // contentFrame is the primary frame for the root element. newFrame
  1.2408 +  // is the frame that will be the child of the initial containing block.
  1.2409 +  // These are usually the same frame but they can be different, in
  1.2410 +  // particular if the root frame is positioned, in which case
  1.2411 +  // contentFrame is the out-of-flow frame and newFrame is the
  1.2412 +  // placeholder.
  1.2413 +  nsIFrame* contentFrame;
  1.2414 +  nsIFrame* newFrame;
  1.2415 +  bool processChildren = false;
  1.2416 +
  1.2417 +  // Check whether we need to build a XUL box or SVG root frame
  1.2418 +#ifdef MOZ_XUL
  1.2419 +  if (aDocElement->IsXUL()) {
  1.2420 +    contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext);
  1.2421 +    InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
  1.2422 +                        contentFrame);
  1.2423 +    newFrame = contentFrame;
  1.2424 +    processChildren = true;
  1.2425 +  }
  1.2426 +  else
  1.2427 +#endif
  1.2428 +  if (aDocElement->IsSVG()) {
  1.2429 +    if (aDocElement->Tag() != nsGkAtoms::svg) {
  1.2430 +      return nullptr;
  1.2431 +    }
  1.2432 +    // We're going to call the right function ourselves, so no need to give a
  1.2433 +    // function to this FrameConstructionData.
  1.2434 +
  1.2435 +    // XXXbz on the other hand, if we converted this whole function to
  1.2436 +    // FrameConstructionData/Item, then we'd need the right function
  1.2437 +    // here... but would probably be able to get away with less code in this
  1.2438 +    // function in general.
  1.2439 +    // Use a null PendingBinding, since our binding is not in fact pending.
  1.2440 +    static const FrameConstructionData rootSVGData = FCDATA_DECL(0, nullptr);
  1.2441 +    already_AddRefed<nsStyleContext> extraRef =
  1.2442 +      nsRefPtr<nsStyleContext>(styleContext).forget();
  1.2443 +    FrameConstructionItem item(&rootSVGData, aDocElement,
  1.2444 +                               aDocElement->Tag(), kNameSpaceID_SVG,
  1.2445 +                               nullptr, extraRef, true, nullptr);
  1.2446 +
  1.2447 +    nsFrameItems frameItems;
  1.2448 +    contentFrame = ConstructOuterSVG(state, item, mDocElementContainingBlock,
  1.2449 +                                     styleContext->StyleDisplay(),
  1.2450 +                                     frameItems);
  1.2451 +    newFrame = frameItems.FirstChild();
  1.2452 +    NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
  1.2453 +  } else if (display->mDisplay == NS_STYLE_DISPLAY_FLEX) {
  1.2454 +    contentFrame = NS_NewFlexContainerFrame(mPresShell, styleContext);
  1.2455 +    InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
  1.2456 +                        contentFrame);
  1.2457 +    newFrame = contentFrame;
  1.2458 +    processChildren = true;
  1.2459 +  } else if (display->mDisplay == NS_STYLE_DISPLAY_GRID) {
  1.2460 +    contentFrame = NS_NewGridContainerFrame(mPresShell, styleContext);
  1.2461 +    InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock,
  1.2462 +                        contentFrame);
  1.2463 +    newFrame = contentFrame;
  1.2464 +    processChildren = true;
  1.2465 +  } else if (display->mDisplay == NS_STYLE_DISPLAY_TABLE) {
  1.2466 +    // We're going to call the right function ourselves, so no need to give a
  1.2467 +    // function to this FrameConstructionData.
  1.2468 +
  1.2469 +    // XXXbz on the other hand, if we converted this whole function to
  1.2470 +    // FrameConstructionData/Item, then we'd need the right function
  1.2471 +    // here... but would probably be able to get away with less code in this
  1.2472 +    // function in general.
  1.2473 +    // Use a null PendingBinding, since our binding is not in fact pending.
  1.2474 +    static const FrameConstructionData rootTableData = FCDATA_DECL(0, nullptr);
  1.2475 +    already_AddRefed<nsStyleContext> extraRef =
  1.2476 +      nsRefPtr<nsStyleContext>(styleContext).forget();
  1.2477 +    FrameConstructionItem item(&rootTableData, aDocElement,
  1.2478 +                               aDocElement->Tag(), kNameSpaceID_None,
  1.2479 +                               nullptr, extraRef, true, nullptr);
  1.2480 +
  1.2481 +    nsFrameItems frameItems;
  1.2482 +    // if the document is a table then just populate it.
  1.2483 +    contentFrame = ConstructTable(state, item, mDocElementContainingBlock,
  1.2484 +                                  styleContext->StyleDisplay(),
  1.2485 +                                  frameItems);
  1.2486 +    newFrame = frameItems.FirstChild();
  1.2487 +    NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
  1.2488 +  } else {
  1.2489 +    MOZ_ASSERT(display->mDisplay == NS_STYLE_DISPLAY_BLOCK,
  1.2490 +               "Unhandled display type for root element");
  1.2491 +    contentFrame = NS_NewBlockFormattingContext(mPresShell, styleContext);
  1.2492 +    nsFrameItems frameItems;
  1.2493 +    // Use a null PendingBinding, since our binding is not in fact pending.
  1.2494 +    ConstructBlock(state, display, aDocElement,
  1.2495 +                   state.GetGeometricParent(display,
  1.2496 +                                            mDocElementContainingBlock),
  1.2497 +                   mDocElementContainingBlock, styleContext,
  1.2498 +                   &contentFrame, frameItems,
  1.2499 +                   display->IsPositioned(contentFrame) ? contentFrame : nullptr,
  1.2500 +                   nullptr);
  1.2501 +    newFrame = frameItems.FirstChild();
  1.2502 +    NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
  1.2503 +  }
  1.2504 +
  1.2505 +  MOZ_ASSERT(newFrame);
  1.2506 +  MOZ_ASSERT(contentFrame);
  1.2507 +
  1.2508 +  NS_ASSERTION(processChildren ? !mRootElementFrame :
  1.2509 +                 mRootElementFrame == contentFrame,
  1.2510 +               "unexpected mRootElementFrame");
  1.2511 +  mRootElementFrame = contentFrame;
  1.2512 +
  1.2513 +  // Figure out which frame has the main style for the document element,
  1.2514 +  // assigning it to mRootElementStyleFrame.
  1.2515 +  // Backgrounds should be propagated from that frame to the viewport.
  1.2516 +  mRootElementStyleFrame = contentFrame->GetParentStyleContextFrame();
  1.2517 +  bool isChild = mRootElementStyleFrame &&
  1.2518 +                 mRootElementStyleFrame->GetParent() == contentFrame;
  1.2519 +  if (!isChild) {
  1.2520 +    mRootElementStyleFrame = mRootElementFrame;
  1.2521 +  }
  1.2522 +
  1.2523 +  if (processChildren) {
  1.2524 +    // Still need to process the child content
  1.2525 +    nsFrameItems childItems;
  1.2526 +
  1.2527 +    NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame) &&
  1.2528 +                 !contentFrame->IsFrameOfType(nsIFrame::eSVG),
  1.2529 +                 "Only XUL frames should reach here");
  1.2530 +    // Use a null PendingBinding, since our binding is not in fact pending.
  1.2531 +    ProcessChildren(state, aDocElement, styleContext, contentFrame, true,
  1.2532 +                    childItems, false, nullptr);
  1.2533 +
  1.2534 +    // Set the initial child lists
  1.2535 +    contentFrame->SetInitialChildList(kPrincipalList, childItems);
  1.2536 +  }
  1.2537 +
  1.2538 +  // set the primary frame
  1.2539 +  aDocElement->SetPrimaryFrame(contentFrame);
  1.2540 +
  1.2541 +  SetInitialSingleChild(mDocElementContainingBlock, newFrame);
  1.2542 +
  1.2543 +  return newFrame;
  1.2544 +}
  1.2545 +
  1.2546 +
  1.2547 +nsIFrame*
  1.2548 +nsCSSFrameConstructor::ConstructRootFrame()
  1.2549 +{
  1.2550 +  AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
  1.2551 +
  1.2552 +  nsStyleSet *styleSet = mPresShell->StyleSet();
  1.2553 +
  1.2554 +  // Set up our style rule observer.
  1.2555 +  // XXXbz wouldn't this make more sense as part of presshell init?
  1.2556 +  {
  1.2557 +    styleSet->SetBindingManager(mDocument->BindingManager());
  1.2558 +  }
  1.2559 +
  1.2560 +  // --------- BUILD VIEWPORT -----------
  1.2561 +  nsIFrame*                 viewportFrame = nullptr;
  1.2562 +  nsRefPtr<nsStyleContext> viewportPseudoStyle;
  1.2563 +
  1.2564 +  viewportPseudoStyle =
  1.2565 +    styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::viewport, nullptr);
  1.2566 +
  1.2567 +  viewportFrame = NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
  1.2568 +
  1.2569 +  // XXXbz do we _have_ to pass a null content pointer to that frame?
  1.2570 +  // Would it really kill us to pass in the root element or something?
  1.2571 +  // What would that break?
  1.2572 +  viewportFrame->Init(nullptr, nullptr, nullptr);
  1.2573 +
  1.2574 +  // Bind the viewport frame to the root view
  1.2575 +  nsView* rootView = mPresShell->GetViewManager()->GetRootView();
  1.2576 +  viewportFrame->SetView(rootView);
  1.2577 +
  1.2578 +  nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame,
  1.2579 +                                            viewportPseudoStyle, rootView);
  1.2580 +  nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
  1.2581 +                                         rootView);
  1.2582 +
  1.2583 +  // The viewport is the containing block for 'fixed' elements
  1.2584 +  mFixedContainingBlock = viewportFrame;
  1.2585 +  // Make it an absolute container for fixed-pos elements
  1.2586 +  mFixedContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.2587 +  mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
  1.2588 +
  1.2589 +  return viewportFrame;
  1.2590 +}
  1.2591 +
  1.2592 +void
  1.2593 +nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
  1.2594 +{
  1.2595 +  NS_PRECONDITION(aDocElement, "No element?");
  1.2596 +  NS_PRECONDITION(!aDocElement->GetParent(), "Not root content?");
  1.2597 +  NS_PRECONDITION(aDocElement->GetCurrentDoc(), "Not in a document?");
  1.2598 +  NS_PRECONDITION(aDocElement->GetCurrentDoc()->GetRootElement() ==
  1.2599 +                  aDocElement, "Not the root of the document?");
  1.2600 +
  1.2601 +  /*
  1.2602 +    how the root frame hierarchy should look
  1.2603 +
  1.2604 +  Galley presentation, non-XUL, with scrolling:
  1.2605 +
  1.2606 +      ViewportFrame [fixed-cb]
  1.2607 +        nsHTMLScrollFrame
  1.2608 +          nsCanvasFrame [abs-cb]
  1.2609 +            root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
  1.2610 +                                nsTableOuterFrame, nsPlaceholderFrame)
  1.2611 +
  1.2612 +  Galley presentation, XUL
  1.2613 +
  1.2614 +      ViewportFrame [fixed-cb]
  1.2615 +        nsRootBoxFrame
  1.2616 +          root element frame (nsDocElementBoxFrame)
  1.2617 +
  1.2618 +  Print presentation, non-XUL
  1.2619 +
  1.2620 +      ViewportFrame
  1.2621 +        nsSimplePageSequenceFrame
  1.2622 +          nsPageFrame [fixed-cb]
  1.2623 +            nsPageContentFrame
  1.2624 +              nsCanvasFrame [abs-cb]
  1.2625 +                root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
  1.2626 +                                    nsTableOuterFrame, nsPlaceholderFrame)
  1.2627 +
  1.2628 +  Print-preview presentation, non-XUL
  1.2629 +
  1.2630 +      ViewportFrame
  1.2631 +        nsHTMLScrollFrame
  1.2632 +          nsSimplePageSequenceFrame
  1.2633 +            nsPageFrame [fixed-cb]
  1.2634 +              nsPageContentFrame
  1.2635 +                nsCanvasFrame [abs-cb]
  1.2636 +                  root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
  1.2637 +                                      nsTableOuterFrame, nsPlaceholderFrame)
  1.2638 +
  1.2639 +  Print/print preview of XUL is not supported.
  1.2640 +  [fixed-cb]: the default containing block for fixed-pos content
  1.2641 +  [abs-cb]: the default containing block for abs-pos content
  1.2642 +
  1.2643 +  Meaning of nsCSSFrameConstructor fields:
  1.2644 +    mRootElementFrame is "root element frame".  This is the primary frame for
  1.2645 +      the root element.
  1.2646 +    mDocElementContainingBlock is the parent of mRootElementFrame
  1.2647 +      (i.e. nsCanvasFrame or nsRootBoxFrame)
  1.2648 +    mFixedContainingBlock is the [fixed-cb]
  1.2649 +    mGfxScrollFrame is the nsHTMLScrollFrame mentioned above, or null if there isn't one
  1.2650 +    mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't one
  1.2651 +  */
  1.2652 +
  1.2653 +  // --------- CREATE ROOT FRAME -------
  1.2654 +
  1.2655 +
  1.2656 +  // Create the root frame. The document element's frame is a child of the
  1.2657 +  // root frame.
  1.2658 +  //
  1.2659 +  // The root frame serves two purposes:
  1.2660 +  // - reserves space for any margins needed for the document element's frame
  1.2661 +  // - renders the document element's background. This ensures the background covers
  1.2662 +  //   the entire canvas as specified by the CSS2 spec
  1.2663 +
  1.2664 +  nsPresContext* presContext = mPresShell->GetPresContext();
  1.2665 +  bool isPaginated = presContext->IsRootPaginatedDocument();
  1.2666 +  nsIFrame* viewportFrame = mFixedContainingBlock;
  1.2667 +  nsStyleContext* viewportPseudoStyle = viewportFrame->StyleContext();
  1.2668 +
  1.2669 +  nsIFrame* rootFrame = nullptr;
  1.2670 +  nsIAtom* rootPseudo;
  1.2671 +
  1.2672 +  if (!isPaginated) {
  1.2673 +#ifdef MOZ_XUL
  1.2674 +    if (aDocElement->IsXUL())
  1.2675 +    {
  1.2676 +      // pass a temporary stylecontext, the correct one will be set later
  1.2677 +      rootFrame = NS_NewRootBoxFrame(mPresShell, viewportPseudoStyle);
  1.2678 +    } else
  1.2679 +#endif
  1.2680 +    {
  1.2681 +      // pass a temporary stylecontext, the correct one will be set later
  1.2682 +      rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
  1.2683 +      mHasRootAbsPosContainingBlock = true;
  1.2684 +    }
  1.2685 +
  1.2686 +    rootPseudo = nsCSSAnonBoxes::canvas;
  1.2687 +    mDocElementContainingBlock = rootFrame;
  1.2688 +  } else {
  1.2689 +    // Create a page sequence frame
  1.2690 +    rootFrame = NS_NewSimplePageSequenceFrame(mPresShell, viewportPseudoStyle);
  1.2691 +    mPageSequenceFrame = rootFrame;
  1.2692 +    rootPseudo = nsCSSAnonBoxes::pageSequence;
  1.2693 +  }
  1.2694 +
  1.2695 +
  1.2696 +  // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
  1.2697 +
  1.2698 +  // If the device supports scrolling (e.g., in galley mode on the screen and
  1.2699 +  // for print-preview, but not when printing), then create a scroll frame that
  1.2700 +  // will act as the scrolling mechanism for the viewport.
  1.2701 +  // XXX Do we even need a viewport when printing to a printer?
  1.2702 +
  1.2703 +  bool isHTML = aDocElement->IsHTML();
  1.2704 +  bool isXUL = false;
  1.2705 +
  1.2706 +  if (!isHTML) {
  1.2707 +    isXUL = aDocElement->IsXUL();
  1.2708 +  }
  1.2709 +
  1.2710 +  // Never create scrollbars for XUL documents
  1.2711 +  bool isScrollable = isPaginated ? presContext->HasPaginatedScrolling() : !isXUL;
  1.2712 +
  1.2713 +  // We no longer need to do overflow propagation here. It's taken care of
  1.2714 +  // when we construct frames for the element whose overflow might be
  1.2715 +  // propagated
  1.2716 +  NS_ASSERTION(!isScrollable || !isXUL,
  1.2717 +               "XUL documents should never be scrollable - see above");
  1.2718 +
  1.2719 +  nsIFrame* newFrame = rootFrame;
  1.2720 +  nsRefPtr<nsStyleContext> rootPseudoStyle;
  1.2721 +  // we must create a state because if the scrollbars are GFX it needs the
  1.2722 +  // state to build the scrollbar frames.
  1.2723 +  nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
  1.2724 +
  1.2725 +  // Start off with the viewport as parent; we'll adjust it as needed.
  1.2726 +  nsIFrame* parentFrame = viewportFrame;
  1.2727 +
  1.2728 +  nsStyleSet* styleSet = mPresShell->StyleSet();
  1.2729 +  // If paginated, make sure we don't put scrollbars in
  1.2730 +  if (!isScrollable) {
  1.2731 +    rootPseudoStyle = styleSet->ResolveAnonymousBoxStyle(rootPseudo,
  1.2732 +                                                         viewportPseudoStyle);
  1.2733 +  } else {
  1.2734 +      if (rootPseudo == nsCSSAnonBoxes::canvas) {
  1.2735 +        rootPseudo = nsCSSAnonBoxes::scrolledCanvas;
  1.2736 +      } else {
  1.2737 +        NS_ASSERTION(rootPseudo == nsCSSAnonBoxes::pageSequence,
  1.2738 +                     "Unknown root pseudo");
  1.2739 +        rootPseudo = nsCSSAnonBoxes::scrolledPageSequence;
  1.2740 +      }
  1.2741 +
  1.2742 +      // Build the frame. We give it the content we are wrapping which is the
  1.2743 +      // document element, the root frame, the parent view port frame, and we
  1.2744 +      // should get back the new frame and the scrollable view if one was
  1.2745 +      // created.
  1.2746 +
  1.2747 +      // resolve a context for the scrollframe
  1.2748 +      nsRefPtr<nsStyleContext>  styleContext;
  1.2749 +      styleContext = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::viewportScroll,
  1.2750 +                                                        viewportPseudoStyle);
  1.2751 +
  1.2752 +      // Note that the viewport scrollframe is always built with
  1.2753 +      // overflow:auto style. This forces the scroll frame to create
  1.2754 +      // anonymous content for both scrollbars. This is necessary even
  1.2755 +      // if the HTML or BODY elements are overriding the viewport
  1.2756 +      // scroll style to 'hidden' --- dynamic style changes might put
  1.2757 +      // scrollbars back on the viewport and we don't want to have to
  1.2758 +      // reframe the viewport to create the scrollbar content.
  1.2759 +      newFrame = nullptr;
  1.2760 +      rootPseudoStyle = BeginBuildingScrollFrame( state,
  1.2761 +                                                  aDocElement,
  1.2762 +                                                  styleContext,
  1.2763 +                                                  viewportFrame,
  1.2764 +                                                  rootPseudo,
  1.2765 +                                                  true,
  1.2766 +                                                  newFrame);
  1.2767 +      parentFrame = newFrame;
  1.2768 +      mGfxScrollFrame = newFrame;
  1.2769 +  }
  1.2770 +
  1.2771 +  rootFrame->SetStyleContextWithoutNotification(rootPseudoStyle);
  1.2772 +  rootFrame->Init(aDocElement, parentFrame, nullptr);
  1.2773 +
  1.2774 +  if (isScrollable) {
  1.2775 +    FinishBuildingScrollFrame(parentFrame, rootFrame);
  1.2776 +  }
  1.2777 +
  1.2778 +  if (isPaginated) { // paginated
  1.2779 +    // Create the first page
  1.2780 +    // Set the initial child lists
  1.2781 +    nsIFrame* canvasFrame;
  1.2782 +    nsIFrame* pageFrame =
  1.2783 +      ConstructPageFrame(mPresShell, presContext, rootFrame, nullptr,
  1.2784 +                         canvasFrame);
  1.2785 +    SetInitialSingleChild(rootFrame, pageFrame);
  1.2786 +
  1.2787 +    // The eventual parent of the document element frame.
  1.2788 +    // XXX should this be set for every new page (in ConstructPageFrame)?
  1.2789 +    mDocElementContainingBlock = canvasFrame;
  1.2790 +    mHasRootAbsPosContainingBlock = true;
  1.2791 +  }
  1.2792 +
  1.2793 +  if (viewportFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
  1.2794 +    SetInitialSingleChild(viewportFrame, newFrame);
  1.2795 +  } else {
  1.2796 +    nsFrameList newFrameList(newFrame, newFrame);
  1.2797 +    viewportFrame->AppendFrames(kPrincipalList, newFrameList);
  1.2798 +  }
  1.2799 +}
  1.2800 +
  1.2801 +nsIFrame*
  1.2802 +nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*  aPresShell,
  1.2803 +                                          nsPresContext* aPresContext,
  1.2804 +                                          nsIFrame*      aParentFrame,
  1.2805 +                                          nsIFrame*      aPrevPageFrame,
  1.2806 +                                          nsIFrame*&     aCanvasFrame)
  1.2807 +{
  1.2808 +  nsStyleContext* parentStyleContext = aParentFrame->StyleContext();
  1.2809 +  nsStyleSet *styleSet = aPresShell->StyleSet();
  1.2810 +
  1.2811 +  nsRefPtr<nsStyleContext> pagePseudoStyle;
  1.2812 +  pagePseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::page,
  1.2813 +                                                       parentStyleContext);
  1.2814 +
  1.2815 +  nsIFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
  1.2816 +
  1.2817 +  // Initialize the page frame and force it to have a view. This makes printing of
  1.2818 +  // the pages easier and faster.
  1.2819 +  pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
  1.2820 +
  1.2821 +  nsRefPtr<nsStyleContext> pageContentPseudoStyle;
  1.2822 +  pageContentPseudoStyle =
  1.2823 +    styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageContent,
  1.2824 +                                       pagePseudoStyle);
  1.2825 +
  1.2826 +  nsIFrame* pageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
  1.2827 +
  1.2828 +  // Initialize the page content frame and force it to have a view. Also make it the
  1.2829 +  // containing block for fixed elements which are repeated on every page.
  1.2830 +  nsIFrame* prevPageContentFrame = nullptr;
  1.2831 +  if (aPrevPageFrame) {
  1.2832 +    prevPageContentFrame = aPrevPageFrame->GetFirstPrincipalChild();
  1.2833 +    NS_ASSERTION(prevPageContentFrame, "missing page content frame");
  1.2834 +  }
  1.2835 +  pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
  1.2836 +  SetInitialSingleChild(pageFrame, pageContentFrame);
  1.2837 +  mFixedContainingBlock = pageContentFrame;
  1.2838 +  // Make it an absolute container for fixed-pos elements
  1.2839 +  mFixedContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.2840 +  mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
  1.2841 +
  1.2842 +  nsRefPtr<nsStyleContext> canvasPseudoStyle;
  1.2843 +  canvasPseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
  1.2844 +                                                         pageContentPseudoStyle);
  1.2845 +
  1.2846 +  aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
  1.2847 +
  1.2848 +  nsIFrame* prevCanvasFrame = nullptr;
  1.2849 +  if (prevPageContentFrame) {
  1.2850 +    prevCanvasFrame = prevPageContentFrame->GetFirstPrincipalChild();
  1.2851 +    NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
  1.2852 +  }
  1.2853 +  aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
  1.2854 +  SetInitialSingleChild(pageContentFrame, aCanvasFrame);
  1.2855 +  return pageFrame;
  1.2856 +}
  1.2857 +
  1.2858 +/* static */
  1.2859 +nsIFrame*
  1.2860 +nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell*    aPresShell,
  1.2861 +                                                 nsIContent*      aContent,
  1.2862 +                                                 nsIFrame*        aFrame,
  1.2863 +                                                 nsStyleContext*  aStyleContext,
  1.2864 +                                                 nsIFrame*        aParentFrame,
  1.2865 +                                                 nsIFrame*        aPrevInFlow,
  1.2866 +                                                 nsFrameState     aTypeBit)
  1.2867 +{
  1.2868 +  nsRefPtr<nsStyleContext> placeholderStyle = aPresShell->StyleSet()->
  1.2869 +    ResolveStyleForNonElement(aStyleContext->GetParent());
  1.2870 +
  1.2871 +  // The placeholder frame gets a pseudo style context
  1.2872 +  nsPlaceholderFrame* placeholderFrame =
  1.2873 +    (nsPlaceholderFrame*)NS_NewPlaceholderFrame(aPresShell, placeholderStyle,
  1.2874 +                                                aTypeBit);
  1.2875 +
  1.2876 +  placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
  1.2877 +
  1.2878 +  // The placeholder frame has a pointer back to the out-of-flow frame
  1.2879 +  placeholderFrame->SetOutOfFlowFrame(aFrame);
  1.2880 +
  1.2881 +  aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
  1.2882 +
  1.2883 +  // Add mapping from absolutely positioned frame to its placeholder frame
  1.2884 +  aPresShell->FrameManager()->RegisterPlaceholderFrame(placeholderFrame);
  1.2885 +
  1.2886 +  return placeholderFrame;
  1.2887 +}
  1.2888 +
  1.2889 +// Clears any lazy bits set in the range [aStartContent, aEndContent).  If
  1.2890 +// aEndContent is null, that means to clear bits in all siblings starting with
  1.2891 +// aStartContent.  aStartContent must not be null unless aEndContent is also
  1.2892 +// null.  We do this so that when new children are inserted under elements whose
  1.2893 +// frame is a leaf the new children don't cause us to try to construct frames
  1.2894 +// for the existing children again.
  1.2895 +static inline void
  1.2896 +ClearLazyBits(nsIContent* aStartContent, nsIContent* aEndContent)
  1.2897 +{
  1.2898 +  NS_PRECONDITION(aStartContent || !aEndContent,
  1.2899 +                  "Must have start child if we have an end child");
  1.2900 +  for (nsIContent* cur = aStartContent; cur != aEndContent;
  1.2901 +       cur = cur->GetNextSibling()) {
  1.2902 +    cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
  1.2903 +  }
  1.2904 +}
  1.2905 +
  1.2906 +nsIFrame*
  1.2907 +nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
  1.2908 +                                            FrameConstructionItem&   aItem,
  1.2909 +                                            nsIFrame*                aParentFrame,
  1.2910 +                                            const nsStyleDisplay*    aStyleDisplay,
  1.2911 +                                            nsFrameItems&            aFrameItems)
  1.2912 +{
  1.2913 +  nsIContent* const content = aItem.mContent;
  1.2914 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.2915 +
  1.2916 +  // Construct a frame-based listbox or combobox
  1.2917 +  dom::HTMLSelectElement* sel = dom::HTMLSelectElement::FromContent(content);
  1.2918 +  MOZ_ASSERT(sel);
  1.2919 +  if (sel->IsCombobox()) {
  1.2920 +    // Construct a frame-based combo box.
  1.2921 +    // The frame-based combo box is built out of three parts. A display area, a button and
  1.2922 +    // a dropdown list. The display area and button are created through anonymous content.
  1.2923 +    // The drop-down list's frame is created explicitly. The combobox frame shares its content
  1.2924 +    // with the drop-down list.
  1.2925 +    nsFrameState flags = NS_BLOCK_FLOAT_MGR;
  1.2926 +    nsIFrame* comboboxFrame = NS_NewComboboxControlFrame(mPresShell, styleContext, flags);
  1.2927 +
  1.2928 +    // Save the history state so we don't restore during construction
  1.2929 +    // since the complete tree is required before we restore.
  1.2930 +    nsILayoutHistoryState *historyState = aState.mFrameState;
  1.2931 +    aState.mFrameState = nullptr;
  1.2932 +    // Initialize the combobox frame
  1.2933 +    InitAndRestoreFrame(aState, content,
  1.2934 +                        aState.GetGeometricParent(aStyleDisplay, aParentFrame),
  1.2935 +                        comboboxFrame);
  1.2936 +
  1.2937 +    aState.AddChild(comboboxFrame, aFrameItems, content, styleContext,
  1.2938 +                    aParentFrame);
  1.2939 +
  1.2940 +    nsIComboboxControlFrame* comboBox = do_QueryFrame(comboboxFrame);
  1.2941 +    NS_ASSERTION(comboBox, "NS_NewComboboxControlFrame returned frame that "
  1.2942 +                 "doesn't implement nsIComboboxControlFrame");
  1.2943 +
  1.2944 +    // Resolve pseudo element style for the dropdown list
  1.2945 +    nsRefPtr<nsStyleContext> listStyle;
  1.2946 +    listStyle = mPresShell->StyleSet()->
  1.2947 +      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::dropDownList, styleContext);
  1.2948 +
  1.2949 +    // Create a listbox
  1.2950 +    nsIFrame* listFrame = NS_NewListControlFrame(mPresShell, listStyle);
  1.2951 +
  1.2952 +    // Notify the listbox that it is being used as a dropdown list.
  1.2953 +    nsIListControlFrame * listControlFrame = do_QueryFrame(listFrame);
  1.2954 +    if (listControlFrame) {
  1.2955 +      listControlFrame->SetComboboxFrame(comboboxFrame);
  1.2956 +    }
  1.2957 +    // Notify combobox that it should use the listbox as it's popup
  1.2958 +    comboBox->SetDropDown(listFrame);
  1.2959 +
  1.2960 +    NS_ASSERTION(!listFrame->IsPositioned(),
  1.2961 +                 "Ended up with positioned dropdown list somehow.");
  1.2962 +    NS_ASSERTION(!listFrame->IsFloating(),
  1.2963 +                 "Ended up with floating dropdown list somehow.");
  1.2964 +
  1.2965 +    // Initialize the scroll frame positioned. Note that it is NOT
  1.2966 +    // initialized as absolutely positioned.
  1.2967 +    nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(mPresShell, styleContext, flags);
  1.2968 +
  1.2969 +    InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
  1.2970 +                          comboboxFrame, listStyle, true,
  1.2971 +                          aItem.mPendingBinding, aFrameItems);
  1.2972 +
  1.2973 +    NS_ASSERTION(listFrame->GetView(), "ListFrame's view is nullptr");
  1.2974 +
  1.2975 +    // Create display and button frames from the combobox's anonymous content.
  1.2976 +    // The anonymous content is appended to existing anonymous content for this
  1.2977 +    // element (the scrollbars).
  1.2978 +
  1.2979 +    nsFrameItems childItems;
  1.2980 +    CreateAnonymousFrames(aState, content, comboboxFrame,
  1.2981 +                          aItem.mPendingBinding, childItems);
  1.2982 +
  1.2983 +    comboboxFrame->SetInitialChildList(kPrincipalList, childItems);
  1.2984 +
  1.2985 +    // Initialize the additional popup child list which contains the
  1.2986 +    // dropdown list frame.
  1.2987 +    nsFrameItems popupItems;
  1.2988 +    popupItems.AddChild(listFrame);
  1.2989 +    comboboxFrame->SetInitialChildList(nsIFrame::kSelectPopupList,
  1.2990 +                                       popupItems);
  1.2991 +
  1.2992 +    aState.mFrameState = historyState;
  1.2993 +    if (aState.mFrameState) {
  1.2994 +      // Restore frame state for the entire subtree of |comboboxFrame|.
  1.2995 +      RestoreFrameState(comboboxFrame, aState.mFrameState);
  1.2996 +    }
  1.2997 +    return comboboxFrame;
  1.2998 +  }
  1.2999 +
  1.3000 +  // Listbox, not combobox
  1.3001 +  nsIFrame* listFrame = NS_NewListControlFrame(mPresShell, styleContext);
  1.3002 +
  1.3003 +  nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(
  1.3004 +      mPresShell, styleContext, NS_BLOCK_FLOAT_MGR);
  1.3005 +
  1.3006 +  // ******* this code stolen from Initialze ScrollFrame ********
  1.3007 +  // please adjust this code to use BuildScrollFrame.
  1.3008 +
  1.3009 +  InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
  1.3010 +                        aParentFrame, styleContext, false,
  1.3011 +                        aItem.mPendingBinding, aFrameItems);
  1.3012 +
  1.3013 +  return listFrame;
  1.3014 +}
  1.3015 +
  1.3016 +/**
  1.3017 + * Used to be InitializeScrollFrame but now it's only used for the select tag
  1.3018 + * But the select tag should really be fixed to use GFX scrollbars that can
  1.3019 + * be create with BuildScrollFrame.
  1.3020 + */
  1.3021 +nsresult
  1.3022 +nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
  1.3023 +                                             nsIFrame*                scrollFrame,
  1.3024 +                                             nsIFrame*                scrolledFrame,
  1.3025 +                                             nsIContent*              aContent,
  1.3026 +                                             nsIFrame*                aParentFrame,
  1.3027 +                                             nsStyleContext*          aStyleContext,
  1.3028 +                                             bool                     aBuildCombobox,
  1.3029 +                                             PendingBinding*          aPendingBinding,
  1.3030 +                                             nsFrameItems&            aFrameItems)
  1.3031 +{
  1.3032 +  const nsStyleDisplay* display = aStyleContext->StyleDisplay();
  1.3033 +
  1.3034 +  // Initialize it
  1.3035 +  nsIFrame* geometricParent = aState.GetGeometricParent(display, aParentFrame);
  1.3036 +
  1.3037 +  // We don't call InitAndRestoreFrame for scrollFrame because we can only
  1.3038 +  // restore the frame state after its parts have been created (in particular,
  1.3039 +  // the scrollable view). So we have to split Init and Restore.
  1.3040 +
  1.3041 +  // Initialize the frame
  1.3042 +  scrollFrame->Init(aContent, geometricParent, nullptr);
  1.3043 +
  1.3044 +  if (!aBuildCombobox) {
  1.3045 +    aState.AddChild(scrollFrame, aFrameItems, aContent,
  1.3046 +                    aStyleContext, aParentFrame);
  1.3047 +  }
  1.3048 +
  1.3049 +  if (aBuildCombobox) {
  1.3050 +    nsContainerFrame::CreateViewForFrame(scrollFrame, true);
  1.3051 +  }
  1.3052 +
  1.3053 +  BuildScrollFrame(aState, aContent, aStyleContext, scrolledFrame,
  1.3054 +                   geometricParent, scrollFrame);
  1.3055 +
  1.3056 +  if (aState.mFrameState) {
  1.3057 +    // Restore frame state for the scroll frame
  1.3058 +    RestoreFrameStateFor(scrollFrame, aState.mFrameState);
  1.3059 +  }
  1.3060 +
  1.3061 +  // Process children
  1.3062 +  nsFrameItems                childItems;
  1.3063 +
  1.3064 +  ProcessChildren(aState, aContent, aStyleContext, scrolledFrame, false,
  1.3065 +                  childItems, false, aPendingBinding);
  1.3066 +
  1.3067 +  // Set the scrolled frame's initial child lists
  1.3068 +  scrolledFrame->SetInitialChildList(kPrincipalList, childItems);
  1.3069 +  return NS_OK;
  1.3070 +}
  1.3071 +
  1.3072 +nsIFrame*
  1.3073 +nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
  1.3074 +                                              FrameConstructionItem&   aItem,
  1.3075 +                                              nsIFrame*                aParentFrame,
  1.3076 +                                              const nsStyleDisplay*    aStyleDisplay,
  1.3077 +                                              nsFrameItems&            aFrameItems)
  1.3078 +{
  1.3079 +  nsIContent* const content = aItem.mContent;
  1.3080 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.3081 +
  1.3082 +  nsIFrame* fieldsetFrame = NS_NewFieldSetFrame(mPresShell, styleContext);
  1.3083 +
  1.3084 +  // Initialize it
  1.3085 +  InitAndRestoreFrame(aState, content,
  1.3086 +                      aState.GetGeometricParent(aStyleDisplay, aParentFrame),
  1.3087 +                      fieldsetFrame);
  1.3088 +
  1.3089 +  // Resolve style and initialize the frame
  1.3090 +  nsRefPtr<nsStyleContext> fieldsetContentStyle;
  1.3091 +  fieldsetContentStyle = mPresShell->StyleSet()->
  1.3092 +    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent, styleContext);
  1.3093 +
  1.3094 +  const nsStyleDisplay* fieldsetContentDisplay = fieldsetContentStyle->StyleDisplay();
  1.3095 +  bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
  1.3096 +  nsIFrame* scrollFrame = nullptr;
  1.3097 +  if (isScrollable) {
  1.3098 +    fieldsetContentStyle =
  1.3099 +      BeginBuildingScrollFrame(aState, content, fieldsetContentStyle,
  1.3100 +                               fieldsetFrame, nsCSSAnonBoxes::scrolledContent,
  1.3101 +                               false, scrollFrame);
  1.3102 +  }
  1.3103 +
  1.3104 +  nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle,
  1.3105 +                                          NS_BLOCK_FLOAT_MGR |
  1.3106 +                                          NS_BLOCK_MARGIN_ROOT);
  1.3107 +  InitAndRestoreFrame(aState, content,
  1.3108 +    scrollFrame ? scrollFrame : fieldsetFrame, blockFrame);
  1.3109 +
  1.3110 +  aState.AddChild(fieldsetFrame, aFrameItems, content, styleContext, aParentFrame);
  1.3111 +
  1.3112 +  // Process children
  1.3113 +  nsFrameConstructorSaveState absoluteSaveState;
  1.3114 +  nsFrameItems                childItems;
  1.3115 +
  1.3116 +  blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.3117 +  if (fieldsetFrame->IsPositioned()) {
  1.3118 +    aState.PushAbsoluteContainingBlock(blockFrame, fieldsetFrame, absoluteSaveState);
  1.3119 +  }
  1.3120 +
  1.3121 +  ProcessChildren(aState, content, styleContext, blockFrame, true,
  1.3122 +                  childItems, true, aItem.mPendingBinding);
  1.3123 +
  1.3124 +  nsFrameItems fieldsetKids;
  1.3125 +  fieldsetKids.AddChild(scrollFrame ? scrollFrame : blockFrame);
  1.3126 +
  1.3127 +  for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
  1.3128 +    nsIFrame* child = e.get();
  1.3129 +    if (child->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame) {
  1.3130 +      // We want the legend to be the first frame in the fieldset child list.
  1.3131 +      // That way the EventStateManager will do the right thing when tabbing
  1.3132 +      // from a selection point within the legend (bug 236071), which is
  1.3133 +      // used for implementing legend access keys (bug 81481).
  1.3134 +      // GetAdjustedParentFrame() below depends on this frame order.
  1.3135 +      childItems.RemoveFrame(child);
  1.3136 +      // Make sure to reparent the legend so it has the fieldset as the parent.
  1.3137 +      fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
  1.3138 +      if (scrollFrame) {
  1.3139 +        StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary(
  1.3140 +            child, blockFrame);
  1.3141 +      }
  1.3142 +      break;
  1.3143 +    }
  1.3144 +  }
  1.3145 +
  1.3146 +  if (isScrollable) {
  1.3147 +    FinishBuildingScrollFrame(scrollFrame, blockFrame);
  1.3148 +  }
  1.3149 +
  1.3150 +  // Set the inner frame's initial child lists
  1.3151 +  blockFrame->SetInitialChildList(kPrincipalList, childItems);
  1.3152 +
  1.3153 +  // Set the outer frame's initial child list
  1.3154 +  fieldsetFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
  1.3155 +
  1.3156 +  fieldsetFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
  1.3157 +
  1.3158 +  // Our new frame returned is the outer frame, which is the fieldset frame.
  1.3159 +  return fieldsetFrame;
  1.3160 +}
  1.3161 +
  1.3162 +static nsIFrame*
  1.3163 +FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame)
  1.3164 +{
  1.3165 +  for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
  1.3166 +    NS_ASSERTION(f->IsGeneratedContentFrame(),
  1.3167 +                 "should not have exited generated content");
  1.3168 +    nsIAtom* pseudo = f->StyleContext()->GetPseudo();
  1.3169 +    if (pseudo == nsCSSPseudoElements::before ||
  1.3170 +        pseudo == nsCSSPseudoElements::after)
  1.3171 +      return f;
  1.3172 +  }
  1.3173 +  return nullptr;
  1.3174 +}
  1.3175 +
  1.3176 +#define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
  1.3177 +#define FULL_CTOR_FCDATA(_flags, _func)                             \
  1.3178 +  { _flags | FCDATA_FUNC_IS_FULL_CTOR, { nullptr }, _func, nullptr }
  1.3179 +
  1.3180 +/* static */
  1.3181 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3182 +nsCSSFrameConstructor::FindTextData(nsIFrame* aParentFrame)
  1.3183 +{
  1.3184 +  if (aParentFrame && IsFrameForSVG(aParentFrame)) {
  1.3185 +    nsIFrame *ancestorFrame =
  1.3186 +      nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
  1.3187 +    if (ancestorFrame) {
  1.3188 +      static const FrameConstructionData sSVGTextData =
  1.3189 +        FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_SVG_TEXT,
  1.3190 +                    NS_NewTextFrame);
  1.3191 +      if (ancestorFrame->IsSVGText()) {
  1.3192 +        return &sSVGTextData;
  1.3193 +      }
  1.3194 +    }
  1.3195 +    return nullptr;
  1.3196 +  }
  1.3197 +
  1.3198 +  static const FrameConstructionData sTextData =
  1.3199 +    FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewTextFrame);
  1.3200 +  return &sTextData;
  1.3201 +}
  1.3202 +
  1.3203 +void
  1.3204 +nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
  1.3205 +                                          nsFrameConstructorState& aState,
  1.3206 +                                          nsIContent*              aContent,
  1.3207 +                                          nsIFrame*                aParentFrame,
  1.3208 +                                          nsStyleContext*          aStyleContext,
  1.3209 +                                          nsFrameItems&            aFrameItems)
  1.3210 +{
  1.3211 +  NS_PRECONDITION(aData, "Must have frame construction data");
  1.3212 +
  1.3213 +  nsIFrame* newFrame = (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext);
  1.3214 +
  1.3215 +  InitAndRestoreFrame(aState, aContent, aParentFrame, newFrame);
  1.3216 +
  1.3217 +  // We never need to create a view for a text frame.
  1.3218 +
  1.3219 +  if (newFrame->IsGeneratedContentFrame()) {
  1.3220 +    nsAutoPtr<nsGenConInitializer> initializer;
  1.3221 +    initializer =
  1.3222 +      static_cast<nsGenConInitializer*>(
  1.3223 +        aContent->UnsetProperty(nsGkAtoms::genConInitializerProperty));
  1.3224 +    if (initializer) {
  1.3225 +      if (initializer->mNode->InitTextFrame(initializer->mList,
  1.3226 +              FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
  1.3227 +        (this->*(initializer->mDirtyAll))();
  1.3228 +      }
  1.3229 +      initializer->mNode.forget();
  1.3230 +    }
  1.3231 +  }
  1.3232 +
  1.3233 +  // Add the newly constructed frame to the flow
  1.3234 +  aFrameItems.AddChild(newFrame);
  1.3235 +
  1.3236 +  if (!aState.mCreatingExtraFrames)
  1.3237 +    aContent->SetPrimaryFrame(newFrame);
  1.3238 +}
  1.3239 +
  1.3240 +/* static */
  1.3241 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3242 +nsCSSFrameConstructor::FindDataByInt(int32_t aInt,
  1.3243 +                                     Element* aElement,
  1.3244 +                                     nsStyleContext* aStyleContext,
  1.3245 +                                     const FrameConstructionDataByInt* aDataPtr,
  1.3246 +                                     uint32_t aDataLength)
  1.3247 +{
  1.3248 +  for (const FrameConstructionDataByInt *curData = aDataPtr,
  1.3249 +         *endData = aDataPtr + aDataLength;
  1.3250 +       curData != endData;
  1.3251 +       ++curData) {
  1.3252 +    if (curData->mInt == aInt) {
  1.3253 +      const FrameConstructionData* data = &curData->mData;
  1.3254 +      if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
  1.3255 +        return data->mFunc.mDataGetter(aElement, aStyleContext);
  1.3256 +      }
  1.3257 +
  1.3258 +      return data;
  1.3259 +    }
  1.3260 +  }
  1.3261 +
  1.3262 +  return nullptr;
  1.3263 +}
  1.3264 +
  1.3265 +/* static */
  1.3266 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3267 +nsCSSFrameConstructor::FindDataByTag(nsIAtom* aTag,
  1.3268 +                                     Element* aElement,
  1.3269 +                                     nsStyleContext* aStyleContext,
  1.3270 +                                     const FrameConstructionDataByTag* aDataPtr,
  1.3271 +                                     uint32_t aDataLength)
  1.3272 +{
  1.3273 +  for (const FrameConstructionDataByTag *curData = aDataPtr,
  1.3274 +         *endData = aDataPtr + aDataLength;
  1.3275 +       curData != endData;
  1.3276 +       ++curData) {
  1.3277 +    if (*curData->mTag == aTag) {
  1.3278 +      const FrameConstructionData* data = &curData->mData;
  1.3279 +      if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
  1.3280 +        return data->mFunc.mDataGetter(aElement, aStyleContext);
  1.3281 +      }
  1.3282 +
  1.3283 +      return data;
  1.3284 +    }
  1.3285 +  }
  1.3286 +
  1.3287 +  return nullptr;
  1.3288 +}
  1.3289 +
  1.3290 +#define SUPPRESS_FCDATA() FCDATA_DECL(FCDATA_SUPPRESS_FRAME, nullptr)
  1.3291 +#define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) }
  1.3292 +#define SIMPLE_INT_CHAIN(_int, _func)                       \
  1.3293 +  { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) }
  1.3294 +#define COMPLEX_INT_CREATE(_int, _func)         \
  1.3295 +  { _int, FULL_CTOR_FCDATA(0, _func) }
  1.3296 +
  1.3297 +#define SIMPLE_TAG_CREATE(_tag, _func)          \
  1.3298 +  { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) }
  1.3299 +#define SIMPLE_TAG_CHAIN(_tag, _func)                                   \
  1.3300 +  { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER,  _func) }
  1.3301 +#define COMPLEX_TAG_CREATE(_tag, _func)             \
  1.3302 +  { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
  1.3303 +
  1.3304 +static bool
  1.3305 +IsFrameForFieldSet(nsIFrame* aFrame, nsIAtom* aFrameType)
  1.3306 +{
  1.3307 +  nsIAtom* pseudo = aFrame->StyleContext()->GetPseudo();
  1.3308 +  if (pseudo == nsCSSAnonBoxes::fieldsetContent ||
  1.3309 +      pseudo == nsCSSAnonBoxes::scrolledContent) {
  1.3310 +    return IsFrameForFieldSet(aFrame->GetParent(), aFrame->GetParent()->GetType());
  1.3311 +  }
  1.3312 +  return aFrameType == nsGkAtoms::fieldSetFrame;
  1.3313 +}
  1.3314 +
  1.3315 +/* static */
  1.3316 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3317 +nsCSSFrameConstructor::FindHTMLData(Element* aElement,
  1.3318 +                                    nsIAtom* aTag,
  1.3319 +                                    int32_t aNameSpaceID,
  1.3320 +                                    nsIFrame* aParentFrame,
  1.3321 +                                    nsStyleContext* aStyleContext)
  1.3322 +{
  1.3323 +  // Ignore the tag if it's not HTML content and if it doesn't extend (via XBL)
  1.3324 +  // a valid HTML namespace.  This check must match the one in
  1.3325 +  // ShouldHaveFirstLineStyle.
  1.3326 +  if (aNameSpaceID != kNameSpaceID_XHTML) {
  1.3327 +    return nullptr;
  1.3328 +  }
  1.3329 +
  1.3330 +  NS_ASSERTION(!aParentFrame ||
  1.3331 +               aParentFrame->StyleContext()->GetPseudo() !=
  1.3332 +                 nsCSSAnonBoxes::fieldsetContent ||
  1.3333 +               aParentFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame,
  1.3334 +               "Unexpected parent for fieldset content anon box");
  1.3335 +  if (aTag == nsGkAtoms::legend &&
  1.3336 +      (!aParentFrame ||
  1.3337 +       !IsFrameForFieldSet(aParentFrame, aParentFrame->GetType()) ||
  1.3338 +       !aElement->GetParent() ||
  1.3339 +       !aElement->GetParent()->IsHTML(nsGkAtoms::fieldset) ||
  1.3340 +       aStyleContext->StyleDisplay()->IsFloatingStyle() ||
  1.3341 +       aStyleContext->StyleDisplay()->IsAbsolutelyPositionedStyle())) {
  1.3342 +    // <legend> is only special inside fieldset, check both the frame tree
  1.3343 +    // parent and content tree parent due to XBL issues. For floated or
  1.3344 +    // absolutely positioned legends we want to construct by display type and
  1.3345 +    // not do special legend stuff.
  1.3346 +    // XXXbz it would be nice if we could just decide this based on the parent
  1.3347 +    // tag, and hence just use a SIMPLE_TAG_CHAIN for legend below, but the
  1.3348 +    // fact that with XBL we could end up with this legend element in some
  1.3349 +    // totally weird insertion point makes that chancy, I think.
  1.3350 +    return nullptr;
  1.3351 +  }
  1.3352 +
  1.3353 +  static const FrameConstructionDataByTag sHTMLData[] = {
  1.3354 +    SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
  1.3355 +    SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
  1.3356 +                     nsCSSFrameConstructor::FindImgData),
  1.3357 +    { &nsGkAtoms::br,
  1.3358 +      FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_LINE_BREAK,
  1.3359 +                  NS_NewBRFrame) },
  1.3360 +    SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame),
  1.3361 +    SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData),
  1.3362 +    SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame),
  1.3363 +    COMPLEX_TAG_CREATE(select, &nsCSSFrameConstructor::ConstructSelectFrame),
  1.3364 +    SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData),
  1.3365 +    SIMPLE_TAG_CHAIN(applet, nsCSSFrameConstructor::FindObjectData),
  1.3366 +    SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
  1.3367 +    COMPLEX_TAG_CREATE(fieldset,
  1.3368 +                       &nsCSSFrameConstructor::ConstructFieldSetFrame),
  1.3369 +    { &nsGkAtoms::legend,
  1.3370 +      FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
  1.3371 +                  NS_NewLegendFrame) },
  1.3372 +    SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
  1.3373 +    SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
  1.3374 +    { &nsGkAtoms::button,
  1.3375 +      FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES,
  1.3376 +                                 NS_NewHTMLButtonControlFrame,
  1.3377 +                                 nsCSSAnonBoxes::buttonContent) },
  1.3378 +    SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
  1.3379 +    SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
  1.3380 +    SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
  1.3381 +    SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame),
  1.3382 +    SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame)
  1.3383 +  };
  1.3384 +
  1.3385 +  return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
  1.3386 +                       ArrayLength(sHTMLData));
  1.3387 +}
  1.3388 +
  1.3389 +/* static */
  1.3390 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3391 +nsCSSFrameConstructor::FindImgData(Element* aElement,
  1.3392 +                                   nsStyleContext* aStyleContext)
  1.3393 +{
  1.3394 +  if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aStyleContext)) {
  1.3395 +    return nullptr;
  1.3396 +  }
  1.3397 +
  1.3398 +  static const FrameConstructionData sImgData = SIMPLE_FCDATA(NS_NewImageFrame);
  1.3399 +  return &sImgData;
  1.3400 +}
  1.3401 +
  1.3402 +/* static */
  1.3403 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3404 +nsCSSFrameConstructor::FindImgControlData(Element* aElement,
  1.3405 +                                          nsStyleContext* aStyleContext)
  1.3406 +{
  1.3407 +  if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aStyleContext)) {
  1.3408 +    return nullptr;
  1.3409 +  }
  1.3410 +
  1.3411 +  static const FrameConstructionData sImgControlData =
  1.3412 +    SIMPLE_FCDATA(NS_NewImageControlFrame);
  1.3413 +  return &sImgControlData;
  1.3414 +}
  1.3415 +
  1.3416 +/* static */
  1.3417 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3418 +nsCSSFrameConstructor::FindInputData(Element* aElement,
  1.3419 +                                     nsStyleContext* aStyleContext)
  1.3420 +{
  1.3421 +  static const FrameConstructionDataByInt sInputData[] = {
  1.3422 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_CHECKBOX, NS_NewGfxCheckboxControlFrame),
  1.3423 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_RADIO, NS_NewGfxRadioControlFrame),
  1.3424 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_FILE, NS_NewFileControlFrame),
  1.3425 +    SIMPLE_INT_CHAIN(NS_FORM_INPUT_IMAGE,
  1.3426 +                     nsCSSFrameConstructor::FindImgControlData),
  1.3427 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_EMAIL, NS_NewTextControlFrame),
  1.3428 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_SEARCH, NS_NewTextControlFrame),
  1.3429 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_TEXT, NS_NewTextControlFrame),
  1.3430 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_TEL, NS_NewTextControlFrame),
  1.3431 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_URL, NS_NewTextControlFrame),
  1.3432 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_RANGE, NS_NewRangeFrame),
  1.3433 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_PASSWORD, NS_NewTextControlFrame),
  1.3434 +    { NS_FORM_INPUT_COLOR,
  1.3435 +      FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewColorControlFrame,
  1.3436 +                                 nsCSSAnonBoxes::buttonContent) },
  1.3437 +    // TODO: this is temporary until a frame is written: bug 635240.
  1.3438 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_NUMBER, NS_NewNumberControlFrame),
  1.3439 +    // TODO: this is temporary until a frame is written: bug 773205.
  1.3440 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_DATE, NS_NewTextControlFrame),
  1.3441 +    // TODO: this is temporary until a frame is written: bug 773205
  1.3442 +    SIMPLE_INT_CREATE(NS_FORM_INPUT_TIME, NS_NewTextControlFrame),
  1.3443 +    { NS_FORM_INPUT_SUBMIT,
  1.3444 +      FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
  1.3445 +                                 nsCSSAnonBoxes::buttonContent) },
  1.3446 +    { NS_FORM_INPUT_RESET,
  1.3447 +      FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
  1.3448 +                                 nsCSSAnonBoxes::buttonContent) },
  1.3449 +    { NS_FORM_INPUT_BUTTON,
  1.3450 +      FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
  1.3451 +                                 nsCSSAnonBoxes::buttonContent) }
  1.3452 +    // Keeping hidden inputs out of here on purpose for so they get frames by
  1.3453 +    // display (in practice, none).
  1.3454 +  };
  1.3455 +
  1.3456 +  nsCOMPtr<nsIFormControl> control = do_QueryInterface(aElement);
  1.3457 +  NS_ASSERTION(control, "input doesn't implement nsIFormControl?");
  1.3458 +
  1.3459 +  return FindDataByInt(control->GetType(), aElement, aStyleContext,
  1.3460 +                       sInputData, ArrayLength(sInputData));
  1.3461 +}
  1.3462 +
  1.3463 +/* static */
  1.3464 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3465 +nsCSSFrameConstructor::FindObjectData(Element* aElement,
  1.3466 +                                      nsStyleContext* aStyleContext)
  1.3467 +{
  1.3468 +  // GetDisplayedType isn't necessarily nsIObjectLoadingContent::TYPE_NULL for
  1.3469 +  // cases when the object is broken/suppressed/etc (e.g. a broken image), but
  1.3470 +  // we want to treat those cases as TYPE_NULL
  1.3471 +  uint32_t type;
  1.3472 +  if (aElement->State().HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
  1.3473 +                                              NS_EVENT_STATE_USERDISABLED |
  1.3474 +                                              NS_EVENT_STATE_SUPPRESSED)) {
  1.3475 +    type = nsIObjectLoadingContent::TYPE_NULL;
  1.3476 +  } else {
  1.3477 +    nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(aElement));
  1.3478 +    NS_ASSERTION(objContent,
  1.3479 +                 "applet, embed and object must implement "
  1.3480 +                 "nsIObjectLoadingContent!");
  1.3481 +
  1.3482 +    objContent->GetDisplayedType(&type);
  1.3483 +  }
  1.3484 +
  1.3485 +  static const FrameConstructionDataByInt sObjectData[] = {
  1.3486 +    SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,
  1.3487 +                      NS_NewEmptyFrame),
  1.3488 +    SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_PLUGIN,
  1.3489 +                      NS_NewObjectFrame),
  1.3490 +    SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_IMAGE,
  1.3491 +                      NS_NewImageFrame),
  1.3492 +    SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,
  1.3493 +                      NS_NewSubDocumentFrame)
  1.3494 +    // Nothing for TYPE_NULL so we'll construct frames by display there
  1.3495 +  };
  1.3496 +
  1.3497 +  return FindDataByInt((int32_t)type, aElement, aStyleContext,
  1.3498 +                       sObjectData, ArrayLength(sObjectData));
  1.3499 +}
  1.3500 +
  1.3501 +/* static */
  1.3502 +const nsCSSFrameConstructor::FrameConstructionData*
  1.3503 +nsCSSFrameConstructor::FindCanvasData(Element* aElement,
  1.3504 +                                      nsStyleContext* aStyleContext)
  1.3505 +{
  1.3506 +  // We want to check whether script is enabled on the document that
  1.3507 +  // could be painting to the canvas.  That's the owner document of
  1.3508 +  // the canvas, except when the owner document is a static document,
  1.3509 +  // in which case it's the original document it was cloned from.
  1.3510 +  nsIDocument* doc = aElement->OwnerDoc();
  1.3511 +  if (doc->IsStaticDocument()) {
  1.3512 +    doc = doc->GetOriginalDocument();
  1.3513 +  }
  1.3514 +  if (!doc->IsScriptEnabled()) {
  1.3515 +    return nullptr;
  1.3516 +  }
  1.3517 +
  1.3518 +  static const FrameConstructionData sCanvasData =
  1.3519 +    FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewHTMLCanvasFrame,
  1.3520 +                               nsCSSAnonBoxes::htmlCanvasContent);
  1.3521 +  return &sCanvasData;
  1.3522 +}
  1.3523 +
  1.3524 +void
  1.3525 +nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
  1.3526 +                                                      nsFrameConstructorState& aState,
  1.3527 +                                                      nsIFrame* aParentFrame,
  1.3528 +                                                      nsFrameItems& aFrameItems)
  1.3529 +{
  1.3530 +  const FrameConstructionData* data = aItem.mFCData;
  1.3531 +  NS_ASSERTION(data, "Must have frame construction data");
  1.3532 +
  1.3533 +  uint32_t bits = data->mBits;
  1.3534 +
  1.3535 +  NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),
  1.3536 +               "Should have dealt with this inside the data finder");
  1.3537 +
  1.3538 +  // Some sets of bits are not compatible with each other
  1.3539 +#define CHECK_ONLY_ONE_BIT(_bit1, _bit2)               \
  1.3540 +  NS_ASSERTION(!(bits & _bit1) || !(bits & _bit2),     \
  1.3541 +               "Only one of these bits should be set")
  1.3542 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_FORCE_NULL_ABSPOS_CONTAINER);
  1.3543 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_WRAP_KIDS_IN_BLOCKS);
  1.3544 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_MAY_NEED_SCROLLFRAME);
  1.3545 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_IS_POPUP);
  1.3546 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_SKIP_ABSPOS_PUSH);
  1.3547 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
  1.3548 +                     FCDATA_DISALLOW_GENERATED_CONTENT);
  1.3549 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_ALLOW_BLOCK_STYLES);
  1.3550 +  CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
  1.3551 +                     FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
  1.3552 +  CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS,
  1.3553 +                     FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
  1.3554 +#undef CHECK_ONLY_ONE_BIT
  1.3555 +  NS_ASSERTION(!(bits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) ||
  1.3556 +               ((bits & FCDATA_FUNC_IS_FULL_CTOR) &&
  1.3557 +                data->mFullConstructor ==
  1.3558 +                  &nsCSSFrameConstructor::ConstructNonScrollableBlock),
  1.3559 +               "Unexpected FCDATA_FORCED_NON_SCROLLABLE_BLOCK flag");
  1.3560 +
  1.3561 +  // Don't create a subdocument frame for iframes if we're creating extra frames
  1.3562 +  if (aState.mCreatingExtraFrames && aItem.mContent->IsHTML() &&
  1.3563 +      aItem.mContent->Tag() == nsGkAtoms::iframe)
  1.3564 +  {
  1.3565 +    return;
  1.3566 +  }
  1.3567 +
  1.3568 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.3569 +  const nsStyleDisplay* display = styleContext->StyleDisplay();
  1.3570 +  nsIContent* const content = aItem.mContent;
  1.3571 +
  1.3572 +  // Get the parent of the content and check if it is a XBL children element.
  1.3573 +  // Push the children element as an ancestor here because it does
  1.3574 +  // not have a frame and would not otherwise be pushed as an ancestor. It is
  1.3575 +  // necessary to do so in order to correctly handle style resolution on
  1.3576 +  // descendants.
  1.3577 +  nsIContent* parent = content->GetParent();
  1.3578 +  TreeMatchContext::AutoAncestorPusher
  1.3579 +    insertionPointPusher(aState.mTreeMatchContext);
  1.3580 +  if (parent && nsContentUtils::IsContentInsertionPoint(parent)) {
  1.3581 +    if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
  1.3582 +      insertionPointPusher.PushAncestorAndStyleScope(parent);
  1.3583 +    } else {
  1.3584 +      insertionPointPusher.PushStyleScope(parent);
  1.3585 +    }
  1.3586 +  }
  1.3587 +
  1.3588 +  // Push the content as a style ancestor now, so we don't have to do
  1.3589 +  // it in our various full-constructor functions.  In particular,
  1.3590 +  // since a number of full-constructor functions don't actually call
  1.3591 +  // ProcessChildren in some cases (e.g. for CSS anonymous table boxes
  1.3592 +  // or for situations where only anonymouse children are having
  1.3593 +  // frames constructed), this is the best place to bottleneck the
  1.3594 +  // pushing of the content instead of having to do it in multiple
  1.3595 +  // places.
  1.3596 +  TreeMatchContext::AutoAncestorPusher
  1.3597 +    ancestorPusher(aState.mTreeMatchContext);
  1.3598 +  if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
  1.3599 +    ancestorPusher.PushAncestorAndStyleScope(content);
  1.3600 +  } else {
  1.3601 +    ancestorPusher.PushStyleScope(content);
  1.3602 +  }
  1.3603 +
  1.3604 +  nsIFrame* newFrame;
  1.3605 +  nsIFrame* primaryFrame;
  1.3606 +  if (bits & FCDATA_FUNC_IS_FULL_CTOR) {
  1.3607 +    newFrame =
  1.3608 +      (this->*(data->mFullConstructor))(aState, aItem, aParentFrame,
  1.3609 +                                        display, aFrameItems);
  1.3610 +    MOZ_ASSERT(newFrame, "Full constructor failed");
  1.3611 +    primaryFrame = newFrame;
  1.3612 +  } else {
  1.3613 +    newFrame =
  1.3614 +      (*data->mFunc.mCreationFunc)(mPresShell, styleContext);
  1.3615 +
  1.3616 +    bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
  1.3617 +    bool isPopup = aItem.mIsPopup;
  1.3618 +    NS_ASSERTION(!isPopup ||
  1.3619 +                 (aState.mPopupItems.containingBlock &&
  1.3620 +                  aState.mPopupItems.containingBlock->GetType() ==
  1.3621 +                    nsGkAtoms::popupSetFrame),
  1.3622 +                 "Should have a containing block here!");
  1.3623 +
  1.3624 +    nsIFrame* geometricParent =
  1.3625 +      isPopup ? aState.mPopupItems.containingBlock :
  1.3626 +      (allowOutOfFlow ? aState.GetGeometricParent(display, aParentFrame)
  1.3627 +                      : aParentFrame);
  1.3628 +
  1.3629 +    // Must init frameToAddToList to null, since it's inout
  1.3630 +    nsIFrame* frameToAddToList = nullptr;
  1.3631 +    if ((bits & FCDATA_MAY_NEED_SCROLLFRAME) &&
  1.3632 +        display->IsScrollableOverflow()) {
  1.3633 +      BuildScrollFrame(aState, content, styleContext, newFrame,
  1.3634 +                       geometricParent, frameToAddToList);
  1.3635 +    } else {
  1.3636 +      InitAndRestoreFrame(aState, content, geometricParent, newFrame);
  1.3637 +      // See whether we need to create a view
  1.3638 +      nsContainerFrame::CreateViewForFrame(newFrame, false);
  1.3639 +      frameToAddToList = newFrame;
  1.3640 +    }
  1.3641 +
  1.3642 +    // Use frameToAddToList as the primary frame.  In the non-scrollframe case
  1.3643 +    // they're equal, but in the scrollframe case newFrame is the scrolled
  1.3644 +    // frame, while frameToAddToList is the scrollframe (and should be the
  1.3645 +    // primary frame).
  1.3646 +    primaryFrame = frameToAddToList;
  1.3647 +
  1.3648 +    // If we need to create a block formatting context to wrap our
  1.3649 +    // kids, do it now.
  1.3650 +    const nsStyleDisplay* maybeAbsoluteContainingBlockDisplay = display;
  1.3651 +    nsIFrame* maybeAbsoluteContainingBlock = newFrame;
  1.3652 +    nsIFrame* possiblyLeafFrame = newFrame;
  1.3653 +    if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS) {
  1.3654 +      nsRefPtr<nsStyleContext> blockContext;
  1.3655 +      blockContext =
  1.3656 +        mPresShell->StyleSet()->ResolveAnonymousBoxStyle(*data->mAnonBoxPseudo,
  1.3657 +                                                         styleContext);
  1.3658 +      nsIFrame* blockFrame =
  1.3659 +        NS_NewBlockFormattingContext(mPresShell, blockContext);
  1.3660 +
  1.3661 +      InitAndRestoreFrame(aState, content, newFrame, blockFrame);
  1.3662 +
  1.3663 +      SetInitialSingleChild(newFrame, blockFrame);
  1.3664 +
  1.3665 +      // Now figure out whether newFrame or blockFrame should be the
  1.3666 +      // absolute container.  It should be the latter if it's
  1.3667 +      // positioned, otherwise the former.
  1.3668 +      const nsStyleDisplay* blockDisplay = blockContext->StyleDisplay();
  1.3669 +      if (blockDisplay->IsPositioned(blockFrame)) {
  1.3670 +        maybeAbsoluteContainingBlockDisplay = blockDisplay;
  1.3671 +        maybeAbsoluteContainingBlock = blockFrame;
  1.3672 +      }
  1.3673 +
  1.3674 +      // Our kids should go into the blockFrame
  1.3675 +      newFrame = blockFrame;
  1.3676 +    }
  1.3677 +
  1.3678 +    aState.AddChild(frameToAddToList, aFrameItems, content, styleContext,
  1.3679 +                    aParentFrame, allowOutOfFlow, allowOutOfFlow, isPopup);
  1.3680 +
  1.3681 +#ifdef MOZ_XUL
  1.3682 +    // Icky XUL stuff, sadly
  1.3683 +
  1.3684 +    if (aItem.mIsRootPopupgroup) {
  1.3685 +      NS_ASSERTION(nsIRootBox::GetRootBox(mPresShell) &&
  1.3686 +                   nsIRootBox::GetRootBox(mPresShell)->GetPopupSetFrame() ==
  1.3687 +                     newFrame,
  1.3688 +                   "Unexpected PopupSetFrame");
  1.3689 +      aState.mPopupItems.containingBlock = newFrame;
  1.3690 +      aState.mHavePendingPopupgroup = false;
  1.3691 +    }
  1.3692 +#endif /* MOZ_XUL */
  1.3693 +
  1.3694 +    // Process the child content if requested
  1.3695 +    nsFrameItems childItems;
  1.3696 +    nsFrameConstructorSaveState absoluteSaveState;
  1.3697 +
  1.3698 +    if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
  1.3699 +      aState.PushAbsoluteContainingBlock(nullptr, nullptr, absoluteSaveState);
  1.3700 +    } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
  1.3701 +      nsIFrame* cb = maybeAbsoluteContainingBlock;
  1.3702 +      cb->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
  1.3703 +      // This check is identical to nsStyleDisplay::IsPositioned except without
  1.3704 +      // the assertion that the style display and frame match. When constructing
  1.3705 +      // scroll frames we intentionally use the style display for the outer, but
  1.3706 +      // make the inner the containing block.
  1.3707 +      if ((maybeAbsoluteContainingBlockDisplay->IsAbsolutelyPositionedStyle() ||
  1.3708 +           maybeAbsoluteContainingBlockDisplay->IsRelativelyPositionedStyle() ||
  1.3709 +           (maybeAbsoluteContainingBlockDisplay->HasTransformStyle() &&
  1.3710 +            cb->IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) ||
  1.3711 +           maybeAbsoluteContainingBlockDisplay->HasPerspectiveStyle()) &&
  1.3712 +          !cb->IsSVGText()) {
  1.3713 +        aState.PushAbsoluteContainingBlock(cb, cb, absoluteSaveState);
  1.3714 +      }
  1.3715 +    }
  1.3716 +
  1.3717 +    if (!aItem.mAnonChildren.IsEmpty()) {
  1.3718 +      NS_ASSERTION(!(bits & FCDATA_USE_CHILD_ITEMS),
  1.3719 +                   "We should not have both anonymous and non-anonymous "
  1.3720 +                   "children in a given FrameConstructorItem");
  1.3721 +      AddFCItemsForAnonymousContent(aState, newFrame, aItem.mAnonChildren,
  1.3722 +                                    aItem.mChildItems);
  1.3723 +      bits |= FCDATA_USE_CHILD_ITEMS;
  1.3724 +    }
  1.3725 +
  1.3726 +    if (bits & FCDATA_USE_CHILD_ITEMS) {
  1.3727 +      nsFrameConstructorSaveState floatSaveState;
  1.3728 +
  1.3729 +      if (ShouldSuppressFloatingOfDescendants(newFrame)) {
  1.3730 +        aState.PushFloatContainingBlock(nullptr, floatSaveState);
  1.3731 +      } else if (newFrame->IsFloatContainingBlock()) {
  1.3732 +        aState.PushFloatContainingBlock(newFrame, floatSaveState);
  1.3733 +      }
  1.3734 +      ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
  1.3735 +                                  childItems);
  1.3736 +    } else {
  1.3737 +      // Process the child frames.
  1.3738 +      ProcessChildren(aState, content, styleContext, newFrame,
  1.3739 +                      !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
  1.3740 +                      childItems,
  1.3741 +                      (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0,
  1.3742 +                      aItem.mPendingBinding, possiblyLeafFrame);
  1.3743 +    }
  1.3744 +
  1.3745 +#ifdef MOZ_XUL
  1.3746 +    // More icky XUL stuff
  1.3747 +    if (aItem.mNameSpaceID == kNameSpaceID_XUL &&
  1.3748 +        (aItem.mTag == nsGkAtoms::treechildren || // trees always need titletips
  1.3749 +         content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
  1.3750 +         content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
  1.3751 +      nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
  1.3752 +      if (rootBox) {
  1.3753 +        rootBox->AddTooltipSupport(content);
  1.3754 +      }
  1.3755 +    }
  1.3756 +#endif
  1.3757 +
  1.3758 +    if (bits & FCDATA_WRAP_KIDS_IN_BLOCKS) {
  1.3759 +      nsFrameItems newItems;
  1.3760 +      nsFrameItems currentBlockItems;
  1.3761 +      nsIFrame* f;
  1.3762 +      while ((f = childItems.FirstChild()) != nullptr) {
  1.3763 +        bool wrapFrame = IsInlineFrame(f) || IsFramePartOfIBSplit(f);
  1.3764 +        if (!wrapFrame) {
  1.3765 +          FlushAccumulatedBlock(aState, content, newFrame,
  1.3766 +                                currentBlockItems, newItems);
  1.3767 +        }
  1.3768 +
  1.3769 +        childItems.RemoveFrame(f);
  1.3770 +        if (wrapFrame) {
  1.3771 +          currentBlockItems.AddChild(f);
  1.3772 +        } else {
  1.3773 +          newItems.AddChild(f);
  1.3774 +        }
  1.3775 +      }
  1.3776 +      FlushAccumulatedBlock(aState, content, newFrame,
  1.3777 +                            currentBlockItems, newItems);
  1.3778 +
  1.3779 +      if (childItems.NotEmpty()) {
  1.3780 +        // an error must have occurred, delete unprocessed frames
  1.3781 +        childItems.DestroyFrames();
  1.3782 +      }
  1.3783 +
  1.3784 +      childItems = newItems;
  1.3785 +    }
  1.3786 +
  1.3787 +    // Set the frame's initial child list
  1.3788 +    // Note that MathML depends on this being called even if
  1.3789 +    // childItems is empty!
  1.3790 +    newFrame->SetInitialChildList(kPrincipalList, childItems);
  1.3791 +  }
  1.3792 +
  1.3793 +  NS_ASSERTION(newFrame->IsFrameOfType(nsIFrame::eLineParticipant) ==
  1.3794 +               ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
  1.3795 +               "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
  1.3796 +
  1.3797 +  if (aItem.mIsAnonymousContentCreatorContent) {
  1.3798 +    primaryFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
  1.3799 +  }
  1.3800 +
  1.3801 +  // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
  1.3802 +  // generated content that doesn't have one yet.  Note that we have to examine
  1.3803 +  // the frame bit, because by this point mIsGeneratedContent has been cleared
  1.3804 +  // on aItem.
  1.3805 +  if ((!aState.mCreatingExtraFrames ||
  1.3806 +       ((primaryFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) &&
  1.3807 +        !aItem.mContent->GetPrimaryFrame())) &&
  1.3808 +       !(bits & FCDATA_SKIP_FRAMESET)) {
  1.3809 +    aItem.mContent->SetPrimaryFrame(primaryFrame);
  1.3810 +  }
  1.3811 +}
  1.3812 +
  1.3813 +// after the node has been constructed and initialized create any
  1.3814 +// anonymous content a node needs.
  1.3815 +nsresult
  1.3816 +nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
  1.3817 +                                             nsIContent*              aParent,
  1.3818 +                                             nsIFrame*                aParentFrame,
  1.3819 +                                             PendingBinding*          aPendingBinding,
  1.3820 +                                             nsFrameItems&            aChildItems)
  1.3821 +{
  1.3822 +  nsAutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> newAnonymousItems;
  1.3823 +  nsresult rv = GetAnonymousContent(aParent, aParentFrame, newAnonymousItems);
  1.3824 +  NS_ENSURE_SUCCESS(rv, rv);
  1.3825 +
  1.3826 +  uint32_t count = newAnonymousItems.Length();
  1.3827 +  if (count == 0) {
  1.3828 +    return NS_OK;
  1.3829 +  }
  1.3830 +
  1.3831 +  nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
  1.3832 +                                                           aPendingBinding);
  1.3833 +  TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
  1.3834 +  if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
  1.3835 +    ancestorPusher.PushAncestorAndStyleScope(aParent->AsElement());
  1.3836 +  } else {
  1.3837 +    ancestorPusher.PushStyleScope(aParent->AsElement());
  1.3838 +  }
  1.3839 +
  1.3840 +  nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
  1.3841 +  NS_ASSERTION(creator,
  1.3842 +               "How can that happen if we have nodes to construct frames for?");
  1.3843 +
  1.3844 +  for (uint32_t i=0; i < count; i++) {
  1.3845 +    nsIContent* content = newAnonymousItems[i].mContent;
  1.3846 +    NS_ASSERTION(content, "null anonymous content?");
  1.3847 +    NS_ASSERTION(!newAnonymousItems[i].mStyleContext, "Unexpected style context");
  1.3848 +    NS_ASSERTION(newAnonymousItems[i].mChildren.IsEmpty(),
  1.3849 +                 "This method is not currently used with frames that implement "
  1.3850 +                 "nsIAnonymousContentCreator::CreateAnonymousContent to "
  1.3851 +                 "output a list where the items have their own children");
  1.3852 +
  1.3853 +    nsIFrame* newFrame = creator->CreateFrameFor(content);
  1.3854 +    if (newFrame) {
  1.3855 +      NS_ASSERTION(content->GetPrimaryFrame(),
  1.3856 +                   "Content must have a primary frame now");
  1.3857 +      newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
  1.3858 +      aChildItems.AddChild(newFrame);
  1.3859 +    } else {
  1.3860 +      FrameConstructionItemList items;
  1.3861 +      {
  1.3862 +        // Skip flex item style-fixup during our AddFrameConstructionItems() call:
  1.3863 +        TreeMatchContext::AutoFlexItemStyleFixupSkipper
  1.3864 +          flexItemStyleFixupSkipper(aState.mTreeMatchContext);
  1.3865 +
  1.3866 +        AddFrameConstructionItems(aState, content, true, aParentFrame, items);
  1.3867 +      }
  1.3868 +      ConstructFramesFromItemList(aState, items, aParentFrame, aChildItems);
  1.3869 +    }
  1.3870 +  }
  1.3871 +
  1.3872 +  return NS_OK;
  1.3873 +}
  1.3874 +
  1.3875 +static void
  1.3876 +SetFlagsOnSubtree(nsIContent *aNode, uintptr_t aFlagsToSet)
  1.3877 +{
  1.3878 +#ifdef DEBUG
  1.3879 +  // Make sure that the node passed to us doesn't have any XBL children
  1.3880 +  {
  1.3881 +    FlattenedChildIterator iter(aNode);
  1.3882 +    NS_ASSERTION(!iter.XBLInvolved() || !iter.GetNextChild(),
  1.3883 +                 "The node should not have any XBL children");
  1.3884 +  }
  1.3885 +#endif
  1.3886 +
  1.3887 +  // Set the flag on the node itself
  1.3888 +  aNode->SetFlags(aFlagsToSet);
  1.3889 +
  1.3890 +  // Set the flag on all of its children recursively
  1.3891 +  uint32_t count;
  1.3892 +  nsIContent * const *children = aNode->GetChildArray(&count);
  1.3893 +
  1.3894 +  for (uint32_t index = 0; index < count; ++index) {
  1.3895 +    SetFlagsOnSubtree(children[index], aFlagsToSet);
  1.3896 +  }
  1.3897 +}
  1.3898 +
  1.3899 +/**
  1.3900 + * This function takes a tree of nsIAnonymousContentCreator::ContentInfo
  1.3901 + * objects where the nsIContent nodes have just been created, and appends the
  1.3902 + * nsIContent children in the tree to their parent. The leaf nsIContent objects
  1.3903 + * are appended first to minimize the number of notifications that are sent
  1.3904 + * out (i.e. by appending as many descendants as posible while their parent is
  1.3905 + * not yet in the document tree).
  1.3906 + *
  1.3907 + * This function is used simply as a convenience so that implementations of
  1.3908 + * nsIAnonymousContentCreator::CreateAnonymousContent don't all have to have
  1.3909 + * their own code to connect the elements that they create.
  1.3910 + */
  1.3911 +static void
  1.3912 +ConnectAnonymousTreeDescendants(nsIContent* aParent,
  1.3913 +                                nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
  1.3914 +{
  1.3915 +  uint32_t count = aContent.Length();
  1.3916 +  for (uint32_t i=0; i < count; i++) {
  1.3917 +    nsIContent* content = aContent[i].mContent;
  1.3918 +    NS_ASSERTION(content, "null anonymous content?");
  1.3919 +
  1.3920 +    ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
  1.3921 +
  1.3922 +    aParent->AppendChildTo(content, false);
  1.3923 +  }
  1.3924 +}
  1.3925 +
  1.3926 +nsresult
  1.3927 +nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
  1.3928 +                                           nsIFrame* aParentFrame,
  1.3929 +                                           nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
  1.3930 +{
  1.3931 +  nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
  1.3932 +  if (!creator)
  1.3933 +    return NS_OK;
  1.3934 +
  1.3935 +  nsresult rv = creator->CreateAnonymousContent(aContent);
  1.3936 +  NS_ENSURE_SUCCESS(rv, rv);
  1.3937 +
  1.3938 +  uint32_t count = aContent.Length();
  1.3939 +  for (uint32_t i=0; i < count; i++) {
  1.3940 +    // get our child's content and set its parent to our content
  1.3941 +    nsIContent* content = aContent[i].mContent;
  1.3942 +    NS_ASSERTION(content, "null anonymous content?");
  1.3943 +
  1.3944 +    // least-surprise CSS binding until we do the SVG specified
  1.3945 +    // cascading rules for <svg:use> - bug 265894
  1.3946 +    if (aParentFrame->GetType() == nsGkAtoms::svgUseFrame) {
  1.3947 +      content->SetFlags(NODE_IS_ANONYMOUS_ROOT);
  1.3948 +    } else {
  1.3949 +      content->SetIsNativeAnonymousRoot();
  1.3950 +    }
  1.3951 +
  1.3952 +    ConnectAnonymousTreeDescendants(content, aContent[i].mChildren);
  1.3953 +
  1.3954 +    bool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
  1.3955 +    rv = content->BindToTree(mDocument, aParent, aParent, true);
  1.3956 +    // If the anonymous content creator requested that the content should be
  1.3957 +    // editable, honor its request.
  1.3958 +    // We need to set the flag on the whole subtree, because existing
  1.3959 +    // children's flags have already been set as part of the BindToTree operation.
  1.3960 +    if (anonContentIsEditable) {
  1.3961 +      NS_ASSERTION(aParentFrame->GetType() == nsGkAtoms::textInputFrame,
  1.3962 +                   "We only expect this for anonymous content under a text control frame");
  1.3963 +      SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
  1.3964 +    }
  1.3965 +    if (NS_FAILED(rv)) {
  1.3966 +      content->UnbindFromTree();
  1.3967 +      return rv;
  1.3968 +    }
  1.3969 +  }
  1.3970 +
  1.3971 +  return NS_OK;
  1.3972 +}
  1.3973 +
  1.3974 +static
  1.3975 +bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
  1.3976 +{
  1.3977 +  return (aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX ||
  1.3978 +#ifdef MOZ_XUL
  1.3979 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_XUL_GRID ||
  1.3980 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_STACK ||
  1.3981 +#endif
  1.3982 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_BOX
  1.3983 +#ifdef MOZ_XUL
  1.3984 +          || aDisplay->mDisplay == NS_STYLE_DISPLAY_XUL_GRID ||
  1.3985 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_STACK ||
  1.3986 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_XUL_GRID_GROUP ||
  1.3987 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_XUL_GRID_LINE ||
  1.3988 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_DECK ||
  1.3989 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_POPUP ||
  1.3990 +          aDisplay->mDisplay == NS_STYLE_DISPLAY_GROUPBOX
  1.3991 +#endif
  1.3992 +          );
  1.3993 +}
  1.3994 +
  1.3995 +
  1.3996 +// XUL frames are not allowed to be out of flow.
  1.3997 +#define SIMPLE_XUL_FCDATA(_func)                                        \
  1.3998 +  FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH,    \
  1.3999 +              _func)
  1.4000 +#define SCROLLABLE_XUL_FCDATA(_func)                                    \
  1.4001 +  FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |   \
  1.4002 +              FCDATA_MAY_NEED_SCROLLFRAME, _func)
  1.4003 +// .. but we allow some XUL frames to be _containers_ for out-of-flow content
  1.4004 +// (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
  1.4005 +#define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)                   \
  1.4006 +  FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
  1.4007 +              FCDATA_MAY_NEED_SCROLLFRAME, _func)
  1.4008 +
  1.4009 +#define SIMPLE_XUL_CREATE(_tag, _func)            \
  1.4010 +  { &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) }
  1.4011 +#define SCROLLABLE_XUL_CREATE(_tag, _func)            \
  1.4012 +  { &nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func) }
  1.4013 +#define SIMPLE_XUL_INT_CREATE(_int, _func)      \
  1.4014 +  { _int, SIMPLE_XUL_FCDATA(_func) }
  1.4015 +#define SCROLLABLE_XUL_INT_CREATE(_int, _func)                          \
  1.4016 +  { _int, SCROLLABLE_XUL_FCDATA(_func) }
  1.4017 +#define SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(_int, _func)         \
  1.4018 +  { _int, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) }
  1.4019 +
  1.4020 +static
  1.4021 +nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell,
  1.4022 +                             nsStyleContext* aStyleContext)
  1.4023 +{
  1.4024 +  nsCOMPtr<nsBoxLayout> layout;
  1.4025 +  NS_NewGridLayout2(aPresShell, getter_AddRefs(layout));
  1.4026 +  return NS_NewBoxFrame(aPresShell, aStyleContext, false, layout);
  1.4027 +}
  1.4028 +
  1.4029 +/* static */
  1.4030 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4031 +nsCSSFrameConstructor::FindXULTagData(Element* aElement,
  1.4032 +                                      nsIAtom* aTag,
  1.4033 +                                      int32_t aNameSpaceID,
  1.4034 +                                      nsStyleContext* aStyleContext)
  1.4035 +{
  1.4036 +  if (aNameSpaceID != kNameSpaceID_XUL) {
  1.4037 +    return nullptr;
  1.4038 +  }
  1.4039 +
  1.4040 +  static const FrameConstructionDataByTag sXULTagData[] = {
  1.4041 +#ifdef MOZ_XUL
  1.4042 +    SCROLLABLE_XUL_CREATE(button, NS_NewButtonBoxFrame),
  1.4043 +    SCROLLABLE_XUL_CREATE(checkbox, NS_NewButtonBoxFrame),
  1.4044 +    SCROLLABLE_XUL_CREATE(radio, NS_NewButtonBoxFrame),
  1.4045 +    SCROLLABLE_XUL_CREATE(autorepeatbutton, NS_NewAutoRepeatBoxFrame),
  1.4046 +    SCROLLABLE_XUL_CREATE(titlebar, NS_NewTitleBarFrame),
  1.4047 +    SCROLLABLE_XUL_CREATE(resizer, NS_NewResizerFrame),
  1.4048 +    SIMPLE_XUL_CREATE(image, NS_NewImageBoxFrame),
  1.4049 +    SIMPLE_XUL_CREATE(spring, NS_NewLeafBoxFrame),
  1.4050 +    SIMPLE_XUL_CREATE(spacer, NS_NewLeafBoxFrame),
  1.4051 +    SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame),
  1.4052 +    SIMPLE_XUL_CREATE(treecol, NS_NewTreeColFrame),
  1.4053 +    SIMPLE_XUL_CREATE(text, NS_NewTextBoxFrame),
  1.4054 +    SIMPLE_TAG_CHAIN(label, nsCSSFrameConstructor::FindXULLabelData),
  1.4055 +    SIMPLE_TAG_CHAIN(description, nsCSSFrameConstructor::FindXULDescriptionData),
  1.4056 +    SIMPLE_XUL_CREATE(menu, NS_NewMenuFrame),
  1.4057 +    SIMPLE_XUL_CREATE(menubutton, NS_NewMenuFrame),
  1.4058 +    SIMPLE_XUL_CREATE(menuitem, NS_NewMenuItemFrame),
  1.4059 +#ifdef XP_MACOSX
  1.4060 +    SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData),
  1.4061 +#else
  1.4062 +    SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
  1.4063 +#endif /* XP_MACOSX */
  1.4064 +    SIMPLE_TAG_CHAIN(popupgroup, nsCSSFrameConstructor::FindPopupGroupData),
  1.4065 +    SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
  1.4066 +    SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
  1.4067 +    SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame),
  1.4068 +    SIMPLE_XUL_CREATE(progressmeter, NS_NewProgressMeterFrame),
  1.4069 +    SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame),
  1.4070 +    SIMPLE_TAG_CHAIN(listboxbody,
  1.4071 +                     nsCSSFrameConstructor::FindXULListBoxBodyData),
  1.4072 +    SIMPLE_TAG_CHAIN(listitem, nsCSSFrameConstructor::FindXULListItemData),
  1.4073 +#endif /* MOZ_XUL */
  1.4074 +    SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame),
  1.4075 +    SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
  1.4076 +    SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame)
  1.4077 +};
  1.4078 +
  1.4079 +  return FindDataByTag(aTag, aElement, aStyleContext, sXULTagData,
  1.4080 +                       ArrayLength(sXULTagData));
  1.4081 +}
  1.4082 +
  1.4083 +#ifdef MOZ_XUL
  1.4084 +/* static */
  1.4085 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4086 +nsCSSFrameConstructor::FindPopupGroupData(Element* aElement,
  1.4087 +                                          nsStyleContext* /* unused */)
  1.4088 +{
  1.4089 +  if (!aElement->IsRootOfNativeAnonymousSubtree()) {
  1.4090 +    return nullptr;
  1.4091 +  }
  1.4092 +
  1.4093 +  static const FrameConstructionData sPopupSetData =
  1.4094 +    SIMPLE_XUL_FCDATA(NS_NewPopupSetFrame);
  1.4095 +  return &sPopupSetData;
  1.4096 +}
  1.4097 +
  1.4098 +/* static */
  1.4099 +const nsCSSFrameConstructor::FrameConstructionData
  1.4100 +nsCSSFrameConstructor::sXULTextBoxData = SIMPLE_XUL_FCDATA(NS_NewTextBoxFrame);
  1.4101 +
  1.4102 +/* static */
  1.4103 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4104 +nsCSSFrameConstructor::FindXULLabelData(Element* aElement,
  1.4105 +                                        nsStyleContext* /* unused */)
  1.4106 +{
  1.4107 +  if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
  1.4108 +    return &sXULTextBoxData;
  1.4109 +  }
  1.4110 +
  1.4111 +  static const FrameConstructionData sLabelData =
  1.4112 +    SIMPLE_XUL_FCDATA(NS_NewXULLabelFrame);
  1.4113 +  return &sLabelData;
  1.4114 +}
  1.4115 +
  1.4116 +static nsIFrame*
  1.4117 +NS_NewXULDescriptionFrame(nsIPresShell* aPresShell, nsStyleContext *aContext)
  1.4118 +{
  1.4119 +  // XXXbz do we really need to set those flags?  If the parent is not
  1.4120 +  // a block we'll get them anyway, and if it is, do we want them?
  1.4121 +  return NS_NewBlockFrame(aPresShell, aContext,
  1.4122 +                          NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT);
  1.4123 +}
  1.4124 +
  1.4125 +/* static */
  1.4126 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4127 +nsCSSFrameConstructor::FindXULDescriptionData(Element* aElement,
  1.4128 +                                              nsStyleContext* /* unused */)
  1.4129 +{
  1.4130 +  if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
  1.4131 +    return &sXULTextBoxData;
  1.4132 +  }
  1.4133 +
  1.4134 +  static const FrameConstructionData sDescriptionData =
  1.4135 +    SIMPLE_XUL_FCDATA(NS_NewXULDescriptionFrame);
  1.4136 +  return &sDescriptionData;
  1.4137 +}
  1.4138 +
  1.4139 +#ifdef XP_MACOSX
  1.4140 +/* static */
  1.4141 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4142 +nsCSSFrameConstructor::FindXULMenubarData(Element* aElement,
  1.4143 +                                          nsStyleContext* aStyleContext)
  1.4144 +{
  1.4145 +  nsCOMPtr<nsIDocShell> treeItem =
  1.4146 +    aStyleContext->PresContext()->GetDocShell();
  1.4147 +  if (treeItem && nsIDocShellTreeItem::typeChrome == treeItem->ItemType()) {
  1.4148 +    nsCOMPtr<nsIDocShellTreeItem> parent;
  1.4149 +    treeItem->GetParent(getter_AddRefs(parent));
  1.4150 +    if (!parent) {
  1.4151 +      // This is the root.  Suppress the menubar, since on Mac
  1.4152 +      // window menus are not attached to the window.
  1.4153 +      static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
  1.4154 +      return &sSuppressData;
  1.4155 +    }
  1.4156 +  }
  1.4157 +
  1.4158 +  static const FrameConstructionData sMenubarData =
  1.4159 +    SIMPLE_XUL_FCDATA(NS_NewMenuBarFrame);
  1.4160 +  return &sMenubarData;
  1.4161 +}
  1.4162 +#endif /* XP_MACOSX */
  1.4163 +
  1.4164 +/* static */
  1.4165 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4166 +nsCSSFrameConstructor::FindXULListBoxBodyData(Element* aElement,
  1.4167 +                                              nsStyleContext* aStyleContext)
  1.4168 +{
  1.4169 +  if (aStyleContext->StyleDisplay()->mDisplay !=
  1.4170 +        NS_STYLE_DISPLAY_XUL_GRID_GROUP) {
  1.4171 +    return nullptr;
  1.4172 +  }
  1.4173 +
  1.4174 +  static const FrameConstructionData sListBoxBodyData =
  1.4175 +    SCROLLABLE_XUL_FCDATA(NS_NewListBoxBodyFrame);
  1.4176 +  return &sListBoxBodyData;
  1.4177 +}
  1.4178 +
  1.4179 +/* static */
  1.4180 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4181 +nsCSSFrameConstructor::FindXULListItemData(Element* aElement,
  1.4182 +                                           nsStyleContext* aStyleContext)
  1.4183 +{
  1.4184 +  if (aStyleContext->StyleDisplay()->mDisplay !=
  1.4185 +        NS_STYLE_DISPLAY_XUL_GRID_LINE) {
  1.4186 +    return nullptr;
  1.4187 +  }
  1.4188 +
  1.4189 +  static const FrameConstructionData sListItemData =
  1.4190 +    SCROLLABLE_XUL_FCDATA(NS_NewListItemFrame);
  1.4191 +  return &sListItemData;
  1.4192 +}
  1.4193 +
  1.4194 +#endif /* MOZ_XUL */
  1.4195 +
  1.4196 +/* static */
  1.4197 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4198 +nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
  1.4199 +                                          Element* aElement,
  1.4200 +                                          nsStyleContext* aStyleContext)
  1.4201 +{
  1.4202 +  static const FrameConstructionDataByInt sXULDisplayData[] = {
  1.4203 +    SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX,
  1.4204 +                                               NS_NewBoxFrame),
  1.4205 +    SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX,
  1.4206 +                                               NS_NewBoxFrame),
  1.4207 +#ifdef MOZ_XUL
  1.4208 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_XUL_GRID, NS_NewGridBoxFrame),
  1.4209 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_XUL_GRID, NS_NewGridBoxFrame),
  1.4210 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_XUL_GRID_GROUP,
  1.4211 +                              NS_NewGridRowGroupFrame),
  1.4212 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_XUL_GRID_LINE,
  1.4213 +                              NS_NewGridRowLeafFrame),
  1.4214 +    SIMPLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_DECK, NS_NewDeckFrame),
  1.4215 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GROUPBOX, NS_NewGroupBoxFrame),
  1.4216 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_STACK, NS_NewStackFrame),
  1.4217 +    SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_STACK, NS_NewStackFrame),
  1.4218 +    { NS_STYLE_DISPLAY_POPUP,
  1.4219 +      FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
  1.4220 +                  FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame) }
  1.4221 +#endif /* MOZ_XUL */
  1.4222 +  };
  1.4223 +
  1.4224 +  // Processing by display here:
  1.4225 +  return FindDataByInt(aDisplay->mDisplay, aElement, aStyleContext,
  1.4226 +                       sXULDisplayData, ArrayLength(sXULDisplayData));
  1.4227 +}
  1.4228 +
  1.4229 +already_AddRefed<nsStyleContext>
  1.4230 +nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
  1.4231 +                                                nsIContent*              aContent,
  1.4232 +                                                nsStyleContext*          aContentStyle,
  1.4233 +                                                nsIFrame*                aParentFrame,
  1.4234 +                                                nsIAtom*                 aScrolledPseudo,
  1.4235 +                                                bool                     aIsRoot,
  1.4236 +                                                nsIFrame*&               aNewFrame)
  1.4237 +{
  1.4238 +  nsIFrame* gfxScrollFrame = aNewFrame;
  1.4239 +
  1.4240 +  nsFrameItems anonymousItems;
  1.4241 +
  1.4242 +  nsRefPtr<nsStyleContext> contentStyle = aContentStyle;
  1.4243 +
  1.4244 +  if (!gfxScrollFrame) {
  1.4245 +    // Build a XULScrollFrame when the child is a box, otherwise an
  1.4246 +    // HTMLScrollFrame
  1.4247 +    // XXXbz this is the lone remaining consumer of IsXULDisplayType.
  1.4248 +    // I wonder whether we can eliminate that somehow.
  1.4249 +    const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
  1.4250 +    if (IsXULDisplayType(displayStyle)) {
  1.4251 +      gfxScrollFrame = NS_NewXULScrollFrame(mPresShell, contentStyle, aIsRoot,
  1.4252 +          displayStyle->mDisplay == NS_STYLE_DISPLAY_STACK ||
  1.4253 +          displayStyle->mDisplay == NS_STYLE_DISPLAY_INLINE_STACK);
  1.4254 +    } else {
  1.4255 +      gfxScrollFrame = NS_NewHTMLScrollFrame(mPresShell, contentStyle, aIsRoot);
  1.4256 +    }
  1.4257 +
  1.4258 +    InitAndRestoreFrame(aState, aContent, aParentFrame, gfxScrollFrame);
  1.4259 +  }
  1.4260 +
  1.4261 +  // if there are any anonymous children for the scroll frame, create
  1.4262 +  // frames for them.
  1.4263 +  // Pass a null pending binding: we don't care how constructors for any of
  1.4264 +  // this anonymous content order with anything else.  It's never been
  1.4265 +  // consistent anyway.
  1.4266 +  CreateAnonymousFrames(aState, aContent, gfxScrollFrame, nullptr,
  1.4267 +                        anonymousItems);
  1.4268 +
  1.4269 +  aNewFrame = gfxScrollFrame;
  1.4270 +
  1.4271 +  // we used the style that was passed in. So resolve another one.
  1.4272 +  nsStyleSet *styleSet = mPresShell->StyleSet();
  1.4273 +  nsRefPtr<nsStyleContext> scrolledChildStyle =
  1.4274 +    styleSet->ResolveAnonymousBoxStyle(aScrolledPseudo, contentStyle);
  1.4275 +
  1.4276 +  if (gfxScrollFrame) {
  1.4277 +     gfxScrollFrame->SetInitialChildList(kPrincipalList, anonymousItems);
  1.4278 +  }
  1.4279 +
  1.4280 +  return scrolledChildStyle.forget();
  1.4281 +}
  1.4282 +
  1.4283 +void
  1.4284 +nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
  1.4285 +                                                 nsIFrame* aScrolledFrame)
  1.4286 +{
  1.4287 +  nsFrameList scrolled(aScrolledFrame, aScrolledFrame);
  1.4288 +  aScrollFrame->AppendFrames(kPrincipalList, scrolled);
  1.4289 +}
  1.4290 +
  1.4291 +
  1.4292 +/**
  1.4293 + * Called to wrap a gfx scrollframe around a frame. The hierarchy will look like this
  1.4294 + *
  1.4295 + * ------- for gfx scrollbars ------
  1.4296 + *
  1.4297 + *
  1.4298 + *            ScrollFrame
  1.4299 + *                 ^
  1.4300 + *                 |
  1.4301 + *               Frame (scrolled frame you passed in)
  1.4302 + *
  1.4303 + *
  1.4304 + *-----------------------------------
  1.4305 + * LEGEND:
  1.4306 + *
  1.4307 + * ScrollFrame: This is a frame that manages gfx cross platform frame based scrollbars.
  1.4308 + *
  1.4309 + * @param aContent the content node of the child to wrap.
  1.4310 + * @param aScrolledFrame The frame of the content to wrap. This should not be
  1.4311 + *                    Initialized. This method will initialize it with a scrolled pseudo
  1.4312 + *                    and no nsIContent. The content will be attached to the scrollframe
  1.4313 + *                    returned.
  1.4314 + * @param aContentStyle the style context that has already been resolved for the content being passed in.
  1.4315 + *
  1.4316 + * @param aParentFrame The parent to attach the scroll frame to
  1.4317 + *
  1.4318 + * @param aNewFrame The new scrollframe or gfx scrollframe that we create. It will contain the
  1.4319 + *                  scrolled frame you passed in. (returned)
  1.4320 + *                  If this is not null, we'll just use it
  1.4321 + * @param aScrolledContentStyle the style that was resolved for the scrolled frame. (returned)
  1.4322 + */
  1.4323 +nsresult
  1.4324 +nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState,
  1.4325 +                                        nsIContent*              aContent,
  1.4326 +                                        nsStyleContext*          aContentStyle,
  1.4327 +                                        nsIFrame*                aScrolledFrame,
  1.4328 +                                        nsIFrame*                aParentFrame,
  1.4329 +                                        nsIFrame*&               aNewFrame)
  1.4330 +{
  1.4331 +    nsRefPtr<nsStyleContext> scrolledContentStyle =
  1.4332 +      BeginBuildingScrollFrame(aState, aContent, aContentStyle, aParentFrame,
  1.4333 +                               nsCSSAnonBoxes::scrolledContent,
  1.4334 +                               false, aNewFrame);
  1.4335 +
  1.4336 +    aScrolledFrame->SetStyleContextWithoutNotification(scrolledContentStyle);
  1.4337 +    InitAndRestoreFrame(aState, aContent, aNewFrame, aScrolledFrame);
  1.4338 +
  1.4339 +    FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
  1.4340 +    return NS_OK;
  1.4341 +}
  1.4342 +
  1.4343 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4344 +nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
  1.4345 +                                       Element* aElement,
  1.4346 +                                       nsIFrame* aParentFrame,
  1.4347 +                                       nsStyleContext* aStyleContext)
  1.4348 +{
  1.4349 +  PR_STATIC_ASSERT(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET)));
  1.4350 +
  1.4351 +  // The style system ensures that floated and positioned frames are
  1.4352 +  // block-level.
  1.4353 +  NS_ASSERTION(!(aDisplay->IsFloatingStyle() ||
  1.4354 +                 aDisplay->IsAbsolutelyPositionedStyle()) ||
  1.4355 +               aDisplay->IsBlockOutsideStyle(),
  1.4356 +               "Style system did not apply CSS2.1 section 9.7 fixups");
  1.4357 +
  1.4358 +  // If this is "body", try propagating its scroll style to the viewport
  1.4359 +  // Note that we need to do this even if the body is NOT scrollable;
  1.4360 +  // it might have dynamically changed from scrollable to not scrollable,
  1.4361 +  // and that might need to be propagated.
  1.4362 +  // XXXbz is this the right place to do this?  If this code moves,
  1.4363 +  // make this function static.
  1.4364 +  bool propagatedScrollToViewport = false;
  1.4365 +  if (aElement->IsHTML(nsGkAtoms::body)) {
  1.4366 +    propagatedScrollToViewport =
  1.4367 +      PropagateScrollToViewport() == aElement;
  1.4368 +  }
  1.4369 +
  1.4370 +  NS_ASSERTION(!propagatedScrollToViewport ||
  1.4371 +               !mPresShell->GetPresContext()->IsPaginated(),
  1.4372 +               "Shouldn't propagate scroll in paginated contexts");
  1.4373 +
  1.4374 +  // If the frame is a block-level frame and is scrollable, then wrap it in a
  1.4375 +  // scroll frame.
  1.4376 +  // XXX Ignore tables for the time being
  1.4377 +  // XXXbz it would be nice to combine this with the other block
  1.4378 +  // case... Think about how do do this?
  1.4379 +  if (aDisplay->IsBlockInsideStyle() &&
  1.4380 +      aDisplay->IsScrollableOverflow() &&
  1.4381 +      !propagatedScrollToViewport) {
  1.4382 +    // Except we don't want to do that for paginated contexts for
  1.4383 +    // frames that are block-outside and aren't frames for native
  1.4384 +    // anonymous stuff.
  1.4385 +    if (mPresShell->GetPresContext()->IsPaginated() &&
  1.4386 +        aDisplay->IsBlockOutsideStyle() &&
  1.4387 +        !aElement->IsInNativeAnonymousSubtree()) {
  1.4388 +      static const FrameConstructionData sForcedNonScrollableBlockData =
  1.4389 +        FULL_CTOR_FCDATA(FCDATA_FORCED_NON_SCROLLABLE_BLOCK,
  1.4390 +                         &nsCSSFrameConstructor::ConstructNonScrollableBlock);
  1.4391 +      return &sForcedNonScrollableBlockData;
  1.4392 +    }
  1.4393 +
  1.4394 +    static const FrameConstructionData sScrollableBlockData =
  1.4395 +      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructScrollableBlock);
  1.4396 +    return &sScrollableBlockData;
  1.4397 +  }
  1.4398 +
  1.4399 +  // Handle various non-scrollable blocks
  1.4400 +  if (aDisplay->IsBlockInsideStyle()) {
  1.4401 +    static const FrameConstructionData sNonScrollableBlockData =
  1.4402 +      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructNonScrollableBlock);
  1.4403 +    return &sNonScrollableBlockData;
  1.4404 +  }
  1.4405 +
  1.4406 +  static const FrameConstructionDataByInt sDisplayData[] = {
  1.4407 +    // To keep the hash table small don't add inline frames (they're
  1.4408 +    // typically things like FONT and B), because we can quickly
  1.4409 +    // find them if we need to.
  1.4410 +    // XXXbz the "quickly" part is a bald-faced lie!
  1.4411 +    { NS_STYLE_DISPLAY_INLINE,
  1.4412 +      FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
  1.4413 +                       &nsCSSFrameConstructor::ConstructInline) },
  1.4414 +    { NS_STYLE_DISPLAY_FLEX,
  1.4415 +      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame) },
  1.4416 +    { NS_STYLE_DISPLAY_INLINE_FLEX,
  1.4417 +      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewFlexContainerFrame) },
  1.4418 +    { NS_STYLE_DISPLAY_GRID,
  1.4419 +      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame) },
  1.4420 +    { NS_STYLE_DISPLAY_INLINE_GRID,
  1.4421 +      FCDATA_DECL(FCDATA_MAY_NEED_SCROLLFRAME, NS_NewGridContainerFrame) },
  1.4422 +    { NS_STYLE_DISPLAY_TABLE,
  1.4423 +      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
  1.4424 +    { NS_STYLE_DISPLAY_INLINE_TABLE,
  1.4425 +      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
  1.4426 +    // NOTE: In the unlikely event that we add another table-part here that has
  1.4427 +    // a desired-parent-type (& hence triggers table fixup), we'll need to also
  1.4428 +    // update the flexbox chunk in nsStyleContext::ApplyStyleFixups().
  1.4429 +    { NS_STYLE_DISPLAY_TABLE_CAPTION,
  1.4430 +      FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_ALLOW_BLOCK_STYLES |
  1.4431 +                  FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |
  1.4432 +                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.4433 +                  NS_NewTableCaptionFrame) },
  1.4434 +    { NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
  1.4435 +      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
  1.4436 +                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.4437 +                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
  1.4438 +    { NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
  1.4439 +      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
  1.4440 +                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.4441 +                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
  1.4442 +    { NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
  1.4443 +      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
  1.4444 +                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.4445 +                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
  1.4446 +    { NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
  1.4447 +      FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
  1.4448 +                  FCDATA_SKIP_ABSPOS_PUSH |
  1.4449 +                  FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.4450 +                  NS_NewTableColGroupFrame) },
  1.4451 +    { NS_STYLE_DISPLAY_TABLE_COLUMN,
  1.4452 +      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
  1.4453 +                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
  1.4454 +                       &nsCSSFrameConstructor::ConstructTableCol) },
  1.4455 +    { NS_STYLE_DISPLAY_TABLE_ROW,
  1.4456 +      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
  1.4457 +                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
  1.4458 +                       &nsCSSFrameConstructor::ConstructTableRowOrRowGroup) },
  1.4459 +    { NS_STYLE_DISPLAY_TABLE_CELL,
  1.4460 +      FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
  1.4461 +                       FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
  1.4462 +                       &nsCSSFrameConstructor::ConstructTableCell) }
  1.4463 +  };
  1.4464 +
  1.4465 +  return FindDataByInt(aDisplay->mDisplay,
  1.4466 +                       aElement, aStyleContext, sDisplayData,
  1.4467 +                       ArrayLength(sDisplayData));
  1.4468 +}
  1.4469 +
  1.4470 +nsIFrame*
  1.4471 +nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
  1.4472 +                                                FrameConstructionItem&   aItem,
  1.4473 +                                                nsIFrame*                aParentFrame,
  1.4474 +                                                const nsStyleDisplay*    aDisplay,
  1.4475 +                                                nsFrameItems&            aFrameItems)
  1.4476 +{
  1.4477 +  nsIContent* const content = aItem.mContent;
  1.4478 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.4479 +
  1.4480 +  nsIFrame* newFrame = nullptr;
  1.4481 +  nsRefPtr<nsStyleContext> scrolledContentStyle
  1.4482 +    = BeginBuildingScrollFrame(aState, content, styleContext,
  1.4483 +                               aState.GetGeometricParent(aDisplay, aParentFrame),
  1.4484 +                               nsCSSAnonBoxes::scrolledContent,
  1.4485 +                               false, newFrame);
  1.4486 +
  1.4487 +  // Create our block frame
  1.4488 +  // pass a temporary stylecontext, the correct one will be set later
  1.4489 +  nsIFrame* scrolledFrame =
  1.4490 +    NS_NewBlockFormattingContext(mPresShell, styleContext);
  1.4491 +
  1.4492 +  // Make sure to AddChild before we call ConstructBlock so that we
  1.4493 +  // end up before our descendants in fixed-pos lists as needed.
  1.4494 +  aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
  1.4495 +
  1.4496 +  nsFrameItems blockItem;
  1.4497 +  ConstructBlock(aState, scrolledContentStyle->StyleDisplay(), content,
  1.4498 +                 newFrame, newFrame, scrolledContentStyle,
  1.4499 +                 &scrolledFrame, blockItem,
  1.4500 +                 aDisplay->IsPositioned(newFrame) ? newFrame : nullptr,
  1.4501 +                 aItem.mPendingBinding);
  1.4502 +
  1.4503 +  NS_ASSERTION(blockItem.FirstChild() == scrolledFrame,
  1.4504 +               "Scrollframe's frameItems should be exactly the scrolled frame");
  1.4505 +  FinishBuildingScrollFrame(newFrame, scrolledFrame);
  1.4506 +
  1.4507 +  return newFrame;
  1.4508 +}
  1.4509 +
  1.4510 +nsIFrame*
  1.4511 +nsCSSFrameConstructor::ConstructNonScrollableBlock(nsFrameConstructorState& aState,
  1.4512 +                                                   FrameConstructionItem&   aItem,
  1.4513 +                                                   nsIFrame*                aParentFrame,
  1.4514 +                                                   const nsStyleDisplay*    aDisplay,
  1.4515 +                                                   nsFrameItems&            aFrameItems)
  1.4516 +{
  1.4517 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.4518 +
  1.4519 +  // We want a block formatting context root in paginated contexts for
  1.4520 +  // every block that would be scrollable in a non-paginated context.
  1.4521 +  // We mark our blocks with a bit here if this condition is true, so
  1.4522 +  // we can check it later in nsFrame::ApplyPaginatedOverflowClipping.
  1.4523 +  bool clipPaginatedOverflow =
  1.4524 +    (aItem.mFCData->mBits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) != 0;
  1.4525 +  nsIFrame* newFrame;
  1.4526 +  if ((aDisplay->IsAbsolutelyPositionedStyle() ||
  1.4527 +       aDisplay->IsFloatingStyle() ||
  1.4528 +       NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay->mDisplay ||
  1.4529 +       clipPaginatedOverflow) &&
  1.4530 +      !aParentFrame->IsSVGText()) {
  1.4531 +    newFrame = NS_NewBlockFormattingContext(mPresShell, styleContext);
  1.4532 +    if (clipPaginatedOverflow) {
  1.4533 +      newFrame->AddStateBits(NS_BLOCK_CLIP_PAGINATED_OVERFLOW);
  1.4534 +    }
  1.4535 +  } else {
  1.4536 +    newFrame = NS_NewBlockFrame(mPresShell, styleContext);
  1.4537 +  }
  1.4538 +
  1.4539 +  ConstructBlock(aState, aDisplay, aItem.mContent,
  1.4540 +                 aState.GetGeometricParent(aDisplay, aParentFrame),
  1.4541 +                 aParentFrame, styleContext, &newFrame,
  1.4542 +                 aFrameItems,
  1.4543 +                 aDisplay->IsPositioned(newFrame) ? newFrame : nullptr,
  1.4544 +                 aItem.mPendingBinding);
  1.4545 +  return newFrame;
  1.4546 +}
  1.4547 +
  1.4548 +
  1.4549 +void
  1.4550 +nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
  1.4551 +                                           nsIContent*              aContent,
  1.4552 +                                           nsIFrame*                aParentFrame,
  1.4553 +                                           nsIFrame*                aNewFrame,
  1.4554 +                                           bool                     aAllowCounters)
  1.4555 +{
  1.4556 +  NS_PRECONDITION(mUpdateCount != 0,
  1.4557 +                  "Should be in an update while creating frames");
  1.4558 +
  1.4559 +  MOZ_ASSERT(aNewFrame, "Null frame cannot be initialized");
  1.4560 +
  1.4561 +  // Initialize the frame
  1.4562 +  aNewFrame->Init(aContent, aParentFrame, nullptr);
  1.4563 +  aNewFrame->AddStateBits(aState.mAdditionalStateBits);
  1.4564 +
  1.4565 +  if (aState.mFrameState) {
  1.4566 +    // Restore frame state for just the newly created frame.
  1.4567 +    RestoreFrameStateFor(aNewFrame, aState.mFrameState);
  1.4568 +  }
  1.4569 +
  1.4570 +  if (aAllowCounters &&
  1.4571 +      mCounterManager.AddCounterResetsAndIncrements(aNewFrame)) {
  1.4572 +    CountersDirty();
  1.4573 +  }
  1.4574 +}
  1.4575 +
  1.4576 +already_AddRefed<nsStyleContext>
  1.4577 +nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*         aParentFrame,
  1.4578 +                                           nsIContent*       aContent,
  1.4579 +                                           nsFrameConstructorState* aState)
  1.4580 +{
  1.4581 +  nsStyleContext* parentStyleContext = nullptr;
  1.4582 +  NS_ASSERTION(aContent->GetParent(), "Must have parent here");
  1.4583 +
  1.4584 +  aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nullptr);
  1.4585 +
  1.4586 +  if (aParentFrame) {
  1.4587 +    // Resolve the style context based on the content object and the parent
  1.4588 +    // style context
  1.4589 +    parentStyleContext = aParentFrame->StyleContext();
  1.4590 +  } else {
  1.4591 +    // Perhaps aParentFrame is a canvasFrame and we're replicating
  1.4592 +    // fixed-pos frames.
  1.4593 +    // XXX should we create a way to tell ConstructFrame which style
  1.4594 +    // context to use, and pass it the style context for the
  1.4595 +    // previous page's fixed-pos frame?
  1.4596 +  }
  1.4597 +
  1.4598 +  return ResolveStyleContext(parentStyleContext, aContent, aState);
  1.4599 +}
  1.4600 +
  1.4601 +already_AddRefed<nsStyleContext>
  1.4602 +nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
  1.4603 +                                           nsIContent* aContent,
  1.4604 +                                           nsFrameConstructorState* aState)
  1.4605 +{
  1.4606 +  nsStyleSet *styleSet = mPresShell->StyleSet();
  1.4607 +  aContent->OwnerDoc()->FlushPendingLinkUpdates();
  1.4608 +
  1.4609 +  if (aContent->IsElement()) {
  1.4610 +    if (aState) {
  1.4611 +      return styleSet->ResolveStyleFor(aContent->AsElement(),
  1.4612 +                                       aParentStyleContext,
  1.4613 +                                       aState->mTreeMatchContext);
  1.4614 +    }
  1.4615 +    return styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext);
  1.4616 +
  1.4617 +  }
  1.4618 +
  1.4619 +  NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
  1.4620 +               "shouldn't waste time creating style contexts for "
  1.4621 +               "comments and processing instructions");
  1.4622 +
  1.4623 +  return styleSet->ResolveStyleForNonElement(aParentStyleContext);
  1.4624 +}
  1.4625 +
  1.4626 +// MathML Mod - RBS
  1.4627 +void
  1.4628 +nsCSSFrameConstructor::FlushAccumulatedBlock(nsFrameConstructorState& aState,
  1.4629 +                                             nsIContent* aContent,
  1.4630 +                                             nsIFrame* aParentFrame,
  1.4631 +                                             nsFrameItems& aBlockItems,
  1.4632 +                                             nsFrameItems& aNewItems)
  1.4633 +{
  1.4634 +  if (aBlockItems.IsEmpty()) {
  1.4635 +    // Nothing to do
  1.4636 +    return;
  1.4637 +  }
  1.4638 +
  1.4639 +  nsIAtom* anonPseudo = nsCSSAnonBoxes::mozMathMLAnonymousBlock;
  1.4640 +
  1.4641 +  nsStyleContext* parentContext =
  1.4642 +    nsFrame::CorrectStyleParentFrame(aParentFrame,
  1.4643 +                                     anonPseudo)->StyleContext();
  1.4644 +  nsStyleSet* styleSet = mPresShell->StyleSet();
  1.4645 +  nsRefPtr<nsStyleContext> blockContext;
  1.4646 +  blockContext = styleSet->
  1.4647 +    ResolveAnonymousBoxStyle(anonPseudo, parentContext);
  1.4648 +
  1.4649 +
  1.4650 +  // then, create a block frame that will wrap the child frames. Make it a
  1.4651 +  // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
  1.4652 +  // is not a suitable block.
  1.4653 +  nsIFrame* blockFrame =
  1.4654 +      NS_NewMathMLmathBlockFrame(mPresShell, blockContext,
  1.4655 +                                 NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT);
  1.4656 +
  1.4657 +  InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
  1.4658 +  ReparentFrames(this, blockFrame, aBlockItems);
  1.4659 +  // abs-pos and floats are disabled in MathML children so we don't have to
  1.4660 +  // worry about messing up those.
  1.4661 +  blockFrame->SetInitialChildList(kPrincipalList, aBlockItems);
  1.4662 +  NS_ASSERTION(aBlockItems.IsEmpty(), "What happened?");
  1.4663 +  aBlockItems.Clear();
  1.4664 +  aNewItems.AddChild(blockFrame);
  1.4665 +}
  1.4666 +
  1.4667 +// Only <math> elements can be floated or positioned.  All other MathML
  1.4668 +// should be in-flow.
  1.4669 +#define SIMPLE_MATHML_CREATE(_tag, _func)                               \
  1.4670 +  { &nsGkAtoms::_tag,                                                   \
  1.4671 +      FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                         \
  1.4672 +                  FCDATA_FORCE_NULL_ABSPOS_CONTAINER |                  \
  1.4673 +                  FCDATA_WRAP_KIDS_IN_BLOCKS, _func) }
  1.4674 +
  1.4675 +/* static */
  1.4676 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4677 +nsCSSFrameConstructor::FindMathMLData(Element* aElement,
  1.4678 +                                      nsIAtom* aTag,
  1.4679 +                                      int32_t aNameSpaceID,
  1.4680 +                                      nsStyleContext* aStyleContext)
  1.4681 +{
  1.4682 +  // Make sure that we remain confined in the MathML world
  1.4683 +  if (aNameSpaceID != kNameSpaceID_MathML)
  1.4684 +    return nullptr;
  1.4685 +
  1.4686 +  // Handle <math> specially, because it sometimes produces inlines
  1.4687 +  if (aTag == nsGkAtoms::math) {
  1.4688 +    // This needs to match the test in EnsureBlockDisplay in
  1.4689 +    // nsRuleNode.cpp.  Though the behavior here for the display:table
  1.4690 +    // case is pretty weird...
  1.4691 +    if (aStyleContext->StyleDisplay()->IsBlockOutsideStyle()) {
  1.4692 +      static const FrameConstructionData sBlockMathData =
  1.4693 +        FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
  1.4694 +                    FCDATA_WRAP_KIDS_IN_BLOCKS,
  1.4695 +                    NS_CreateNewMathMLmathBlockFrame);
  1.4696 +      return &sBlockMathData;
  1.4697 +    }
  1.4698 +
  1.4699 +    static const FrameConstructionData sInlineMathData =
  1.4700 +      FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
  1.4701 +                  FCDATA_IS_LINE_PARTICIPANT |
  1.4702 +                  FCDATA_WRAP_KIDS_IN_BLOCKS,
  1.4703 +                  NS_NewMathMLmathInlineFrame);
  1.4704 +    return &sInlineMathData;
  1.4705 +  }
  1.4706 +
  1.4707 +
  1.4708 +  static const FrameConstructionDataByTag sMathMLData[] = {
  1.4709 +    SIMPLE_MATHML_CREATE(annotation_, NS_NewMathMLTokenFrame),
  1.4710 +    SIMPLE_MATHML_CREATE(annotation_xml_, NS_NewMathMLmrowFrame),
  1.4711 +    SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame),
  1.4712 +    SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame),
  1.4713 +    SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame),
  1.4714 +    SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame),
  1.4715 +    SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame),
  1.4716 +    SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame),
  1.4717 +    SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmmultiscriptsFrame),
  1.4718 +    SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmmultiscriptsFrame),
  1.4719 +    SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmmultiscriptsFrame),
  1.4720 +    SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame),
  1.4721 +    SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame),
  1.4722 +    SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame),
  1.4723 +    SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmphantomFrame),
  1.4724 +    SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame),
  1.4725 +    SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame),
  1.4726 +    SIMPLE_MATHML_CREATE(none, NS_NewMathMLmspaceFrame),
  1.4727 +    SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmspaceFrame),
  1.4728 +    SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmfencedFrame),
  1.4729 +    SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame),
  1.4730 +    SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmrowFrame),
  1.4731 +    SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmsqrtFrame),
  1.4732 +    SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame),
  1.4733 +    SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmactionFrame),
  1.4734 +    SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame),
  1.4735 +    SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame),
  1.4736 +    SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame),
  1.4737 +    SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLsemanticsFrame)
  1.4738 +  };
  1.4739 +
  1.4740 +  return FindDataByTag(aTag, aElement, aStyleContext, sMathMLData,
  1.4741 +                       ArrayLength(sMathMLData));
  1.4742 +}
  1.4743 +
  1.4744 +
  1.4745 +nsIFrame*
  1.4746 +nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
  1.4747 +                                   nsFrameConstructorState& aState,
  1.4748 +                                   FrameConstructionItem&   aItem,
  1.4749 +                                   nsIFrame*                aParentFrame,
  1.4750 +                                   const nsStyleDisplay*    aDisplay,
  1.4751 +                                   nsFrameItems&            aFrameItems,
  1.4752 +                                   FrameCreationFunc        aConstructor,
  1.4753 +                                   FrameCreationFunc        aInnerConstructor,
  1.4754 +                                   nsICSSAnonBoxPseudo*     aInnerPseudo,
  1.4755 +                                   bool                     aCandidateRootFrame)
  1.4756 +{
  1.4757 +  nsIContent* const content = aItem.mContent;
  1.4758 +  nsStyleContext* const styleContext = aItem.mStyleContext;
  1.4759 +
  1.4760 +  // Create the outer frame:
  1.4761 +  nsIFrame* newFrame = aConstructor(mPresShell, styleContext);
  1.4762 +
  1.4763 +  InitAndRestoreFrame(aState, content,
  1.4764 +                      aCandidateRootFrame ?
  1.4765 +                        aState.GetGeometricParent(styleContext->StyleDisplay(),
  1.4766 +                                                  aParentFrame) :
  1.4767 +                        aParentFrame,
  1.4768 +                      newFrame);
  1.4769 +
  1.4770 +  // Create the pseudo SC for the anonymous wrapper child as a child of the SC:
  1.4771 +  nsRefPtr<nsStyleContext> scForAnon;
  1.4772 +  scForAnon = mPresShell->StyleSet()->
  1.4773 +    ResolveAnonymousBoxStyle(aInnerPseudo, styleContext);
  1.4774 +
  1.4775 +  // Create the anonymous inner wrapper frame
  1.4776 +  nsIFrame* innerFrame = aInnerConstructor(mPresShell, scForAnon);
  1.4777 +
  1.4778 +  InitAndRestoreFrame(aState, content, newFrame, innerFrame);
  1.4779 +
  1.4780 +  // Put the newly created frames into the right child list
  1.4781 +  SetInitialSingleChild(newFrame, innerFrame);
  1.4782 +
  1.4783 +  aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame,
  1.4784 +                  aCandidateRootFrame, aCandidateRootFrame);
  1.4785 +
  1.4786 +  if (!mRootElementFrame && aCandidateRootFrame) {
  1.4787 +    // The frame we're constructing will be the root element frame.
  1.4788 +    // Set mRootElementFrame before processing children.
  1.4789 +    mRootElementFrame = newFrame;
  1.4790 +  }
  1.4791 +
  1.4792 +  nsFrameItems childItems;
  1.4793 +
  1.4794 +  // Process children
  1.4795 +  NS_ASSERTION(aItem.mAnonChildren.IsEmpty(),
  1.4796 +               "nsIAnonymousContentCreator::CreateAnonymousContent should not "
  1.4797 +               "be implemented for frames for which we explicitly create an "
  1.4798 +               "anonymous child to wrap its child frames");
  1.4799 +  if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
  1.4800 +    ConstructFramesFromItemList(aState, aItem.mChildItems,
  1.4801 +                                innerFrame, childItems);
  1.4802 +  } else {
  1.4803 +    ProcessChildren(aState, content, styleContext, innerFrame,
  1.4804 +                    true, childItems, false, aItem.mPendingBinding);
  1.4805 +  }
  1.4806 +
  1.4807 +  // Set the inner wrapper frame's initial primary list
  1.4808 +  innerFrame->SetInitialChildList(kPrincipalList, childItems);
  1.4809 +
  1.4810 +  return newFrame;
  1.4811 +}
  1.4812 +
  1.4813 +nsIFrame*
  1.4814 +nsCSSFrameConstructor::ConstructOuterSVG(nsFrameConstructorState& aState,
  1.4815 +                                         FrameConstructionItem&   aItem,
  1.4816 +                                         nsIFrame*                aParentFrame,
  1.4817 +                                         const nsStyleDisplay*    aDisplay,
  1.4818 +                                         nsFrameItems&            aFrameItems)
  1.4819 +{
  1.4820 +  return ConstructFrameWithAnonymousChild(
  1.4821 +      aState, aItem, aParentFrame, aDisplay, aFrameItems,
  1.4822 +      NS_NewSVGOuterSVGFrame, NS_NewSVGOuterSVGAnonChildFrame,
  1.4823 +      nsCSSAnonBoxes::mozSVGOuterSVGAnonChild, true);
  1.4824 +}
  1.4825 +
  1.4826 +nsIFrame*
  1.4827 +nsCSSFrameConstructor::ConstructMarker(nsFrameConstructorState& aState,
  1.4828 +                                       FrameConstructionItem&   aItem,
  1.4829 +                                       nsIFrame*                aParentFrame,
  1.4830 +                                       const nsStyleDisplay*    aDisplay,
  1.4831 +                                       nsFrameItems&            aFrameItems)
  1.4832 +{
  1.4833 +  return ConstructFrameWithAnonymousChild(
  1.4834 +      aState, aItem, aParentFrame, aDisplay, aFrameItems,
  1.4835 +      NS_NewSVGMarkerFrame, NS_NewSVGMarkerAnonChildFrame,
  1.4836 +      nsCSSAnonBoxes::mozSVGMarkerAnonChild, false);
  1.4837 +}
  1.4838 +
  1.4839 +// Only outer <svg> elements can be floated or positioned.  All other SVG
  1.4840 +// should be in-flow.
  1.4841 +#define SIMPLE_SVG_FCDATA(_func)                                        \
  1.4842 +  FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
  1.4843 +              FCDATA_SKIP_ABSPOS_PUSH |                                 \
  1.4844 +              FCDATA_DISALLOW_GENERATED_CONTENT,  _func)
  1.4845 +#define SIMPLE_SVG_CREATE(_tag, _func)            \
  1.4846 +  { &nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func) }
  1.4847 +
  1.4848 +static bool
  1.4849 +IsFilterPrimitiveChildTag(const nsIAtom* aTag)
  1.4850 +{
  1.4851 +  return aTag == nsGkAtoms::feDistantLight ||
  1.4852 +         aTag == nsGkAtoms::fePointLight ||
  1.4853 +         aTag == nsGkAtoms::feSpotLight ||
  1.4854 +         aTag == nsGkAtoms::feFuncR ||
  1.4855 +         aTag == nsGkAtoms::feFuncG ||
  1.4856 +         aTag == nsGkAtoms::feFuncB ||
  1.4857 +         aTag == nsGkAtoms::feFuncA ||
  1.4858 +         aTag == nsGkAtoms::feMergeNode;
  1.4859 +}
  1.4860 +
  1.4861 +/* static */
  1.4862 +const nsCSSFrameConstructor::FrameConstructionData*
  1.4863 +nsCSSFrameConstructor::FindSVGData(Element* aElement,
  1.4864 +                                   nsIAtom* aTag,
  1.4865 +                                   int32_t aNameSpaceID,
  1.4866 +                                   nsIFrame* aParentFrame,
  1.4867 +                                   bool aIsWithinSVGText,
  1.4868 +                                   bool aAllowsTextPathChild,
  1.4869 +                                   nsStyleContext* aStyleContext)
  1.4870 +{
  1.4871 +  if (aNameSpaceID != kNameSpaceID_SVG) {
  1.4872 +    return nullptr;
  1.4873 +  }
  1.4874 +
  1.4875 +  static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
  1.4876 +  static const FrameConstructionData sContainerData =
  1.4877 +    SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame);
  1.4878 +
  1.4879 +  bool parentIsSVG = aIsWithinSVGText;
  1.4880 +  nsIContent* parentContent =
  1.4881 +    aParentFrame ? aParentFrame->GetContent() : nullptr;
  1.4882 +  // XXXbz should this really be based on the XBL-resolved tag of the parent
  1.4883 +  // frame's content?  Should it not be based on the type of the parent frame
  1.4884 +  // (e.g. whether it's an SVG frame)?
  1.4885 +  if (parentContent) {
  1.4886 +    int32_t parentNSID;
  1.4887 +    nsIAtom* parentTag =
  1.4888 +      parentContent->OwnerDoc()->BindingManager()->
  1.4889 +        ResolveTag(parentContent, &parentNSID);
  1.4890 +
  1.4891 +    // It's not clear whether the SVG spec intends to allow any SVG
  1.4892 +    // content within svg:foreignObject at all (SVG 1.1, section
  1.4893 +    // 23.2), but if it does, it better be svg:svg.  So given that
  1.4894 +    // we're allowing it, treat it as a non-SVG parent.
  1.4895 +    parentIsSVG = parentNSID == kNameSpaceID_SVG &&
  1.4896 +                  parentTag != nsGkAtoms::foreignObject;
  1.4897 +  }
  1.4898 +
  1.4899 +  if ((aTag != nsGkAtoms::svg && !parentIsSVG) ||
  1.4900 +      (aTag == nsGkAtoms::desc || aTag == nsGkAtoms::title)) {
  1.4901 +    // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
  1.4902 +    // svg:svg not contained within svg:svg are incorrect, although they
  1.4903 +    // don't seem to specify error handling.  Ignore them, since many of
  1.4904 +    // our frame classes can't deal.  It *may* be that the document
  1.4905 +    // should at that point be considered in error according to F.2, but
  1.4906 +    // it's hard to tell.
  1.4907 +    //
  1.4908 +    // Style mutation can't change this situation, so don't bother
  1.4909 +    // adding to the undisplayed content map.
  1.4910 +    //
  1.4911 +    // We don't currently handle any UI for desc/title
  1.4912 +    return &sSuppressData;
  1.4913 +  }
  1.4914 +
  1.4915 +  // We don't need frames for animation elements
  1.4916 +  if (aElement->IsNodeOfType(nsINode::eANIMATION)) {
  1.4917 +    return &sSuppressData;
  1.4918 +  }
  1.4919 +
  1.4920 +  if (aTag == nsGkAtoms::svg && !parentIsSVG) {
  1.4921 +    // We need outer <svg> elements to have an nsSVGOuterSVGFrame regardless
  1.4922 +    // of whether they fail conditional processing attributes, since various
  1.4923 +    // SVG frames assume that one exists.  We handle the non-rendering
  1.4924 +    // of failing outer <svg> element contents like <switch> statements,
  1.4925 +    // and do the PassesConditionalProcessingTests call in
  1.4926 +    // nsSVGOuterSVGFrame::Init.
  1.4927 +    static const FrameConstructionData sOuterSVGData =
  1.4928 +      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
  1.4929 +    return &sOuterSVGData;
  1.4930 +  }
  1.4931 +
  1.4932 +  if (aTag == nsGkAtoms::marker) {
  1.4933 +    static const FrameConstructionData sMarkerSVGData =
  1.4934 +      FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructMarker);
  1.4935 +    return &sMarkerSVGData;
  1.4936 +  }
  1.4937 +
  1.4938 +  nsCOMPtr<SVGTests> tests(do_QueryInterface(aElement));
  1.4939 +  if (tests && !tests->PassesConditionalProcessingTests()) {
  1.4940 +    // Elements with failing conditional processing attributes never get
  1.4941 +    // rendered.  Note that this is not where we select which frame in a
  1.4942 +    // <switch> to render!  That happens in nsSVGSwitchFrame::PaintSVG.
  1.4943 +    return &sContainerData;
  1.4944 +  }
  1.4945 +
  1.4946 +  // Prevent bad frame types being children of filters or parents of filter
  1.4947 +  // primitives.  If aParentFrame is null, we know that the frame that will
  1.4948 +  // be created will be an nsInlineFrame, so it can never be a filter.
  1.4949 +  bool parentIsFilter = aParentFrame &&
  1.4950 +    aParentFrame->GetType() == nsGkAtoms::svgFilterFrame;
  1.4951 +  bool filterPrimitive = aElement->IsNodeOfType(nsINode::eFILTER);
  1.4952 +  if ((parentIsFilter && !filterPrimitive) ||
  1.4953 +      (!parentIsFilter && filterPrimitive)) {
  1.4954 +    return &sSuppressData;
  1.4955 +  }
  1.4956 +
  1.4957 +  // Prevent bad frame types being children of filter primitives or parents of
  1.4958 +  // filter primitive children.  If aParentFrame is null, we know that the frame
  1.4959 +  // that will be created will be an nsInlineFrame, so it can never be a filter
  1.4960 +  // primitive.
  1.4961 +  bool parentIsFEContainerFrame = aParentFrame &&
  1.4962 +    aParentFrame->GetType() == nsGkAtoms::svgFEContainerFrame;
  1.4963 +  if ((parentIsFEContainerFrame && !IsFilterPrimitiveChildTag(aTag)) ||
  1.4964 +      (!parentIsFEContainerFrame && IsFilterPrimitiveChildTag(aTag))) {
  1.4965 +    return &sSuppressData;
  1.4966 +  }
  1.4967 +
  1.4968 +  // Special cases for text/tspan/textPath, because the kind of frame
  1.4969 +  // they get depends on the parent frame.  We ignore 'a' elements when
  1.4970 +  // determining the parent, however.
  1.4971 +  if (aIsWithinSVGText) {
  1.4972 +    // If aIsWithinSVGText is true, then we know that the "SVG text uses
  1.4973 +    // CSS frames" pref was true when this SVG fragment was first constructed.
  1.4974 +
  1.4975 +    // We don't use ConstructInline because we want different behavior
  1.4976 +    // for generated content.
  1.4977 +    static const FrameConstructionData sTSpanData =
  1.4978 +      FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |
  1.4979 +                  FCDATA_SKIP_ABSPOS_PUSH |
  1.4980 +                  FCDATA_DISALLOW_GENERATED_CONTENT |
  1.4981 +                  FCDATA_IS_LINE_PARTICIPANT |
  1.4982 +                  FCDATA_IS_INLINE |
  1.4983 +                  FCDATA_USE_CHILD_ITEMS,
  1.4984 +                  NS_NewInlineFrame);
  1.4985 +    if (aTag == nsGkAtoms::textPath) {
  1.4986 +      if (aAllowsTextPathChild) {
  1.4987 +        return &sTSpanData;
  1.4988 +      }
  1.4989 +    } else if (aTag == nsGkAtoms::tspan ||
  1.4990 +               aTag == nsGkAtoms::altGlyph ||
  1.4991 +               aTag == nsGkAtoms::a) {
  1.4992 +      return &sTSpanData;
  1.4993 +    }
  1.4994 +    return &sSuppressData;
  1.4995 +  } else if (aTag == nsGkAtoms::text) {
  1.4996 +    static const FrameConstructionData sTextData =
  1.4997 +      FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW |
  1.4998 +                                 FCDATA_ALLOW_BLOCK_STYLES,
  1.4999 +                                 NS_NewSVGTextFrame,
  1.5000 +                                 nsCSSAnonBoxes::mozSVGText);
  1.5001 +    return &sTextData;
  1.5002 +  } else if (aTag == nsGkAtoms::tspan ||
  1.5003 +             aTag == nsGkAtoms::altGlyph ||
  1.5004 +             aTag == nsGkAtoms::textPath) {
  1.5005 +    return &sSuppressData;
  1.5006 +  }
  1.5007 +
  1.5008 +  static const FrameConstructionDataByTag sSVGData[] = {
  1.5009 +    SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame),
  1.5010 +    SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame),
  1.5011 +    SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame),
  1.5012 +    SIMPLE_SVG_CREATE(polygon, NS_NewSVGPathGeometryFrame),
  1.5013 +    SIMPLE_SVG_CREATE(polyline, NS_NewSVGPathGeometryFrame),
  1.5014 +    SIMPLE_SVG_CREATE(circle, NS_NewSVGPathGeometryFrame),
  1.5015 +    SIMPLE_SVG_CREATE(ellipse, NS_NewSVGPathGeometryFrame),
  1.5016 +    SIMPLE_SVG_CREATE(line, NS_NewSVGPathGeometryFrame),
  1.5017 +    SIMPLE_SVG_CREATE(rect, NS_NewSVGPathGeometryFrame),
  1.5018 +    SIMPLE_SVG_CREATE(path, NS_NewSVGPathGeometryFrame),
  1.5019 +    SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame),
  1.5020 +    SIMPLE_SVG_CREATE(generic_, NS_NewSVGGenericContainerFrame),
  1.5021 +    { &nsGkAtoms::foreignObject,
  1.5022 +      FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW,
  1.5023 +                                 NS_NewSVGForeignObjectFrame,
  1.5024 +                                 nsCSSAnonBoxes::mozSVGForeignContent) },
  1.5025 +    SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame),
  1.5026 +    SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame),
  1.5027 +    SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame),
  1.5028 +    SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame),
  1.5029 +    SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame),
  1.5030 +    SIMPLE_SVG_CREATE(view, NS_NewSVGViewFrame),
  1.5031 +    SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame),
  1.5032 +    SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame),
  1.5033 +    SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame),
  1.5034 +    SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame),
  1.5035 +    SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame),
  1.5036 +    SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame),
  1.5037 +    SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame),
  1.5038 +    SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame),
  1.5039 +    SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame),
  1.5040 +    SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame),
  1.5041 +    SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame),
  1.5042 +    SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame),
  1.5043 +    SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame),
  1.5044 +    SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame),
  1.5045 +    SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame),
  1.5046 +    SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame),
  1.5047 +    SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame),
  1.5048 +    SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame),
  1.5049 +    SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame),
  1.5050 +    SIMPLE_SVG_CREATE(feDropShadow, NS_NewSVGFELeafFrame),
  1.5051 +    SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame),
  1.5052 +    SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame),
  1.5053 +    SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame),
  1.5054 +    SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame),
  1.5055 +    SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame),
  1.5056 +    SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame),
  1.5057 +    SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame),
  1.5058 +    SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame),
  1.5059 +    SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame),
  1.5060 +    SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame)
  1.5061 +  };
  1.5062 +
  1.5063 +  const FrameConstructionData* data =
  1.5064 +    FindDataByTag(aTag, aElement, aStyleContext, sSVGData,
  1.5065 +                  ArrayLength(sSVGData));
  1.5066 +
  1.5067 +  if (!data) {
  1.5068 +    data = &sContainerData;
  1.5069 +  }
  1.5070 +
  1.5071 +  return data;
  1.5072 +}
  1.5073 +
  1.5074 +void
  1.5075 +nsCSSFrameConstructor::AddPageBreakItem(nsIContent* aContent,
  1.5076 +                                        nsStyleContext* aMainStyleContext,
  1.5077 +                                        FrameConstructionItemList& aItems)
  1.5078 +{
  1.5079 +  // Use the same parent style context that |aMainStyleContext| has, since
  1.5080 +  // that's easier to re-resolve and it doesn't matter in practice.
  1.5081 +  // (Getting different parents can result in framechange hints, e.g.,
  1.5082 +  // for user-modify.)
  1.5083 +  nsRefPtr<nsStyleContext> pseudoStyle =
  1.5084 +    mPresShell->StyleSet()->
  1.5085 +      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageBreak,
  1.5086 +                               aMainStyleContext->GetParent());
  1.5087 +
  1.5088 +  NS_ASSERTION(pseudoStyle->StyleDisplay()->mDisplay ==
  1.5089 +                 NS_STYLE_DISPLAY_BLOCK, "Unexpected display");
  1.5090 +
  1.5091 +  static const FrameConstructionData sPageBreakData =
  1.5092 +    FCDATA_DECL(FCDATA_SKIP_FRAMESET, NS_NewPageBreakFrame);
  1.5093 +
  1.5094 +  // Lie about the tag and namespace so we don't trigger anything
  1.5095 +  // interesting during frame construction.
  1.5096 +  aItems.AppendItem(&sPageBreakData, aContent, nsCSSAnonBoxes::pageBreak,
  1.5097 +                    kNameSpaceID_None, nullptr, pseudoStyle.forget(),
  1.5098 +                    true, nullptr);
  1.5099 +}
  1.5100 +
  1.5101 +void
  1.5102 +nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState,
  1.5103 +                                                 nsIContent* aContent,
  1.5104 +                                                 bool aSuppressWhiteSpaceOptimizations,
  1.5105 +                                                 nsIFrame* aParentFrame,
  1.5106 +                                                 FrameConstructionItemList& aItems)
  1.5107 +{
  1.5108 +  aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
  1.5109 +  if (aContent->IsElement()) {
  1.5110 +    // We can't just remove our pending restyle flags, since we may
  1.5111 +    // have restyle-later-siblings set on us.  But we _can_ remove the
  1.5112 +    // "is possible restyle root" flags, and need to.  Otherwise we can
  1.5113 +    // end up with stale such flags (e.g. if we used to have a
  1.5114 +    // display:none parent when our last restyle was posted and
  1.5115 +    // processed and now no longer do).
  1.5116 +    aContent->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS &
  1.5117 +                         ~ELEMENT_PENDING_RESTYLE_FLAGS);
  1.5118 +  }
  1.5119 +
  1.5120 +  // XXX the GetContent() != aContent check is needed due to bug 135040.
  1.5121 +  // Remove it once that's fixed.
  1.5122 +  if (aContent->GetPrimaryFrame() &&
  1.5123 +      aContent->GetPrimaryFrame()->GetContent() == aContent &&
  1.5124 +      !aState.mCreatingExtraFrames) {
  1.5125 +    NS_ERROR("asked to create frame construction item for a node that already "
  1.5126 +             "has a frame");
  1.5127 +    return;
  1.5128 +  }
  1.5129 +
  1.5130 +  // don't create a whitespace frame if aParent doesn't want it
  1.5131 +  if (!NeedFrameFor(aState, aParentFrame, aContent)) {
  1.5132 +    return;
  1.5133 +  }
  1.5134 +
  1.5135 +  // never create frames for comments or PIs
  1.5136 +  if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
  1.5137 +      aContent->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION))
  1.5138 +    return;
  1.5139 +
  1.5140 +  nsRefPtr<nsStyleContext> styleContext;
  1.5141 +  styleContext = ResolveStyleContext(aParentFrame, aContent, &aState);
  1.5142 +
  1.5143 +  uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
  1.5144 +  if (aParentFrame->IsSVGText()) {
  1.5145 +    flags |= ITEM_IS_WITHIN_SVG_TEXT;
  1.5146 +  }
  1.5147 +  if (aParentFrame->GetType() == nsGkAtoms::blockFrame &&
  1.5148 +      aParentFrame->GetParent() &&
  1.5149 +      aParentFrame->GetParent()->GetType() == nsGkAtoms::svgTextFrame) {
  1.5150 +    flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
  1.5151 +  }
  1.5152 +  AddFrameConstructionItemsInternal(aState, aContent, aParentFrame,
  1.5153 +                                    aContent->Tag(), aContent->GetNameSpaceID(),
  1.5154 +                                    aSuppressWhiteSpaceOptimizations,
  1.5155 +                                    styleContext,
  1.5156 +                                    flags, nullptr,
  1.5157 +                                    aItems);
  1.5158 +}
  1.5159 +
  1.5160 +/* static */ void
  1.5161 +nsCSSFrameConstructor::SetAsUndisplayedContent(FrameConstructionItemList& aList,
  1.5162 +                                               nsIContent* aContent,
  1.5163 +                                               nsStyleContext* aStyleContext,
  1.5164 +                                               bool aIsGeneratedContent)
  1.5165 +{
  1.5166 +  if (aStyleContext->GetPseudo()) {
  1.5167 +    if (aIsGeneratedContent) {
  1.5168 +      aContent->UnbindFromTree();
  1.5169 +    }
  1.5170 +    return;
  1.5171 +  }
  1.5172 +
  1.5173 +  NS_ASSERTION(!aIsGeneratedContent, "Should have had pseudo type");
  1.5174 +  aList.AppendUndisplayedItem(aContent, aStyleContext);
  1.5175 +}
  1.5176 +
  1.5177 +void
  1.5178 +nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
  1.5179 +                                                         nsIContent* aContent,
  1.5180 +                                                         nsIFrame* aParentFrame,
  1.5181 +                                                         nsIAtom* aTag,
  1.5182 +                                                         int32_t aNameSpaceID,
  1.5183 +                                                         bool aSuppressWhiteSpaceOptimizations,
  1.5184 +                                                         nsStyleContext* aStyleContext,
  1.5185 +                                                         uint32_t aFlags,
  1.5186 +                                                         nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
  1.5187 +                                                         FrameConstructionItemList& aItems)
  1.5188 +{
  1.5189 +  NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT) ||
  1.5190 +                  aContent->IsElement(),
  1.5191 +                  "Shouldn't get anything else here!");
  1.5192 +
  1.5193 +  // The following code allows the user to specify the base tag
  1.5194 +  // of an element using XBL.  XUL and HTML objects (like boxes, menus, etc.)
  1.5195 +  // can then be extended arbitrarily.
  1.5196 +  const nsStyleDisplay* display = aStyleContext->StyleDisplay();
  1.5197 +  nsRefPtr<nsStyleContext> styleContext(aStyleContext);
  1.5198 +  PendingBinding* pendingBinding = nullptr;
  1.5199 +  if ((aFlags & ITEM_ALLOW_XBL_BASE) && display->mBinding)
  1.5200 +  {
  1.5201 +    // Ensure that our XBL bindings are installed.
  1.5202 +
  1.5203 +    nsXBLService* xblService = nsXBLService::GetInstance();
  1.5204 +    if (!xblService)
  1.5205 +      return;
  1.5206 +
  1.5207 +    bool resolveStyle;
  1.5208 +
  1.5209 +    nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
  1.5210 +
  1.5211 +    nsresult rv = xblService->LoadBindings(aContent, display->mBinding->GetURI(),
  1.5212 +                                           display->mBinding->mOriginPrincipal,
  1.5213 +                                           getter_AddRefs(newPendingBinding->mBinding),
  1.5214 +                                           &resolveStyle);
  1.5215 +    if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
  1.5216 +      return;
  1.5217 +
  1.5218 +    if (newPendingBinding->mBinding) {
  1.5219 +      pendingBinding = newPendingBinding;
  1.5220 +      // aState takes over owning newPendingBinding
  1.5221 +      aState.AddPendingBinding(newPendingBinding.forget());
  1.5222 +    }
  1.5223 +
  1.5224 +    if (resolveStyle) {
  1.5225 +      styleContext =
  1.5226 +        ResolveStyleContext(styleContext->GetParent(), aContent, &aState);
  1.5227 +      display = styleContext->StyleDisplay();
  1.5228 +      aStyleContext = styleContext;
  1.5229 +    }
  1.5230 +
  1.5231 +    aTag = mDocument->BindingManager()->ResolveTag(aContent, &aNameSpaceID);
  1.5232 +  }
  1.5233 +
  1.5234 +  bool isGeneratedContent = ((aFlags & ITEM_IS_GENERATED_CONTENT) != 0);
  1.5235 +
  1.5236 +  // Pre-check for display "none" - if we find that, don't create
  1.5237 +  // any frame at all
  1.5238 +  if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
  1.5239 +    SetAsUndisplayedContent(aItems, aContent, styleContext, isGeneratedContent);
  1.5240 +    return;
  1.5241 +  }
  1.5242 +
  1.5243 +  bool isText = !aContent->IsElement();
  1.5244 +
  1.5245 +  // never create frames for non-option/optgroup kids of <select> and
  1.5246 +  // non-option kids of <optgroup> inside a <select>.
  1.5247 +  // XXXbz it's not clear how this should best work with XBL.
  1.5248 +  nsIContent *parent = aContent->GetParent();
  1.5249 +  if (parent) {
  1.5250 +    // Check tag first, since that check will usually fail
  1.5251 +    nsIAtom* parentTag = parent->Tag();
  1.5252 +    if ((parentTag == nsGkAtoms::select || parentTag == nsGkAtoms::optgroup) &&
  1.5253 +        parent->IsHTML() &&
  1.5254 +        // <option> is ok no matter what
  1.5255 +        !aContent->IsHTML(nsGkAtoms::option) &&
  1.5256 +        // <optgroup> is OK in <select> but not in <optgroup>
  1.5257 +        (!aContent->IsHTML(nsGkAtoms::optgroup) ||
  1.5258 +         parentTag != nsGkAtoms::select) &&
  1.5259 +        // Allow native anonymous content no matter what
  1.5260 +        !aContent->IsRootOfNativeAnonymousSubtree()) {
  1.5261 +      // No frame for aContent
  1.5262 +      if (!isText) {
  1.5263 +        SetAsUndisplayedContent(aItems, aContent, styleContext,
  1.5264 +                                isGeneratedContent);
  1.5265 +      }
  1.5266 +      return;
  1.5267 +    }
  1.5268 +  }
  1.5269 +
  1.5270 +  bool isPopup = false;
  1.5271 +  // Try to find frame construction data for this content
  1.5272 +  const FrameConstructionData* data;
  1.5273 +  if (isText) {
  1.5274 +    data = FindTextData(aParentFrame);
  1.5275 +    if (!data) {
  1.5276 +      // Nothing to do here; suppressed text inside SVG
  1.5277 +      return;
  1.5278 +    }
  1.5279 +  } else {
  1.5280 +    Element* element = aContent->AsElement();
  1.5281 +
  1.5282 +    // Don't create frames for non-SVG element children of SVG elements.
  1.5283 +    if (aNameSpaceID != kNameSpaceID_SVG &&
  1.5284 +        ((aParentFrame &&
  1.5285 +          IsFrameForSVG(aParentFrame) &&
  1.5286 +          !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)) ||
  1.5287 +         (aFlags & ITEM_IS_WITHIN_SVG_TEXT))) {
  1.5288 +      SetAsUndisplayedContent(aItems, element, styleContext,
  1.5289 +                              isGeneratedContent);
  1.5290 +      return;
  1.5291 +    }
  1.5292 +
  1.5293 +    data = FindHTMLData(element, aTag, aNameSpaceID, aParentFrame,
  1.5294 +                        styleContext);
  1.5295 +    if (!data) {
  1.5296 +      data = FindXULTagData(element, aTag, aNameSpaceID, styleContext);
  1.5297 +    }
  1.5298 +    if (!data) {
  1.5299 +      data = FindMathMLData(element, aTag, aNameSpaceID, styleContext);
  1.5300 +    }
  1.5301 +    if (!data) {
  1.5302 +      data = FindSVGData(element, aTag, aNameSpaceID, aParentFrame,
  1.5303 +                         aFlags & ITEM_IS_WITHIN_SVG_TEXT,
  1.5304 +                         aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD,
  1.5305 +                         styleContext);
  1.5306 +    }
  1.5307 +
  1.5308 +    // Now check for XUL display types
  1.5309 +    if (!data) {
  1.5310 +      data = FindXULDisplayData(display, element, styleContext);
  1.5311 +    }
  1.5312 +
  1.5313 +    // And general display types
  1.5314 +    if (!data) {
  1.5315 +      data = FindDisplayData(display, element, aParentFrame, styleContext);
  1.5316 +    }
  1.5317 +
  1.5318 +    NS_ASSERTION(data, "Should have frame construction data now");
  1.5319 +
  1.5320 +    if (data->mBits & FCDATA_SUPPRESS_FRAME) {
  1.5321 +      SetAsUndisplayedContent(aItems, element, styleContext, isGeneratedContent);
  1.5322 +      return;
  1.5323 +    }
  1.5324 +
  1.5325 +#ifdef MOZ_XUL
  1.5326 +    if ((data->mBits & FCDATA_IS_POPUP) &&
  1.5327 +        (!aParentFrame || // Parent is inline
  1.5328 +         aParentFrame->GetType() != nsGkAtoms::menuFrame)) {
  1.5329 +      if (!aState.mPopupItems.containingBlock &&
  1.5330 +          !aState.mHavePendingPopupgroup) {
  1.5331 +        SetAsUndisplayedContent(aItems, element, styleContext,
  1.5332 +                                isGeneratedContent);
  1.5333 +        return;
  1.5334 +      }
  1.5335 +
  1.5336 +      isPopup = true;
  1.5337 +    }
  1.5338 +#endif /* MOZ_XUL */
  1.5339 +  }
  1.5340 +
  1.5341 +  uint32_t bits = data->mBits;
  1.5342 +
  1.5343 +  // Inside colgroups, suppress everything except columns.
  1.5344 +  if (aParentFrame &&
  1.5345 +      aParentFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
  1.5346 +      (!(bits & FCDATA_IS_TABLE_PART) ||
  1.5347 +       display->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN)) {
  1.5348 +    SetAsUndisplayedContent(aItems, aContent, styleContext, isGeneratedContent);
  1.5349 +    return;
  1.5350 +  }
  1.5351 +
  1.5352 +  bool canHavePageBreak =
  1.5353 +    (aFlags & ITEM_ALLOW_PAGE_BREAK) &&
  1.5354 +    aState.mPresContext->IsPaginated() &&
  1.5355 +    !display->IsAbsolutelyPositionedStyle() &&
  1.5356 +    !(bits & FCDATA_IS_TABLE_PART) &&
  1.5357 +    !(bits & FCDATA_IS_SVG_TEXT);
  1.5358 +
  1.5359 +  if (canHavePageBreak && display->mBreakBefore) {
  1.5360 +    AddPageBreakItem(aContent, aStyleContext, aItems);
  1.5361 +  }
  1.5362 +
  1.5363 +  FrameConstructionItem* item =
  1.5364 +    aItems.AppendItem(data, aContent, aTag, aNameSpaceID,
  1.5365 +                      pendingBinding, styleContext.forget(),
  1.5366 +                      aSuppressWhiteSpaceOptimizations, aAnonChildren);
  1.5367 +  if (!item) {
  1.5368 +    if (isGeneratedContent) {
  1.5369 +      aContent->UnbindFromTree();
  1.5370 +    }
  1.5371 +    return;
  1.5372 +  }
  1.5373 +
  1.5374 +  item->mIsText = isText;
  1.5375 +  item->mIsGeneratedContent = isGeneratedContent;
  1.5376 +  item->mIsAnonymousContentCreatorContent =
  1.5377 +    aFlags & ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT;
  1.5378 +  if (isGeneratedContent) {
  1.5379 +    NS_ADDREF(item->mContent);
  1.5380 +  }
  1.5381 +  item->mIsRootPopupgroup =
  1.5382 +    aNameSpaceID == kNameSpaceID_XUL && aTag == nsGkAtoms::popupgroup &&
  1.5383 +    aContent->IsRootOfNativeAnonymousSubtree();
  1.5384 +  if (item->mIsRootPopupgroup) {
  1.5385 +    aState.mHavePendingPopupgroup = true;
  1.5386 +  }
  1.5387 +  item->mIsPopup = isPopup;
  1.5388 +  item->mIsForSVGAElement = aNameSpaceID == kNameSpaceID_SVG &&
  1.5389 +                            aTag == nsGkAtoms::a;
  1.5390 +
  1.5391 +  if (canHavePageBreak && display->mBreakAfter) {
  1.5392 +    AddPageBreakItem(aContent, aStyleContext, aItems);
  1.5393 +  }
  1.5394 +
  1.5395 +  if (bits & FCDATA_IS_INLINE) {
  1.5396 +    // To correctly set item->mIsAllInline we need to build up our child items
  1.5397 +    // right now.
  1.5398 +    BuildInlineChildItems(aState, *item,
  1.5399 +                          aFlags & ITEM_IS_WITHIN_SVG_TEXT,
  1.5400 +                          aFlags & ITEM_ALLOWS_TEXT_PATH_CHILD);
  1.5401 +    item->mHasInlineEnds = true;
  1.5402 +    item->mIsBlock = false;
  1.5403 +  } else {
  1.5404 +    // Compute a boolean isInline which is guaranteed to be false for blocks
  1.5405 +    // (but may also be false for some inlines).
  1.5406 +    bool isInline =
  1.5407 +      // Table-internal things are inline-outside if and only if they're kids of
  1.5408 +      // inlines, since they'll trigger construction of inline-table
  1.5409 +      // pseudos.
  1.5410 +      ((bits & FCDATA_IS_TABLE_PART) &&
  1.5411 +       (!aParentFrame || // No aParentFrame means inline
  1.5412 +        aParentFrame->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE)) ||
  1.5413 +      // Things that are inline-outside but aren't inline frames are inline
  1.5414 +      display->IsInlineOutsideStyle() ||
  1.5415 +      // Popups that are certainly out of flow.
  1.5416 +      isPopup;
  1.5417 +
  1.5418 +    // Set mIsAllInline conservatively.  It just might be that even an inline
  1.5419 +    // that has mIsAllInline false doesn't need an {ib} split.  So this is just
  1.5420 +    // an optimization to keep from doing too much work in cases when we can
  1.5421 +    // show that mIsAllInline is true..
  1.5422 +    item->mIsAllInline = item->mHasInlineEnds = isInline ||
  1.5423 +      // Figure out whether we're guaranteed this item will be out of flow.
  1.5424 +      // This is not a precise test, since one of our ancestor inlines might add
  1.5425 +      // an absolute containing block (if it's relatively positioned) when there
  1.5426 +      // wasn't such a containing block before.  But it's conservative in the
  1.5427 +      // sense that anything that will really end up as an in-flow non-inline
  1.5428 +      // will test false here.  In other words, if this test is true we're
  1.5429 +      // guaranteed to be inline; if it's false we don't know what we'll end up
  1.5430 +      // as.
  1.5431 +      //
  1.5432 +      // If we make this test precise, we can remove some of the code dealing
  1.5433 +      // with the imprecision in ConstructInline and adjust the comments on
  1.5434 +      // mIsAllInline and mIsBlock in the header.  And probably remove mIsBlock
  1.5435 +      // altogether, since then it will always be equal to !mHasInlineEnds.
  1.5436 +      (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
  1.5437 +       aState.GetGeometricParent(display, nullptr));
  1.5438 +
  1.5439 +    // Set mIsBlock conservatively.  It's OK to set it false for some real
  1.5440 +    // blocks, but not OK to set it true for things that aren't blocks.  Since
  1.5441 +    // isOutOfFlow might be false even in cases when the frame will end up
  1.5442 +    // out-of-flow, we can't use it here.  But we _can_ say that the frame will
  1.5443 +    // for sure end up in-flow if it's not floated or absolutely positioned.
  1.5444 +    item->mIsBlock = !isInline &&
  1.5445 +                     !display->IsAbsolutelyPositionedStyle() &&
  1.5446 +                     !display->IsFloatingStyle() &&
  1.5447 +                     !(bits & FCDATA_IS_SVG_TEXT);
  1.5448 +  }
  1.5449 +
  1.5450 +  if (item->mIsAllInline) {
  1.5451 +    aItems.InlineItemAdded();
  1.5452 +  } else if (item->mIsBlock) {
  1.5453 +    aItems.BlockItemAdded();
  1.5454 +  }
  1.5455 +
  1.5456 +  // Our item should be treated as a line participant if we have the relevant
  1.5457 +  // bit and are going to be in-flow.  Note that this really only matters if
  1.5458 +  // our ancestor is a box or some such, so the fact that we might have an
  1.5459 +  // inline ancestor that might become a containing block is not relevant here.
  1.5460 +  if ((bits & FCDATA_IS_LINE_PARTICIPANT) &&
  1.5461 +      ((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
  1.5462 +       !aState.GetGeometricParent(display, nullptr))) {
  1.5463 +    item->mIsLineParticipant = true;
  1.5464 +    aItems.LineParticipantItemAdded();
  1.5465 +  }
  1.5466 +}
  1.5467 +
  1.5468 +static void
  1.5469 +DestroyContent(void* aPropertyValue)
  1.5470 +{
  1.5471 +  nsIContent* content = static_cast<nsIContent*>(aPropertyValue);
  1.5472 +  content->UnbindFromTree();
  1.5473 +  NS_RELEASE(content);
  1.5474 +}
  1.5475 +
  1.5476 +NS_DECLARE_FRAME_PROPERTY(BeforeProperty, DestroyContent)
  1.5477 +NS_DECLARE_FRAME_PROPERTY(AfterProperty, DestroyContent)
  1.5478 +
  1.5479 +static const FramePropertyDescriptor*
  1.5480 +GenConPseudoToProperty(nsIAtom* aPseudo)
  1.5481 +{
  1.5482 +  NS_ASSERTION(aPseudo == nsCSSPseudoElements::before ||
  1.5483 +               aPseudo == nsCSSPseudoElements::after,
  1.5484 +               "Bad gen-con pseudo");
  1.5485 +  return aPseudo == nsCSSPseudoElements::before ? BeforeProperty()
  1.5486 +      : AfterProperty();
  1.5487 +}
  1.5488 +
  1.5489 +/**
  1.5490 + * Return true if the frame construction item pointed to by aIter will
  1.5491 + * create a frame adjacent to a line boundary in the frame tree, and that
  1.5492 + * line boundary is induced by a content node adjacent to the frame's
  1.5493 + * content node in the content tree. The latter condition is necessary so
  1.5494 + * that ContentAppended/ContentInserted/ContentRemoved can easily find any
  1.5495 + * text nodes that were suppressed here.
  1.5496 + */
  1.5497 +bool
  1.5498 +nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter)
  1.5499 +{
  1.5500 +  if (aIter.item().mSuppressWhiteSpaceOptimizations) {
  1.5501 +    return false;
  1.5502 +  }
  1.5503 +
  1.5504 +  if (aIter.AtStart()) {
  1.5505 +    if (aIter.List()->HasLineBoundaryAtStart() &&
  1.5506 +        !aIter.item().mContent->GetPreviousSibling())
  1.5507 +      return true;
  1.5508 +  } else {
  1.5509 +    FCItemIterator prev = aIter;
  1.5510 +    prev.Prev();
  1.5511 +    if (prev.item().IsLineBoundary() &&
  1.5512 +        !prev.item().mSuppressWhiteSpaceOptimizations &&
  1.5513 +        aIter.item().mContent->GetPreviousSibling() == prev.item().mContent)
  1.5514 +      return true;
  1.5515 +  }
  1.5516 +
  1.5517 +  FCItemIterator next = aIter;
  1.5518 +  next.Next();
  1.5519 +  if (next.IsDone()) {
  1.5520 +    if (aIter.List()->HasLineBoundaryAtEnd() &&
  1.5521 +        !aIter.item().mContent->GetNextSibling())
  1.5522 +      return true;
  1.5523 +  } else {
  1.5524 +    if (next.item().IsLineBoundary() &&
  1.5525 +        !next.item().mSuppressWhiteSpaceOptimizations &&
  1.5526 +        aIter.item().mContent->GetNextSibling() == next.item().mContent)
  1.5527 +      return true;
  1.5528 +  }
  1.5529 +
  1.5530 +  return false;
  1.5531 +}
  1.5532 +
  1.5533 +void
  1.5534 +nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState& aState,
  1.5535 +                                               FCItemIterator& aIter,
  1.5536 +                                               nsIFrame* aParentFrame,
  1.5537 +                                               nsFrameItems& aFrameItems)
  1.5538 +{
  1.5539 +  nsIFrame* adjParentFrame = aParentFrame;
  1.5540 +  FrameConstructionItem& item = aIter.item();
  1.5541 +  nsStyleContext* styleContext = item.mStyleContext;
  1.5542 +  AdjustParentFrame(adjParentFrame, item.mFCData, styleContext);
  1.5543 +
  1.5544 +  if (item.mIsText) {
  1.5545 +    // If this is collapsible whitespace next to a line boundary,
  1.5546 +    // don't create a frame. item.IsWhitespace() also sets the
  1.5547 +    // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
  1.5548 +    // end up creating a frame, nsTextFrame::Init will clear the flag.)
  1.5549 +    // We don't do this for generated content, because some generated
  1.5550 +    // text content is empty text nodes that are about to be initialized.
  1.5551 +    // (We check mAdditionalStateBits because only the generated content
  1.5552 +    // container's frame construction item is marked with
  1.5553 +    // mIsGeneratedContent, and we might not have an aParentFrame.)
  1.5554 +    // We don't do it for content that may have XBL anonymous siblings,
  1.5555 +    // because they make it difficult to correctly create the frame
  1.5556 +    // due to dynamic changes.
  1.5557 +    // We don't do it for SVG text, since we might need to position and
  1.5558 +    // measure the white space glyphs due to x/y/dx/dy attributes.
  1.5559 +    if (AtLineBoundary(aIter) &&
  1.5560 +        !styleContext->StyleText()->WhiteSpaceOrNewlineIsSignificant() &&
  1.5561 +        aIter.List()->ParentHasNoXBLChildren() &&
  1.5562 +        !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
  1.5563 +        (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) &&
  1.5564 +        !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT) &&
  1.5565 +        !mAlwaysCreateFramesForIgnorableWhitespace &&
  1.5566 +        item.IsWhitespace(aState))
  1.5567 +      return;
  1.5568 +
  1.5569 +    ConstructTextFrame(item.mFCData, aState, item.mContent,
  1.5570 +                       adjParentFrame, styleContext,
  1.5571 +                       aFrameItems);
  1.5572 +    return;
  1.5573 +  }
  1.5574 +
  1.5575 +  // Start background loads during frame construction so that we're
  1.5576 +  // guaranteed that they will be started before onload fires.
  1.5577 +  styleContext->StartBackgroundImageLoads();
  1.5578 +
  1.5579 +  nsFrameState savedStateBits = aState.mAdditionalStateBits;
  1.5580 +  if (item.mIsGeneratedContent) {
  1.5581 +    // Ensure that frames created here are all tagged with
  1.5582 +    // NS_FRAME_GENERATED_CONTENT.
  1.5583 +    aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
  1.5584 +
  1.5585 +    // Note that we're not necessarily setting this property on the primary
  1.5586 +    // frame for the content for which this is generated content.  We might be
  1.5587 +    // setting it on a table pseudo-frame inserted under that instead.  That's
  1.5588 +    // OK, though; we just need to do the property set so that the content will
  1.5589 +    // get cleaned up when the frame is destroyed.
  1.5590 +    aParentFrame->Properties().Set(GenConPseudoToProperty(styleContext->GetPseudo()),
  1.5591 +                                   item.mContent);
  1.5592 +
  1.5593 +    // Now that we've passed ownership of item.mContent to the frame, unset
  1.5594 +    // our generated content flag so we don't release or unbind it ourselves.
  1.5595 +    item.mIsGeneratedContent = false;
  1.5596 +  }
  1.5597 +
  1.5598 +  // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
  1.5599 +  ConstructFrameFromItemInternal(item, aState, adjParentFrame, aFrameItems);
  1.5600 +
  1.5601 +  aState.mAdditionalStateBits = savedStateBits;
  1.5602 +}
  1.5603 +
  1.5604 +
  1.5605 +inline bool
  1.5606 +IsRootBoxFrame(nsIFrame *aFrame)
  1.5607 +{
  1.5608 +  return (aFrame->GetType() == nsGkAtoms::rootFrame);
  1.5609 +}
  1.5610 +
  1.5611 +nsresult
  1.5612 +nsCSSFrameConstructor::ReconstructDocElementHierarchy()
  1.5613 +{
  1.5614 +  Element* rootElement = mDocument->GetRootElement();
  1.5615 +  if (!rootElement) {
  1.5616 +    /* nothing to do */
  1.5617 +    return NS_OK;
  1.5618 +  }
  1.5619 +  return RecreateFramesForContent(rootElement, false);
  1.5620 +}
  1.5621 +
  1.5622 +nsIFrame*
  1.5623 +nsCSSFrameConstructor::GetFrameFor(nsIContent* aContent)
  1.5624 +{
  1.5625 +  // Get the primary frame associated with the content
  1.5626 +  nsIFrame* frame = aContent->GetPrimaryFrame();
  1.5627 +
  1.5628 +  if (!frame)
  1.5629 +    return nullptr;
  1.5630 +
  1.5631 +  // If the content of the frame is not the desired content then this is not
  1.5632 +  // really a frame for the desired content.
  1.5633 +  // XXX This check is needed due to bug 135040. Remove it once that's fixed.
  1.5634 +  if (frame->GetContent() != aContent) {
  1.5635 +    return nullptr;
  1.5636 +  }
  1.5637 +
  1.5638 +  nsIFrame* insertionFrame = frame->GetContentInsertionFrame();
  1.5639 +
  1.5640 +  NS_ASSERTION(insertionFrame == frame || !frame->IsLeaf(),
  1.5641 +    "The insertion frame is the primary frame or the primary frame isn't a leaf");
  1.5642 +
  1.5643 +  return insertionFrame;
  1.5644 +}
  1.5645 +
  1.5646 +nsIFrame*
  1.5647 +nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame,
  1.5648 +                                                  ContainingBlockType aType)
  1.5649 +{
  1.5650 +  NS_PRECONDITION(nullptr != mRootElementFrame, "no root element frame");
  1.5651 +
  1.5652 +  // Starting with aFrame, look for a frame that is absolutely positioned or
  1.5653 +  // relatively positioned (and transformed, if aType is FIXED)
  1.5654 +  for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
  1.5655 +    if (frame->IsFrameOfType(nsIFrame::eMathML)) {
  1.5656 +      // If it's mathml, bail out -- no absolute positioning out from inside
  1.5657 +      // mathml frames.  Note that we don't make this part of the loop
  1.5658 +      // condition because of the stuff at the end of this method...
  1.5659 +      return nullptr;
  1.5660 +    }
  1.5661 +
  1.5662 +    // If the frame is positioned, we will probably return it as the containing
  1.5663 +    // block (see the exceptions below).  Otherwise, we'll start looking at the
  1.5664 +    // parent frame, unless we're dealing with a scrollframe.
  1.5665 +    // Scrollframes are special since they're not positioned, but their
  1.5666 +    // scrolledframe might be.  So, we need to check this special case to return
  1.5667 +    // the correct containing block (the scrolledframe) in that case.
  1.5668 +    // If we're looking for a fixed-pos containing block and the frame is
  1.5669 +    // not transformed, skip it.
  1.5670 +    if (!frame->IsPositioned() ||
  1.5671 +        (aType == FIXED_POS &&
  1.5672 +         !frame->StyleDisplay()->HasTransform(frame) &&
  1.5673 +         !frame->StyleDisplay()->HasPerspectiveStyle())) {
  1.5674 +      continue;
  1.5675 +    }
  1.5676 +    nsIFrame* absPosCBCandidate = frame;
  1.5677 +    nsIAtom* type = absPosCBCandidate->GetType();
  1.5678 +    if (type == nsGkAtoms::fieldSetFrame) {
  1.5679 +      absPosCBCandidate = static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
  1.5680 +      if (!absPosCBCandidate) {
  1.5681 +        continue;
  1.5682 +      }
  1.5683 +      type = absPosCBCandidate->GetType();
  1.5684 +    }
  1.5685 +    if (type == nsGkAtoms::scrollFrame) {
  1.5686 +      nsIScrollableFrame* scrollFrame = do_QueryFrame(absPosCBCandidate);
  1.5687 +      absPosCBCandidate = scrollFrame->GetScrolledFrame();
  1.5688 +      if (!absPosCBCandidate) {
  1.5689 +        continue;
  1.5690 +      }
  1.5691 +      type = absPosCBCandidate->GetType();
  1.5692 +    }
  1.5693 +    // Only first continuations can be containing blocks.
  1.5694 +    absPosCBCandidate = absPosCBCandidate->FirstContinuation();
  1.5695 +    // Is the frame really an absolute container?
  1.5696 +    if (!absPosCBCandidate->IsAbsoluteContainer()) {
  1.5697 +      continue;
  1.5698 +    }
  1.5699 +
  1.5700 +    // For tables, skip the inner frame and consider the outer table frame.
  1.5701 +    if (type == nsGkAtoms::tableFrame) {
  1.5702 +      continue;
  1.5703 +    }
  1.5704 +    // For outer table frames, we can just return absPosCBCandidate.
  1.5705 +    return absPosCBCandidate;
  1.5706 +  }
  1.5707 +
  1.5708 +  // It is possible for the search for the containing block to fail, because
  1.5709 +  // no absolute container can be found in the parent chain.  In those cases,
  1.5710 +  // we fall back to the document element's containing block.
  1.5711 +  if (aType == FIXED_POS) {
  1.5712 +    return mFixedContainingBlock;
  1.5713 +  }
  1.5714 +  return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nullptr;
  1.5715 +}
  1.5716 +
  1.5717 +nsIFrame*
  1.5718 +nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
  1.5719 +{
  1.5720 +  // Starting with aFrame, look for a frame that is a float containing block.
  1.5721 +  // IF we hit a mathml frame, bail out; we don't allow floating out of mathml
  1.5722 +  // frames, because they don't seem to be able to deal.
  1.5723 +  // The logic here needs to match the logic in ProcessChildren()
  1.5724 +  for (nsIFrame* containingBlock = aFrame;
  1.5725 +       containingBlock &&
  1.5726 +         !ShouldSuppressFloatingOfDescendants(containingBlock);
  1.5727 +       containingBlock = containingBlock->GetParent()) {
  1.5728 +    if (containingBlock->IsFloatContainingBlock()) {
  1.5729 +      return containingBlock;
  1.5730 +    }
  1.5731 +  }
  1.5732 +
  1.5733 +  // If we didn't find a containing block, then there just isn't
  1.5734 +  // one.... return null
  1.5735 +  return nullptr;
  1.5736 +}
  1.5737 +
  1.5738 +/**
  1.5739 + * This function will check whether aContainer has :after generated content.
  1.5740 + * If so, appending to it should actually insert.  The return value is the
  1.5741 + * parent to use for newly-appended content.  *aAfterFrame points to the :after
  1.5742 + * frame before which appended content should go, if there is one.
  1.5743 + */
  1.5744 +static nsIFrame*
  1.5745 +AdjustAppendParentForAfterContent(nsPresContext* aPresContext,
  1.5746 +                                  nsIContent* aContainer,
  1.5747 +                                  nsIFrame* aParentFrame,
  1.5748 +                                  nsIFrame** aAfterFrame)
  1.5749 +{
  1.5750 +  // See if the parent has an :after pseudo-element.  Check for the presence
  1.5751 +  // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive.
  1.5752 +  nsStyleContext* parentStyle = aParentFrame->StyleContext();
  1.5753 +  if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle,
  1.5754 +                                    nsCSSPseudoElements::ePseudo_after,
  1.5755 +                                    aPresContext)) {
  1.5756 +    // Ensure that the :after frame is on the principal child list.
  1.5757 +    aParentFrame->DrainSelfOverflowList();
  1.5758 +
  1.5759 +    nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame);
  1.5760 +    if (afterFrame) {
  1.5761 +      *aAfterFrame = afterFrame;
  1.5762 +      return afterFrame->GetParent();
  1.5763 +    }
  1.5764 +  }
  1.5765 +
  1.5766 +  *aAfterFrame = nullptr;
  1.5767 +
  1.5768 +  if (IsFramePartOfIBSplit(aParentFrame)) {
  1.5769 +    // We might be in a situation where the last part of the {ib} split was
  1.5770 +    // empty.  Since we have no ::after pseudo-element, we do in fact want to be
  1.5771 +    // appending to that last part, so advance to it if needed.  Note that here
  1.5772 +    // aParentFrame is the result of a GetLastIBSplitSibling call, so must be
  1.5773 +    // either the last or next to last ib-split sibling.
  1.5774 +    nsIFrame* trailingInline = GetIBSplitSibling(aParentFrame);
  1.5775 +    if (trailingInline) {
  1.5776 +      aParentFrame = trailingInline;
  1.5777 +    }
  1.5778 +
  1.5779 +    // Always make sure to look at the last continuation of the frame
  1.5780 +    // for the {ib} case, even if that continuation is empty.  We
  1.5781 +    // don't do this for the non-ib-split-frame case, since in the
  1.5782 +    // other cases appending to the last nonempty continuation is fine
  1.5783 +    // and in fact not doing that can confuse code that doesn't know
  1.5784 +    // to pull kids from continuations other than its next one.
  1.5785 +    aParentFrame = aParentFrame->LastContinuation();
  1.5786 +  }
  1.5787 +
  1.5788 +  return aParentFrame;
  1.5789 +}
  1.5790 +
  1.5791 +/**
  1.5792 + * This function will get the previous sibling to use for an append operation.
  1.5793 + * it takes a parent frame (must not be null) and its :after frame (may be
  1.5794 + * null).
  1.5795 + */
  1.5796 +static nsIFrame*
  1.5797 +FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame)
  1.5798 +{
  1.5799 +  if (aAfterFrame) {
  1.5800 +    NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent");
  1.5801 +    NS_ASSERTION(aAfterFrame->GetPrevSibling() ||
  1.5802 +                 aParentFrame->GetFirstPrincipalChild() == aAfterFrame,
  1.5803 +                 ":after frame must be on the principal child list here");
  1.5804 +    return aAfterFrame->GetPrevSibling();
  1.5805 +  }
  1.5806 +
  1.5807 +  aParentFrame->DrainSelfOverflowList();
  1.5808 +
  1.5809 +  return aParentFrame->GetLastChild(kPrincipalList);
  1.5810 +}
  1.5811 +
  1.5812 +/**
  1.5813 + * This function will get the next sibling for a frame insert operation given
  1.5814 + * the parent and previous sibling.  aPrevSibling may be null.
  1.5815 + */
  1.5816 +static nsIFrame*
  1.5817 +GetInsertNextSibling(nsIFrame* aParentFrame, nsIFrame* aPrevSibling)
  1.5818 +{
  1.5819 +  if (aPrevSibling) {
  1.5820 +    return aPrevSibling->GetNextSibling();
  1.5821 +  }
  1.5822 +
  1.5823 +  return aParentFrame->GetFirstPrincipalChild();
  1.5824 +}
  1.5825 +
  1.5826 +/**
  1.5827 + * This function is called by ContentAppended() and ContentInserted() when
  1.5828 + * appending flowed frames to a parent's principal child list. It handles the
  1.5829 + * case where the parent is the trailing inline of an {ib} split.
  1.5830 + */
  1.5831 +nsresult
  1.5832 +nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&       aState,
  1.5833 +                                            nsIFrame*                      aParentFrame,
  1.5834 +                                            nsFrameItems&                  aFrameList,
  1.5835 +                                            nsIFrame*                      aPrevSibling,
  1.5836 +                                            bool                           aIsRecursiveCall)
  1.5837 +{
  1.5838 +  NS_PRECONDITION(!IsFramePartOfIBSplit(aParentFrame) ||
  1.5839 +                  !GetIBSplitSibling(aParentFrame) ||
  1.5840 +                  !GetIBSplitSibling(aParentFrame)->GetFirstPrincipalChild(),
  1.5841 +                  "aParentFrame has a ib-split sibling with kids?");
  1.5842 +  NS_PRECONDITION(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame,
  1.5843 +                  "Parent and prevsibling don't match");
  1.5844 +
  1.5845 +  nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
  1.5846 +
  1.5847 +  NS_ASSERTION(nextSibling ||
  1.5848 +               !aParentFrame->GetNextContinuation() ||
  1.5849 +               !aParentFrame->GetNextContinuation()->GetFirstPrincipalChild() ||
  1.5850 +               aIsRecursiveCall,
  1.5851 +               "aParentFrame has later continuations with kids?");
  1.5852 +  NS_ASSERTION(nextSibling ||
  1.5853 +               !IsFramePartOfIBSplit(aParentFrame) ||
  1.5854 +               (IsInlineFrame(aParentFrame) &&
  1.5855 +                !GetIBSplitSibling(aParentFrame) &&
  1.5856 +                !aParentFrame->GetNextContinuation()) ||
  1.5857 +               aIsRecursiveCall,
  1.5858 +               "aParentFrame is not last?");
  1.5859 +
  1.5860 +  // If we're inserting a list of frames at the end of the trailing inline
  1.5861 +  // of an {ib} split, we may need to create additional {ib} siblings to parent
  1.5862 +  // them.
  1.5863 +  if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
  1.5864 +    // When we get here, our frame list might start with a block.  If it does
  1.5865 +    // so, and aParentFrame is an inline, and it and all its previous
  1.5866 +    // continuations have no siblings, then put the initial blocks from the
  1.5867 +    // frame list into the previous block of the {ib} split.  Note that we
  1.5868 +    // didn't want to stop at the block part of the split when figuring out
  1.5869 +    // initial parent, because that could screw up float parenting; it's easier
  1.5870 +    // to do this little fixup here instead.
  1.5871 +    if (aFrameList.NotEmpty() && !aFrameList.FirstChild()->IsInlineOutside()) {
  1.5872 +      // See whether our trailing inline is empty
  1.5873 +      nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
  1.5874 +      if (firstContinuation->PrincipalChildList().IsEmpty()) {
  1.5875 +        // Our trailing inline is empty.  Collect our starting blocks from
  1.5876 +        // aFrameList, get the right parent frame for them, and put them in.
  1.5877 +        nsFrameList::FrameLinkEnumerator firstNonBlockEnumerator =
  1.5878 +          FindFirstNonBlock(aFrameList);
  1.5879 +        nsFrameList blockKids = aFrameList.ExtractHead(firstNonBlockEnumerator);
  1.5880 +        NS_ASSERTION(blockKids.NotEmpty(), "No blocks?");
  1.5881 +
  1.5882 +        nsIFrame* prevBlock =
  1.5883 +          GetIBSplitPrevSibling(firstContinuation)->LastContinuation();
  1.5884 +        NS_ASSERTION(prevBlock, "Should have previous block here");
  1.5885 +
  1.5886 +        MoveChildrenTo(aState.mPresContext, aParentFrame, prevBlock, blockKids);
  1.5887 +      }
  1.5888 +    }
  1.5889 +
  1.5890 +    // We want to put some of the frames into this inline frame.
  1.5891 +    nsFrameList::FrameLinkEnumerator firstBlockEnumerator(aFrameList);
  1.5892 +    FindFirstBlock(firstBlockEnumerator);
  1.5893 +
  1.5894 +    nsFrameList inlineKids = aFrameList.ExtractHead(firstBlockEnumerator);
  1.5895 +    if (!inlineKids.IsEmpty()) {
  1.5896 +      AppendFrames(aParentFrame, kPrincipalList, inlineKids);
  1.5897 +    }
  1.5898 +
  1.5899 +    if (!aFrameList.IsEmpty()) {
  1.5900 +      bool positioned = aParentFrame->IsRelativelyPositioned();
  1.5901 +      nsFrameItems ibSiblings;
  1.5902 +      CreateIBSiblings(aState, aParentFrame, positioned, aFrameList,
  1.5903 +                       ibSiblings);
  1.5904 +
  1.5905 +      // Make sure to trigger reflow of the inline that used to be our
  1.5906 +      // last one and now isn't anymore, since its GetSkipSides() has
  1.5907 +      // changed.
  1.5908 +      mPresShell->FrameNeedsReflow(aParentFrame,
  1.5909 +                                   nsIPresShell::eTreeChange,
  1.5910 +                                   NS_FRAME_HAS_DIRTY_CHILDREN);
  1.5911 +
  1.5912 +      // Recurse so we create new ib siblings as needed for aParentFrame's parent
  1.5913 +      return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
  1.5914 +                                  aParentFrame, true);
  1.5915 +    }
  1.5916 +
  1.5917 +    return NS_OK;
  1.5918 +  }
  1.5919 +
  1.5920 +  // Insert the frames after our aPrevSibling
  1.5921 +  return InsertFrames(aParentFrame, kPrincipalList, aPrevSibling, aFrameList);
  1.5922 +}
  1.5923 +
  1.5924 +#define UNSET_DISPLAY 255
  1.5925 +
  1.5926 +// This gets called to see if the frames corresponding to aSibling and aContent
  1.5927 +// should be siblings in the frame tree. Although (1) rows and cols, (2) row
  1.5928 +// groups and col groups, (3) row groups and captions, (4) legends and content
  1.5929 +// inside fieldsets, (5) popups and other kids of the menu are siblings from a
  1.5930 +// content perspective, they are not considered siblings in the frame tree.
  1.5931 +bool
  1.5932 +nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aSibling,
  1.5933 +                                      nsIContent*            aContent,
  1.5934 +                                      uint8_t&               aDisplay)
  1.5935 +{
  1.5936 +  nsIFrame* parentFrame = aSibling->GetParent();
  1.5937 +  nsIAtom* parentType = nullptr;
  1.5938 +  if (parentFrame) {
  1.5939 +    parentType = parentFrame->GetType();
  1.5940 +  }
  1.5941 +
  1.5942 +  uint8_t siblingDisplay = aSibling->GetDisplay();
  1.5943 +  if ((NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == siblingDisplay) ||
  1.5944 +      (NS_STYLE_DISPLAY_TABLE_COLUMN       == siblingDisplay) ||
  1.5945 +      (NS_STYLE_DISPLAY_TABLE_CAPTION      == siblingDisplay) ||
  1.5946 +      (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == siblingDisplay) ||
  1.5947 +      (NS_STYLE_DISPLAY_TABLE_ROW_GROUP    == siblingDisplay) ||
  1.5948 +      (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == siblingDisplay) ||
  1.5949 +      nsGkAtoms::menuFrame == parentType) {
  1.5950 +    // if we haven't already, construct a style context to find the display type of aContent
  1.5951 +    if (UNSET_DISPLAY == aDisplay) {
  1.5952 +      nsRefPtr<nsStyleContext> styleContext;
  1.5953 +      nsIFrame* styleParent = aSibling->GetParentStyleContextFrame();
  1.5954 +      if (!styleParent) {
  1.5955 +        NS_NOTREACHED("Shouldn't happen");
  1.5956 +        return false;
  1.5957 +      }
  1.5958 +      // XXXbz when this code is killed, the state argument to
  1.5959 +      // ResolveStyleContext can be made non-optional.
  1.5960 +      styleContext = ResolveStyleContext(styleParent, aContent, nullptr);
  1.5961 +      const nsStyleDisplay* display = styleContext->StyleDisplay();
  1.5962 +      aDisplay = display->mDisplay;
  1.5963 +    }
  1.5964 +    if (nsGkAtoms::menuFrame == parentType) {
  1.5965 +      return
  1.5966 +        (NS_STYLE_DISPLAY_POPUP == aDisplay) ==
  1.5967 +        (NS_STYLE_DISPLAY_POPUP == siblingDisplay);
  1.5968 +    }
  1.5969 +    // To have decent performance we want to return false in cases in which
  1.5970 +    // reordering the two siblings has no effect on display.  To ensure
  1.5971 +    // correctness, we MUST return false in cases where the two siblings have
  1.5972 +    // the same desired parent type and live on different display lists.
  1.5973 +    // Specificaly, columns and column groups should only consider columns and
  1.5974 +    // column groups as valid siblings.  Captions should only consider other
  1.5975 +    // captions.  All other things should consider each other as valid
  1.5976 +    // siblings.  The restriction in the |if| above on siblingDisplay is ok,
  1.5977 +    // because for correctness the only part that really needs to happen is to
  1.5978 +    // not consider captions, column groups, and row/header/footer groups
  1.5979 +    // siblings of each other.  Treating a column or colgroup as a valid
  1.5980 +    // sibling of a non-table-related frame will just mean we end up reframing.
  1.5981 +    if ((siblingDisplay == NS_STYLE_DISPLAY_TABLE_CAPTION) !=
  1.5982 +        (aDisplay == NS_STYLE_DISPLAY_TABLE_CAPTION)) {
  1.5983 +      // One's a caption and the other is not.  Not valid siblings.
  1.5984 +      return false;
  1.5985 +    }
  1.5986 +
  1.5987 +    if ((siblingDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP ||
  1.5988 +         siblingDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN) !=
  1.5989 +        (aDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP ||
  1.5990 +         aDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN)) {
  1.5991 +      // One's a column or column group and the other is not.  Not valid
  1.5992 +      // siblings.
  1.5993 +      return false;
  1.5994 +    }
  1.5995 +    // Fall through; it's possible that the display type was overridden and
  1.5996 +    // a different sort of frame was constructed, so we may need to return false
  1.5997 +    // below.
  1.5998 +  }
  1.5999 +
  1.6000 +  if (IsFrameForFieldSet(parentFrame, parentType)) {
  1.6001 +    // Legends can be sibling of legends but not of other content in the fieldset
  1.6002 +    nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType();
  1.6003 +    bool legendContent = aContent->IsHTML(nsGkAtoms::legend);
  1.6004 +
  1.6005 +    if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
  1.6006 +        (!legendContent && (nsGkAtoms::legendFrame == sibType)))
  1.6007 +      return false;
  1.6008 +  }
  1.6009 +
  1.6010 +  return true;
  1.6011 +}
  1.6012 +
  1.6013 +nsIFrame*
  1.6014 +nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
  1.6015 +                                                  nsIContent* aTargetContent,
  1.6016 +                                                  uint8_t& aTargetContentDisplay,
  1.6017 +                                                  bool aPrevSibling)
  1.6018 +{
  1.6019 +  nsIFrame* sibling = aContent->GetPrimaryFrame();
  1.6020 +  if (!sibling || sibling->GetContent() != aContent) {
  1.6021 +    // XXX the GetContent() != aContent check is needed due to bug 135040.
  1.6022 +    // Remove it once that's fixed.
  1.6023 +    return nullptr;
  1.6024 +  }
  1.6025 +
  1.6026 +  // If the frame is out-of-flow, GetPrimaryFrame() will have returned the
  1.6027 +  // out-of-flow frame; we want the placeholder.
  1.6028 +  if (sibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
  1.6029 +    nsIFrame* placeholderFrame = GetPlaceholderFrameFor(sibling);
  1.6030 +    NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
  1.6031 +    sibling = placeholderFrame;
  1.6032 +  }
  1.6033 +
  1.6034 +  // The frame we have now should never be a continuation
  1.6035 +  NS_ASSERTION(!sibling->GetPrevContinuation(), "How did that happen?");
  1.6036 +
  1.6037 +  if (aPrevSibling) {
  1.6038 +    // The frame may be a ib-split frame (a split inline frame that
  1.6039 +    // contains a block).  Get the last part of that split.
  1.6040 +    if (IsFramePartOfIBSplit(sibling)) {
  1.6041 +      sibling = GetLastIBSplitSibling(sibling, true);
  1.6042 +    }
  1.6043 +
  1.6044 +    // The frame may have a continuation. If so, we want the last
  1.6045 +    // non-overflow-container continuation as our previous sibling.
  1.6046 +    sibling = sibling->GetTailContinuation();
  1.6047 +  }
  1.6048 +
  1.6049 +  if (aTargetContent &&
  1.6050 +      !IsValidSibling(sibling, aTargetContent, aTargetContentDisplay)) {
  1.6051 +    sibling = nullptr;
  1.6052 +  }
  1.6053 +
  1.6054 +  return sibling;
  1.6055 +}
  1.6056 +
  1.6057 +nsIFrame*
  1.6058 +nsCSSFrameConstructor::FindPreviousSibling(FlattenedChildIterator aIter,
  1.6059 +                                           uint8_t& aTargetContentDisplay)
  1.6060 +{
  1.6061 +  nsIContent* child = aIter.Get();
  1.6062 +
  1.6063 +  // Note: not all content objects are associated with a frame (e.g., if it's
  1.6064 +  // `display: none') so keep looking until we find a previous frame
  1.6065 +  while (nsIContent* sibling = aIter.GetPreviousChild()) {
  1.6066 +    nsIFrame* prevSibling =
  1.6067 +      FindFrameForContentSibling(sibling, child, aTargetContentDisplay, true);
  1.6068 +
  1.6069 +    if (prevSibling) {
  1.6070 +      // Found a previous sibling, we're done!
  1.6071 +      return prevSibling;
  1.6072 +    }
  1.6073 +  }
  1.6074 +
  1.6075 +  return nullptr;
  1.6076 +}
  1.6077 +
  1.6078 +nsIFrame*
  1.6079 +nsCSSFrameConstructor::FindNextSibling(FlattenedChildIterator aIter,
  1.6080 +                                       uint8_t& aTargetContentDisplay)
  1.6081 +{
  1.6082 +  nsIContent* child = aIter.Get();
  1.6083 +
  1.6084 +  while (nsIContent* sibling = aIter.GetNextChild()) {
  1.6085 +    nsIFrame* nextSibling =
  1.6086 +      FindFrameForContentSibling(sibling, child, aTargetContentDisplay, false);
  1.6087 +
  1.6088 +    if (nextSibling) {
  1.6089 +      // We found a next sibling, we're done!
  1.6090 +      return nextSibling;
  1.6091 +    }
  1.6092 +  }
  1.6093 +
  1.6094 +  return nullptr;
  1.6095 +}
  1.6096 +
  1.6097 +// For fieldsets, returns the area frame, if the child is not a legend.
  1.6098 +static nsIFrame*
  1.6099 +GetAdjustedParentFrame(nsIFrame*       aParentFrame,
  1.6100 +                       nsIAtom*        aParentFrameType,
  1.6101 +                       nsIContent*     aChildContent)
  1.6102 +{
  1.6103 +  NS_PRECONDITION(nsGkAtoms::tableOuterFrame != aParentFrameType,
  1.6104 +                  "Shouldn't be happening!");
  1.6105 +
  1.6106 +  nsIFrame* newParent = nullptr;
  1.6107 +
  1.6108 +  if (nsGkAtoms::fieldSetFrame == aParentFrameType) {
  1.6109 +    // If the parent is a fieldSet, use the fieldSet's area frame as the
  1.6110 +    // parent unless the new content is a legend.
  1.6111 +    if (!aChildContent->IsHTML(nsGkAtoms::legend)) {
  1.6112 +      newParent = GetFieldSetBlockFrame(aParentFrame);
  1.6113 +    }
  1.6114 +  }
  1.6115 +  return (newParent) ? newParent : aParentFrame;
  1.6116 +}
  1.6117 +
  1.6118 +nsIFrame*
  1.6119 +nsCSSFrameConstructor::GetInsertionPrevSibling(nsIFrame*& aParentFrame,
  1.6120 +                                               nsIContent* aContainer,
  1.6121 +                                               nsIContent* aChild,
  1.6122 +                                               bool* aIsAppend,
  1.6123 +                                               bool* aIsRangeInsertSafe,
  1.6124 +                                               nsIContent* aStartSkipChild,
  1.6125 +                                               nsIContent* aEndSkipChild)
  1.6126 +{
  1.6127 +  *aIsAppend = false;
  1.6128 +
  1.6129 +  // Find the frame that precedes the insertion point. Walk backwards
  1.6130 +  // from the parent frame to get the parent content, because if an
  1.6131 +  // XBL insertion point is involved, we'll need to use _that_ to find
  1.6132 +  // the preceding frame.
  1.6133 +
  1.6134 +  NS_PRECONDITION(aParentFrame, "Must have parent frame to start with");
  1.6135 +  nsIContent* container = aParentFrame->GetContent();
  1.6136 +
  1.6137 +  FlattenedChildIterator iter(container);
  1.6138 +  bool xblCase = iter.XBLInvolved() || container != aContainer;
  1.6139 +  if (xblCase || !aChild->IsRootOfAnonymousSubtree()) {
  1.6140 +    // The check for IsRootOfAnonymousSubtree() is because editor is
  1.6141 +    // severely broken and calls us directly for native anonymous
  1.6142 +    // nodes that it creates.
  1.6143 +    if (aStartSkipChild) {
  1.6144 +      iter.Seek(aStartSkipChild);
  1.6145 +    } else {
  1.6146 +      iter.Seek(aChild);
  1.6147 +    }
  1.6148 +  } else {
  1.6149 +    // Prime the iterator for the call to FindPreviousSibling.
  1.6150 +    iter.GetNextChild();
  1.6151 +    NS_WARNING("Someone passed native anonymous content directly into frame "
  1.6152 +               "construction.  Stop doing that!");
  1.6153 +  }
  1.6154 +
  1.6155 +  // Note that FindPreviousSibling is passed the iterator by value, so that
  1.6156 +  // the later usage of the iterator starts from the same place.
  1.6157 +  uint8_t childDisplay = UNSET_DISPLAY;
  1.6158 +  nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay);
  1.6159 +
  1.6160 +  // Now, find the geometric parent so that we can handle
  1.6161 +  // continuations properly. Use the prev sibling if we have it;
  1.6162 +  // otherwise use the next sibling.
  1.6163 +  if (prevSibling) {
  1.6164 +    aParentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
  1.6165 +  }
  1.6166 +  else {
  1.6167 +    // If there is no previous sibling, then find the frame that follows
  1.6168 +    if (aEndSkipChild) {
  1.6169 +      iter.Seek(aEndSkipChild);
  1.6170 +      iter.GetPreviousChild();
  1.6171 +    }
  1.6172 +    nsIFrame* nextSibling = FindNextSibling(iter, childDisplay);
  1.6173 +
  1.6174 +    if (nextSibling) {
  1.6175 +      aParentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
  1.6176 +    }
  1.6177 +    else {
  1.6178 +      // No previous or next sibling, so treat this like an appended frame.
  1.6179 +      *aIsAppend = true;
  1.6180 +      if (IsFramePartOfIBSplit(aParentFrame)) {
  1.6181 +        // Since we're appending, we'll walk to the last anonymous frame
  1.6182 +        // that was created for the broken inline frame.  But don't walk
  1.6183 +        // to the trailing inline if it's empty; stop at the block.
  1.6184 +        aParentFrame = GetLastIBSplitSibling(aParentFrame, false);
  1.6185 +      }
  1.6186 +      // Get continuation that parents the last child.  This MUST be done
  1.6187 +      // before the AdjustAppendParentForAfterContent call.
  1.6188 +      aParentFrame = nsLayoutUtils::LastContinuationWithChild(aParentFrame);
  1.6189 +      // Deal with fieldsets
  1.6190 +      aParentFrame = ::GetAdjustedParentFrame(aParentFrame,
  1.6191 +                                              aParentFrame->GetType(),
  1.6192 +                                              aChild);
  1.6193 +      nsIFrame* appendAfterFrame;
  1.6194 +      aParentFrame =
  1.6195 +        ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(),
  1.6196 +                                            container, aParentFrame,
  1.6197 +                                            &appendAfterFrame);
  1.6198 +      prevSibling = ::FindAppendPrevSibling(aParentFrame, appendAfterFrame);
  1.6199 +    }
  1.6200 +  }
  1.6201 +
  1.6202 +  *aIsRangeInsertSafe = (childDisplay == UNSET_DISPLAY);
  1.6203 +  return prevSibling;
  1.6204 +}
  1.6205 +
  1.6206 +static bool
  1.6207 +IsSpecialFramesetChild(nsIContent* aContent)
  1.6208 +{
  1.6209 +  // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
  1.6210 +  return aContent->IsHTML() &&
  1.6211 +    (aContent->Tag() == nsGkAtoms::frameset ||
  1.6212 +     aContent->Tag() == nsGkAtoms::frame);
  1.6213 +}
  1.6214 +
  1.6215 +static void
  1.6216 +InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node);
  1.6217 +
  1.6218 +#ifdef MOZ_XUL
  1.6219 +
  1.6220 +static
  1.6221 +bool
  1.6222 +IsXULListBox(nsIContent* aContainer)
  1.6223 +{
  1.6224 +  return (aContainer->IsXUL() && aContainer->Tag() == nsGkAtoms::listbox);
  1.6225 +}
  1.6226 +
  1.6227 +static
  1.6228 +nsListBoxBodyFrame*
  1.6229 +MaybeGetListBoxBodyFrame(nsIContent* aContainer, nsIContent* aChild)
  1.6230 +{
  1.6231 +  if (!aContainer)
  1.6232 +    return nullptr;
  1.6233 +
  1.6234 +  if (IsXULListBox(aContainer) &&
  1.6235 +      aChild->IsXUL() && aChild->Tag() == nsGkAtoms::listitem) {
  1.6236 +    nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(aContainer);
  1.6237 +    nsCOMPtr<nsIBoxObject> boxObject;
  1.6238 +    xulElement->GetBoxObject(getter_AddRefs(boxObject));
  1.6239 +    nsCOMPtr<nsPIListBoxObject> listBoxObject = do_QueryInterface(boxObject);
  1.6240 +    if (listBoxObject) {
  1.6241 +      return listBoxObject->GetListBoxBody(false);
  1.6242 +    }
  1.6243 +  }
  1.6244 +
  1.6245 +  return nullptr;
  1.6246 +}
  1.6247 +#endif
  1.6248 +
  1.6249 +void
  1.6250 +nsCSSFrameConstructor::AddTextItemIfNeeded(nsFrameConstructorState& aState,
  1.6251 +                                           nsIFrame* aParentFrame,
  1.6252 +                                           nsIContent* aPossibleTextContent,
  1.6253 +                                           FrameConstructionItemList& aItems)
  1.6254 +{
  1.6255 +  NS_PRECONDITION(aPossibleTextContent, "Must have node");
  1.6256 +  if (!aPossibleTextContent->IsNodeOfType(nsINode::eTEXT) ||
  1.6257 +      !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
  1.6258 +    // Not text, or not suppressed due to being all-whitespace (if it
  1.6259 +    // were being suppressed, it would have the
  1.6260 +    // NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
  1.6261 +    return;
  1.6262 +  }
  1.6263 +  NS_ASSERTION(!aPossibleTextContent->GetPrimaryFrame(),
  1.6264 +               "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
  1.6265 +  AddFrameConstructionItems(aState, aPossibleTextContent, false,
  1.6266 +                            aParentFrame, aItems);
  1.6267 +}
  1.6268 +
  1.6269 +void
  1.6270 +nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aParentContent,
  1.6271 +                                           nsIContent* aContent)
  1.6272 +{
  1.6273 +  if (!aContent->IsNodeOfType(nsINode::eTEXT) ||
  1.6274 +      !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
  1.6275 +    // Not text, or not suppressed due to being all-whitespace (if it
  1.6276 +    // were being suppressed, it would have the
  1.6277 +    // NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
  1.6278 +    return;
  1.6279 +  }
  1.6280 +  NS_ASSERTION(!aContent->GetPrimaryFrame(),
  1.6281 +               "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
  1.6282 +  ContentInserted(aParentContent, aContent, nullptr, false);
  1.6283 +}
  1.6284 +
  1.6285 +// For inserts aChild should be valid, for appends it should be null.
  1.6286 +// Returns true if this operation can be lazy, false if not.
  1.6287 +bool
  1.6288 +nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
  1.6289 +                                            nsIContent* aContainer,
  1.6290 +                                            nsIContent* aChild)
  1.6291 +{
  1.6292 +  if (mPresShell->GetPresContext()->IsChrome() || !aContainer ||
  1.6293 +      aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXUL()) {
  1.6294 +    return false;
  1.6295 +  }
  1.6296 +
  1.6297 +  if (aOperation == CONTENTINSERT) {
  1.6298 +    if (aChild->IsRootOfAnonymousSubtree() ||
  1.6299 +        aChild->HasFlag(NODE_IS_IN_SHADOW_TREE) ||
  1.6300 +        aChild->IsEditable() || aChild->IsXUL()) {
  1.6301 +      return false;
  1.6302 +    }
  1.6303 +  } else { // CONTENTAPPEND
  1.6304 +    NS_ASSERTION(aOperation == CONTENTAPPEND,
  1.6305 +                 "operation should be either insert or append");
  1.6306 +    for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
  1.6307 +      NS_ASSERTION(!child->IsRootOfAnonymousSubtree(),
  1.6308 +                   "Should be coming through the CONTENTAPPEND case");
  1.6309 +      if (child->IsXUL() || child->IsEditable()) {
  1.6310 +        return false;
  1.6311 +      }
  1.6312 +    }
  1.6313 +  }
  1.6314 +
  1.6315 +  // We can construct lazily; just need to set suitable bits in the content
  1.6316 +  // tree.
  1.6317 +
  1.6318 +  // Walk up the tree setting the NODE_DESCENDANTS_NEED_FRAMES bit as we go.
  1.6319 +  nsIContent* content = aContainer;
  1.6320 +#ifdef DEBUG
  1.6321 +  // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
  1.6322 +  // we want to assert, but leaf frames that process their own children and may
  1.6323 +  // ignore anonymous children (eg framesets) make this complicated. So we set
  1.6324 +  // these two booleans if we encounter these situations and unset them if we
  1.6325 +  // hit a node with a leaf frame.
  1.6326 +  bool noPrimaryFrame = false;
  1.6327 +  bool needsFrameBitSet = false;
  1.6328 +#endif
  1.6329 +  while (content &&
  1.6330 +         !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
  1.6331 +#ifdef DEBUG
  1.6332 +    if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
  1.6333 +      noPrimaryFrame = needsFrameBitSet = false;
  1.6334 +    }
  1.6335 +    if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
  1.6336 +      noPrimaryFrame = true;
  1.6337 +    }
  1.6338 +    if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
  1.6339 +      needsFrameBitSet = true;
  1.6340 +    }
  1.6341 +#endif
  1.6342 +    content->SetFlags(NODE_DESCENDANTS_NEED_FRAMES);
  1.6343 +    content = content->GetFlattenedTreeParent();
  1.6344 +  }
  1.6345 +#ifdef DEBUG
  1.6346 +  if (content && content->GetPrimaryFrame() &&
  1.6347 +      content->GetPrimaryFrame()->IsLeaf()) {
  1.6348 +    noPrimaryFrame = needsFrameBitSet = false;
  1.6349 +  }
  1.6350 +  NS_ASSERTION(!noPrimaryFrame, "Ancestors of nodes with frames to be "
  1.6351 +    "constructed lazily should have frames");
  1.6352 +  NS_ASSERTION(!needsFrameBitSet, "Ancestors of nodes with frames to be "
  1.6353 +    "constructed lazily should not have NEEDS_FRAME bit set");
  1.6354 +#endif
  1.6355 +
  1.6356 +  // Set NODE_NEEDS_FRAME on the new nodes.
  1.6357 +  if (aOperation == CONTENTINSERT) {
  1.6358 +    NS_ASSERTION(!aChild->GetPrimaryFrame() ||
  1.6359 +                 aChild->GetPrimaryFrame()->GetContent() != aChild,
  1.6360 +                 //XXX the aChild->GetPrimaryFrame()->GetContent() != aChild
  1.6361 +                 // check is needed due to bug 135040. Remove it once that's
  1.6362 +                 // fixed.
  1.6363 +                 "setting NEEDS_FRAME on a node that already has a frame?");
  1.6364 +    aChild->SetFlags(NODE_NEEDS_FRAME);
  1.6365 +  } else { // CONTENTAPPEND
  1.6366 +    for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
  1.6367 +      NS_ASSERTION(!child->GetPrimaryFrame() ||
  1.6368 +                   child->GetPrimaryFrame()->GetContent() != child,
  1.6369 +                   //XXX the child->GetPrimaryFrame()->GetContent() != child
  1.6370 +                   // check is needed due to bug 135040. Remove it once that's
  1.6371 +                   // fixed.
  1.6372 +                   "setting NEEDS_FRAME on a node that already has a frame?");
  1.6373 +      child->SetFlags(NODE_NEEDS_FRAME);
  1.6374 +    }
  1.6375 +  }
  1.6376 +
  1.6377 +  RestyleManager()->PostRestyleEventForLazyConstruction();
  1.6378 +  return true;
  1.6379 +}
  1.6380 +
  1.6381 +void
  1.6382 +nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent)
  1.6383 +{
  1.6384 +  NS_ASSERTION(!aContent->HasFlag(NODE_NEEDS_FRAME),
  1.6385 +    "shouldn't get here with a content node that has needs frame bit set");
  1.6386 +  NS_ASSERTION(aContent->HasFlag(NODE_DESCENDANTS_NEED_FRAMES),
  1.6387 +    "should only get here with a content node that has descendants needing frames");
  1.6388 +
  1.6389 +  aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
  1.6390 +
  1.6391 +  // We could either descend first (on nodes that don't have NODE_NEEDS_FRAME
  1.6392 +  // set) or issue content notifications for our kids first. In absence of
  1.6393 +  // anything definitive either way we'll go with the latter.
  1.6394 +
  1.6395 +  // It might be better to use GetChildArray and scan it completely first and
  1.6396 +  // then issue all notifications. (We have to scan it completely first because
  1.6397 +  // constructing frames can set attributes, which can change the storage of
  1.6398 +  // child lists).
  1.6399 +
  1.6400 +  // Scan the children of aContent to see what operations (if any) we need to
  1.6401 +  // perform.
  1.6402 +  uint32_t childCount = aContent->GetChildCount();
  1.6403 +  bool inRun = false;
  1.6404 +  nsIContent* firstChildInRun = nullptr;
  1.6405 +  for (uint32_t i = 0; i < childCount; i++) {
  1.6406 +    nsIContent* child = aContent->GetChildAt(i);
  1.6407 +    if (child->HasFlag(NODE_NEEDS_FRAME)) {
  1.6408 +      NS_ASSERTION(!child->GetPrimaryFrame() ||
  1.6409 +                   child->GetPrimaryFrame()->GetContent() != child,
  1.6410 +                   //XXX the child->GetPrimaryFrame()->GetContent() != child
  1.6411 +                   // check is needed due to bug 135040. Remove it once that's
  1.6412 +                   // fixed.
  1.6413 +                   "NEEDS_FRAME set on a node that already has a frame?");
  1.6414 +      if (!inRun) {
  1.6415 +        inRun = true;
  1.6416 +        firstChildInRun = child;
  1.6417 +      }
  1.6418 +    } else {
  1.6419 +      if (inRun) {
  1.6420 +        inRun = false;
  1.6421 +        // generate a ContentRangeInserted for [startOfRun,i)
  1.6422 +        ContentRangeInserted(aContent, firstChildInRun, child, nullptr,
  1.6423 +                             false);
  1.6424 +      }
  1.6425 +    }
  1.6426 +  }
  1.6427 +  if (inRun) {
  1.6428 +    ContentAppended(aContent, firstChildInRun, false);
  1.6429 +  }
  1.6430 +
  1.6431 +  // Now descend.
  1.6432 +  FlattenedChildIterator iter(aContent);
  1.6433 +  for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
  1.6434 +    if (child->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
  1.6435 +      CreateNeededFrames(child);
  1.6436 +    }
  1.6437 +  }
  1.6438 +}
  1.6439 +
  1.6440 +void nsCSSFrameConstructor::CreateNeededFrames()
  1.6441 +{
  1.6442 +  NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
  1.6443 +               "Someone forgot a script blocker");
  1.6444 +
  1.6445 +  Element* rootElement = mDocument->GetRootElement();
  1.6446 +  NS_ASSERTION(!rootElement || !rootElement->HasFlag(NODE_NEEDS_FRAME),
  1.6447 +    "root element should not have frame created lazily");
  1.6448 +  if (rootElement && rootElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
  1.6449 +    BeginUpdate();
  1.6450 +    CreateNeededFrames(rootElement);
  1.6451 +    EndUpdate();
  1.6452 +  }
  1.6453 +}
  1.6454 +
  1.6455 +void
  1.6456 +nsCSSFrameConstructor::IssueSingleInsertNofications(nsIContent* aContainer,
  1.6457 +                                                    nsIContent* aStartChild,
  1.6458 +                                                    nsIContent* aEndChild,
  1.6459 +                                                    bool aAllowLazyConstruction)
  1.6460 +{
  1.6461 +  for (nsIContent* child = aStartChild;
  1.6462 +       child != aEndChild;
  1.6463 +       child = child->GetNextSibling()) {
  1.6464 +    if ((child->GetPrimaryFrame() ||
  1.6465 +         GetUndisplayedContent(child))
  1.6466 +#ifdef MOZ_XUL
  1.6467 +        //  Except listboxes suck, so do NOT skip anything here if
  1.6468 +        //  we plan to notify a listbox.
  1.6469 +        && !MaybeGetListBoxBodyFrame(aContainer, child)
  1.6470 +#endif
  1.6471 +        ) {
  1.6472 +      // Already have a frame or undisplayed entry for this content; a
  1.6473 +      // previous ContentInserted in this loop must have reconstructed
  1.6474 +      // its insertion parent.  Skip it.
  1.6475 +      continue;
  1.6476 +    }
  1.6477 +    // Call ContentInserted with this node.
  1.6478 +    ContentInserted(aContainer, child, mTempFrameTreeState,
  1.6479 +                    aAllowLazyConstruction);
  1.6480 +  }
  1.6481 +}
  1.6482 +
  1.6483 +nsIFrame*
  1.6484 +nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aContainer,
  1.6485 +                                              nsIContent* aStartChild,
  1.6486 +                                              nsIContent* aEndChild,
  1.6487 +                                              bool aAllowLazyConstruction)
  1.6488 +{
  1.6489 +  // See if we have an XBL insertion point. If so, then that's our
  1.6490 +  // real parent frame; if not, then the frame hasn't been built yet
  1.6491 +  // and we just bail.
  1.6492 +  bool multiple = false;
  1.6493 +  nsIFrame* insertionPoint = GetInsertionPoint(aContainer, nullptr, &multiple);
  1.6494 +  if (!insertionPoint && !multiple)
  1.6495 +    return nullptr; // Don't build the frames.
  1.6496 +
  1.6497 +  bool hasInsertion = false;
  1.6498 +  if (!multiple) {
  1.6499 +    // XXXbz XBL2/sXBL issue
  1.6500 +    nsIDocument* document = aStartChild->GetDocument();
  1.6501 +    // XXXbz how would |document| be null here?
  1.6502 +    if (document && aStartChild->GetXBLInsertionParent()) {
  1.6503 +      hasInsertion = true;
  1.6504 +    }
  1.6505 +  }
  1.6506 +
  1.6507 +  if (multiple || hasInsertion) {
  1.6508 +    // We have an insertion point.  There are some additional tests we need to do
  1.6509 +    // in order to ensure that an append is a safe operation.
  1.6510 +    uint32_t childCount = 0;
  1.6511 +
  1.6512 +    if (!multiple) {
  1.6513 +      // We may need to make multiple ContentInserted calls instead.  A
  1.6514 +      // reasonable heuristic to employ (in order to maintain good performance)
  1.6515 +      // is to find out if the insertion point's content node contains any
  1.6516 +      // explicit children.  If it does not, then it is highly likely that
  1.6517 +      // an append is occurring.  (Note it is not definite, and there are insane
  1.6518 +      // cases we will not deal with by employing this heuristic, but it beats
  1.6519 +      // always falling back to multiple ContentInserted calls).
  1.6520 +      //
  1.6521 +      // In the multiple insertion point case, we know we're going to need to do
  1.6522 +      // multiple ContentInserted calls anyway.
  1.6523 +      // XXXndeakin This test doesn't work in the new world. Or rather, it works, but
  1.6524 +      // it's slow
  1.6525 +      childCount = insertionPoint->GetContent()->GetChildCount();
  1.6526 +    }
  1.6527 +
  1.6528 +    // If we have multiple insertion points or if we have an insertion point
  1.6529 +    // and the operation is not a true append or if the insertion point already
  1.6530 +    // has explicit children, then we must fall back.
  1.6531 +    if (multiple || aEndChild != nullptr || childCount > 0) {
  1.6532 +      // Now comes the fun part.  For each inserted child, make a
  1.6533 +      // ContentInserted call as if it had just gotten inserted and
  1.6534 +      // let ContentInserted handle the mess.
  1.6535 +      IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
  1.6536 +                                   aAllowLazyConstruction);
  1.6537 +      return nullptr;
  1.6538 +    }
  1.6539 +  }
  1.6540 +
  1.6541 +  return insertionPoint;
  1.6542 +}
  1.6543 +
  1.6544 +bool
  1.6545 +nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
  1.6546 +                                                nsIContent* aStartChild,
  1.6547 +                                                nsIContent* aEndChild)
  1.6548 +{
  1.6549 +  if (aParentFrame->GetType() == nsGkAtoms::frameSetFrame) {
  1.6550 +    // Check whether we have any kids we care about.
  1.6551 +    for (nsIContent* cur = aStartChild;
  1.6552 +         cur != aEndChild;
  1.6553 +         cur = cur->GetNextSibling()) {
  1.6554 +      if (IsSpecialFramesetChild(cur)) {
  1.6555 +        // Just reframe the parent, since framesets are weird like that.
  1.6556 +        RecreateFramesForContent(aParentFrame->GetContent(), false);
  1.6557 +        return true;
  1.6558 +      }
  1.6559 +    }
  1.6560 +  }
  1.6561 +  return false;
  1.6562 +}
  1.6563 +
  1.6564 +nsresult
  1.6565 +nsCSSFrameConstructor::ContentAppended(nsIContent*     aContainer,
  1.6566 +                                       nsIContent*     aFirstNewContent,
  1.6567 +                                       bool            aAllowLazyConstruction)
  1.6568 +{
  1.6569 +  AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
  1.6570 +  NS_PRECONDITION(mUpdateCount != 0,
  1.6571 +                  "Should be in an update while creating frames");
  1.6572 +
  1.6573 +#ifdef DEBUG
  1.6574 +  if (gNoisyContentUpdates) {
  1.6575 +    printf("nsCSSFrameConstructor::ContentAppended container=%p "
  1.6576 +           "first-child=%p lazy=%d\n",
  1.6577 +           static_cast<void*>(aContainer), aFirstNewContent,
  1.6578 +           aAllowLazyConstruction);
  1.6579 +    if (gReallyNoisyContentUpdates && aContainer) {
  1.6580 +      aContainer->List(stdout, 0);
  1.6581 +    }
  1.6582 +  }
  1.6583 +#endif
  1.6584 +
  1.6585 +#ifdef DEBUG
  1.6586 +  for (nsIContent* child = aFirstNewContent;
  1.6587 +       child;
  1.6588 +       child = child->GetNextSibling()) {
  1.6589 +    // XXX the GetContent() != child check is needed due to bug 135040.
  1.6590 +    // Remove it once that's fixed.
  1.6591 +    NS_ASSERTION(!child->GetPrimaryFrame() ||
  1.6592 +                 child->GetPrimaryFrame()->GetContent() != child,
  1.6593 +                 "asked to construct a frame for a node that already has a frame");
  1.6594 +  }
  1.6595 +#endif
  1.6596 +
  1.6597 +#ifdef MOZ_XUL
  1.6598 +  if (aContainer) {
  1.6599 +    int32_t namespaceID;
  1.6600 +    nsIAtom* tag =
  1.6601 +      mDocument->BindingManager()->ResolveTag(aContainer, &namespaceID);
  1.6602 +
  1.6603 +    // Just ignore tree tags, anyway we don't create any frames for them.
  1.6604 +    if (tag == nsGkAtoms::treechildren ||
  1.6605 +        tag == nsGkAtoms::treeitem ||
  1.6606 +        tag == nsGkAtoms::treerow)
  1.6607 +      return NS_OK;
  1.6608 +
  1.6609 +  }
  1.6610 +#endif // MOZ_XUL
  1.6611 +
  1.6612 +  if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
  1.6613 +    // Recreate frames if content is appended into a ShadowRoot
  1.6614 +    // because children of ShadowRoot are rendered in place of children
  1.6615 +    // of the host.
  1.6616 +    nsIContent* bindingParent = aContainer->GetBindingParent();
  1.6617 +    LAYOUT_PHASE_TEMP_EXIT();
  1.6618 +    nsresult rv = RecreateFramesForContent(bindingParent, false);
  1.6619 +    LAYOUT_PHASE_TEMP_REENTER();
  1.6620 +    return rv;
  1.6621 +  }
  1.6622 +
  1.6623 +  // Get the frame associated with the content
  1.6624 +  nsIFrame* parentFrame = GetFrameFor(aContainer);
  1.6625 +
  1.6626 +  // See comment in ContentRangeInserted for why this is necessary.
  1.6627 +  if (!parentFrame && !aContainer->IsActiveChildrenElement()) {
  1.6628 +    return NS_OK;
  1.6629 +  }
  1.6630 +
  1.6631 +  if (aAllowLazyConstruction &&
  1.6632 +      MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) {
  1.6633 +    return NS_OK;
  1.6634 +  }
  1.6635 +
  1.6636 +  LAYOUT_PHASE_TEMP_EXIT();
  1.6637 +  parentFrame = GetRangeInsertionPoint(aContainer,
  1.6638 +                                       aFirstNewContent, nullptr,
  1.6639 +                                       aAllowLazyConstruction);
  1.6640 +  LAYOUT_PHASE_TEMP_REENTER();
  1.6641 +  if (!parentFrame) {
  1.6642 +    return NS_OK;
  1.6643 +  }
  1.6644 +
  1.6645 +  LAYOUT_PHASE_TEMP_EXIT();
  1.6646 +  if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
  1.6647 +    LAYOUT_PHASE_TEMP_REENTER();
  1.6648 +    return NS_OK;
  1.6649 +  }
  1.6650 +  LAYOUT_PHASE_TEMP_REENTER();
  1.6651 +
  1.6652 +  if (parentFrame->IsLeaf()) {
  1.6653 +    // Nothing to do here; we shouldn't be constructing kids of leaves
  1.6654 +    // Clear lazy bits so we don't try to construct again.
  1.6655 +    ClearLazyBits(aFirstNewContent, nullptr);
  1.6656 +    return NS_OK;
  1.6657 +  }
  1.6658 +
  1.6659 +  if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
  1.6660 +    LAYOUT_PHASE_TEMP_EXIT();
  1.6661 +    nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
  1.6662 +    LAYOUT_PHASE_TEMP_REENTER();
  1.6663 +    return rv;
  1.6664 +  }
  1.6665 +
  1.6666 +  // If the frame we are manipulating is a ib-split frame (that is, one
  1.6667 +  // that's been created as a result of a block-in-inline situation) then we
  1.6668 +  // need to append to the last ib-split sibling, not to the frame itself.
  1.6669 +  bool parentIBSplit = IsFramePartOfIBSplit(parentFrame);
  1.6670 +  if (parentIBSplit) {
  1.6671 +#ifdef DEBUG
  1.6672 +    if (gNoisyContentUpdates) {
  1.6673 +      printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
  1.6674 +      nsFrame::ListTag(stdout, parentFrame);
  1.6675 +      printf(" is ib-split\n");
  1.6676 +    }
  1.6677 +#endif
  1.6678 +
  1.6679 +    // Since we're appending, we'll walk to the last anonymous frame
  1.6680 +    // that was created for the broken inline frame.  But don't walk
  1.6681 +    // to the trailing inline if it's empty; stop at the block.
  1.6682 +    parentFrame = GetLastIBSplitSibling(parentFrame, false);
  1.6683 +  }
  1.6684 +
  1.6685 +  // Get continuation that parents the last child.  This MUST be done
  1.6686 +  // before the AdjustAppendParentForAfterContent call.
  1.6687 +  parentFrame = nsLayoutUtils::LastContinuationWithChild(parentFrame);
  1.6688 +
  1.6689 +  // We should never get here with fieldsets, since they have multiple
  1.6690 +  // insertion points.
  1.6691 +  NS_ASSERTION(parentFrame->GetType() != nsGkAtoms::fieldSetFrame,
  1.6692 +               "Unexpected parent");
  1.6693 +
  1.6694 +  // Deal with possible :after generated content on the parent
  1.6695 +  nsIFrame* parentAfterFrame;
  1.6696 +  parentFrame =
  1.6697 +    ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(),
  1.6698 +                                        aContainer, parentFrame,
  1.6699 +                                        &parentAfterFrame);
  1.6700 +
  1.6701 +  // Create some new frames
  1.6702 +  nsFrameConstructorState state(mPresShell,
  1.6703 +                                GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
  1.6704 +                                GetAbsoluteContainingBlock(parentFrame, ABS_POS),
  1.6705 +                                GetFloatContainingBlock(parentFrame));
  1.6706 +  state.mTreeMatchContext.InitAncestors(aContainer->AsElement());
  1.6707 +
  1.6708 +  // See if the containing block has :first-letter style applied.
  1.6709 +  bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
  1.6710 +  nsIFrame* containingBlock = state.mFloatedItems.containingBlock;
  1.6711 +  if (containingBlock) {
  1.6712 +    haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
  1.6713 +    haveFirstLineStyle =
  1.6714 +      ShouldHaveFirstLineStyle(containingBlock->GetContent(),
  1.6715 +                               containingBlock->StyleContext());
  1.6716 +  }
  1.6717 +
  1.6718 +  if (haveFirstLetterStyle) {
  1.6719 +    // Before we get going, remove the current letter frames
  1.6720 +    RemoveLetterFrames(state.mPresContext, state.mPresShell,
  1.6721 +                       containingBlock);
  1.6722 +  }
  1.6723 +
  1.6724 +  nsIAtom* frameType = parentFrame->GetType();
  1.6725 +
  1.6726 +  FlattenedChildIterator iter(aContainer);
  1.6727 +  bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
  1.6728 +  FrameConstructionItemList items;
  1.6729 +  if (aFirstNewContent->GetPreviousSibling() &&
  1.6730 +      GetParentType(frameType) == eTypeBlock &&
  1.6731 +      haveNoXBLChildren) {
  1.6732 +    // If there's a text node in the normal content list just before the new
  1.6733 +    // items, and it has no frame, make a frame construction item for it. If it
  1.6734 +    // doesn't need a frame, ConstructFramesFromItemList below won't give it
  1.6735 +    // one.  No need to do all this if our parent type is not block, though,
  1.6736 +    // since WipeContainingBlock already handles that situation.
  1.6737 +    //
  1.6738 +    // Because we're appending, we don't need to worry about any text
  1.6739 +    // after the appended content; there can only be XBL anonymous content
  1.6740 +    // (text in an XBL binding is not suppressed) or generated content
  1.6741 +    // (and bare text nodes are not generated). Native anonymous content
  1.6742 +    // generated by frames never participates in inline layout.
  1.6743 +    AddTextItemIfNeeded(state, parentFrame,
  1.6744 +                        aFirstNewContent->GetPreviousSibling(), items);
  1.6745 +  }
  1.6746 +  for (nsIContent* child = aFirstNewContent;
  1.6747 +       child;
  1.6748 +       child = child->GetNextSibling()) {
  1.6749 +    AddFrameConstructionItems(state, child, false, parentFrame, items);
  1.6750 +  }
  1.6751 +
  1.6752 +  nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, parentAfterFrame);
  1.6753 +
  1.6754 +  // Perform special check for diddling around with the frames in
  1.6755 +  // a ib-split inline frame.
  1.6756 +  // If we're appending before :after content, then we're not really
  1.6757 +  // appending, so let WipeContainingBlock know that.
  1.6758 +  LAYOUT_PHASE_TEMP_EXIT();
  1.6759 +  if (WipeContainingBlock(state, containingBlock, parentFrame, items,
  1.6760 +                          true, prevSibling)) {
  1.6761 +    LAYOUT_PHASE_TEMP_REENTER();
  1.6762 +    return NS_OK;
  1.6763 +  }
  1.6764 +  LAYOUT_PHASE_TEMP_REENTER();
  1.6765 +
  1.6766 +  // If the parent is a block frame, and we're not in a special case
  1.6767 +  // where frames can be moved around, determine if the list is for the
  1.6768 +  // start or end of the block.
  1.6769 +  if (nsLayoutUtils::GetAsBlock(parentFrame) && !haveFirstLetterStyle &&
  1.6770 +      !haveFirstLineStyle && !parentIBSplit) {
  1.6771 +    items.SetLineBoundaryAtStart(!prevSibling ||
  1.6772 +        !prevSibling->IsInlineOutside() ||
  1.6773 +        prevSibling->GetType() == nsGkAtoms::brFrame);
  1.6774 +    // :after content can't be <br> so no need to check it
  1.6775 +    items.SetLineBoundaryAtEnd(!parentAfterFrame ||
  1.6776 +        !parentAfterFrame->IsInlineOutside());
  1.6777 +  }
  1.6778 +  // To suppress whitespace-only text frames, we have to verify that
  1.6779 +  // our container's DOM child list matches its flattened tree child list.
  1.6780 +  items.SetParentHasNoXBLChildren(haveNoXBLChildren);
  1.6781 +
  1.6782 +  nsFrameItems frameItems;
  1.6783 +  ConstructFramesFromItemList(state, items, parentFrame, frameItems);
  1.6784 +
  1.6785 +  for (nsIContent* child = aFirstNewContent;
  1.6786 +       child;
  1.6787 +       child = child->GetNextSibling()) {
  1.6788 +    // Invalidate now instead of before the WipeContainingBlock call, just in
  1.6789 +    // case we do wipe; in that case we don't need to do this walk at all.
  1.6790 +    // XXXbz does that matter?  Would it make more sense to save some virtual
  1.6791 +    // GetChildAt calls instead and do this during construction of our
  1.6792 +    // FrameConstructionItemList?
  1.6793 +    InvalidateCanvasIfNeeded(mPresShell, child);
  1.6794 +  }
  1.6795 +
  1.6796 +  // if the container is a table and a caption was appended, it needs to be put
  1.6797 +  // in the outer table frame's additional child list.
  1.6798 +  nsFrameItems captionItems;
  1.6799 +  if (nsGkAtoms::tableFrame == frameType) {
  1.6800 +    // Pull out the captions.  Note that we don't want to do that as we go,
  1.6801 +    // because processing a single caption can add a whole bunch of things to
  1.6802 +    // the frame items due to pseudoframe processing.  So we'd have to pull
  1.6803 +    // captions from a list anyway; might as well do that here.
  1.6804 +    // XXXbz this is no longer true; we could pull captions directly out of the
  1.6805 +    // FrameConstructionItemList now.
  1.6806 +    PullOutCaptionFrames(frameItems, captionItems);
  1.6807 +  }
  1.6808 +
  1.6809 +  if (haveFirstLineStyle && parentFrame == containingBlock) {
  1.6810 +    // It's possible that some of the new frames go into a
  1.6811 +    // first-line frame. Look at them and see...
  1.6812 +    AppendFirstLineFrames(state, containingBlock->GetContent(),
  1.6813 +                          containingBlock, frameItems);
  1.6814 +  }
  1.6815 +
  1.6816 +  // Notify the parent frame passing it the list of new frames
  1.6817 +  // Append the flowed frames to the principal child list; captions
  1.6818 +  // need special treatment
  1.6819 +  if (captionItems.NotEmpty()) { // append the caption to the outer table
  1.6820 +    NS_ASSERTION(nsGkAtoms::tableFrame == frameType, "how did that happen?");
  1.6821 +    nsIFrame* outerTable = parentFrame->GetParent();
  1.6822 +    AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
  1.6823 +  }
  1.6824 +
  1.6825 +  if (frameItems.NotEmpty()) { // append the in-flow kids
  1.6826 +    AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
  1.6827 +  }
  1.6828 +
  1.6829 +  // Recover first-letter frames
  1.6830 +  if (haveFirstLetterStyle) {
  1.6831 +    RecoverLetterFrames(containingBlock);
  1.6832 +  }
  1.6833 +
  1.6834 +#ifdef DEBUG
  1.6835 +  if (gReallyNoisyContentUpdates) {
  1.6836 +    printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
  1.6837 +    parentFrame->List(stdout, 0);
  1.6838 +  }
  1.6839 +#endif
  1.6840 +
  1.6841 +#ifdef ACCESSIBILITY
  1.6842 +  nsAccessibilityService* accService = nsIPresShell::AccService();
  1.6843 +  if (accService) {
  1.6844 +    accService->ContentRangeInserted(mPresShell, aContainer,
  1.6845 +                                     aFirstNewContent, nullptr);
  1.6846 +  }
  1.6847 +#endif
  1.6848 +
  1.6849 +  return NS_OK;
  1.6850 +}
  1.6851 +
  1.6852 +#ifdef MOZ_XUL
  1.6853 +
  1.6854 +enum content_operation
  1.6855 +{
  1.6856 +    CONTENT_INSERTED,
  1.6857 +    CONTENT_REMOVED
  1.6858 +};
  1.6859 +
  1.6860 +// Helper function to lookup the listbox body frame and send a notification
  1.6861 +// for insertion or removal of content
  1.6862 +static
  1.6863 +bool NotifyListBoxBody(nsPresContext*    aPresContext,
  1.6864 +                         nsIContent*        aContainer,
  1.6865 +                         nsIContent*        aChild,
  1.6866 +                         // Only used for the removed notification
  1.6867 +                         nsIContent*        aOldNextSibling,
  1.6868 +                         nsIDocument*       aDocument,
  1.6869 +                         nsIFrame*          aChildFrame,
  1.6870 +                         content_operation  aOperation)
  1.6871 +{
  1.6872 +  nsListBoxBodyFrame* listBoxBodyFrame =
  1.6873 +    MaybeGetListBoxBodyFrame(aContainer, aChild);
  1.6874 +  if (listBoxBodyFrame) {
  1.6875 +    if (aOperation == CONTENT_REMOVED) {
  1.6876 +      // Except if we have an aChildFrame and its parent is not the right
  1.6877 +      // thing, then we don't do this.  Pseudo frames are so much fun....
  1.6878 +      if (!aChildFrame || aChildFrame->GetParent() == listBoxBodyFrame) {
  1.6879 +        listBoxBodyFrame->OnContentRemoved(aPresContext, aContainer,
  1.6880 +                                           aChildFrame, aOldNextSibling);
  1.6881 +        return true;
  1.6882 +      }
  1.6883 +    } else {
  1.6884 +      listBoxBodyFrame->OnContentInserted(aPresContext, aChild);
  1.6885 +      return true;
  1.6886 +    }
  1.6887 +  }
  1.6888 +
  1.6889 +  return false;
  1.6890 +}
  1.6891 +#endif // MOZ_XUL
  1.6892 +
  1.6893 +nsresult
  1.6894 +nsCSSFrameConstructor::ContentInserted(nsIContent*            aContainer,
  1.6895 +                                       nsIContent*            aChild,
  1.6896 +                                       nsILayoutHistoryState* aFrameState,
  1.6897 +                                       bool                   aAllowLazyConstruction)
  1.6898 +{
  1.6899 +  return ContentRangeInserted(aContainer,
  1.6900 +                              aChild,
  1.6901 +                              aChild->GetNextSibling(),
  1.6902 +                              aFrameState,
  1.6903 +                              aAllowLazyConstruction);
  1.6904 +}
  1.6905 +
  1.6906 +// ContentRangeInserted handles creating frames for a range of nodes that
  1.6907 +// aren't at the end of their childlist. ContentRangeInserted isn't a real
  1.6908 +// content notification, but rather it handles regular ContentInserted calls
  1.6909 +// for a single node as well as the lazy construction of frames for a range of
  1.6910 +// nodes when called from CreateNeededFrames. For a range of nodes to be
  1.6911 +// suitable to have its frames constructed all at once they must meet the same
  1.6912 +// conditions that ContentAppended imposes (GetRangeInsertionPoint checks
  1.6913 +// these), plus more. Namely when finding the insertion prevsibling we must not
  1.6914 +// need to consult something specific to any one node in the range, so that the
  1.6915 +// insertion prevsibling would be the same for each node in the range. So we
  1.6916 +// pass the first node in the range to GetInsertionPrevSibling, and if
  1.6917 +// IsValidSibling (the only place GetInsertionPrevSibling might look at the
  1.6918 +// passed in node itself) needs to resolve style on the node we record this and
  1.6919 +// return that this range needs to be split up and inserted separately. Table
  1.6920 +// captions need extra attention as we need to determine where to insert them
  1.6921 +// in the caption list, while skipping any nodes in the range being inserted
  1.6922 +// (because when we treat the caption frames the other nodes have had their
  1.6923 +// frames constructed but not yet inserted into the frame tree).
  1.6924 +nsresult
  1.6925 +nsCSSFrameConstructor::ContentRangeInserted(nsIContent*            aContainer,
  1.6926 +                                            nsIContent*            aStartChild,
  1.6927 +                                            nsIContent*            aEndChild,
  1.6928 +                                            nsILayoutHistoryState* aFrameState,
  1.6929 +                                            bool                   aAllowLazyConstruction)
  1.6930 +{
  1.6931 +  AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
  1.6932 +  NS_PRECONDITION(mUpdateCount != 0,
  1.6933 +                  "Should be in an update while creating frames");
  1.6934 +
  1.6935 +  NS_PRECONDITION(aStartChild, "must always pass a child");
  1.6936 +
  1.6937 +  // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
  1.6938 +  // the :empty pseudo-class?
  1.6939 +#ifdef DEBUG
  1.6940 +  if (gNoisyContentUpdates) {
  1.6941 +    printf("nsCSSFrameConstructor::ContentRangeInserted container=%p "
  1.6942 +           "start-child=%p end-child=%p lazy=%d\n",
  1.6943 +           static_cast<void*>(aContainer),
  1.6944 +           static_cast<void*>(aStartChild), static_cast<void*>(aEndChild),
  1.6945 +           aAllowLazyConstruction);
  1.6946 +    if (gReallyNoisyContentUpdates) {
  1.6947 +      if (aContainer) {
  1.6948 +        aContainer->List(stdout,0);
  1.6949 +      } else {
  1.6950 +        aStartChild->List(stdout, 0);
  1.6951 +      }
  1.6952 +    }
  1.6953 +  }
  1.6954 +#endif
  1.6955 +
  1.6956 +#ifdef DEBUG
  1.6957 +  for (nsIContent* child = aStartChild;
  1.6958 +       child != aEndChild;
  1.6959 +       child = child->GetNextSibling()) {
  1.6960 +    // XXX the GetContent() != child check is needed due to bug 135040.
  1.6961 +    // Remove it once that's fixed.
  1.6962 +    NS_ASSERTION(!child->GetPrimaryFrame() ||
  1.6963 +                 child->GetPrimaryFrame()->GetContent() != child,
  1.6964 +                 "asked to construct a frame for a node that already has a frame");
  1.6965 +  }
  1.6966 +#endif
  1.6967 +
  1.6968 +  bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
  1.6969 +  NS_ASSERTION(isSingleInsert || !aAllowLazyConstruction,
  1.6970 +               "range insert shouldn't be lazy");
  1.6971 +  NS_ASSERTION(isSingleInsert || aEndChild,
  1.6972 +               "range should not include all nodes after aStartChild");
  1.6973 +
  1.6974 +#ifdef MOZ_XUL
  1.6975 +  if (aContainer && IsXULListBox(aContainer)) {
  1.6976 +    if (isSingleInsert) {
  1.6977 +      if (NotifyListBoxBody(mPresShell->GetPresContext(), aContainer,
  1.6978 +                            // The insert case in NotifyListBoxBody
  1.6979 +                            // doesn't use "old next sibling".
  1.6980 +                            aStartChild, nullptr,
  1.6981 +                            mDocument, nullptr, CONTENT_INSERTED)) {
  1.6982 +        return NS_OK;
  1.6983 +      }
  1.6984 +    } else {
  1.6985 +      // We don't handle a range insert to a listbox parent, issue single
  1.6986 +      // ContertInserted calls for each node inserted.
  1.6987 +      LAYOUT_PHASE_TEMP_EXIT();
  1.6988 +      IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
  1.6989 +                                   aAllowLazyConstruction);
  1.6990 +      LAYOUT_PHASE_TEMP_REENTER();
  1.6991 +      return NS_OK;
  1.6992 +    }
  1.6993 +  }
  1.6994 +#endif // MOZ_XUL
  1.6995 +
  1.6996 +  // If we have a null parent, then this must be the document element being
  1.6997 +  // inserted, or some other child of the document in the DOM (might be a PI,
  1.6998 +  // say).
  1.6999 +  if (! aContainer) {
  1.7000 +    NS_ASSERTION(isSingleInsert,
  1.7001 +                 "root node insertion should be a single insertion");
  1.7002 +    Element *docElement = mDocument->GetRootElement();
  1.7003 +
  1.7004 +    if (aStartChild != docElement) {
  1.7005 +      // Not the root element; just bail out
  1.7006 +      return NS_OK;
  1.7007 +    }
  1.7008 +
  1.7009 +    NS_PRECONDITION(nullptr == mRootElementFrame,
  1.7010 +                    "root element frame already created");
  1.7011 +
  1.7012 +    // Create frames for the document element and its child elements
  1.7013 +    nsIFrame* docElementFrame =
  1.7014 +      ConstructDocElementFrame(docElement, aFrameState);
  1.7015 +
  1.7016 +    if (docElementFrame) {
  1.7017 +      InvalidateCanvasIfNeeded(mPresShell, aStartChild);
  1.7018 +#ifdef DEBUG
  1.7019 +      if (gReallyNoisyContentUpdates) {
  1.7020 +        printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
  1.7021 +               "model:\n");
  1.7022 +        mFixedContainingBlock->List(stdout, 0);
  1.7023 +      }
  1.7024 +#endif
  1.7025 +    }
  1.7026 +
  1.7027 +    if (aFrameState) {
  1.7028 +      // Restore frame state for the root scroll frame if there is one
  1.7029 +      nsIFrame* rootScrollFrame = mPresShell->GetRootScrollFrame();
  1.7030 +      if (rootScrollFrame) {
  1.7031 +        RestoreFrameStateFor(rootScrollFrame, aFrameState);
  1.7032 +      }
  1.7033 +    }
  1.7034 +
  1.7035 +#ifdef ACCESSIBILITY
  1.7036 +    nsAccessibilityService* accService = nsIPresShell::AccService();
  1.7037 +    if (accService) {
  1.7038 +      accService->ContentRangeInserted(mPresShell, aContainer,
  1.7039 +                                       aStartChild, aEndChild);
  1.7040 +    }
  1.7041 +#endif
  1.7042 +
  1.7043 +    return NS_OK;
  1.7044 +  }
  1.7045 +
  1.7046 +  if (aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
  1.7047 +    // Recreate frames if content is inserted into a ShadowRoot
  1.7048 +    // because children of ShadowRoot are rendered in place of
  1.7049 +    // the children of the host.
  1.7050 +    nsIContent* bindingParent = aContainer->GetBindingParent();
  1.7051 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7052 +    nsresult rv = RecreateFramesForContent(bindingParent, false);
  1.7053 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7054 +    return rv;
  1.7055 +  }
  1.7056 +
  1.7057 +  nsIFrame* parentFrame = GetFrameFor(aContainer);
  1.7058 +  // The xbl:children element won't have a frame, but default content can have the children as
  1.7059 +  // a parent. While its uncommon to change the structure of the default content itself, a label,
  1.7060 +  // for example, can be reframed by having its value attribute set or removed.
  1.7061 +  if (!parentFrame && !aContainer->IsActiveChildrenElement()) {
  1.7062 +    return NS_OK;
  1.7063 +  }
  1.7064 +
  1.7065 +  // Otherwise, we've got parent content. Find its frame.
  1.7066 +  NS_ASSERTION(!parentFrame || parentFrame->GetContent() == aContainer, "New XBL code is possibly wrong!");
  1.7067 +
  1.7068 +  if (aAllowLazyConstruction &&
  1.7069 +      MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) {
  1.7070 +    return NS_OK;
  1.7071 +  }
  1.7072 +
  1.7073 +  if (isSingleInsert) {
  1.7074 +    // See if we have an XBL insertion point. If so, then that's our
  1.7075 +    // real parent frame; if not, then the frame hasn't been built yet
  1.7076 +    // and we just bail.
  1.7077 +    parentFrame = GetInsertionPoint(aContainer, aStartChild);
  1.7078 +  } else {
  1.7079 +    // Get our insertion point. If we need to issue single ContentInserted's
  1.7080 +    // GetRangeInsertionPoint will take care of that for us.
  1.7081 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7082 +    parentFrame = GetRangeInsertionPoint(aContainer, aStartChild, aEndChild,
  1.7083 +                                         aAllowLazyConstruction);
  1.7084 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7085 +  }
  1.7086 +
  1.7087 +  if (!parentFrame) {
  1.7088 +    return NS_OK;
  1.7089 +  }
  1.7090 +
  1.7091 +  bool isAppend, isRangeInsertSafe;
  1.7092 +  nsIFrame* prevSibling =
  1.7093 +    GetInsertionPrevSibling(parentFrame, aContainer, aStartChild,
  1.7094 +                            &isAppend, &isRangeInsertSafe);
  1.7095 +
  1.7096 +  // check if range insert is safe
  1.7097 +  if (!isSingleInsert && !isRangeInsertSafe) {
  1.7098 +    // must fall back to a single ContertInserted for each child in the range
  1.7099 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7100 +    IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
  1.7101 +                                 aAllowLazyConstruction);
  1.7102 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7103 +    return NS_OK;
  1.7104 +  }
  1.7105 +
  1.7106 +  nsIContent* container = parentFrame->GetContent();
  1.7107 +
  1.7108 +  nsIAtom* frameType = parentFrame->GetType();
  1.7109 +  LAYOUT_PHASE_TEMP_EXIT();
  1.7110 +  if (MaybeRecreateForFrameset(parentFrame, aStartChild, aEndChild)) {
  1.7111 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7112 +    return NS_OK;
  1.7113 +  }
  1.7114 +  LAYOUT_PHASE_TEMP_REENTER();
  1.7115 +
  1.7116 +  // We should only get here with fieldsets when doing a single insert, because
  1.7117 +  // fieldsets have multiple insertion points.
  1.7118 +  NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame,
  1.7119 +               "Unexpected parent");
  1.7120 +  if (IsFrameForFieldSet(parentFrame, frameType) &&
  1.7121 +      aStartChild->Tag() == nsGkAtoms::legend) {
  1.7122 +    // Just reframe the parent, since figuring out whether this
  1.7123 +    // should be the new legend and then handling it is too complex.
  1.7124 +    // We could do a little better here --- check if the fieldset already
  1.7125 +    // has a legend which occurs earlier in its child list than this node,
  1.7126 +    // and if so, proceed. But we'd have to extend nsFieldSetFrame
  1.7127 +    // to locate this legend in the inserted frames and extract it.
  1.7128 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7129 +    nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
  1.7130 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7131 +    return rv;
  1.7132 +  }
  1.7133 +
  1.7134 +  // Don't construct kids of leaves
  1.7135 +  if (parentFrame->IsLeaf()) {
  1.7136 +    // Clear lazy bits so we don't try to construct again.
  1.7137 +    ClearLazyBits(aStartChild, aEndChild);
  1.7138 +    return NS_OK;
  1.7139 +  }
  1.7140 +
  1.7141 +  if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
  1.7142 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7143 +    nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
  1.7144 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7145 +    return rv;
  1.7146 +  }
  1.7147 +
  1.7148 +  nsFrameConstructorState state(mPresShell,
  1.7149 +                                GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
  1.7150 +                                GetAbsoluteContainingBlock(parentFrame, ABS_POS),
  1.7151 +                                GetFloatContainingBlock(parentFrame),
  1.7152 +                                aFrameState);
  1.7153 +  state.mTreeMatchContext.InitAncestors(aContainer ?
  1.7154 +                                          aContainer->AsElement() :
  1.7155 +                                          nullptr);
  1.7156 +
  1.7157 +  // Recover state for the containing block - we need to know if
  1.7158 +  // it has :first-letter or :first-line style applied to it. The
  1.7159 +  // reason we care is that the internal structure in these cases
  1.7160 +  // is not the normal structure and requires custom updating
  1.7161 +  // logic.
  1.7162 +  nsIFrame* containingBlock = state.mFloatedItems.containingBlock;
  1.7163 +  bool haveFirstLetterStyle = false;
  1.7164 +  bool haveFirstLineStyle = false;
  1.7165 +
  1.7166 +  // In order to shave off some cycles, we only dig up the
  1.7167 +  // containing block haveFirst* flags if the parent frame where
  1.7168 +  // the insertion/append is occurring is an inline or block
  1.7169 +  // container. For other types of containers this isn't relevant.
  1.7170 +  uint8_t parentDisplay = parentFrame->GetDisplay();
  1.7171 +
  1.7172 +  // Examine the parentFrame where the insertion is taking
  1.7173 +  // place. If it's a certain kind of container then some special
  1.7174 +  // processing is done.
  1.7175 +  if ((NS_STYLE_DISPLAY_BLOCK == parentDisplay) ||
  1.7176 +      (NS_STYLE_DISPLAY_LIST_ITEM == parentDisplay) ||
  1.7177 +      (NS_STYLE_DISPLAY_INLINE == parentDisplay) ||
  1.7178 +      (NS_STYLE_DISPLAY_INLINE_BLOCK == parentDisplay)) {
  1.7179 +    // Recover the special style flags for the containing block
  1.7180 +    if (containingBlock) {
  1.7181 +      haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
  1.7182 +      haveFirstLineStyle =
  1.7183 +        ShouldHaveFirstLineStyle(containingBlock->GetContent(),
  1.7184 +                                 containingBlock->StyleContext());
  1.7185 +    }
  1.7186 +
  1.7187 +    if (haveFirstLetterStyle) {
  1.7188 +      // If our current parentFrame is a Letter frame, use its parent as our
  1.7189 +      // new parent hint
  1.7190 +      if (parentFrame->GetType() == nsGkAtoms::letterFrame) {
  1.7191 +        // If parentFrame is out of flow, then we actually want the parent of
  1.7192 +        // the placeholder frame.
  1.7193 +        if (parentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
  1.7194 +          nsPlaceholderFrame* placeholderFrame =
  1.7195 +            GetPlaceholderFrameFor(parentFrame);
  1.7196 +          NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
  1.7197 +          parentFrame = placeholderFrame->GetParent();
  1.7198 +        } else {
  1.7199 +          parentFrame = parentFrame->GetParent();
  1.7200 +        }
  1.7201 +      }
  1.7202 +
  1.7203 +      // Remove the old letter frames before doing the insertion
  1.7204 +      RemoveLetterFrames(state.mPresContext, mPresShell,
  1.7205 +                         state.mFloatedItems.containingBlock);
  1.7206 +
  1.7207 +      // Removing the letterframes messes around with the frame tree, removing
  1.7208 +      // and creating frames.  We need to reget our prevsibling, parent frame,
  1.7209 +      // etc.
  1.7210 +      prevSibling = GetInsertionPrevSibling(parentFrame, aContainer,
  1.7211 +                                            aStartChild, &isAppend,
  1.7212 +                                            &isRangeInsertSafe);
  1.7213 +
  1.7214 +      // Need check whether a range insert is still safe.
  1.7215 +      if (!isSingleInsert && !isRangeInsertSafe) {
  1.7216 +        // Need to recover the letter frames first.
  1.7217 +        RecoverLetterFrames(state.mFloatedItems.containingBlock);
  1.7218 +
  1.7219 +        // must fall back to a single ContertInserted for each child in the range
  1.7220 +        LAYOUT_PHASE_TEMP_EXIT();
  1.7221 +        IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
  1.7222 +                                     aAllowLazyConstruction);
  1.7223 +        LAYOUT_PHASE_TEMP_REENTER();
  1.7224 +        return NS_OK;
  1.7225 +      }
  1.7226 +
  1.7227 +      container = parentFrame->GetContent();
  1.7228 +      frameType = parentFrame->GetType();
  1.7229 +    }
  1.7230 +  }
  1.7231 +
  1.7232 +  if (!prevSibling) {
  1.7233 +    // We're inserting the new frames as the first child. See if the
  1.7234 +    // parent has a :before pseudo-element
  1.7235 +    nsIFrame* firstChild = parentFrame->GetFirstPrincipalChild();
  1.7236 +
  1.7237 +    if (firstChild &&
  1.7238 +        nsLayoutUtils::IsGeneratedContentFor(container, firstChild,
  1.7239 +                                             nsCSSPseudoElements::before)) {
  1.7240 +      // Insert the new frames after the last continuation of the :before
  1.7241 +      prevSibling = firstChild->GetTailContinuation();
  1.7242 +      parentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
  1.7243 +      // Don't change isAppend here; we'll can call AppendFrames as needed, and
  1.7244 +      // the change to our prevSibling doesn't affect that.
  1.7245 +    }
  1.7246 +  }
  1.7247 +
  1.7248 +  FrameConstructionItemList items;
  1.7249 +  ParentType parentType = GetParentType(frameType);
  1.7250 +  FlattenedChildIterator iter(aContainer);
  1.7251 +  bool haveNoXBLChildren = (!iter.XBLInvolved() || !iter.GetNextChild());
  1.7252 +  if (aStartChild->GetPreviousSibling() &&
  1.7253 +      parentType == eTypeBlock && haveNoXBLChildren) {
  1.7254 +    // If there's a text node in the normal content list just before the
  1.7255 +    // new nodes, and it has no frame, make a frame construction item for
  1.7256 +    // it, because it might need a frame now.  No need to do this if our
  1.7257 +    // parent type is not block, though, since WipeContainingBlock
  1.7258 +    // already handles that sitation.
  1.7259 +    AddTextItemIfNeeded(state, parentFrame, aStartChild->GetPreviousSibling(),
  1.7260 +                        items);
  1.7261 +  }
  1.7262 +
  1.7263 +  if (isSingleInsert) {
  1.7264 +    AddFrameConstructionItems(state, aStartChild,
  1.7265 +                              aStartChild->IsRootOfAnonymousSubtree(),
  1.7266 +                              parentFrame, items);
  1.7267 +  } else {
  1.7268 +    for (nsIContent* child = aStartChild;
  1.7269 +         child != aEndChild;
  1.7270 +         child = child->GetNextSibling()){
  1.7271 +      AddFrameConstructionItems(state, child, false, parentFrame, items);
  1.7272 +    }
  1.7273 +  }
  1.7274 +
  1.7275 +  if (aEndChild && parentType == eTypeBlock && haveNoXBLChildren) {
  1.7276 +    // If there's a text node in the normal content list just after the
  1.7277 +    // new nodes, and it has no frame, make a frame construction item for
  1.7278 +    // it, because it might need a frame now.  No need to do this if our
  1.7279 +    // parent type is not block, though, since WipeContainingBlock
  1.7280 +    // already handles that sitation.
  1.7281 +    AddTextItemIfNeeded(state, parentFrame, aEndChild, items);
  1.7282 +  }
  1.7283 +
  1.7284 +  // Perform special check for diddling around with the frames in
  1.7285 +  // a special inline frame.
  1.7286 +  // If we're appending before :after content, then we're not really
  1.7287 +  // appending, so let WipeContainingBlock know that.
  1.7288 +  LAYOUT_PHASE_TEMP_EXIT();
  1.7289 +  if (WipeContainingBlock(state, containingBlock, parentFrame, items,
  1.7290 +                          isAppend, prevSibling)) {
  1.7291 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7292 +    return NS_OK;
  1.7293 +  }
  1.7294 +  LAYOUT_PHASE_TEMP_REENTER();
  1.7295 +
  1.7296 +  // If the container is a table and a caption will be appended, it needs to be
  1.7297 +  // put in the outer table frame's additional child list.
  1.7298 +  // We make no attempt here to set flags to indicate whether the list
  1.7299 +  // will be at the start or end of a block. It doesn't seem worthwhile.
  1.7300 +  nsFrameItems frameItems, captionItems;
  1.7301 +  ConstructFramesFromItemList(state, items, parentFrame, frameItems);
  1.7302 +
  1.7303 +  if (frameItems.NotEmpty()) {
  1.7304 +    for (nsIContent* child = aStartChild;
  1.7305 +         child != aEndChild;
  1.7306 +         child = child->GetNextSibling()){
  1.7307 +      InvalidateCanvasIfNeeded(mPresShell, child);
  1.7308 +    }
  1.7309 +
  1.7310 +    if (nsGkAtoms::tableFrame == frameType ||
  1.7311 +        nsGkAtoms::tableOuterFrame == frameType) {
  1.7312 +      PullOutCaptionFrames(frameItems, captionItems);
  1.7313 +    }
  1.7314 +  }
  1.7315 +
  1.7316 +  // If the parent of our current prevSibling is different from the frame we'll
  1.7317 +  // actually use as the parent, then the calculated insertion point is now
  1.7318 +  // invalid and as it is unknown where to insert correctly we append instead
  1.7319 +  // (bug 341858).
  1.7320 +  // This can affect our prevSibling and isAppend, but should not have any
  1.7321 +  // effect on the WipeContainingBlock above, since this should only happen
  1.7322 +  // when neither parent is a ib-split frame and should not affect whitespace
  1.7323 +  // handling inside table-related frames (and in fact, can only happen when
  1.7324 +  // one of the parents is an outer table and one is an inner table or when the
  1.7325 +  // parent is a fieldset or fieldset content frame).  So it won't affect the
  1.7326 +  // {ib} or XUL box cases in WipeContainingBlock(), and the table pseudo
  1.7327 +  // handling will only be affected by us maybe thinking we're not inserting
  1.7328 +  // at the beginning, whereas we really are.  That would have made us reframe
  1.7329 +  // unnecessarily, but that's ok.
  1.7330 +  // XXXbz we should push our frame construction item code up higher, so we
  1.7331 +  // know what our items are by the time we start figuring out previous
  1.7332 +  // siblings
  1.7333 +  if (prevSibling && frameItems.NotEmpty() &&
  1.7334 +      frameItems.FirstChild()->GetParent() != prevSibling->GetParent()) {
  1.7335 +#ifdef DEBUG
  1.7336 +    nsIFrame* frame1 = frameItems.FirstChild()->GetParent();
  1.7337 +    nsIFrame* frame2 = prevSibling->GetParent();
  1.7338 +    NS_ASSERTION(!IsFramePartOfIBSplit(frame1) &&
  1.7339 +                 !IsFramePartOfIBSplit(frame2),
  1.7340 +                 "Neither should be ib-split");
  1.7341 +    NS_ASSERTION((frame1->GetType() == nsGkAtoms::tableFrame &&
  1.7342 +                  frame2->GetType() == nsGkAtoms::tableOuterFrame) ||
  1.7343 +                 (frame1->GetType() == nsGkAtoms::tableOuterFrame &&
  1.7344 +                  frame2->GetType() == nsGkAtoms::tableFrame) ||
  1.7345 +                 frame1->GetType() == nsGkAtoms::fieldSetFrame ||
  1.7346 +                 (frame1->GetParent() &&
  1.7347 +                  frame1->GetParent()->GetType() == nsGkAtoms::fieldSetFrame),
  1.7348 +                 "Unexpected frame types");
  1.7349 +#endif
  1.7350 +    isAppend = true;
  1.7351 +    nsIFrame* appendAfterFrame;
  1.7352 +    parentFrame =
  1.7353 +      ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(),
  1.7354 +                                          container,
  1.7355 +                                          frameItems.FirstChild()->GetParent(),
  1.7356 +                                          &appendAfterFrame);
  1.7357 +    prevSibling = ::FindAppendPrevSibling(parentFrame, appendAfterFrame);
  1.7358 +  }
  1.7359 +
  1.7360 +  if (haveFirstLineStyle && parentFrame == containingBlock) {
  1.7361 +    // It's possible that the new frame goes into a first-line
  1.7362 +    // frame. Look at it and see...
  1.7363 +    if (isAppend) {
  1.7364 +      // Use append logic when appending
  1.7365 +      AppendFirstLineFrames(state, containingBlock->GetContent(),
  1.7366 +                            containingBlock, frameItems);
  1.7367 +    }
  1.7368 +    else {
  1.7369 +      // Use more complicated insert logic when inserting
  1.7370 +      // XXXbz this method is a no-op, so it's easy for the args being passed
  1.7371 +      // here to make no sense without anyone noticing...  If it ever stops
  1.7372 +      // being a no-op, vet them carefully!
  1.7373 +      InsertFirstLineFrames(state, container, containingBlock, &parentFrame,
  1.7374 +                            prevSibling, frameItems);
  1.7375 +    }
  1.7376 +  }
  1.7377 +
  1.7378 +  // We might have captions; put them into the caption list of the
  1.7379 +  // outer table frame.
  1.7380 +  if (captionItems.NotEmpty()) {
  1.7381 +    NS_ASSERTION(nsGkAtoms::tableFrame == frameType ||
  1.7382 +                 nsGkAtoms::tableOuterFrame == frameType,
  1.7383 +                 "parent for caption is not table?");
  1.7384 +    // We need to determine where to put the caption items; start with the
  1.7385 +    // the parent frame that has already been determined and get the insertion
  1.7386 +    // prevsibling of the first caption item.
  1.7387 +    nsIFrame* captionParent = parentFrame;
  1.7388 +    bool captionIsAppend;
  1.7389 +    nsIFrame* captionPrevSibling = nullptr;
  1.7390 +
  1.7391 +    // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
  1.7392 +    bool ignored;
  1.7393 +    if (isSingleInsert) {
  1.7394 +      captionPrevSibling =
  1.7395 +        GetInsertionPrevSibling(captionParent, aContainer, aStartChild,
  1.7396 +                                &captionIsAppend, &ignored);
  1.7397 +    } else {
  1.7398 +      nsIContent* firstCaption = captionItems.FirstChild()->GetContent();
  1.7399 +      // It is very important here that we skip the children in
  1.7400 +      // [aStartChild,aEndChild) when looking for a
  1.7401 +      // prevsibling.
  1.7402 +      captionPrevSibling =
  1.7403 +        GetInsertionPrevSibling(captionParent, aContainer, firstCaption,
  1.7404 +                                &captionIsAppend, &ignored,
  1.7405 +                                aStartChild, aEndChild);
  1.7406 +    }
  1.7407 +
  1.7408 +    nsIFrame* outerTable = nullptr;
  1.7409 +    if (GetCaptionAdjustedParent(captionParent, captionItems.FirstChild(),
  1.7410 +                                 &outerTable)) {
  1.7411 +      // If the parent is not an outer table frame we will try to add frames
  1.7412 +      // to a named child list that the parent does not honour and the frames
  1.7413 +      // will get lost
  1.7414 +      NS_ASSERTION(nsGkAtoms::tableOuterFrame == outerTable->GetType(),
  1.7415 +                   "Pseudo frame construction failure; "
  1.7416 +                   "a caption can be only a child of an outer table frame");
  1.7417 +
  1.7418 +      // If the parent of our current prevSibling is different from the frame
  1.7419 +      // we'll actually use as the parent, then the calculated insertion
  1.7420 +      // point is now invalid (bug 341382).
  1.7421 +      if (captionPrevSibling &&
  1.7422 +          captionPrevSibling->GetParent() != outerTable) {
  1.7423 +          captionPrevSibling = nullptr;
  1.7424 +      }
  1.7425 +      if (captionIsAppend) {
  1.7426 +        AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
  1.7427 +      } else {
  1.7428 +        InsertFrames(outerTable, nsIFrame::kCaptionList,
  1.7429 +                     captionPrevSibling, captionItems);
  1.7430 +      }
  1.7431 +    }
  1.7432 +  }
  1.7433 +
  1.7434 +  if (frameItems.NotEmpty()) {
  1.7435 +    // Notify the parent frame
  1.7436 +    if (isAppend) {
  1.7437 +      AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
  1.7438 +    } else {
  1.7439 +      InsertFrames(parentFrame, kPrincipalList, prevSibling, frameItems);
  1.7440 +    }
  1.7441 +  }
  1.7442 +
  1.7443 +  if (haveFirstLetterStyle) {
  1.7444 +    // Recover the letter frames for the containing block when
  1.7445 +    // it has first-letter style.
  1.7446 +    RecoverLetterFrames(state.mFloatedItems.containingBlock);
  1.7447 +  }
  1.7448 +
  1.7449 +#ifdef DEBUG
  1.7450 +  if (gReallyNoisyContentUpdates && parentFrame) {
  1.7451 +    printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame model:\n");
  1.7452 +    parentFrame->List(stdout, 0);
  1.7453 +  }
  1.7454 +#endif
  1.7455 +
  1.7456 +#ifdef ACCESSIBILITY
  1.7457 +  nsAccessibilityService* accService = nsIPresShell::AccService();
  1.7458 +  if (accService) {
  1.7459 +    accService->ContentRangeInserted(mPresShell, aContainer,
  1.7460 +                                     aStartChild, aEndChild);
  1.7461 +  }
  1.7462 +#endif
  1.7463 +
  1.7464 +  return NS_OK;
  1.7465 +}
  1.7466 +
  1.7467 +nsresult
  1.7468 +nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
  1.7469 +                                      nsIContent* aChild,
  1.7470 +                                      nsIContent* aOldNextSibling,
  1.7471 +                                      RemoveFlags aFlags,
  1.7472 +                                      bool*     aDidReconstruct)
  1.7473 +{
  1.7474 +  AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
  1.7475 +  NS_PRECONDITION(mUpdateCount != 0,
  1.7476 +                  "Should be in an update while destroying frames");
  1.7477 +
  1.7478 +  *aDidReconstruct = false;
  1.7479 +
  1.7480 +  // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
  1.7481 +  // the :empty pseudo-class?
  1.7482 +
  1.7483 +#ifdef DEBUG
  1.7484 +  if (gNoisyContentUpdates) {
  1.7485 +    printf("nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
  1.7486 +           "old-next-sibling=%p\n",
  1.7487 +           static_cast<void*>(aContainer),
  1.7488 +           static_cast<void*>(aChild),
  1.7489 +           static_cast<void*>(aOldNextSibling));
  1.7490 +    if (gReallyNoisyContentUpdates) {
  1.7491 +      aContainer->List(stdout, 0);
  1.7492 +    }
  1.7493 +  }
  1.7494 +#endif
  1.7495 +
  1.7496 +  nsPresContext *presContext = mPresShell->GetPresContext();
  1.7497 +  nsresult                  rv = NS_OK;
  1.7498 +
  1.7499 +  // Find the child frame that maps the content
  1.7500 +  nsIFrame* childFrame = aChild->GetPrimaryFrame();
  1.7501 +
  1.7502 +  if (!childFrame || childFrame->GetContent() != aChild) {
  1.7503 +    // XXXbz the GetContent() != aChild check is needed due to bug 135040.
  1.7504 +    // Remove it once that's fixed.
  1.7505 +    ClearUndisplayedContentIn(aChild, aContainer);
  1.7506 +  }
  1.7507 +
  1.7508 +#ifdef MOZ_XUL
  1.7509 +  if (NotifyListBoxBody(presContext, aContainer, aChild, aOldNextSibling,
  1.7510 +                        mDocument, childFrame, CONTENT_REMOVED))
  1.7511 +    return NS_OK;
  1.7512 +
  1.7513 +#endif // MOZ_XUL
  1.7514 +
  1.7515 +  // If we're removing the root, then make sure to remove things starting at
  1.7516 +  // the viewport's child instead of the primary frame (which might even be
  1.7517 +  // null if the root had an XBL binding or display:none, even though the
  1.7518 +  // frames above it got created).  We do the adjustment after the childFrame
  1.7519 +  // check above, because we do want to clear any undisplayed content we might
  1.7520 +  // have for the root.  Detecting removal of a root is a little exciting; in
  1.7521 +  // particular, having a null aContainer is necessary but NOT sufficient.  Due
  1.7522 +  // to how we process reframes, the content node might not even be in our
  1.7523 +  // document by now.  So explicitly check whether the viewport's first kid's
  1.7524 +  // content node is aChild.
  1.7525 +  bool isRoot = false;
  1.7526 +  if (!aContainer) {
  1.7527 +    nsIFrame* viewport = GetRootFrame();
  1.7528 +    if (viewport) {
  1.7529 +      nsIFrame* firstChild = viewport->GetFirstPrincipalChild();
  1.7530 +      if (firstChild && firstChild->GetContent() == aChild) {
  1.7531 +        isRoot = true;
  1.7532 +        childFrame = firstChild;
  1.7533 +        NS_ASSERTION(!childFrame->GetNextSibling(), "How did that happen?");
  1.7534 +      }
  1.7535 +    }
  1.7536 +  }
  1.7537 +
  1.7538 +  if (aContainer && aContainer->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
  1.7539 +    // Recreate frames if content is removed from a ShadowRoot
  1.7540 +    // because it may contain an insertion point which can change
  1.7541 +    // how the host is rendered.
  1.7542 +    nsIContent* bindingParent = aContainer->GetBindingParent();
  1.7543 +    *aDidReconstruct = true;
  1.7544 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7545 +    nsresult rv = RecreateFramesForContent(bindingParent, false);
  1.7546 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7547 +    return rv;
  1.7548 +  }
  1.7549 +
  1.7550 +  if (childFrame) {
  1.7551 +    InvalidateCanvasIfNeeded(mPresShell, aChild);
  1.7552 +
  1.7553 +    // See whether we need to remove more than just childFrame
  1.7554 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7555 +    if (MaybeRecreateContainerForFrameRemoval(childFrame, &rv)) {
  1.7556 +      LAYOUT_PHASE_TEMP_REENTER();
  1.7557 +      *aDidReconstruct = true;
  1.7558 +      return rv;
  1.7559 +    }
  1.7560 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7561 +
  1.7562 +    // Get the childFrame's parent frame
  1.7563 +    nsIFrame* parentFrame = childFrame->GetParent();
  1.7564 +    nsIAtom* parentType = parentFrame->GetType();
  1.7565 +
  1.7566 +    if (parentType == nsGkAtoms::frameSetFrame &&
  1.7567 +        IsSpecialFramesetChild(aChild)) {
  1.7568 +      // Just reframe the parent, since framesets are weird like that.
  1.7569 +      *aDidReconstruct = true;
  1.7570 +      LAYOUT_PHASE_TEMP_EXIT();
  1.7571 +      nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
  1.7572 +      LAYOUT_PHASE_TEMP_REENTER();
  1.7573 +      return rv;
  1.7574 +    }
  1.7575 +
  1.7576 +    // If we're a child of MathML, then we should reframe the MathML content.
  1.7577 +    // If we're non-MathML, then we would be wrapped in a block so we need to
  1.7578 +    // check our grandparent in that case.
  1.7579 +    nsIFrame* possibleMathMLAncestor = parentType == nsGkAtoms::blockFrame ?
  1.7580 +         parentFrame->GetParent() : parentFrame;
  1.7581 +    if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) {
  1.7582 +      *aDidReconstruct = true;
  1.7583 +      LAYOUT_PHASE_TEMP_EXIT();
  1.7584 +      nsresult rv = RecreateFramesForContent(possibleMathMLAncestor->GetContent(), false);
  1.7585 +      LAYOUT_PHASE_TEMP_REENTER();
  1.7586 +      return rv;
  1.7587 +    }
  1.7588 +
  1.7589 +    // Undo XUL wrapping if it's no longer needed.
  1.7590 +    // (If we're in the XUL block-wrapping situation, parentFrame is the
  1.7591 +    // wrapper frame.)
  1.7592 +    nsIFrame* grandparentFrame = parentFrame->GetParent();
  1.7593 +    if (grandparentFrame && grandparentFrame->IsBoxFrame() &&
  1.7594 +        (grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
  1.7595 +        // check if this frame is the only one needing wrapping
  1.7596 +        aChild == AnyKidsNeedBlockParent(parentFrame->GetFirstPrincipalChild()) &&
  1.7597 +        !AnyKidsNeedBlockParent(childFrame->GetNextSibling())) {
  1.7598 +      *aDidReconstruct = true;
  1.7599 +      LAYOUT_PHASE_TEMP_EXIT();
  1.7600 +      nsresult rv = RecreateFramesForContent(grandparentFrame->GetContent(), true);
  1.7601 +      LAYOUT_PHASE_TEMP_REENTER();
  1.7602 +      return rv;
  1.7603 +    }
  1.7604 +
  1.7605 +#ifdef ACCESSIBILITY
  1.7606 +    nsAccessibilityService* accService = nsIPresShell::AccService();
  1.7607 +    if (accService) {
  1.7608 +      accService->ContentRemoved(mPresShell, aContainer, aChild);
  1.7609 +    }
  1.7610 +#endif
  1.7611 +
  1.7612 +    // Examine the containing-block for the removed content and see if
  1.7613 +    // :first-letter style applies.
  1.7614 +    nsIFrame* inflowChild = childFrame;
  1.7615 +    if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
  1.7616 +      inflowChild = GetPlaceholderFrameFor(childFrame);
  1.7617 +      NS_ASSERTION(inflowChild, "No placeholder for out-of-flow?");
  1.7618 +    }
  1.7619 +    nsIFrame* containingBlock =
  1.7620 +      GetFloatContainingBlock(inflowChild->GetParent());
  1.7621 +    bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
  1.7622 +    if (haveFLS) {
  1.7623 +      // Trap out to special routine that handles adjusting a blocks
  1.7624 +      // frame tree when first-letter style is present.
  1.7625 +#ifdef NOISY_FIRST_LETTER
  1.7626 +      printf("ContentRemoved: containingBlock=");
  1.7627 +      nsFrame::ListTag(stdout, containingBlock);
  1.7628 +      printf(" parentFrame=");
  1.7629 +      nsFrame::ListTag(stdout, parentFrame);
  1.7630 +      printf(" childFrame=");
  1.7631 +      nsFrame::ListTag(stdout, childFrame);
  1.7632 +      printf("\n");
  1.7633 +#endif
  1.7634 +
  1.7635 +      // First update the containing blocks structure by removing the
  1.7636 +      // existing letter frames. This makes the subsequent logic
  1.7637 +      // simpler.
  1.7638 +      RemoveLetterFrames(presContext, mPresShell, containingBlock);
  1.7639 +
  1.7640 +      // Recover childFrame and parentFrame
  1.7641 +      childFrame = aChild->GetPrimaryFrame();
  1.7642 +      if (!childFrame || childFrame->GetContent() != aChild) {
  1.7643 +        // XXXbz the GetContent() != aChild check is needed due to bug 135040.
  1.7644 +        // Remove it once that's fixed.
  1.7645 +        ClearUndisplayedContentIn(aChild, aContainer);
  1.7646 +        return NS_OK;
  1.7647 +      }
  1.7648 +      parentFrame = childFrame->GetParent();
  1.7649 +      parentType = parentFrame->GetType();
  1.7650 +
  1.7651 +#ifdef NOISY_FIRST_LETTER
  1.7652 +      printf("  ==> revised parentFrame=");
  1.7653 +      nsFrame::ListTag(stdout, parentFrame);
  1.7654 +      printf(" childFrame=");
  1.7655 +      nsFrame::ListTag(stdout, childFrame);
  1.7656 +      printf("\n");
  1.7657 +#endif
  1.7658 +    }
  1.7659 +
  1.7660 +#ifdef DEBUG
  1.7661 +    if (gReallyNoisyContentUpdates) {
  1.7662 +      printf("nsCSSFrameConstructor::ContentRemoved: childFrame=");
  1.7663 +      nsFrame::ListTag(stdout, childFrame);
  1.7664 +      putchar('\n');
  1.7665 +      parentFrame->List(stdout, 0);
  1.7666 +    }
  1.7667 +#endif
  1.7668 +
  1.7669 +
  1.7670 +    // Notify the parent frame that it should delete the frame
  1.7671 +    if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
  1.7672 +      childFrame = GetPlaceholderFrameFor(childFrame);
  1.7673 +      NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.");
  1.7674 +      parentFrame = childFrame->GetParent();
  1.7675 +    }
  1.7676 +    rv = RemoveFrame(nsLayoutUtils::GetChildListNameFor(childFrame),
  1.7677 +                     childFrame);
  1.7678 +    //XXXfr NS_ENSURE_SUCCESS(rv, rv) ?
  1.7679 +
  1.7680 +    if (isRoot) {
  1.7681 +      mRootElementFrame = nullptr;
  1.7682 +      mRootElementStyleFrame = nullptr;
  1.7683 +      mDocElementContainingBlock = nullptr;
  1.7684 +      mPageSequenceFrame = nullptr;
  1.7685 +      mGfxScrollFrame = nullptr;
  1.7686 +      mHasRootAbsPosContainingBlock = false;
  1.7687 +      mFixedContainingBlock = GetRootFrame();
  1.7688 +    }
  1.7689 +
  1.7690 +    if (haveFLS && mRootElementFrame) {
  1.7691 +      RecoverLetterFrames(containingBlock);
  1.7692 +    }
  1.7693 +
  1.7694 +    // If we're just reconstructing frames for the element, then the
  1.7695 +    // following ContentInserted notification on the element will
  1.7696 +    // take care of fixing up any adjacent text nodes.  We don't need
  1.7697 +    // to do this if the table parent type of our parent type is not
  1.7698 +    // eTypeBlock, though, because in that case the whitespace isn't
  1.7699 +    // being suppressed due to us anyway.
  1.7700 +    if (aContainer && !aChild->IsRootOfAnonymousSubtree() &&
  1.7701 +        aFlags != REMOVE_FOR_RECONSTRUCTION &&
  1.7702 +        GetParentType(parentType) == eTypeBlock) {
  1.7703 +      // Adjacent whitespace-only text nodes might have been suppressed if
  1.7704 +      // this node does not have inline ends. Create frames for them now
  1.7705 +      // if necessary.
  1.7706 +      // Reframe any text node just before the node being removed, if there is
  1.7707 +      // one, and if it's not the last child or the first child. If a whitespace
  1.7708 +      // textframe was being suppressed and it's now the last child or first
  1.7709 +      // child then it can stay suppressed since the parent must be a block
  1.7710 +      // and hence it's adjacent to a block end.
  1.7711 +      // If aOldNextSibling is null, then the text node before the node being
  1.7712 +      // removed is the last node, and we don't need to worry about it.
  1.7713 +      if (aOldNextSibling) {
  1.7714 +        nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
  1.7715 +        if (prevSibling && prevSibling->GetPreviousSibling()) {
  1.7716 +          LAYOUT_PHASE_TEMP_EXIT();
  1.7717 +          ReframeTextIfNeeded(aContainer, prevSibling);
  1.7718 +          LAYOUT_PHASE_TEMP_REENTER();
  1.7719 +        }
  1.7720 +      }
  1.7721 +      // Reframe any text node just after the node being removed, if there is
  1.7722 +      // one, and if it's not the last child or the first child.
  1.7723 +      if (aOldNextSibling && aOldNextSibling->GetNextSibling() &&
  1.7724 +          aOldNextSibling->GetPreviousSibling()) {
  1.7725 +        LAYOUT_PHASE_TEMP_EXIT();
  1.7726 +        ReframeTextIfNeeded(aContainer, aOldNextSibling);
  1.7727 +        LAYOUT_PHASE_TEMP_REENTER();
  1.7728 +      }
  1.7729 +    }
  1.7730 +
  1.7731 +#ifdef DEBUG
  1.7732 +    if (gReallyNoisyContentUpdates && parentFrame) {
  1.7733 +      printf("nsCSSFrameConstructor::ContentRemoved: resulting frame model:\n");
  1.7734 +      parentFrame->List(stdout, 0);
  1.7735 +    }
  1.7736 +#endif
  1.7737 +  }
  1.7738 +
  1.7739 +  return rv;
  1.7740 +}
  1.7741 +
  1.7742 +/**
  1.7743 + * This method invalidates the canvas when frames are removed or added for a
  1.7744 + * node that might have its background propagated to the canvas, i.e., a
  1.7745 + * document root node or an HTML BODY which is a child of the root node.
  1.7746 + *
  1.7747 + * @param aFrame a frame for a content node about to be removed or a frame that
  1.7748 + *               was just created for a content node that was inserted.
  1.7749 + */
  1.7750 +static void
  1.7751 +InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node)
  1.7752 +{
  1.7753 +  NS_PRECONDITION(presShell->GetRootFrame(), "What happened here?");
  1.7754 +  NS_PRECONDITION(presShell->GetPresContext(), "Say what?");
  1.7755 +
  1.7756 +  //  Note that both in ContentRemoved and ContentInserted the content node
  1.7757 +  //  will still have the right parent pointer, so looking at that is ok.
  1.7758 +
  1.7759 +  nsIContent* parent = node->GetParent();
  1.7760 +  if (parent) {
  1.7761 +    // Has a parent; might not be what we want
  1.7762 +    nsIContent* grandParent = parent->GetParent();
  1.7763 +    if (grandParent) {
  1.7764 +      // Has a grandparent, so not what we want
  1.7765 +      return;
  1.7766 +    }
  1.7767 +
  1.7768 +    // Check whether it's an HTML body
  1.7769 +    if (node->Tag() != nsGkAtoms::body ||
  1.7770 +        !node->IsHTML()) {
  1.7771 +      return;
  1.7772 +    }
  1.7773 +  }
  1.7774 +
  1.7775 +  // At this point the node has no parent or it's an HTML <body> child of the
  1.7776 +  // root.  We might not need to invalidate in this case (eg we might be in
  1.7777 +  // XHTML or something), but chances are we want to.  Play it safe.
  1.7778 +  // Invalidate the viewport.
  1.7779 +
  1.7780 +  nsIFrame* rootFrame = presShell->GetRootFrame();
  1.7781 +  rootFrame->InvalidateFrameSubtree();
  1.7782 +}
  1.7783 +
  1.7784 +nsIFrame*
  1.7785 +nsCSSFrameConstructor::EnsureFrameForTextNode(nsGenericDOMDataNode* aContent)
  1.7786 +{
  1.7787 +  if (aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
  1.7788 +      !mAlwaysCreateFramesForIgnorableWhitespace) {
  1.7789 +    // Text frame may have been suppressed. Disable suppression and signal
  1.7790 +    // that a flush should be performed. We do this on a document-wide
  1.7791 +    // basis so that pages that repeatedly query metrics for
  1.7792 +    // collapsed-whitespace text nodes don't trigger pathological behavior.
  1.7793 +    mAlwaysCreateFramesForIgnorableWhitespace = true;
  1.7794 +    nsAutoScriptBlocker blocker;
  1.7795 +    BeginUpdate();
  1.7796 +    ReconstructDocElementHierarchy();
  1.7797 +    EndUpdate();
  1.7798 +  }
  1.7799 +  return aContent->GetPrimaryFrame();
  1.7800 +}
  1.7801 +
  1.7802 +nsresult
  1.7803 +nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
  1.7804 +                                            CharacterDataChangeInfo* aInfo)
  1.7805 +{
  1.7806 +  AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
  1.7807 +  nsresult      rv = NS_OK;
  1.7808 +
  1.7809 +  if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
  1.7810 +       !aContent->TextIsOnlyWhitespace()) ||
  1.7811 +      (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
  1.7812 +       aContent->TextIsOnlyWhitespace())) {
  1.7813 +#ifdef DEBUG
  1.7814 +    nsIFrame* frame = aContent->GetPrimaryFrame();
  1.7815 +    NS_ASSERTION(!frame || !frame->IsGeneratedContentFrame(),
  1.7816 +                 "Bit should never be set on generated content");
  1.7817 +#endif
  1.7818 +    LAYOUT_PHASE_TEMP_EXIT();
  1.7819 +    nsresult rv = RecreateFramesForContent(aContent, false);
  1.7820 +    LAYOUT_PHASE_TEMP_REENTER();
  1.7821 +    return rv;
  1.7822 +  }
  1.7823 +
  1.7824 +  // Find the child frame
  1.7825 +  nsIFrame* frame = aContent->GetPrimaryFrame();
  1.7826 +
  1.7827 +  // Notify the first frame that maps the content. It will generate a reflow
  1.7828 +  // command
  1.7829 +
  1.7830 +  // It's possible the frame whose content changed isn't inserted into the
  1.7831 +  // frame hierarchy yet, or that there is no frame that maps the content
  1.7832 +  if (nullptr != frame) {
  1.7833 +#if 0
  1.7834 +    NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
  1.7835 +       ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p",
  1.7836 +        aContent, ContentTag(aContent, 0),
  1.7837 +        aSubContent, frame));
  1.7838 +#endif
  1.7839 +
  1.7840 +    // Special check for text content that is a child of a letter frame.  If
  1.7841 +    // this happens, we should remove the letter frame, do whatever we're
  1.7842 +    // planning to do with this notification, then put the letter frame back.
  1.7843 +    // Note that this is basically what RecreateFramesForContent ends up doing;
  1.7844 +    // the reason we dont' want to call that here is that our text content
  1.7845 +    // could be native anonymous, in which case RecreateFramesForContent would
  1.7846 +    // completely barf on it.  And recreating the non-anonymous ancestor would
  1.7847 +    // just lead us to come back into this notification (e.g. if quotes or
  1.7848 +    // counters are involved), leading to a loop.
  1.7849 +    nsIFrame* block = GetFloatContainingBlock(frame);
  1.7850 +    bool haveFirstLetterStyle = false;
  1.7851 +    if (block) {
  1.7852 +      // See if the block has first-letter style applied to it.
  1.7853 +      haveFirstLetterStyle = HasFirstLetterStyle(block);
  1.7854 +      if (haveFirstLetterStyle) {
  1.7855 +        RemoveLetterFrames(mPresShell->GetPresContext(), mPresShell,
  1.7856 +                           block);
  1.7857 +        // Reget |frame|, since we might have killed it.
  1.7858 +        // Do we really need to call CharacterDataChanged in this case, though?
  1.7859 +        frame = aContent->GetPrimaryFrame();
  1.7860 +        NS_ASSERTION(frame, "Should have frame here!");
  1.7861 +      }
  1.7862 +    }
  1.7863 +
  1.7864 +    frame->CharacterDataChanged(aInfo);
  1.7865 +
  1.7866 +    if (haveFirstLetterStyle) {
  1.7867 +      RecoverLetterFrames(block);
  1.7868 +    }
  1.7869 +  }
  1.7870 +
  1.7871 +  return rv;
  1.7872 +}
  1.7873 +
  1.7874 +void
  1.7875 +nsCSSFrameConstructor::BeginUpdate() {
  1.7876 +  NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
  1.7877 +               "Someone forgot a script blocker");
  1.7878 +
  1.7879 +  nsRootPresContext* rootPresContext =
  1.7880 +    mPresShell->GetPresContext()->GetRootPresContext();
  1.7881 +  if (rootPresContext) {
  1.7882 +    rootPresContext->IncrementDOMGeneration();
  1.7883 +  }
  1.7884 +
  1.7885 +  ++sGlobalGenerationNumber;
  1.7886 +  ++mUpdateCount;
  1.7887 +}
  1.7888 +
  1.7889 +void
  1.7890 +nsCSSFrameConstructor::EndUpdate()
  1.7891 +{
  1.7892 +  if (mUpdateCount == 1) {
  1.7893 +    // This is the end of our last update.  Before we decrement
  1.7894 +    // mUpdateCount, recalc quotes and counters as needed.
  1.7895 +
  1.7896 +    RecalcQuotesAndCounters();
  1.7897 +    NS_ASSERTION(mUpdateCount == 1, "Odd update count");
  1.7898 +  }
  1.7899 +  NS_ASSERTION(mUpdateCount, "Negative mUpdateCount!");
  1.7900 +  --mUpdateCount;
  1.7901 +}
  1.7902 +
  1.7903 +void
  1.7904 +nsCSSFrameConstructor::RecalcQuotesAndCounters()
  1.7905 +{
  1.7906 +  if (mQuotesDirty) {
  1.7907 +    mQuotesDirty = false;
  1.7908 +    mQuoteList.RecalcAll();
  1.7909 +  }
  1.7910 +
  1.7911 +  if (mCountersDirty) {
  1.7912 +    mCountersDirty = false;
  1.7913 +    mCounterManager.RecalcAll();
  1.7914 +  }
  1.7915 +
  1.7916 +  NS_ASSERTION(!mQuotesDirty, "Quotes updates will be lost");
  1.7917 +  NS_ASSERTION(!mCountersDirty, "Counter updates will be lost");
  1.7918 +}
  1.7919 +
  1.7920 +void
  1.7921 +nsCSSFrameConstructor::WillDestroyFrameTree()
  1.7922 +{
  1.7923 +#if defined(DEBUG_dbaron_off)
  1.7924 +  mCounterManager.Dump();
  1.7925 +#endif
  1.7926 +
  1.7927 +  mIsDestroyingFrameTree = true;
  1.7928 +
  1.7929 +  // Prevent frame tree destruction from being O(N^2)
  1.7930 +  mQuoteList.Clear();
  1.7931 +  mCounterManager.Clear();
  1.7932 +
  1.7933 +  // Remove our presshell as a style flush observer.  But leave
  1.7934 +  // RestyleManager::mObservingRefreshDriver true so we don't readd to
  1.7935 +  // it even if someone tries to post restyle events on us from this
  1.7936 +  // point on for some reason.
  1.7937 +  mPresShell->GetPresContext()->RefreshDriver()->
  1.7938 +    RemoveStyleFlushObserver(mPresShell);
  1.7939 +
  1.7940 +  nsFrameManager::Destroy();
  1.7941 +}
  1.7942 +
  1.7943 +//STATIC
  1.7944 +
  1.7945 +// XXXbz I'd really like this method to go away. Once we have inline-block and
  1.7946 +// I can just use that for sized broken images, that can happen, maybe.
  1.7947 +void nsCSSFrameConstructor::GetAlternateTextFor(nsIContent*    aContent,
  1.7948 +                                                nsIAtom*       aTag,  // content object's tag
  1.7949 +                                                nsXPIDLString& aAltText)
  1.7950 +{
  1.7951 +  // The "alt" attribute specifies alternate text that is rendered
  1.7952 +  // when the image can not be displayed
  1.7953 +
  1.7954 +  // If there's no "alt" attribute, and aContent is an input
  1.7955 +  // element, then use the value of the "value" attribute
  1.7956 +  if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText) &&
  1.7957 +      nsGkAtoms::input == aTag) {
  1.7958 +    // If there's no "value" attribute either, then use the localized string
  1.7959 +    // for "Submit" as the alternate text.
  1.7960 +    if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
  1.7961 +      nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
  1.7962 +                                         "Submit", aAltText);
  1.7963 +    }
  1.7964 +  }
  1.7965 +}
  1.7966 +
  1.7967 +nsIFrame*
  1.7968 +nsCSSFrameConstructor::CreateContinuingOuterTableFrame(nsIPresShell*    aPresShell,
  1.7969 +                                                       nsPresContext*  aPresContext,
  1.7970 +                                                       nsIFrame*        aFrame,
  1.7971 +                                                       nsIFrame*        aParentFrame,
  1.7972 +                                                       nsIContent*      aContent,
  1.7973 +                                                       nsStyleContext*  aStyleContext)
  1.7974 +{
  1.7975 +  nsIFrame* newFrame = NS_NewTableOuterFrame(aPresShell, aStyleContext);
  1.7976 +
  1.7977 +  newFrame->Init(aContent, aParentFrame, aFrame);
  1.7978 +
  1.7979 +  // Create a continuing inner table frame, and if there's a caption then
  1.7980 +  // replicate the caption
  1.7981 +  nsFrameItems  newChildFrames;
  1.7982 +
  1.7983 +  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
  1.7984 +  if (childFrame) {
  1.7985 +    nsIFrame* continuingTableFrame =
  1.7986 +      CreateContinuingFrame(aPresContext, childFrame, newFrame);
  1.7987 +    newChildFrames.AddChild(continuingTableFrame);
  1.7988 +
  1.7989 +    NS_ASSERTION(!childFrame->GetNextSibling(),"there can be only one inner table frame");
  1.7990 +  }
  1.7991 +
  1.7992 +  // Set the outer table's initial child list
  1.7993 +  newFrame->SetInitialChildList(kPrincipalList, newChildFrames);
  1.7994 +
  1.7995 +  return newFrame;
  1.7996 +}
  1.7997 +
  1.7998 +nsIFrame*
  1.7999 +nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell,
  1.8000 +                                                  nsPresContext*  aPresContext,
  1.8001 +                                                  nsIFrame*        aFrame,
  1.8002 +                                                  nsIFrame*        aParentFrame,
  1.8003 +                                                  nsIContent*      aContent,
  1.8004 +                                                  nsStyleContext*  aStyleContext)
  1.8005 +{
  1.8006 +  nsIFrame* newFrame = NS_NewTableFrame(aPresShell, aStyleContext);
  1.8007 +
  1.8008 +  newFrame->Init(aContent, aParentFrame, aFrame);
  1.8009 +
  1.8010 +  // Replicate any header/footer frames
  1.8011 +  nsFrameItems  childFrames;
  1.8012 +  nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
  1.8013 +  for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
  1.8014 +    // See if it's a header/footer, possibly wrapped in a scroll frame.
  1.8015 +    nsTableRowGroupFrame* rowGroupFrame =
  1.8016 +      static_cast<nsTableRowGroupFrame*>(childFrame);
  1.8017 +    // If the row group was continued, then don't replicate it.
  1.8018 +    nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
  1.8019 +    if (rgNextInFlow) {
  1.8020 +      rowGroupFrame->SetRepeatable(false);
  1.8021 +    }
  1.8022 +    else if (rowGroupFrame->IsRepeatable()) {
  1.8023 +      // Replicate the header/footer frame.
  1.8024 +      nsTableRowGroupFrame*   headerFooterFrame;
  1.8025 +      nsFrameItems            childItems;
  1.8026 +      nsFrameConstructorState state(mPresShell,
  1.8027 +                                    GetAbsoluteContainingBlock(newFrame, FIXED_POS),
  1.8028 +                                    GetAbsoluteContainingBlock(newFrame, ABS_POS),
  1.8029 +                                    nullptr);
  1.8030 +      state.mCreatingExtraFrames = true;
  1.8031 +
  1.8032 +      nsStyleContext* const headerFooterStyleContext = rowGroupFrame->StyleContext();
  1.8033 +      headerFooterFrame = static_cast<nsTableRowGroupFrame*>
  1.8034 +                                     (NS_NewTableRowGroupFrame(aPresShell, headerFooterStyleContext));
  1.8035 +
  1.8036 +      nsIContent* headerFooter = rowGroupFrame->GetContent();
  1.8037 +      headerFooterFrame->Init(headerFooter, newFrame, nullptr);
  1.8038 +
  1.8039 +      nsFrameConstructorSaveState absoluteSaveState;
  1.8040 +      MakeTablePartAbsoluteContainingBlockIfNeeded(state,
  1.8041 +                                                   headerFooterStyleContext->StyleDisplay(),
  1.8042 +                                                   absoluteSaveState,
  1.8043 +                                                   headerFooterFrame);
  1.8044 +
  1.8045 +      ProcessChildren(state, headerFooter, rowGroupFrame->StyleContext(),
  1.8046 +                      headerFooterFrame, true, childItems, false,
  1.8047 +                      nullptr);
  1.8048 +      NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
  1.8049 +      headerFooterFrame->SetInitialChildList(kPrincipalList, childItems);
  1.8050 +      headerFooterFrame->SetRepeatable(true);
  1.8051 +
  1.8052 +      // Table specific initialization
  1.8053 +      headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
  1.8054 +
  1.8055 +      // XXX Deal with absolute and fixed frames...
  1.8056 +      childFrames.AddChild(headerFooterFrame);
  1.8057 +    }
  1.8058 +  }
  1.8059 +
  1.8060 +  // Set the table frame's initial child list
  1.8061 +  newFrame->SetInitialChildList(kPrincipalList, childFrames);
  1.8062 +
  1.8063 +  return newFrame;
  1.8064 +}
  1.8065 +
  1.8066 +nsIFrame*
  1.8067 +nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
  1.8068 +                                             nsIFrame*       aFrame,
  1.8069 +                                             nsIFrame*       aParentFrame,
  1.8070 +                                             bool            aIsFluid)
  1.8071 +{
  1.8072 +  nsIPresShell*              shell = aPresContext->PresShell();
  1.8073 +  nsStyleContext*            styleContext = aFrame->StyleContext();
  1.8074 +  nsIFrame*                  newFrame = nullptr;
  1.8075 +  nsIFrame*                  nextContinuation = aFrame->GetNextContinuation();
  1.8076 +  nsIFrame*                  nextInFlow = aFrame->GetNextInFlow();
  1.8077 +
  1.8078 +  // Use the frame type to determine what type of frame to create
  1.8079 +  nsIAtom* frameType = aFrame->GetType();
  1.8080 +  nsIContent* content = aFrame->GetContent();
  1.8081 +
  1.8082 +  NS_ASSERTION(aFrame->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE,
  1.8083 +               "why CreateContinuingFrame for a non-splittable frame?");
  1.8084 +
  1.8085 +  if (nsGkAtoms::textFrame == frameType) {
  1.8086 +    newFrame = NS_NewContinuingTextFrame(shell, styleContext);
  1.8087 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8088 +  } else if (nsGkAtoms::inlineFrame == frameType) {
  1.8089 +    newFrame = NS_NewInlineFrame(shell, styleContext);
  1.8090 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8091 +  } else if (nsGkAtoms::blockFrame == frameType) {
  1.8092 +    newFrame = NS_NewBlockFrame(shell, styleContext);
  1.8093 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8094 +#ifdef MOZ_XUL
  1.8095 +  } else if (nsGkAtoms::XULLabelFrame == frameType) {
  1.8096 +    newFrame = NS_NewXULLabelFrame(shell, styleContext);
  1.8097 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8098 +#endif
  1.8099 +  } else if (nsGkAtoms::columnSetFrame == frameType) {
  1.8100 +    newFrame = NS_NewColumnSetFrame(shell, styleContext, nsFrameState(0));
  1.8101 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8102 +  } else if (nsGkAtoms::pageFrame == frameType) {
  1.8103 +    nsIFrame* canvasFrame;
  1.8104 +    newFrame = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame,
  1.8105 +                                  canvasFrame);
  1.8106 +  } else if (nsGkAtoms::tableOuterFrame == frameType) {
  1.8107 +    newFrame =
  1.8108 +      CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
  1.8109 +                                      content, styleContext);
  1.8110 +
  1.8111 +  } else if (nsGkAtoms::tableFrame == frameType) {
  1.8112 +    newFrame =
  1.8113 +      CreateContinuingTableFrame(shell, aPresContext, aFrame, aParentFrame,
  1.8114 +                                 content, styleContext);
  1.8115 +
  1.8116 +  } else if (nsGkAtoms::tableRowGroupFrame == frameType) {
  1.8117 +    newFrame = NS_NewTableRowGroupFrame(shell, styleContext);
  1.8118 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8119 +    if (newFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
  1.8120 +      nsTableFrame::RegisterPositionedTablePart(newFrame);
  1.8121 +    }
  1.8122 +  } else if (nsGkAtoms::tableRowFrame == frameType) {
  1.8123 +    newFrame = NS_NewTableRowFrame(shell, styleContext);
  1.8124 +
  1.8125 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8126 +    if (newFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
  1.8127 +      nsTableFrame::RegisterPositionedTablePart(newFrame);
  1.8128 +    }
  1.8129 +
  1.8130 +    // Create a continuing frame for each table cell frame
  1.8131 +    nsFrameItems  newChildList;
  1.8132 +    nsIFrame* cellFrame = aFrame->GetFirstPrincipalChild();
  1.8133 +    while (cellFrame) {
  1.8134 +      // See if it's a table cell frame
  1.8135 +      if (IS_TABLE_CELL(cellFrame->GetType())) {
  1.8136 +        nsIFrame* continuingCellFrame =
  1.8137 +          CreateContinuingFrame(aPresContext, cellFrame, newFrame);
  1.8138 +        newChildList.AddChild(continuingCellFrame);
  1.8139 +      }
  1.8140 +      cellFrame = cellFrame->GetNextSibling();
  1.8141 +    }
  1.8142 +
  1.8143 +    // Set the table cell's initial child list
  1.8144 +    newFrame->SetInitialChildList(kPrincipalList, newChildList);
  1.8145 +
  1.8146 +  } else if (IS_TABLE_CELL(frameType)) {
  1.8147 +    // Warning: If you change this and add a wrapper frame around table cell
  1.8148 +    // frames, make sure Bug 368554 doesn't regress!
  1.8149 +    // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
  1.8150 +    newFrame = NS_NewTableCellFrame(shell, styleContext, IsBorderCollapse(aParentFrame));
  1.8151 +
  1.8152 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8153 +    if (newFrame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN) {
  1.8154 +      nsTableFrame::RegisterPositionedTablePart(newFrame);
  1.8155 +    }
  1.8156 +
  1.8157 +    // Create a continuing area frame
  1.8158 +    nsIFrame* blockFrame = aFrame->GetFirstPrincipalChild();
  1.8159 +    nsIFrame* continuingBlockFrame =
  1.8160 +      CreateContinuingFrame(aPresContext, blockFrame, newFrame);
  1.8161 +
  1.8162 +    // Set the table cell's initial child list
  1.8163 +    SetInitialSingleChild(newFrame, continuingBlockFrame);
  1.8164 +  } else if (nsGkAtoms::lineFrame == frameType) {
  1.8165 +    newFrame = NS_NewFirstLineFrame(shell, styleContext);
  1.8166 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8167 +  } else if (nsGkAtoms::letterFrame == frameType) {
  1.8168 +    newFrame = NS_NewFirstLetterFrame(shell, styleContext);
  1.8169 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8170 +  } else if (nsGkAtoms::imageFrame == frameType) {
  1.8171 +    newFrame = NS_NewImageFrame(shell, styleContext);
  1.8172 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8173 +  } else if (nsGkAtoms::imageControlFrame == frameType) {
  1.8174 +    newFrame = NS_NewImageControlFrame(shell, styleContext);
  1.8175 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8176 +  } else if (nsGkAtoms::placeholderFrame == frameType) {
  1.8177 +    // create a continuing out of flow frame
  1.8178 +    nsIFrame* oofFrame = nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
  1.8179 +    nsIFrame* oofContFrame =
  1.8180 +      CreateContinuingFrame(aPresContext, oofFrame, aParentFrame);
  1.8181 +    newFrame =
  1.8182 +      CreatePlaceholderFrameFor(shell, content, oofContFrame, styleContext,
  1.8183 +                                aParentFrame, aFrame,
  1.8184 +                                aFrame->GetStateBits() & PLACEHOLDER_TYPE_MASK);
  1.8185 +  } else if (nsGkAtoms::fieldSetFrame == frameType) {
  1.8186 +    newFrame = NS_NewFieldSetFrame(shell, styleContext);
  1.8187 +
  1.8188 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8189 +
  1.8190 +    // Create a continuing area frame
  1.8191 +    // XXXbz we really shouldn't have to do this by hand!
  1.8192 +    nsIFrame* blockFrame = GetFieldSetBlockFrame(aFrame);
  1.8193 +    if (blockFrame) {
  1.8194 +      nsIFrame* continuingBlockFrame =
  1.8195 +        CreateContinuingFrame(aPresContext, blockFrame, newFrame);
  1.8196 +      // Set the fieldset's initial child list
  1.8197 +      SetInitialSingleChild(newFrame, continuingBlockFrame);
  1.8198 +    } else {
  1.8199 +      MOZ_ASSERT(aFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
  1.8200 +                 "FieldSet block may only be null for overflow containers");
  1.8201 +    }
  1.8202 +  } else if (nsGkAtoms::legendFrame == frameType) {
  1.8203 +    newFrame = NS_NewLegendFrame(shell, styleContext);
  1.8204 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8205 +  } else if (nsGkAtoms::flexContainerFrame == frameType) {
  1.8206 +    newFrame = NS_NewFlexContainerFrame(shell, styleContext);
  1.8207 +    newFrame->Init(content, aParentFrame, aFrame);
  1.8208 +  } else {
  1.8209 +    NS_RUNTIMEABORT("unexpected frame type");
  1.8210 +  }
  1.8211 +
  1.8212 +  // Init() set newFrame to be a fluid continuation of aFrame.
  1.8213 +  // If we want a non-fluid continuation, we need to call SetPrevContinuation()
  1.8214 +  // to reset NS_FRAME_IS_FLUID_CONTINUATION.
  1.8215 +  if (!aIsFluid) {
  1.8216 +    newFrame->SetPrevContinuation(aFrame);
  1.8217 +  }
  1.8218 +
  1.8219 +  // A continuation of generated content is also generated content
  1.8220 +  if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
  1.8221 +    newFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT);
  1.8222 +  }
  1.8223 +
  1.8224 +  // A continuation of nsIAnonymousContentCreator content is also
  1.8225 +  // nsIAnonymousContentCreator created content
  1.8226 +  if (aFrame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
  1.8227 +    newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
  1.8228 +  }
  1.8229 +
  1.8230 +  // A continuation of an out-of-flow is also an out-of-flow
  1.8231 +  if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
  1.8232 +    newFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
  1.8233 +  }
  1.8234 +
  1.8235 +  if (nextInFlow) {
  1.8236 +    nextInFlow->SetPrevInFlow(newFrame);
  1.8237 +    newFrame->SetNextInFlow(nextInFlow);
  1.8238 +  } else if (nextContinuation) {
  1.8239 +    nextContinuation->SetPrevContinuation(newFrame);
  1.8240 +    newFrame->SetNextContinuation(nextContinuation);
  1.8241 +  }
  1.8242 +
  1.8243 +  NS_POSTCONDITION(!newFrame->GetNextSibling(), "unexpected sibling");
  1.8244 +  return newFrame;
  1.8245 +}
  1.8246 +
  1.8247 +nsresult
  1.8248 +nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
  1.8249 +{
  1.8250 +  // Now deal with fixed-pos things....  They should appear on all pages,
  1.8251 +  // so we want to move over the placeholders when processing the child
  1.8252 +  // of the pageContentFrame.
  1.8253 +
  1.8254 +  nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
  1.8255 +  if (!prevPageContentFrame) {
  1.8256 +    return NS_OK;
  1.8257 +  }
  1.8258 +  nsIFrame* canvasFrame = aParentFrame->GetFirstPrincipalChild();
  1.8259 +  nsIFrame* prevCanvasFrame = prevPageContentFrame->GetFirstPrincipalChild();
  1.8260 +  if (!canvasFrame || !prevCanvasFrame) {
  1.8261 +    // document's root element frame missing
  1.8262 +    return NS_ERROR_UNEXPECTED;
  1.8263 +  }
  1.8264 +
  1.8265 +  nsFrameItems fixedPlaceholders;
  1.8266 +  nsIFrame* firstFixed = prevPageContentFrame->GetFirstChild(nsIFrame::kFixedList);
  1.8267 +  if (!firstFixed) {
  1.8268 +    return NS_OK;
  1.8269 +  }
  1.8270 +
  1.8271 +  // Don't allow abs-pos descendants of the fixed content to escape the content.
  1.8272 +  // This should not normally be possible (because fixed-pos elements should
  1.8273 +  // be absolute containers) but fixed-pos tables currently aren't abs-pos
  1.8274 +  // containers.
  1.8275 +  nsFrameConstructorState state(mPresShell, aParentFrame,
  1.8276 +                                nullptr,
  1.8277 +                                mRootElementFrame);
  1.8278 +  state.mCreatingExtraFrames = true;
  1.8279 +
  1.8280 +  // We can't use an ancestor filter here, because we're not going to
  1.8281 +  // be usefully recurring down the tree.  This means that other
  1.8282 +  // places in frame construction can't assume a filter is
  1.8283 +  // initialized!
  1.8284 +
  1.8285 +  // Iterate across fixed frames and replicate each whose placeholder is a
  1.8286 +  // descendant of aFrame. (We don't want to explicitly copy placeholders that
  1.8287 +  // are within fixed frames, because that would cause duplicates on the new
  1.8288 +  // page - bug 389619)
  1.8289 +  for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
  1.8290 +    nsIFrame* prevPlaceholder = GetPlaceholderFrameFor(fixed);
  1.8291 +    if (prevPlaceholder &&
  1.8292 +        nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
  1.8293 +      // We want to use the same style as the primary style frame for
  1.8294 +      // our content
  1.8295 +      nsIContent* content = fixed->GetContent();
  1.8296 +      nsStyleContext* styleContext =
  1.8297 +        nsLayoutUtils::GetStyleFrame(content)->StyleContext();
  1.8298 +      FrameConstructionItemList items;
  1.8299 +      AddFrameConstructionItemsInternal(state, content, canvasFrame,
  1.8300 +                                        content->Tag(),
  1.8301 +                                        content->GetNameSpaceID(),
  1.8302 +                                        true,
  1.8303 +                                        styleContext,
  1.8304 +                                        ITEM_ALLOW_XBL_BASE |
  1.8305 +                                          ITEM_ALLOW_PAGE_BREAK,
  1.8306 +                                        nullptr, items);
  1.8307 +      ConstructFramesFromItemList(state, items, canvasFrame, fixedPlaceholders);
  1.8308 +    }
  1.8309 +  }
  1.8310 +
  1.8311 +  // Add the placeholders to our primary child list.
  1.8312 +  // XXXbz this is a little screwed up, since the fixed frames will have
  1.8313 +  // broken auto-positioning. Oh, well.
  1.8314 +  NS_ASSERTION(!canvasFrame->GetFirstPrincipalChild(),
  1.8315 +               "leaking frames; doc root continuation must be empty");
  1.8316 +  canvasFrame->SetInitialChildList(kPrincipalList, fixedPlaceholders);
  1.8317 +  return NS_OK;
  1.8318 +}
  1.8319 +
  1.8320 +nsIFrame*
  1.8321 +nsCSSFrameConstructor::GetInsertionPoint(nsIContent*   aContainer,
  1.8322 +                                         nsIContent*   aChildContent,
  1.8323 +                                         bool*         aMultiple)
  1.8324 +{
  1.8325 +  nsBindingManager *bindingManager = mDocument->BindingManager();
  1.8326 +
  1.8327 +  nsIContent* insertionElement;
  1.8328 +  if (aChildContent) {
  1.8329 +    // We've got an explicit insertion child. Check to see if it's
  1.8330 +    // anonymous.
  1.8331 +    if (aChildContent->GetBindingParent() == aContainer) {
  1.8332 +      // This child content is anonymous. Don't use the insertion
  1.8333 +      // point, since that's only for the explicit kids.
  1.8334 +      return GetFrameFor(aContainer);
  1.8335 +    }
  1.8336 +
  1.8337 +    insertionElement = bindingManager->FindNestedInsertionPoint(aContainer, aChildContent);
  1.8338 +  }
  1.8339 +  else {
  1.8340 +    bool multiple;
  1.8341 +    insertionElement = bindingManager->FindNestedSingleInsertionPoint(aContainer, &multiple);
  1.8342 +
  1.8343 +    if (multiple) {
  1.8344 +      if (aMultiple) {
  1.8345 +        *aMultiple = true;
  1.8346 +      }
  1.8347 +      return nullptr;
  1.8348 +    }
  1.8349 +  }
  1.8350 +
  1.8351 +  if (!insertionElement) {
  1.8352 +    insertionElement = aContainer;
  1.8353 +  }
  1.8354 +
  1.8355 +  nsIFrame* insertionPoint = GetFrameFor(insertionElement);
  1.8356 +
  1.8357 +  // fieldsets have multiple insertion points.  Note that we might
  1.8358 +  // have to look at insertionElement here...
  1.8359 +  if (aMultiple && insertionElement->IsHTML(nsGkAtoms::fieldset)) {
  1.8360 +    *aMultiple = true;
  1.8361 +  }
  1.8362 +
  1.8363 +  return insertionPoint;
  1.8364 +}
  1.8365 +
  1.8366 +// Capture state for the frame tree rooted at the frame associated with the
  1.8367 +// content object, aContent
  1.8368 +void
  1.8369 +nsCSSFrameConstructor::CaptureStateForFramesOf(nsIContent* aContent,
  1.8370 +                                               nsILayoutHistoryState* aHistoryState)
  1.8371 +{
  1.8372 +  if (!aHistoryState) {
  1.8373 +    return;
  1.8374 +  }
  1.8375 +  nsIFrame* frame = aContent->GetPrimaryFrame();
  1.8376 +  if (frame == mRootElementFrame) {
  1.8377 +    frame = mFixedContainingBlock;
  1.8378 +  }
  1.8379 +  for ( ; frame;
  1.8380 +        frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
  1.8381 +    CaptureFrameState(frame, aHistoryState);
  1.8382 +  }
  1.8383 +}
  1.8384 +
  1.8385 +static bool EqualURIs(mozilla::css::URLValue *aURI1,
  1.8386 +                      mozilla::css::URLValue *aURI2)
  1.8387 +{
  1.8388 +  return aURI1 == aURI2 ||    // handle null==null, and optimize
  1.8389 +         (aURI1 && aURI2 && aURI1->URIEquals(*aURI2));
  1.8390 +}
  1.8391 +
  1.8392 +nsresult
  1.8393 +nsCSSFrameConstructor::MaybeRecreateFramesForElement(Element* aElement)
  1.8394 +{
  1.8395 +  nsRefPtr<nsStyleContext> oldContext = GetUndisplayedContent(aElement);
  1.8396 +  if (!oldContext) {
  1.8397 +    return NS_OK;
  1.8398 +  }
  1.8399 +
  1.8400 +  // The parent has a frame, so try resolving a new context.
  1.8401 +  nsRefPtr<nsStyleContext> newContext = mPresShell->StyleSet()->
  1.8402 +    ResolveStyleFor(aElement, oldContext->GetParent());
  1.8403 +
  1.8404 +  ChangeUndisplayedContent(aElement, newContext);
  1.8405 +  const nsStyleDisplay* disp = newContext->StyleDisplay();
  1.8406 +  if (disp->mDisplay == NS_STYLE_DISPLAY_NONE) {
  1.8407 +    // We can skip trying to recreate frames here, but only if our style
  1.8408 +    // context does not have a binding URI that differs from our old one.
  1.8409 +    // Otherwise, we should try to recreate, because we may want to apply the
  1.8410 +    // new binding
  1.8411 +    if (!disp->mBinding) {
  1.8412 +      return NS_OK;
  1.8413 +    }
  1.8414 +    const nsStyleDisplay* oldDisp = oldContext->PeekStyleDisplay();
  1.8415 +    if (oldDisp && EqualURIs(disp->mBinding, oldDisp->mBinding)) {
  1.8416 +      return NS_OK;
  1.8417 +    }
  1.8418 +  }
  1.8419 +
  1.8420 +  return RecreateFramesForContent(aElement, false);
  1.8421 +}
  1.8422 +
  1.8423 +static nsIFrame*
  1.8424 +FindFirstNonWhitespaceChild(nsIFrame* aParentFrame)
  1.8425 +{
  1.8426 +  nsIFrame* f = aParentFrame->GetFirstPrincipalChild();
  1.8427 +  while (f && f->GetType() == nsGkAtoms::textFrame &&
  1.8428 +         f->GetContent()->TextIsOnlyWhitespace()) {
  1.8429 +    f = f->GetNextSibling();
  1.8430 +  }
  1.8431 +  return f;
  1.8432 +}
  1.8433 +
  1.8434 +static nsIFrame*
  1.8435 +FindNextNonWhitespaceSibling(nsIFrame* aFrame)
  1.8436 +{
  1.8437 +  nsIFrame* f = aFrame;
  1.8438 +  do {
  1.8439 +    f = f->GetNextSibling();
  1.8440 +  } while (f && f->GetType() == nsGkAtoms::textFrame &&
  1.8441 +           f->GetContent()->TextIsOnlyWhitespace());
  1.8442 +  return f;
  1.8443 +}
  1.8444 +
  1.8445 +static nsIFrame*
  1.8446 +FindPreviousNonWhitespaceSibling(nsIFrame* aFrame)
  1.8447 +{
  1.8448 +  nsIFrame* f = aFrame;
  1.8449 +  do {
  1.8450 +    f = f->GetPrevSibling();
  1.8451 +  } while (f && f->GetType() == nsGkAtoms::textFrame &&
  1.8452 +           f->GetContent()->TextIsOnlyWhitespace());
  1.8453 +  return f;
  1.8454 +}
  1.8455 +
  1.8456 +bool
  1.8457 +nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
  1.8458 +                                                             nsresult* aResult)
  1.8459 +{
  1.8460 +  NS_PRECONDITION(aFrame, "Must have a frame");
  1.8461 +  NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root");
  1.8462 +  NS_PRECONDITION(aResult, "Null out param?");
  1.8463 +  NS_PRECONDITION(aFrame == aFrame->FirstContinuation(),
  1.8464 +                  "aFrame not the result of GetPrimaryFrame()?");
  1.8465 +
  1.8466 +  if (IsFramePartOfIBSplit(aFrame)) {
  1.8467 +    // The removal functions can't handle removal of an {ib} split directly; we
  1.8468 +    // need to rebuild the containing block.
  1.8469 +#ifdef DEBUG
  1.8470 +    if (gNoisyContentUpdates) {
  1.8471 +      printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
  1.8472 +             "frame=");
  1.8473 +      nsFrame::ListTag(stdout, aFrame);
  1.8474 +      printf(" is ib-split\n");
  1.8475 +    }
  1.8476 +#endif
  1.8477 +
  1.8478 +    *aResult = ReframeContainingBlock(aFrame);
  1.8479 +    return true;
  1.8480 +  }
  1.8481 +
  1.8482 +  if (aFrame->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame &&
  1.8483 +      aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) {
  1.8484 +    // When we remove the legend for a fieldset, we should reframe
  1.8485 +    // the fieldset to ensure another legend is used, if there is one
  1.8486 +    *aResult = RecreateFramesForContent(aFrame->GetParent()->GetContent(), false);
  1.8487 +    return true;
  1.8488 +  }
  1.8489 +
  1.8490 +  // Now check for possibly needing to reconstruct due to a pseudo parent
  1.8491 +  nsIFrame* inFlowFrame =
  1.8492 +    (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ?
  1.8493 +      GetPlaceholderFrameFor(aFrame) : aFrame;
  1.8494 +  MOZ_ASSERT(inFlowFrame, "How did that happen?");
  1.8495 +  MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(),
  1.8496 +             "placeholder for primary frame has previous continuations?");
  1.8497 +  nsIFrame* parent = inFlowFrame->GetParent();
  1.8498 +  if (IsTablePseudo(parent)) {
  1.8499 +    if (FindFirstNonWhitespaceChild(parent) == inFlowFrame ||
  1.8500 +        !FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation()) ||
  1.8501 +        // If we're a table-column-group, then the GetFirstChild check above is
  1.8502 +        // not going to catch cases when we're the first child.
  1.8503 +        (inFlowFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
  1.8504 +         parent->GetFirstChild(nsIFrame::kColGroupList) == inFlowFrame) ||
  1.8505 +        // Similar if we're a table-caption.
  1.8506 +        (inFlowFrame->GetType() == nsGkAtoms::tableCaptionFrame &&
  1.8507 +         parent->GetFirstChild(nsIFrame::kCaptionList) == inFlowFrame)) {
  1.8508 +      // We're the first or last frame in the pseudo.  Need to reframe.
  1.8509 +      // Good enough to recreate frames for |parent|'s content
  1.8510 +      *aResult = RecreateFramesForContent(parent->GetContent(), true);
  1.8511 +      return true;
  1.8512 +    }
  1.8513 +  }
  1.8514 +
  1.8515 +  // Might need to reconstruct things if this frame's nextSibling is a table
  1.8516 +  // pseudo, since removal of this frame might mean that this pseudo needs to
  1.8517 +  // get merged with the frame's prevSibling if that's also a table pseudo.
  1.8518 +  nsIFrame* nextSibling =
  1.8519 +    FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation());
  1.8520 +  NS_ASSERTION(!IsTablePseudo(inFlowFrame), "Shouldn't happen here");
  1.8521 +  if (nextSibling && IsTablePseudo(nextSibling)) {
  1.8522 +    nsIFrame* prevSibling = FindPreviousNonWhitespaceSibling(inFlowFrame);
  1.8523 +    if (prevSibling && IsTablePseudo(prevSibling)) {
  1.8524 +#ifdef DEBUG
  1.8525 +      if (gNoisyContentUpdates) {
  1.8526 +        printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
  1.8527 +                 "frame=");
  1.8528 +        nsFrame::ListTag(stdout, aFrame);
  1.8529 +        printf(" has a table pseudo next sibling of different type and a "
  1.8530 +                 "table pseudo prevsibling\n");
  1.8531 +      }
  1.8532 +#endif
  1.8533 +      // Good enough to recreate frames for aFrame's parent's content; even if
  1.8534 +      // aFrame's parent is a table pseudo, that'll be the right content node.
  1.8535 +      *aResult = RecreateFramesForContent(parent->GetContent(), true);
  1.8536 +      return true;
  1.8537 +    }
  1.8538 +  }
  1.8539 +
  1.8540 +  // Might need to reconstruct things if the removed frame's nextSibling is an
  1.8541 +  // anonymous flex item.  The removed frame might've been what divided two
  1.8542 +  // runs of inline content into two anonymous flex items, which would now
  1.8543 +  // need to be merged.
  1.8544 +  // NOTE: It's fine that we've advanced nextSibling past whitespace (up above);
  1.8545 +  // we're only interested in anonymous flex items here, and those can never
  1.8546 +  // be adjacent to whitespace, since they absorb contiguous runs of inline
  1.8547 +  // non-replaced content (including whitespace).
  1.8548 +  if (nextSibling && IsAnonymousFlexItem(nextSibling)) {
  1.8549 +    NS_ABORT_IF_FALSE(parent->GetType() == nsGkAtoms::flexContainerFrame,
  1.8550 +                      "anonymous flex items should only exist as children "
  1.8551 +                      "of flex container frames");
  1.8552 +#ifdef DEBUG
  1.8553 +    if (gNoisyContentUpdates) {
  1.8554 +      printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
  1.8555 +             "frame=");
  1.8556 +      nsFrame::ListTag(stdout, aFrame);
  1.8557 +      printf(" has an anonymous flex item as its next sibling\n");
  1.8558 +    }
  1.8559 +#endif // DEBUG
  1.8560 +    // Recreate frames for the flex container (the removed frame's parent)
  1.8561 +    *aResult = RecreateFramesForContent(parent->GetContent(), true);
  1.8562 +    return true;
  1.8563 +  }
  1.8564 +
  1.8565 +  // Might need to reconstruct things if the removed frame's nextSibling is
  1.8566 +  // null and its parent is an anonymous flex item. (This might be the last
  1.8567 +  // remaining child of that anonymous flex item, which can then go away.)
  1.8568 +  if (!nextSibling && IsAnonymousFlexItem(parent)) {
  1.8569 +    NS_ABORT_IF_FALSE(parent->GetParent() &&
  1.8570 +                      parent->GetParent()->GetType() == nsGkAtoms::flexContainerFrame,
  1.8571 +                      "anonymous flex items should only exist as children "
  1.8572 +                      "of flex container frames");
  1.8573 +#ifdef DEBUG
  1.8574 +    if (gNoisyContentUpdates) {
  1.8575 +      printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
  1.8576 +             "frame=");
  1.8577 +      nsFrame::ListTag(stdout, aFrame);
  1.8578 +      printf(" has an anonymous flex item as its parent\n");
  1.8579 +    }
  1.8580 +#endif // DEBUG
  1.8581 +    // Recreate frames for the flex container (the removed frame's grandparent)
  1.8582 +    *aResult = RecreateFramesForContent(parent->GetParent()->GetContent(),
  1.8583 +                                        true);
  1.8584 +    return true;
  1.8585 +  }
  1.8586 +
  1.8587 +#ifdef MOZ_XUL
  1.8588 +  if (aFrame->GetType() == nsGkAtoms::popupSetFrame) {
  1.8589 +    nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
  1.8590 +    if (rootBox && rootBox->GetPopupSetFrame() == aFrame) {
  1.8591 +      *aResult = ReconstructDocElementHierarchy();
  1.8592 +      return true;
  1.8593 +    }
  1.8594 +  }
  1.8595 +#endif
  1.8596 +
  1.8597 +  // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
  1.8598 +  // a non-fluid continuation, i.e. it was split by bidi resolution
  1.8599 +  if (!inFlowFrame->GetPrevSibling() &&
  1.8600 +      !inFlowFrame->GetNextSibling() &&
  1.8601 +      ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
  1.8602 +       (parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
  1.8603 +    *aResult = RecreateFramesForContent(parent->GetContent(), true);
  1.8604 +    return true;
  1.8605 +  }
  1.8606 +
  1.8607 +  // We might still need to reconstruct things if the parent of inFlowFrame is
  1.8608 +  // ib-split, since in that case the removal of aFrame might affect the
  1.8609 +  // splitting of its parent.
  1.8610 +  if (!IsFramePartOfIBSplit(parent)) {
  1.8611 +    return false;
  1.8612 +  }
  1.8613 +
  1.8614 +  // If inFlowFrame is not the only in-flow child of |parent|, then removing
  1.8615 +  // it will change nothing about the {ib} split.
  1.8616 +  if (inFlowFrame != parent->GetFirstPrincipalChild() ||
  1.8617 +      inFlowFrame->LastContinuation()->GetNextSibling()) {
  1.8618 +    return false;
  1.8619 +  }
  1.8620 +
  1.8621 +  // If the parent is the first or last part of the {ib} split, then
  1.8622 +  // removing one of its kids will have no effect on the splitting.
  1.8623 +  // Get the first continuation up front so we don't have to do it twice.
  1.8624 +  nsIFrame* parentFirstContinuation = parent->FirstContinuation();
  1.8625 +  if (!GetIBSplitSibling(parentFirstContinuation) ||
  1.8626 +      !GetIBSplitPrevSibling(parentFirstContinuation)) {
  1.8627 +    return false;
  1.8628 +  }
  1.8629 +
  1.8630 +#ifdef DEBUG
  1.8631 +  if (gNoisyContentUpdates) {
  1.8632 +    printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
  1.8633 +           "frame=");
  1.8634 +    nsFrame::ListTag(stdout, parent);
  1.8635 +    printf(" is ib-split\n");
  1.8636 +  }
  1.8637 +#endif
  1.8638 +
  1.8639 +  *aResult = ReframeContainingBlock(parent);
  1.8640 +  return true;
  1.8641 +}
  1.8642 +
  1.8643 +nsresult
  1.8644 +nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
  1.8645 +                                                bool aAsyncInsert)
  1.8646 +{
  1.8647 +  NS_PRECONDITION(!aAsyncInsert || aContent->IsElement(),
  1.8648 +                  "Can only insert elements async");
  1.8649 +  // If there is no document, we don't want to recreate frames for it.  (You
  1.8650 +  // shouldn't generally be giving this method content without a document
  1.8651 +  // anyway).
  1.8652 +  // Rebuilding the frame tree can have bad effects, especially if it's the
  1.8653 +  // frame tree for chrome (see bug 157322).
  1.8654 +  NS_ENSURE_TRUE(aContent->GetDocument(), NS_ERROR_FAILURE);
  1.8655 +
  1.8656 +  // Is the frame ib-split? If so, we need to reframe the containing
  1.8657 +  // block *here*, rather than trying to remove and re-insert the
  1.8658 +  // content (which would otherwise result in *two* nested reframe
  1.8659 +  // containing block from ContentRemoved() and ContentInserted(),
  1.8660 +  // below!).  We'd really like to optimize away one of those
  1.8661 +  // containing block reframes, hence the code here.
  1.8662 +
  1.8663 +  nsIFrame* frame = aContent->GetPrimaryFrame();
  1.8664 +  if (frame && frame->IsFrameOfType(nsIFrame::eMathML)) {
  1.8665 +    // Reframe the topmost MathML element to prevent exponential blowup
  1.8666 +    // (see bug 397518)
  1.8667 +    while (true) {
  1.8668 +      nsIContent* parentContent = aContent->GetParent();
  1.8669 +      nsIFrame* parentContentFrame = parentContent->GetPrimaryFrame();
  1.8670 +      if (!parentContentFrame || !parentContentFrame->IsFrameOfType(nsIFrame::eMathML))
  1.8671 +        break;
  1.8672 +      aContent = parentContent;
  1.8673 +      frame = parentContentFrame;
  1.8674 +    }
  1.8675 +  }
  1.8676 +
  1.8677 +  if (frame) {
  1.8678 +    nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame);
  1.8679 +    if (nonGeneratedAncestor->GetContent() != aContent) {
  1.8680 +      return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), aAsyncInsert);
  1.8681 +    }
  1.8682 +
  1.8683 +    if (frame->GetStateBits() & NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT) {
  1.8684 +      // Recreate the frames for the entire nsIAnonymousContentCreator tree
  1.8685 +      // since |frame| or one of its descendants may need an nsStyleContext
  1.8686 +      // that associates it to a CSS pseudo-element, and only the
  1.8687 +      // nsIAnonymousContentCreator that created this content knows how to make
  1.8688 +      // that happen.
  1.8689 +      nsIAnonymousContentCreator* acc = nullptr;
  1.8690 +      nsIFrame* ancestor = frame->GetParent();
  1.8691 +      while (!(acc = do_QueryFrame(ancestor))) {
  1.8692 +        ancestor = ancestor->GetParent();
  1.8693 +      }
  1.8694 +      NS_ASSERTION(acc, "Where is the nsIAnonymousContentCreator? We may fail "
  1.8695 +                        "to recreate its content correctly");
  1.8696 +      // nsSVGUseFrame is special, and we know this is unnecessary for it.
  1.8697 +      if (ancestor->GetType() != nsGkAtoms::svgUseFrame) {
  1.8698 +        NS_ASSERTION(aContent->IsInNativeAnonymousSubtree(),
  1.8699 +                     "Why is NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT set?");
  1.8700 +        return RecreateFramesForContent(ancestor->GetContent(), aAsyncInsert);
  1.8701 +      }
  1.8702 +    }
  1.8703 +
  1.8704 +    nsIFrame* parent = frame->GetParent();
  1.8705 +    nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
  1.8706 +    // If the parent frame is a leaf then the subsequent insert will fail to
  1.8707 +    // create a frame, so we need to recreate the parent content. This happens
  1.8708 +    // with native anonymous content from the editor.
  1.8709 +    if (parent && parent->IsLeaf() && parentContent &&
  1.8710 +        parentContent != aContent) {
  1.8711 +      return RecreateFramesForContent(parentContent, aAsyncInsert);
  1.8712 +    }
  1.8713 +  }
  1.8714 +
  1.8715 +  nsresult rv = NS_OK;
  1.8716 +
  1.8717 +  if (frame && MaybeRecreateContainerForFrameRemoval(frame, &rv)) {
  1.8718 +    return rv;
  1.8719 +  }
  1.8720 +
  1.8721 +  nsINode* containerNode = aContent->GetParentNode();
  1.8722 +  // XXXbz how can containerNode be null here?
  1.8723 +  if (containerNode) {
  1.8724 +    // Before removing the frames associated with the content object,
  1.8725 +    // ask them to save their state onto a temporary state object.
  1.8726 +    CaptureStateForFramesOf(aContent, mTempFrameTreeState);
  1.8727 +
  1.8728 +    // Need the nsIContent parent, which might be null here, since we need to
  1.8729 +    // pass it to ContentInserted and ContentRemoved.
  1.8730 +    nsCOMPtr<nsIContent> container = aContent->GetParent();
  1.8731 +
  1.8732 +    // Remove the frames associated with the content object.
  1.8733 +    bool didReconstruct;
  1.8734 +    rv = ContentRemoved(container, aContent,
  1.8735 +                        aContent->IsRootOfAnonymousSubtree() ?
  1.8736 +                          nullptr :
  1.8737 +                          aContent->GetNextSibling(),
  1.8738 +                        REMOVE_FOR_RECONSTRUCTION, &didReconstruct);
  1.8739 +
  1.8740 +    if (NS_SUCCEEDED(rv) && !didReconstruct) {
  1.8741 +      // Now, recreate the frames associated with this content object. If
  1.8742 +      // ContentRemoved triggered reconstruction, then we don't need to do this
  1.8743 +      // because the frames will already have been built.
  1.8744 +      if (aAsyncInsert) {
  1.8745 +        RestyleManager()->PostRestyleEvent(
  1.8746 +          aContent->AsElement(), nsRestyleHint(0), nsChangeHint_ReconstructFrame);
  1.8747 +      } else {
  1.8748 +        rv = ContentInserted(container, aContent, mTempFrameTreeState, false);
  1.8749 +      }
  1.8750 +    }
  1.8751 +  }
  1.8752 +
  1.8753 +  return rv;
  1.8754 +}
  1.8755 +
  1.8756 +//////////////////////////////////////////////////////////////////////
  1.8757 +
  1.8758 +// Block frame construction code
  1.8759 +
  1.8760 +already_AddRefed<nsStyleContext>
  1.8761 +nsCSSFrameConstructor::GetFirstLetterStyle(nsIContent* aContent,
  1.8762 +                                           nsStyleContext* aStyleContext)
  1.8763 +{
  1.8764 +  if (aContent) {
  1.8765 +    return mPresShell->StyleSet()->
  1.8766 +      ResolvePseudoElementStyle(aContent->AsElement(),
  1.8767 +                                nsCSSPseudoElements::ePseudo_firstLetter,
  1.8768 +                                aStyleContext,
  1.8769 +                                nullptr);
  1.8770 +  }
  1.8771 +  return nullptr;
  1.8772 +}
  1.8773 +
  1.8774 +already_AddRefed<nsStyleContext>
  1.8775 +nsCSSFrameConstructor::GetFirstLineStyle(nsIContent* aContent,
  1.8776 +                                         nsStyleContext* aStyleContext)
  1.8777 +{
  1.8778 +  if (aContent) {
  1.8779 +    return mPresShell->StyleSet()->
  1.8780 +      ResolvePseudoElementStyle(aContent->AsElement(),
  1.8781 +                                nsCSSPseudoElements::ePseudo_firstLine,
  1.8782 +                                aStyleContext,
  1.8783 +                                nullptr);
  1.8784 +  }
  1.8785 +  return nullptr;
  1.8786 +}
  1.8787 +
  1.8788 +// Predicate to see if a given content (block element) has
  1.8789 +// first-letter style applied to it.
  1.8790 +bool
  1.8791 +nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(nsIContent* aContent,
  1.8792 +                                                  nsStyleContext* aStyleContext)
  1.8793 +{
  1.8794 +  return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
  1.8795 +                                       nsCSSPseudoElements::ePseudo_firstLetter,
  1.8796 +                                       mPresShell->GetPresContext());
  1.8797 +}
  1.8798 +
  1.8799 +bool
  1.8800 +nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame)
  1.8801 +{
  1.8802 +  NS_PRECONDITION(aBlockFrame, "Need a frame");
  1.8803 +  NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
  1.8804 +               "Not a block frame?");
  1.8805 +
  1.8806 +  return (aBlockFrame->GetStateBits() & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0;
  1.8807 +}
  1.8808 +
  1.8809 +bool
  1.8810 +nsCSSFrameConstructor::ShouldHaveFirstLineStyle(nsIContent* aContent,
  1.8811 +                                                nsStyleContext* aStyleContext)
  1.8812 +{
  1.8813 +  bool hasFirstLine =
  1.8814 +    nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
  1.8815 +                                  nsCSSPseudoElements::ePseudo_firstLine,
  1.8816 +                                  mPresShell->GetPresContext());
  1.8817 +  if (hasFirstLine) {
  1.8818 +    // But disable for fieldsets
  1.8819 +    int32_t namespaceID;
  1.8820 +    nsIAtom* tag = mDocument->BindingManager()->ResolveTag(aContent,
  1.8821 +                                                           &namespaceID);
  1.8822 +    // This check must match the one in FindHTMLData.
  1.8823 +    hasFirstLine = tag != nsGkAtoms::fieldset ||
  1.8824 +      namespaceID != kNameSpaceID_XHTML;
  1.8825 +  }
  1.8826 +
  1.8827 +  return hasFirstLine;
  1.8828 +}
  1.8829 +
  1.8830 +void
  1.8831 +nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(nsIContent* aContent,
  1.8832 +                                                   nsStyleContext* aStyleContext,
  1.8833 +                                                   bool* aHaveFirstLetterStyle,
  1.8834 +                                                   bool* aHaveFirstLineStyle)
  1.8835 +{
  1.8836 +  *aHaveFirstLetterStyle =
  1.8837 +    ShouldHaveFirstLetterStyle(aContent, aStyleContext);
  1.8838 +  *aHaveFirstLineStyle =
  1.8839 +    ShouldHaveFirstLineStyle(aContent, aStyleContext);
  1.8840 +}
  1.8841 +
  1.8842 +/* static */
  1.8843 +const nsCSSFrameConstructor::PseudoParentData
  1.8844 +nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
  1.8845 +  { // Cell
  1.8846 +    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
  1.8847 +                     FCDATA_USE_CHILD_ITEMS |
  1.8848 +                     FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
  1.8849 +                     &nsCSSFrameConstructor::ConstructTableCell),
  1.8850 +    &nsCSSAnonBoxes::tableCell
  1.8851 +  },
  1.8852 +  { // Row
  1.8853 +    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
  1.8854 +                     FCDATA_USE_CHILD_ITEMS |
  1.8855 +                     FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
  1.8856 +                     &nsCSSFrameConstructor::ConstructTableRowOrRowGroup),
  1.8857 +    &nsCSSAnonBoxes::tableRow
  1.8858 +  },
  1.8859 +  { // Row group
  1.8860 +    FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
  1.8861 +                     FCDATA_USE_CHILD_ITEMS |
  1.8862 +                     FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.8863 +                     &nsCSSFrameConstructor::ConstructTableRowOrRowGroup),
  1.8864 +    &nsCSSAnonBoxes::tableRowGroup
  1.8865 +  },
  1.8866 +  { // Column group
  1.8867 +    FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
  1.8868 +                FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
  1.8869 +                FCDATA_SKIP_ABSPOS_PUSH |
  1.8870 +                FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
  1.8871 +                NS_NewTableColGroupFrame),
  1.8872 +    &nsCSSAnonBoxes::tableColGroup
  1.8873 +  },
  1.8874 +  { // Table
  1.8875 +    FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
  1.8876 +                     &nsCSSFrameConstructor::ConstructTable),
  1.8877 +    &nsCSSAnonBoxes::table
  1.8878 +  }
  1.8879 +};
  1.8880 +
  1.8881 +void
  1.8882 +nsCSSFrameConstructor::CreateNeededAnonFlexItems(
  1.8883 +  nsFrameConstructorState& aState,
  1.8884 +  FrameConstructionItemList& aItems,
  1.8885 +  nsIFrame* aParentFrame)
  1.8886 +{
  1.8887 +  if (aItems.IsEmpty() ||
  1.8888 +      aParentFrame->GetType() != nsGkAtoms::flexContainerFrame) {
  1.8889 +    return;
  1.8890 +  }
  1.8891 +
  1.8892 +  FCItemIterator iter(aItems);
  1.8893 +  do {
  1.8894 +    // Advance iter past children that don't want to be wrapped
  1.8895 +    if (iter.SkipItemsThatDontNeedAnonFlexItem(aState)) {
  1.8896 +      // Hit the end of the items without finding any remaining children that
  1.8897 +      // need to be wrapped. We're finished!
  1.8898 +      return;
  1.8899 +    }
  1.8900 +
  1.8901 +    // If our next potentially-wrappable child is whitespace, then see if
  1.8902 +    // there's anything wrappable immediately after it. If not, we just drop
  1.8903 +    // the whitespace and move on. (We're not supposed to create any anonymous
  1.8904 +    // flex items that _only_ contain whitespace).
  1.8905 +    // (BUT if this is generated content, then we don't give whitespace nodes
  1.8906 +    // any special treatment, because they're probably not really whitespace --
  1.8907 +    // they're just temporarily empty, waiting for their generated text.)
  1.8908 +    // XXXdholbert If this node's generated text will *actually end up being
  1.8909 +    // entirely whitespace*, then we technically should still skip over it, per
  1.8910 +    // the flexbox spec. I'm not bothering with that at this point, since it's
  1.8911 +    // a pretty extreme edge case.
  1.8912 +    if (!aParentFrame->IsGeneratedContentFrame() &&
  1.8913 +        iter.item().IsWhitespace(aState)) {
  1.8914 +      FCItemIterator afterWhitespaceIter(iter);
  1.8915 +      bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
  1.8916 +      bool nextChildNeedsAnonFlexItem =
  1.8917 +        !hitEnd && afterWhitespaceIter.item().NeedsAnonFlexItem(aState);
  1.8918 +
  1.8919 +      if (!nextChildNeedsAnonFlexItem) {
  1.8920 +        // There's nothing after the whitespace that we need to wrap, so we
  1.8921 +        // just drop this run of whitespace.
  1.8922 +        iter.DeleteItemsTo(afterWhitespaceIter);
  1.8923 +        if (hitEnd) {
  1.8924 +          // Nothing left to do -- we're finished!
  1.8925 +          return;
  1.8926 +        }
  1.8927 +        // else, we have a next child and it does not want to be wrapped.  So,
  1.8928 +        // we jump back to the beginning of the loop to skip over that child
  1.8929 +        // (and anything else non-wrappable after it)
  1.8930 +        NS_ABORT_IF_FALSE(!iter.IsDone() &&
  1.8931 +                          !iter.item().NeedsAnonFlexItem(aState),
  1.8932 +                          "hitEnd and/or nextChildNeedsAnonFlexItem lied");
  1.8933 +        continue;
  1.8934 +      }
  1.8935 +    }
  1.8936 +
  1.8937 +    // Now |iter| points to the first child that needs to be wrapped in an
  1.8938 +    // anonymous flex item. Now we see how many children after it also want
  1.8939 +    // to be wrapped in an anonymous flex item.
  1.8940 +    FCItemIterator endIter(iter); // iterator to find the end of the group
  1.8941 +    endIter.SkipItemsThatNeedAnonFlexItem(aState);
  1.8942 +
  1.8943 +    NS_ASSERTION(iter != endIter,
  1.8944 +                 "Should've had at least one wrappable child to seek past");
  1.8945 +
  1.8946 +    // Now, we create the anonymous flex item to contain the children
  1.8947 +    // between |iter| and |endIter|.
  1.8948 +    nsIAtom* pseudoType = nsCSSAnonBoxes::anonymousFlexItem;
  1.8949 +    nsStyleContext* parentStyle = aParentFrame->StyleContext();
  1.8950 +    nsIContent* parentContent = aParentFrame->GetContent();
  1.8951 +    already_AddRefed<nsStyleContext> wrapperStyle =
  1.8952 +      mPresShell->StyleSet()->ResolveAnonymousBoxStyle(pseudoType, parentStyle);
  1.8953 +
  1.8954 +    static const FrameConstructionData sBlockFormattingContextFCData =
  1.8955 +      FCDATA_DECL(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
  1.8956 +                  NS_NewBlockFormattingContext);
  1.8957 +
  1.8958 +    FrameConstructionItem* newItem =
  1.8959 +      new FrameConstructionItem(&sBlockFormattingContextFCData,
  1.8960 +                                // Use the content of our parent frame
  1.8961 +                                parentContent,
  1.8962 +                                // Lie about the tag; it doesn't matter anyway
  1.8963 +                                pseudoType,
  1.8964 +                                iter.item().mNameSpaceID,
  1.8965 +                                // no pending binding
  1.8966 +                                nullptr,
  1.8967 +                                wrapperStyle,
  1.8968 +                                true, nullptr);
  1.8969 +
  1.8970 +    newItem->mIsAllInline = newItem->mHasInlineEnds =
  1.8971 +      newItem->mStyleContext->StyleDisplay()->IsInlineOutsideStyle();
  1.8972 +    newItem->mIsBlock = !newItem->mIsAllInline;
  1.8973 +
  1.8974 +    NS_ABORT_IF_FALSE(!newItem->mIsAllInline && newItem->mIsBlock,
  1.8975 +                      "expecting anonymous flex items to be block-level "
  1.8976 +                      "(this will make a difference when we encounter "
  1.8977 +                      "'flex-align: baseline')");
  1.8978 +
  1.8979 +    // Anonymous flex items induce line boundaries around their
  1.8980 +    // contents.
  1.8981 +    newItem->mChildItems.SetLineBoundaryAtStart(true);
  1.8982 +    newItem->mChildItems.SetLineBoundaryAtEnd(true);
  1.8983 +    // The parent of the items in aItems is also the parent of the items
  1.8984 +    // in mChildItems
  1.8985 +    newItem->mChildItems.SetParentHasNoXBLChildren(
  1.8986 +      aItems.ParentHasNoXBLChildren());
  1.8987 +
  1.8988 +    // Eat up all items between |iter| and |endIter| and put them in our
  1.8989 +    // wrapper. This advances |iter| to point to |endIter|.
  1.8990 +    iter.AppendItemsToList(endIter, newItem->mChildItems);
  1.8991 +
  1.8992 +    iter.InsertItem(newItem);
  1.8993 +  } while (!iter.IsDone());
  1.8994 +}
  1.8995 +
  1.8996 +/*
  1.8997 + * This function works as follows: we walk through the child list (aItems) and
  1.8998 + * find items that cannot have aParentFrame as their parent.  We wrap
  1.8999 + * continuous runs of such items into a FrameConstructionItem for a frame that
  1.9000 + * gets them closer to their desired parents.  For example, a run of non-row
  1.9001 + * children of a row-group will get wrapped in a row.  When we later construct
  1.9002 + * the frame for this wrapper (in this case for the row), it'll be the correct
  1.9003 + * parent for the cells in the set of items we wrapped or we'll wrap cells
  1.9004 + * around everything else.  At the end of this method, aItems is guaranteed to
  1.9005 + * contain only items for frames that can be direct kids of aParentFrame.
  1.9006 + */
  1.9007 +void
  1.9008 +nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
  1.9009 +                                                FrameConstructionItemList& aItems,
  1.9010 +                                                nsIFrame* aParentFrame)
  1.9011 +{
  1.9012 +  ParentType ourParentType = GetParentType(aParentFrame);
  1.9013 +  if (aItems.AllWantParentType(ourParentType)) {
  1.9014 +    // Nothing to do here
  1.9015 +    return;
  1.9016 +  }
  1.9017 +
  1.9018 +  FCItemIterator iter(aItems);
  1.9019 +  do {
  1.9020 +    if (iter.SkipItemsWantingParentType(ourParentType)) {
  1.9021 +      // Nothing else to do here; we're finished
  1.9022 +      return;
  1.9023 +    }
  1.9024 +
  1.9025 +    // Now we're pointing to the first child that wants a different parent
  1.9026 +    // type.
  1.9027 +
  1.9028 +    // Now try to figure out what kids we can group together.  We can generally
  1.9029 +    // group everything that has a different desired parent type from us.  Two
  1.9030 +    // exceptions to this:
  1.9031 +    // 1) If our parent type is table, we can't group columns with anything
  1.9032 +    //    else other than whitespace.
  1.9033 +    // 2) Whitespace that lies between two things we can group which both want
  1.9034 +    //    a non-block parent should be dropped, even if we can't group them
  1.9035 +    //    with each other and even if the whitespace wants a parent of
  1.9036 +    //    ourParentType.  Ends of the list count as things that don't want a
  1.9037 +    //    block parent (so that for example we'll drop a whitespace-only list).
  1.9038 +
  1.9039 +    FCItemIterator endIter(iter); /* iterator to find the end of the group */
  1.9040 +    ParentType groupingParentType = endIter.item().DesiredParentType();
  1.9041 +    if (aItems.AllWantParentType(groupingParentType) &&
  1.9042 +        groupingParentType != eTypeBlock) {
  1.9043 +      // Just group them all and be done with it.  We need the check for
  1.9044 +      // eTypeBlock here to catch the "all the items are whitespace" case
  1.9045 +      // described above.
  1.9046 +      endIter.SetToEnd();
  1.9047 +    } else {
  1.9048 +      // Locate the end of the group.
  1.9049 +
  1.9050 +      // Keep track of the type the previous item wanted, in case we have to
  1.9051 +      // deal with whitespace.  Start it off with ourParentType, since that's
  1.9052 +      // the last thing |iter| would have skipped over.
  1.9053 +      ParentType prevParentType = ourParentType;
  1.9054 +      do {
  1.9055 +        /* Walk an iterator past any whitespace that we might be able to drop from the list */
  1.9056 +        FCItemIterator spaceEndIter(endIter);
  1.9057 +        if (prevParentType != eTypeBlock &&
  1.9058 +            !aParentFrame->IsGeneratedContentFrame() &&
  1.9059 +            spaceEndIter.item().IsWhitespace(aState)) {
  1.9060 +          bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
  1.9061 +
  1.9062 +          // We drop the whitespace if these are not trailing spaces and the next item
  1.9063 +          // does not want a block parent (see case 2 above)
  1.9064 +          // if these are trailing spaces and aParentFrame is a tabular container
  1.9065 +          // according to rule 1.3 of CSS 2.1 Sec 17.2.1. (Being a tabular container
  1.9066 +          // pretty much means ourParentType != eTypeBlock besides the eTypeColGroup case,
  1.9067 +          // which won't reach here.)
  1.9068 +          if ((trailingSpaces && ourParentType != eTypeBlock) ||
  1.9069 +              (!trailingSpaces && spaceEndIter.item().DesiredParentType() !=
  1.9070 +               eTypeBlock)) {
  1.9071 +            bool updateStart = (iter == endIter);
  1.9072 +            endIter.DeleteItemsTo(spaceEndIter);
  1.9073 +            NS_ASSERTION(trailingSpaces == endIter.IsDone(), "These should match");
  1.9074 +
  1.9075 +            if (updateStart) {
  1.9076 +              iter = endIter;
  1.9077 +            }
  1.9078 +
  1.9079 +            if (trailingSpaces) {
  1.9080 +              break; /* Found group end */
  1.9081 +            }
  1.9082 +
  1.9083 +            if (updateStart) {
  1.9084 +              // Update groupingParentType, since it might have been eTypeBlock
  1.9085 +              // just because of the whitespace.
  1.9086 +              groupingParentType = iter.item().DesiredParentType();
  1.9087 +            }
  1.9088 +          }
  1.9089 +        }
  1.9090 +
  1.9091 +        // Now endIter points to a non-whitespace item or a non-droppable
  1.9092 +        // whitespace item. In the latter case, if this is the end of the group
  1.9093 +        // we'll traverse this whitespace again.  But it'll all just be quick
  1.9094 +        // DesiredParentType() checks which will match ourParentType (that's
  1.9095 +        // what it means that this is the group end), so it's OK.
  1.9096 +        prevParentType = endIter.item().DesiredParentType();
  1.9097 +        if (prevParentType == ourParentType) {
  1.9098 +          // End the group at endIter.
  1.9099 +          break;
  1.9100 +        }
  1.9101 +
  1.9102 +        if (ourParentType == eTypeTable &&
  1.9103 +            (prevParentType == eTypeColGroup) !=
  1.9104 +            (groupingParentType == eTypeColGroup)) {
  1.9105 +          // Either we started with columns and now found something else, or vice
  1.9106 +          // versa.  In any case, end the grouping.
  1.9107 +          break;
  1.9108 +        }
  1.9109 +
  1.9110 +        // Include the whitespace we didn't drop (if any) in the group, since
  1.9111 +        // this is not the end of the group.  Note that this doesn't change
  1.9112 +        // prevParentType, since if we didn't drop the whitespace then we ended
  1.9113 +        // at something that wants a block parent.
  1.9114 +        endIter = spaceEndIter;
  1.9115 +
  1.9116 +        endIter.Next();
  1.9117 +      } while (!endIter.IsDone());
  1.9118 +    }
  1.9119 +
  1.9120 +    if (iter == endIter) {
  1.9121 +      // Nothing to wrap here; just skipped some whitespace
  1.9122 +      continue;
  1.9123 +    }
  1.9124 +
  1.9125 +    // Now group together all the items between iter and endIter.  The right
  1.9126 +    // parent type to use depends on ourParentType.
  1.9127 +    ParentType wrapperType;
  1.9128 +    switch (ourParentType) {
  1.9129 +      case eTypeBlock:
  1.9130 +        wrapperType = eTypeTable;
  1.9131 +        break;
  1.9132 +      case eTypeRow:
  1.9133 +        // The parent type for a cell is eTypeBlock, since that's what a cell
  1.9134 +        // looks like to its kids.
  1.9135 +        wrapperType = eTypeBlock;
  1.9136 +        break;
  1.9137 +      case eTypeRowGroup:
  1.9138 +        wrapperType = eTypeRow;
  1.9139 +        break;
  1.9140 +      case eTypeTable:
  1.9141 +        // Either colgroup or rowgroup, depending on what we're grouping.
  1.9142 +        wrapperType = groupingParentType == eTypeColGroup ?
  1.9143 +          eTypeColGroup : eTypeRowGroup;
  1.9144 +        break;
  1.9145 +      default:
  1.9146 +        MOZ_CRASH("Colgroups should be suppresing non-col child items");
  1.9147 +    }
  1.9148 +
  1.9149 +    const PseudoParentData& pseudoData = sPseudoParentData[wrapperType];
  1.9150 +    nsIAtom* pseudoType = *pseudoData.mPseudoType;
  1.9151 +    nsStyleContext* parentStyle = aParentFrame->StyleContext();
  1.9152 +    nsIContent* parentContent = aParentFrame->GetContent();
  1.9153 +
  1.9154 +    if (pseudoType == nsCSSAnonBoxes::table &&
  1.9155 +        parentStyle->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE) {
  1.9156 +      pseudoType = nsCSSAnonBoxes::inlineTable;
  1.9157 +    }
  1.9158 +
  1.9159 +    already_AddRefed<nsStyleContext> wrapperStyle =
  1.9160 +      mPresShell->StyleSet()->ResolveAnonymousBoxStyle(pseudoType, parentStyle);
  1.9161 +    FrameConstructionItem* newItem =
  1.9162 +      new FrameConstructionItem(&pseudoData.mFCData,
  1.9163 +                                // Use the content of our parent frame
  1.9164 +                                parentContent,
  1.9165 +                                // Lie about the tag; it doesn't matter anyway
  1.9166 +                                pseudoType,
  1.9167 +                                // The namespace does matter, however; it needs
  1.9168 +                                // to match that of our first child item to
  1.9169 +                                // match the old behavior
  1.9170 +                                iter.item().mNameSpaceID,
  1.9171 +                                // no pending binding
  1.9172 +                                nullptr,
  1.9173 +                                wrapperStyle,
  1.9174 +                                true, nullptr);
  1.9175 +
  1.9176 +    // Here we're cheating a tad... technically, table-internal items should be
  1.9177 +    // inline if aParentFrame is inline, but they'll get wrapped in an
  1.9178 +    // inline-table in the end, so it'll all work out.  In any case, arguably
  1.9179 +    // we don't need to maintain this state at this point... but it's better
  1.9180 +    // to, I guess.
  1.9181 +    newItem->mIsAllInline = newItem->mHasInlineEnds =
  1.9182 +      newItem->mStyleContext->StyleDisplay()->IsInlineOutsideStyle();
  1.9183 +
  1.9184 +    // Table pseudo frames always induce line boundaries around their
  1.9185 +    // contents.
  1.9186 +    newItem->mChildItems.SetLineBoundaryAtStart(true);
  1.9187 +    newItem->mChildItems.SetLineBoundaryAtEnd(true);
  1.9188 +    // The parent of the items in aItems is also the parent of the items
  1.9189 +    // in mChildItems
  1.9190 +    newItem->mChildItems.SetParentHasNoXBLChildren(
  1.9191 +      aItems.ParentHasNoXBLChildren());
  1.9192 +
  1.9193 +    // Eat up all items between |iter| and |endIter| and put them in our wrapper
  1.9194 +    // Advances |iter| to point to |endIter|.
  1.9195 +    iter.AppendItemsToList(endIter, newItem->mChildItems);
  1.9196 +
  1.9197 +    iter.InsertItem(newItem);
  1.9198 +
  1.9199 +    // Now |iter| points to the item that was the first one we didn't wrap;
  1.9200 +    // loop and see whether we need to skip it or wrap it in something
  1.9201 +    // different.
  1.9202 +  } while (!iter.IsDone());
  1.9203 +}
  1.9204 +
  1.9205 +inline void
  1.9206 +nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState,
  1.9207 +                                                   FrameConstructionItemList& aItems,
  1.9208 +                                                   nsIFrame* aParentFrame,
  1.9209 +                                                   nsFrameItems& aFrameItems)
  1.9210 +{
  1.9211 +  CreateNeededTablePseudos(aState, aItems, aParentFrame);
  1.9212 +  CreateNeededAnonFlexItems(aState, aItems, aParentFrame);
  1.9213 +
  1.9214 +  aItems.SetTriedConstructingFrames();
  1.9215 +  for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
  1.9216 +    NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
  1.9217 +                 "Needed pseudos didn't get created; expect bad things");
  1.9218 +    ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
  1.9219 +  }
  1.9220 +
  1.9221 +  NS_ASSERTION(!aState.mHavePendingPopupgroup,
  1.9222 +               "Should have proccessed it by now");
  1.9223 +}
  1.9224 +
  1.9225 +void
  1.9226 +nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
  1.9227 +            nsFrameConstructorState& aState,
  1.9228 +            nsIFrame* aFrame,
  1.9229 +            nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
  1.9230 +            FrameConstructionItemList& aItemsToConstruct,
  1.9231 +            uint32_t aExtraFlags)
  1.9232 +{
  1.9233 +  for (uint32_t i = 0; i < aAnonymousItems.Length(); ++i) {
  1.9234 +    nsIContent* content = aAnonymousItems[i].mContent;
  1.9235 +#ifdef DEBUG
  1.9236 +    nsIAnonymousContentCreator* creator = do_QueryFrame(aFrame);
  1.9237 +    NS_ASSERTION(!creator || !creator->CreateFrameFor(content),
  1.9238 +                 "If you need to use CreateFrameFor, you need to call "
  1.9239 +                 "CreateAnonymousFrames manually and not follow the standard "
  1.9240 +                 "ProcessChildren() codepath for this frame");
  1.9241 +#endif
  1.9242 +    // Assert some things about this content
  1.9243 +    NS_ABORT_IF_FALSE(!(content->GetFlags() &
  1.9244 +                        (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME)),
  1.9245 +                      "Should not be marked as needing frames");
  1.9246 +    NS_ABORT_IF_FALSE(!content->IsElement() ||
  1.9247 +                      !(content->GetFlags() & ELEMENT_ALL_RESTYLE_FLAGS),
  1.9248 +                      "Should have no pending restyle flags");
  1.9249 +    NS_ABORT_IF_FALSE(!content->GetPrimaryFrame(),
  1.9250 +                      "Should have no existing frame");
  1.9251 +    NS_ABORT_IF_FALSE(!content->IsNodeOfType(nsINode::eCOMMENT) &&
  1.9252 +                      !content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION),
  1.9253 +                      "Why is someone creating garbage anonymous content");
  1.9254 +
  1.9255 +    nsRefPtr<nsStyleContext> styleContext;
  1.9256 +    TreeMatchContext::AutoFlexItemStyleFixupSkipper
  1.9257 +      flexItemStyleFixupSkipper(aState.mTreeMatchContext);
  1.9258 +    if (aAnonymousItems[i].mStyleContext) {
  1.9259 +      styleContext = aAnonymousItems[i].mStyleContext.forget();
  1.9260 +    } else {
  1.9261 +      styleContext = ResolveStyleContext(aFrame, content, &aState);
  1.9262 +    }
  1.9263 +
  1.9264 +    nsTArray<nsIAnonymousContentCreator::ContentInfo>* anonChildren = nullptr;
  1.9265 +    if (!aAnonymousItems[i].mChildren.IsEmpty()) {
  1.9266 +      anonChildren = &aAnonymousItems[i].mChildren;
  1.9267 +    }
  1.9268 +
  1.9269 +    uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK |
  1.9270 +                     ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT | aExtraFlags;
  1.9271 +
  1.9272 +    AddFrameConstructionItemsInternal(aState, content, aFrame,
  1.9273 +                                      content->Tag(), content->GetNameSpaceID(),
  1.9274 +                                      true, styleContext, flags,
  1.9275 +                                      anonChildren, aItemsToConstruct);
  1.9276 +  }
  1.9277 +}
  1.9278 +
  1.9279 +void
  1.9280 +nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
  1.9281 +                                       nsIContent*              aContent,
  1.9282 +                                       nsStyleContext*          aStyleContext,
  1.9283 +                                       nsIFrame*                aFrame,
  1.9284 +                                       const bool               aCanHaveGeneratedContent,
  1.9285 +                                       nsFrameItems&            aFrameItems,
  1.9286 +                                       const bool               aAllowBlockStyles,
  1.9287 +                                       PendingBinding*          aPendingBinding,
  1.9288 +                                       nsIFrame*                aPossiblyLeafFrame)
  1.9289 +{
  1.9290 +  NS_PRECONDITION(aFrame, "Must have parent frame here");
  1.9291 +  NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
  1.9292 +                  "Parent frame in ProcessChildren should be its own "
  1.9293 +                  "content insertion frame");
  1.9294 +  const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH;
  1.9295 +  static_assert(kMaxDepth <= UINT16_MAX, "mCurrentDepth type is too narrow");
  1.9296 +  AutoRestore<uint16_t> savedDepth(mCurrentDepth);
  1.9297 +  if (mCurrentDepth != UINT16_MAX) {
  1.9298 +    ++mCurrentDepth;
  1.9299 +  }
  1.9300 +
  1.9301 +  if (!aPossiblyLeafFrame) {
  1.9302 +    aPossiblyLeafFrame = aFrame;
  1.9303 +  }
  1.9304 +
  1.9305 +  // XXXbz ideally, this would do all the pushing of various
  1.9306 +  // containing blocks as needed, so callers don't have to do it...
  1.9307 +
  1.9308 +  bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
  1.9309 +  if (aAllowBlockStyles) {
  1.9310 +    ShouldHaveSpecialBlockStyle(aContent, aStyleContext, &haveFirstLetterStyle,
  1.9311 +                                &haveFirstLineStyle);
  1.9312 +  }
  1.9313 +
  1.9314 +  // The logic here needs to match the logic in GetFloatContainingBlock()
  1.9315 +  nsFrameConstructorSaveState floatSaveState;
  1.9316 +  if (ShouldSuppressFloatingOfDescendants(aFrame)) {
  1.9317 +    aState.PushFloatContainingBlock(nullptr, floatSaveState);
  1.9318 +  } else if (aFrame->IsFloatContainingBlock()) {
  1.9319 +    aState.PushFloatContainingBlock(aFrame, floatSaveState);
  1.9320 +  }
  1.9321 +
  1.9322 +  nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
  1.9323 +                                                           aPendingBinding);
  1.9324 +
  1.9325 +  FrameConstructionItemList itemsToConstruct;
  1.9326 +
  1.9327 +  // If we have first-letter or first-line style then frames can get
  1.9328 +  // moved around so don't set these flags.
  1.9329 +  if (aAllowBlockStyles && !haveFirstLetterStyle && !haveFirstLineStyle) {
  1.9330 +    itemsToConstruct.SetLineBoundaryAtStart(true);
  1.9331 +    itemsToConstruct.SetLineBoundaryAtEnd(true);
  1.9332 +  }
  1.9333 +
  1.9334 +  // Create any anonymous frames we need here.  This must happen before the
  1.9335 +  // non-anonymous children are processed to ensure that popups are never
  1.9336 +  // constructed before the popupset.
  1.9337 +  nsAutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
  1.9338 +  GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
  1.9339 +#ifdef DEBUG
  1.9340 +  for (uint32_t i = 0; i < anonymousItems.Length(); ++i) {
  1.9341 +    NS_ABORT_IF_FALSE(anonymousItems[i].mContent->IsRootOfAnonymousSubtree(),
  1.9342 +                      "Content should know it's an anonymous subtree");
  1.9343 +  }
  1.9344 +#endif
  1.9345 +  AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
  1.9346 +                                itemsToConstruct);
  1.9347 +
  1.9348 +  if (!aPossiblyLeafFrame->IsLeaf()) {
  1.9349 +    // :before/:after content should have the same style context parent
  1.9350 +    // as normal kids.
  1.9351 +    // Note that we don't use this style context for looking up things like
  1.9352 +    // special block styles because in some cases involving table pseudo-frames
  1.9353 +    // it has nothing to do with the parent frame's desired behavior.
  1.9354 +    nsStyleContext* styleContext;
  1.9355 +
  1.9356 +    if (aCanHaveGeneratedContent) {
  1.9357 +      aFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
  1.9358 +      styleContext =
  1.9359 +        nsFrame::CorrectStyleParentFrame(aFrame, nullptr)->StyleContext();
  1.9360 +      // Probe for generated content before
  1.9361 +      CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
  1.9362 +                                 nsCSSPseudoElements::ePseudo_before,
  1.9363 +                                 itemsToConstruct);
  1.9364 +    }
  1.9365 +
  1.9366 +    const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth);
  1.9367 +    if (!addChildItems) {
  1.9368 +      NS_WARNING("ProcessChildren max depth exceeded");
  1.9369 +    }
  1.9370 +
  1.9371 +    FlattenedChildIterator iter(aContent);
  1.9372 +    for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
  1.9373 +      // Get the parent of the content and check if it is a XBL children element
  1.9374 +      // (if the content is a children element then parent != aContent because the
  1.9375 +      // FlattenedChildIterator will transitively iterate through <xbl:children>
  1.9376 +      // for default content). Push the children element as an ancestor here because
  1.9377 +      // it does not have a frame and would not otherwise be pushed as an ancestor.
  1.9378 +      nsIContent* parent = child->GetParent();
  1.9379 +      MOZ_ASSERT(parent, "Parent must be non-null because we are iterating children.");
  1.9380 +      TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
  1.9381 +      if (parent != aContent && parent->IsElement()) {
  1.9382 +        if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
  1.9383 +          ancestorPusher.PushAncestorAndStyleScope(parent->AsElement());
  1.9384 +        } else {
  1.9385 +          ancestorPusher.PushStyleScope(parent->AsElement());
  1.9386 +        }
  1.9387 +      }
  1.9388 +
  1.9389 +      // Frame construction item construction should not post
  1.9390 +      // restyles, so removing restyle flags here is safe.
  1.9391 +      if (child->IsElement()) {
  1.9392 +        child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
  1.9393 +      }
  1.9394 +      if (addChildItems) {
  1.9395 +        AddFrameConstructionItems(aState, child, iter.XBLInvolved(), aFrame,
  1.9396 +                                  itemsToConstruct);
  1.9397 +      } else {
  1.9398 +        ClearLazyBits(child, child->GetNextSibling());
  1.9399 +      }
  1.9400 +    }
  1.9401 +    itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
  1.9402 +
  1.9403 +    if (aCanHaveGeneratedContent) {
  1.9404 +      // Probe for generated content after
  1.9405 +      CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
  1.9406 +                                 nsCSSPseudoElements::ePseudo_after,
  1.9407 +                                 itemsToConstruct);
  1.9408 +    }
  1.9409 +  } else {
  1.9410 +    ClearLazyBits(aContent->GetFirstChild(), nullptr);
  1.9411 +  }
  1.9412 +
  1.9413 +  ConstructFramesFromItemList(aState, itemsToConstruct, aFrame, aFrameItems);
  1.9414 +
  1.9415 +  NS_ASSERTION(!aAllowBlockStyles || !aFrame->IsBoxFrame(),
  1.9416 +               "can't be both block and box");
  1.9417 +
  1.9418 +  if (haveFirstLetterStyle) {
  1.9419 +    WrapFramesInFirstLetterFrame(aContent, aFrame, aFrameItems);
  1.9420 +  }
  1.9421 +  if (haveFirstLineStyle) {
  1.9422 +    WrapFramesInFirstLineFrame(aState, aContent, aFrame, nullptr,
  1.9423 +                               aFrameItems);
  1.9424 +  }
  1.9425 +
  1.9426 +  // We might end up with first-line frames that change
  1.9427 +  // AnyKidsNeedBlockParent() without changing itemsToConstruct, but that
  1.9428 +  // should never happen for cases whan aFrame->IsBoxFrame().
  1.9429 +  NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsBoxFrame(),
  1.9430 +               "Shouldn't have first-line style if we're a box");
  1.9431 +  NS_ASSERTION(!aFrame->IsBoxFrame() ||
  1.9432 +               itemsToConstruct.AnyItemsNeedBlockParent() ==
  1.9433 +                 (AnyKidsNeedBlockParent(aFrameItems.FirstChild()) != nullptr),
  1.9434 +               "Something went awry in our block parent calculations");
  1.9435 +
  1.9436 +  if (aFrame->IsBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
  1.9437 +    // XXXbz we could do this on the FrameConstructionItemList level,
  1.9438 +    // no?  And if we cared we could look through the item list
  1.9439 +    // instead of groveling through the framelist here..
  1.9440 +    nsStyleContext *frameStyleContext = aFrame->StyleContext();
  1.9441 +    // Report a warning for non-GC frames, for chrome:
  1.9442 +    if (!aFrame->IsGeneratedContentFrame() &&
  1.9443 +        mPresShell->GetPresContext()->IsChrome()) {
  1.9444 +      nsIContent *badKid = AnyKidsNeedBlockParent(aFrameItems.FirstChild());
  1.9445 +      nsDependentAtomString parentTag(aContent->Tag()), kidTag(badKid->Tag());
  1.9446 +      const char16_t* params[] = { parentTag.get(), kidTag.get() };
  1.9447 +      const nsStyleDisplay *display = frameStyleContext->StyleDisplay();
  1.9448 +      const char *message =
  1.9449 +        (display->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX)
  1.9450 +          ? "NeededToWrapXULInlineBox" : "NeededToWrapXUL";
  1.9451 +      nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
  1.9452 +                                      NS_LITERAL_CSTRING("FrameConstructor"),
  1.9453 +                                      mDocument,
  1.9454 +                                      nsContentUtils::eXUL_PROPERTIES,
  1.9455 +                                      message,
  1.9456 +                                      params, ArrayLength(params));
  1.9457 +    }
  1.9458 +
  1.9459 +    nsRefPtr<nsStyleContext> blockSC = mPresShell->StyleSet()->
  1.9460 +      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozXULAnonymousBlock,
  1.9461 +                               frameStyleContext);
  1.9462 +    nsIFrame *blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
  1.9463 +    // We might, in theory, want to set NS_BLOCK_FLOAT_MGR and
  1.9464 +    // NS_BLOCK_MARGIN_ROOT, but I think it's a bad idea given that
  1.9465 +    // a real block placed here wouldn't get those set on it.
  1.9466 +
  1.9467 +    InitAndRestoreFrame(aState, aContent, aFrame, blockFrame, false);
  1.9468 +
  1.9469 +    NS_ASSERTION(!blockFrame->HasView(), "need to do view reparenting");
  1.9470 +    ReparentFrames(this, blockFrame, aFrameItems);
  1.9471 +
  1.9472 +    blockFrame->SetInitialChildList(kPrincipalList, aFrameItems);
  1.9473 +    NS_ASSERTION(aFrameItems.IsEmpty(), "How did that happen?");
  1.9474 +    aFrameItems.Clear();
  1.9475 +    aFrameItems.AddChild(blockFrame);
  1.9476 +
  1.9477 +    aFrame->AddStateBits(NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK);
  1.9478 +  }
  1.9479 +}
  1.9480 +
  1.9481 +//----------------------------------------------------------------------
  1.9482 +
  1.9483 +// Support for :first-line style
  1.9484 +
  1.9485 +// Special routine to handle placing a list of frames into a block
  1.9486 +// frame that has first-line style. The routine ensures that the first
  1.9487 +// collection of inline frames end up in a first-line frame.
  1.9488 +// NOTE: aState may have containing block information related to a
  1.9489 +// different part of the frame tree than where the first line occurs.
  1.9490 +// In particular aState may be set up for where ContentInserted or
  1.9491 +// ContentAppended is inserting content, which may be some
  1.9492 +// non-first-in-flow continuation of the block to which the first-line
  1.9493 +// belongs. So this function needs to be careful about how it uses
  1.9494 +// aState.
  1.9495 +void
  1.9496 +nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
  1.9497 +  nsFrameConstructorState& aState,
  1.9498 +  nsIContent*              aBlockContent,
  1.9499 +  nsIFrame*                aBlockFrame,
  1.9500 +  nsIFrame*                aLineFrame,
  1.9501 +  nsFrameItems&            aFrameItems)
  1.9502 +{
  1.9503 +  // Find the part of aFrameItems that we want to put in the first-line
  1.9504 +  nsFrameList::FrameLinkEnumerator link(aFrameItems);
  1.9505 +  while (!link.AtEnd() && link.NextFrame()->IsInlineOutside()) {
  1.9506 +    link.Next();
  1.9507 +  }
  1.9508 +
  1.9509 +  nsFrameList firstLineChildren = aFrameItems.ExtractHead(link);
  1.9510 +
  1.9511 +  if (firstLineChildren.IsEmpty()) {
  1.9512 +    // Nothing is supposed to go into the first-line; nothing to do
  1.9513 +    return;
  1.9514 +  }
  1.9515 +
  1.9516 +  if (!aLineFrame) {
  1.9517 +    // Create line frame
  1.9518 +    nsStyleContext* parentStyle =
  1.9519 +      nsFrame::CorrectStyleParentFrame(aBlockFrame,
  1.9520 +                                       nsCSSPseudoElements::firstLine)->
  1.9521 +        StyleContext();
  1.9522 +    nsRefPtr<nsStyleContext> firstLineStyle = GetFirstLineStyle(aBlockContent,
  1.9523 +                                                                parentStyle);
  1.9524 +
  1.9525 +    aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
  1.9526 +
  1.9527 +    // Initialize the line frame
  1.9528 +    InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, aLineFrame);
  1.9529 +
  1.9530 +    // The lineFrame will be the block's first child; the rest of the
  1.9531 +    // frame list (after lastInlineFrame) will be the second and
  1.9532 +    // subsequent children; insert lineFrame into aFrameItems.
  1.9533 +    aFrameItems.InsertFrame(nullptr, nullptr, aLineFrame);
  1.9534 +
  1.9535 +    NS_ASSERTION(aLineFrame->StyleContext() == firstLineStyle,
  1.9536 +                 "Bogus style context on line frame");
  1.9537 +  }
  1.9538 +
  1.9539 +  // Give the inline frames to the lineFrame <b>after</b> reparenting them
  1.9540 +  ReparentFrames(this, aLineFrame, firstLineChildren);
  1.9541 +  if (aLineFrame->PrincipalChildList().IsEmpty() &&
  1.9542 +      (aLineFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
  1.9543 +    aLineFrame->SetInitialChildList(kPrincipalList, firstLineChildren);
  1.9544 +  } else {
  1.9545 +    AppendFrames(aLineFrame, kPrincipalList, firstLineChildren);
  1.9546 +  }
  1.9547 +}
  1.9548 +
  1.9549 +// Special routine to handle appending a new frame to a block frame's
  1.9550 +// child list. Takes care of placing the new frame into the right
  1.9551 +// place when first-line style is present.
  1.9552 +void
  1.9553 +nsCSSFrameConstructor::AppendFirstLineFrames(
  1.9554 +  nsFrameConstructorState& aState,
  1.9555 +  nsIContent*              aBlockContent,
  1.9556 +  nsIFrame*                aBlockFrame,
  1.9557 +  nsFrameItems&            aFrameItems)
  1.9558 +{
  1.9559 +  // It's possible that aBlockFrame needs to have a first-line frame
  1.9560 +  // created because it doesn't currently have any children.
  1.9561 +  const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
  1.9562 +  if (blockKids.IsEmpty()) {
  1.9563 +    WrapFramesInFirstLineFrame(aState, aBlockContent,
  1.9564 +                               aBlockFrame, nullptr, aFrameItems);
  1.9565 +    return;
  1.9566 +  }
  1.9567 +
  1.9568 +  // Examine the last block child - if it's a first-line frame then
  1.9569 +  // appended frames need special treatment.
  1.9570 +  nsIFrame* lastBlockKid = blockKids.LastChild();
  1.9571 +  if (lastBlockKid->GetType() != nsGkAtoms::lineFrame) {
  1.9572 +    // No first-line frame at the end of the list, therefore there is
  1.9573 +    // an intervening block between any first-line frame the frames
  1.9574 +    // we are appending. Therefore, we don't need any special
  1.9575 +    // treatment of the appended frames.
  1.9576 +    return;
  1.9577 +  }
  1.9578 +
  1.9579 +  WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame,
  1.9580 +                             lastBlockKid, aFrameItems);
  1.9581 +}
  1.9582 +
  1.9583 +// Special routine to handle inserting a new frame into a block
  1.9584 +// frame's child list. Takes care of placing the new frame into the
  1.9585 +// right place when first-line style is present.
  1.9586 +nsresult
  1.9587 +nsCSSFrameConstructor::InsertFirstLineFrames(
  1.9588 +  nsFrameConstructorState& aState,
  1.9589 +  nsIContent*              aContent,
  1.9590 +  nsIFrame*                aBlockFrame,
  1.9591 +  nsIFrame**               aParentFrame,
  1.9592 +  nsIFrame*                aPrevSibling,
  1.9593 +  nsFrameItems&            aFrameItems)
  1.9594 +{
  1.9595 +  nsresult rv = NS_OK;
  1.9596 +  // XXXbz If you make this method actually do something, check to
  1.9597 +  // make sure that the caller is passing what you expect.  In
  1.9598 +  // particular, which content is aContent?  And audit the rest of
  1.9599 +  // this code too; it makes bogus assumptions and may not build.
  1.9600 +#if 0
  1.9601 +  nsIFrame* parentFrame = *aParentFrame;
  1.9602 +  nsIFrame* newFrame = aFrameItems.childList;
  1.9603 +  bool isInline = IsInlineOutside(newFrame);
  1.9604 +
  1.9605 +  if (!aPrevSibling) {
  1.9606 +    // Insertion will become the first frame. Two cases: we either
  1.9607 +    // already have a first-line frame or we don't.
  1.9608 +    nsIFrame* firstBlockKid = aBlockFrame->GetFirstPrincipalChild();
  1.9609 +    if (firstBlockKid->GetType() == nsGkAtoms::lineFrame) {
  1.9610 +      // We already have a first-line frame
  1.9611 +      nsIFrame* lineFrame = firstBlockKid;
  1.9612 +
  1.9613 +      if (isInline) {
  1.9614 +        // Easy case: the new inline frame will go into the lineFrame.
  1.9615 +        ReparentFrame(this, lineFrame, newFrame);
  1.9616 +        InsertFrames(lineFrame, kPrincipalList, nullptr, newFrame);
  1.9617 +
  1.9618 +        // Since the frame is going into the lineFrame, don't let it
  1.9619 +        // go into the block too.
  1.9620 +        aFrameItems.childList = nullptr;
  1.9621 +        aFrameItems.lastChild = nullptr;
  1.9622 +      }
  1.9623 +      else {
  1.9624 +        // Harder case: We are about to insert a block level element
  1.9625 +        // before the first-line frame.
  1.9626 +        // XXX need a method to steal away frames from the line-frame
  1.9627 +      }
  1.9628 +    }
  1.9629 +    else {
  1.9630 +      // We do not have a first-line frame
  1.9631 +      if (isInline) {
  1.9632 +        // We now need a first-line frame to contain the inline frame.
  1.9633 +        nsIFrame* lineFrame = NS_NewFirstLineFrame(firstLineStyle);
  1.9634 +
  1.9635 +        if (NS_SUCCEEDED(rv)) {
  1.9636 +          // Lookup first-line style context
  1.9637 +          nsStyleContext* parentStyle =
  1.9638 +            nsFrame::CorrectStyleParentFrame(aBlockFrame,
  1.9639 +                                             nsCSSPseudoElements::firstLine)->
  1.9640 +              StyleContext();
  1.9641 +          nsRefPtr<nsStyleContext> firstLineStyle =
  1.9642 +            GetFirstLineStyle(aContent, parentStyle);
  1.9643 +
  1.9644 +          // Initialize the line frame
  1.9645 +          InitAndRestoreFrame(aState, aContent, aBlockFrame, lineFrame);
  1.9646 +
  1.9647 +          // Make sure the caller inserts the lineFrame into the
  1.9648 +          // blocks list of children.
  1.9649 +          aFrameItems.childList = lineFrame;
  1.9650 +          aFrameItems.lastChild = lineFrame;
  1.9651 +
  1.9652 +          // Give the inline frames to the lineFrame <b>after</b>
  1.9653 +          // reparenting them
  1.9654 +          NS_ASSERTION(lineFrame->StyleContext() == firstLineStyle,
  1.9655 +                       "Bogus style context on line frame");
  1.9656 +          ReparentFrame(aPresContext, lineFrame, newFrame);
  1.9657 +          lineFrame->SetInitialChildList(kPrincipalList, newFrame);
  1.9658 +        }
  1.9659 +      }
  1.9660 +      else {
  1.9661 +        // Easy case: the regular insertion logic can insert the new
  1.9662 +        // frame because it's a block frame.
  1.9663 +      }
  1.9664 +    }
  1.9665 +  }
  1.9666 +  else {
  1.9667 +    // Insertion will not be the first frame.
  1.9668 +    nsIFrame* prevSiblingParent = aPrevSibling->GetParent();
  1.9669 +    if (prevSiblingParent == aBlockFrame) {
  1.9670 +      // Easy case: The prev-siblings parent is the block
  1.9671 +      // frame. Therefore the prev-sibling is not currently in a
  1.9672 +      // line-frame. Therefore the new frame which is going after it,
  1.9673 +      // regardless of type, is not going into a line-frame.
  1.9674 +    }
  1.9675 +    else {
  1.9676 +      // If the prevSiblingParent is not the block-frame then it must
  1.9677 +      // be a line-frame (if it were a letter-frame, that logic would
  1.9678 +      // already have adjusted the prev-sibling to be the
  1.9679 +      // letter-frame).
  1.9680 +      if (isInline) {
  1.9681 +        // Easy case: the insertion can go where the caller thinks it
  1.9682 +        // should go (which is into prevSiblingParent).
  1.9683 +      }
  1.9684 +      else {
  1.9685 +        // Block elements don't end up in line-frames, therefore
  1.9686 +        // change the insertion point to aBlockFrame. However, there
  1.9687 +        // might be more inline elements following aPrevSibling that
  1.9688 +        // need to be pulled out of the line-frame and become children
  1.9689 +        // of the block.
  1.9690 +        nsIFrame* nextSibling = aPrevSibling->GetNextSibling();
  1.9691 +        nsIFrame* nextLineFrame = prevSiblingParent->GetNextInFlow();
  1.9692 +        if (nextSibling || nextLineFrame) {
  1.9693 +          // Oy. We have work to do. Create a list of the new frames
  1.9694 +          // that are going into the block by stripping them away from
  1.9695 +          // the line-frame(s).
  1.9696 +          if (nextSibling) {
  1.9697 +            nsLineFrame* lineFrame = (nsLineFrame*) prevSiblingParent;
  1.9698 +            nsFrameList tail = lineFrame->StealFramesAfter(aPrevSibling);
  1.9699 +            // XXX do something with 'tail'
  1.9700 +          }
  1.9701 +
  1.9702 +          nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame;
  1.9703 +          for (;;) {
  1.9704 +            nextLineFrame = nextLineFrame->GetNextInFlow();
  1.9705 +            if (!nextLineFrame) {
  1.9706 +              break;
  1.9707 +            }
  1.9708 +            nsIFrame* kids = nextLineFrame->GetFirstPrincipalChild();
  1.9709 +          }
  1.9710 +        }
  1.9711 +        else {
  1.9712 +          // We got lucky: aPrevSibling was the last inline frame in
  1.9713 +          // the line-frame.
  1.9714 +          ReparentFrame(this, aBlockFrame, newFrame);
  1.9715 +          InsertFrames(aBlockFrame, kPrincipalList,
  1.9716 +                       prevSiblingParent, newFrame);
  1.9717 +          aFrameItems.childList = nullptr;
  1.9718 +          aFrameItems.lastChild = nullptr;
  1.9719 +        }
  1.9720 +      }
  1.9721 +    }
  1.9722 +  }
  1.9723 +
  1.9724 +#endif
  1.9725 +  return rv;
  1.9726 +}
  1.9727 +
  1.9728 +//----------------------------------------------------------------------
  1.9729 +
  1.9730 +// First-letter support
  1.9731 +
  1.9732 +// Determine how many characters in the text fragment apply to the
  1.9733 +// first letter
  1.9734 +static int32_t
  1.9735 +FirstLetterCount(const nsTextFragment* aFragment)
  1.9736 +{
  1.9737 +  int32_t count = 0;
  1.9738 +  int32_t firstLetterLength = 0;
  1.9739 +
  1.9740 +  int32_t i, n = aFragment->GetLength();
  1.9741 +  for (i = 0; i < n; i++) {
  1.9742 +    char16_t ch = aFragment->CharAt(i);
  1.9743 +    // FIXME: take content language into account when deciding whitespace.
  1.9744 +    if (dom::IsSpaceCharacter(ch)) {
  1.9745 +      if (firstLetterLength) {
  1.9746 +        break;
  1.9747 +      }
  1.9748 +      count++;
  1.9749 +      continue;
  1.9750 +    }
  1.9751 +    // XXX I18n
  1.9752 +    if ((ch == '\'') || (ch == '\"')) {
  1.9753 +      if (firstLetterLength) {
  1.9754 +        break;
  1.9755 +      }
  1.9756 +      // keep looping
  1.9757 +      firstLetterLength = 1;
  1.9758 +    }
  1.9759 +    else {
  1.9760 +      count++;
  1.9761 +      break;
  1.9762 +    }
  1.9763 +  }
  1.9764 +
  1.9765 +  return count;
  1.9766 +}
  1.9767 +
  1.9768 +static bool
  1.9769 +NeedFirstLetterContinuation(nsIContent* aContent)
  1.9770 +{
  1.9771 +  NS_PRECONDITION(aContent, "null ptr");
  1.9772 +
  1.9773 +  bool result = false;
  1.9774 +  if (aContent) {
  1.9775 +    const nsTextFragment* frag = aContent->GetText();
  1.9776 +    if (frag) {
  1.9777 +      int32_t flc = FirstLetterCount(frag);
  1.9778 +      int32_t tl = frag->GetLength();
  1.9779 +      if (flc < tl) {
  1.9780 +        result = true;
  1.9781 +      }
  1.9782 +    }
  1.9783 +  }
  1.9784 +  return result;
  1.9785 +}
  1.9786 +
  1.9787 +static bool IsFirstLetterContent(nsIContent* aContent)
  1.9788 +{
  1.9789 +  return aContent->TextLength() &&
  1.9790 +         !aContent->TextIsOnlyWhitespace();
  1.9791 +}
  1.9792 +
  1.9793 +/**
  1.9794 + * Create a letter frame, only make it a floating frame.
  1.9795 + */
  1.9796 +void
  1.9797 +nsCSSFrameConstructor::CreateFloatingLetterFrame(
  1.9798 +  nsFrameConstructorState& aState,
  1.9799 +  nsIFrame* aBlockFrame,
  1.9800 +  nsIContent* aTextContent,
  1.9801 +  nsIFrame* aTextFrame,
  1.9802 +  nsIContent* aBlockContent,
  1.9803 +  nsIFrame* aParentFrame,
  1.9804 +  nsStyleContext* aStyleContext,
  1.9805 +  nsFrameItems& aResult)
  1.9806 +{
  1.9807 +  // Create the first-letter-frame
  1.9808 +  nsIFrame* letterFrame;
  1.9809 +  nsStyleSet *styleSet = mPresShell->StyleSet();
  1.9810 +
  1.9811 +  letterFrame = NS_NewFirstLetterFrame(mPresShell, aStyleContext);
  1.9812 +  // We don't want to use a text content for a non-text frame (because we want
  1.9813 +  // its primary frame to be a text frame).  So use its parent for the
  1.9814 +  // first-letter.
  1.9815 +  nsIContent* letterContent = aTextContent->GetParent();
  1.9816 +  nsIFrame* containingBlock = aState.GetGeometricParent(
  1.9817 +    aStyleContext->StyleDisplay(), aParentFrame);
  1.9818 +  InitAndRestoreFrame(aState, letterContent, containingBlock, letterFrame);
  1.9819 +
  1.9820 +  // Init the text frame to refer to the letter frame. Make sure we
  1.9821 +  // get a proper style context for it (the one passed in is for the
  1.9822 +  // letter frame and will have the float property set on it; the text
  1.9823 +  // frame shouldn't have that set).
  1.9824 +  nsRefPtr<nsStyleContext> textSC;
  1.9825 +  textSC = styleSet->ResolveStyleForNonElement(aStyleContext);
  1.9826 +  aTextFrame->SetStyleContextWithoutNotification(textSC);
  1.9827 +  InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
  1.9828 +
  1.9829 +  // And then give the text frame to the letter frame
  1.9830 +  SetInitialSingleChild(letterFrame, aTextFrame);
  1.9831 +
  1.9832 +  // See if we will need to continue the text frame (does it contain
  1.9833 +  // more than just the first-letter text or not?) If it does, then we
  1.9834 +  // create (in advance) a continuation frame for it.
  1.9835 +  nsIFrame* nextTextFrame = nullptr;
  1.9836 +  if (NeedFirstLetterContinuation(aTextContent)) {
  1.9837 +    // Create continuation
  1.9838 +    nextTextFrame =
  1.9839 +      CreateContinuingFrame(aState.mPresContext, aTextFrame, aParentFrame);
  1.9840 +    // Repair the continuations style context
  1.9841 +    nsStyleContext* parentStyleContext = aStyleContext->GetParent();
  1.9842 +    if (parentStyleContext) {
  1.9843 +      nsRefPtr<nsStyleContext> newSC;
  1.9844 +      newSC = styleSet->ResolveStyleForNonElement(parentStyleContext);
  1.9845 +      nextTextFrame->SetStyleContext(newSC);
  1.9846 +    }
  1.9847 +  }
  1.9848 +
  1.9849 +  NS_ASSERTION(aResult.IsEmpty(), "aResult should be an empty nsFrameItems!");
  1.9850 +  // Put the new float before any of the floats in the block we're doing
  1.9851 +  // first-letter for, that is, before any floats whose parent is
  1.9852 +  // containingBlock.
  1.9853 +  nsFrameList::FrameLinkEnumerator link(aState.mFloatedItems);
  1.9854 +  while (!link.AtEnd() && link.NextFrame()->GetParent() != containingBlock) {
  1.9855 +    link.Next();
  1.9856 +  }
  1.9857 +
  1.9858 +  aState.AddChild(letterFrame, aResult, letterContent, aStyleContext,
  1.9859 +                  aParentFrame, false, true, false, true,
  1.9860 +                  link.PrevFrame());
  1.9861 +
  1.9862 +  if (nextTextFrame) {
  1.9863 +    aResult.AddChild(nextTextFrame);
  1.9864 +  }
  1.9865 +}
  1.9866 +
  1.9867 +/**
  1.9868 + * Create a new letter frame for aTextFrame. The letter frame will be
  1.9869 + * a child of aParentFrame.
  1.9870 + */
  1.9871 +void
  1.9872 +nsCSSFrameConstructor::CreateLetterFrame(nsIFrame* aBlockFrame,
  1.9873 +                                         nsIFrame* aBlockContinuation,
  1.9874 +                                         nsIContent* aTextContent,
  1.9875 +                                         nsIFrame* aParentFrame,
  1.9876 +                                         nsFrameItems& aResult)
  1.9877 +{
  1.9878 +  NS_PRECONDITION(aTextContent->IsNodeOfType(nsINode::eTEXT),
  1.9879 +                  "aTextContent isn't text");
  1.9880 +  NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
  1.9881 +                 "Not a block frame?");
  1.9882 +
  1.9883 +  // Get style context for the first-letter-frame
  1.9884 +  nsStyleContext* parentStyleContext =
  1.9885 +    nsFrame::CorrectStyleParentFrame(aParentFrame,
  1.9886 +                                     nsCSSPseudoElements::firstLetter)->
  1.9887 +      StyleContext();
  1.9888 +
  1.9889 +  // Use content from containing block so that we can actually
  1.9890 +  // find a matching style rule.
  1.9891 +  nsIContent* blockContent = aBlockFrame->GetContent();
  1.9892 +
  1.9893 +  // Create first-letter style rule
  1.9894 +  nsRefPtr<nsStyleContext> sc = GetFirstLetterStyle(blockContent,
  1.9895 +                                                    parentStyleContext);
  1.9896 +  if (sc) {
  1.9897 +    nsRefPtr<nsStyleContext> textSC;
  1.9898 +    textSC = mPresShell->StyleSet()->ResolveStyleForNonElement(sc);
  1.9899 +
  1.9900 +    // Create a new text frame (the original one will be discarded)
  1.9901 +    // pass a temporary stylecontext, the correct one will be set
  1.9902 +    // later.  Start off by unsetting the primary frame for
  1.9903 +    // aTextContent, so it's no longer pointing to the to-be-destroyed
  1.9904 +    // frame.
  1.9905 +    // XXXbz it would be really nice to destroy the old frame _first_,
  1.9906 +    // then create the new one, so we could avoid this hack.
  1.9907 +    aTextContent->SetPrimaryFrame(nullptr);
  1.9908 +    nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
  1.9909 +
  1.9910 +    NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame),
  1.9911 +                 "Containing block is confused");
  1.9912 +    nsFrameConstructorState state(mPresShell,
  1.9913 +                                  GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
  1.9914 +                                  GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
  1.9915 +                                  aBlockContinuation);
  1.9916 +
  1.9917 +    // Create the right type of first-letter frame
  1.9918 +    const nsStyleDisplay* display = sc->StyleDisplay();
  1.9919 +    if (display->IsFloatingStyle() && !aParentFrame->IsSVGText()) {
  1.9920 +      // Make a floating first-letter frame
  1.9921 +      CreateFloatingLetterFrame(state, aBlockFrame, aTextContent, textFrame,
  1.9922 +                                blockContent, aParentFrame, sc, aResult);
  1.9923 +    }
  1.9924 +    else {
  1.9925 +      // Make an inflow first-letter frame
  1.9926 +      nsIFrame* letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
  1.9927 +
  1.9928 +      // Initialize the first-letter-frame.  We don't want to use a text
  1.9929 +      // content for a non-text frame (because we want its primary frame to
  1.9930 +      // be a text frame).  So use its parent for the first-letter.
  1.9931 +      nsIContent* letterContent = aTextContent->GetParent();
  1.9932 +      letterFrame->Init(letterContent, aParentFrame, nullptr);
  1.9933 +
  1.9934 +      InitAndRestoreFrame(state, aTextContent, letterFrame, textFrame);
  1.9935 +
  1.9936 +      SetInitialSingleChild(letterFrame, textFrame);
  1.9937 +      aResult.Clear();
  1.9938 +      aResult.AddChild(letterFrame);
  1.9939 +      NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
  1.9940 +                   "should have the first continuation here");
  1.9941 +      aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
  1.9942 +    }
  1.9943 +    aTextContent->SetPrimaryFrame(textFrame);
  1.9944 +  }
  1.9945 +}
  1.9946 +
  1.9947 +void
  1.9948 +nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
  1.9949 +  nsIContent*              aBlockContent,
  1.9950 +  nsIFrame*                aBlockFrame,
  1.9951 +  nsFrameItems&            aBlockFrames)
  1.9952 +{
  1.9953 +  aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
  1.9954 +
  1.9955 +  nsIFrame* parentFrame = nullptr;
  1.9956 +  nsIFrame* textFrame = nullptr;
  1.9957 +  nsIFrame* prevFrame = nullptr;
  1.9958 +  nsFrameItems letterFrames;
  1.9959 +  bool stopLooking = false;
  1.9960 +  WrapFramesInFirstLetterFrame(aBlockFrame, aBlockFrame, aBlockFrame,
  1.9961 +                               aBlockFrames.FirstChild(),
  1.9962 +                               &parentFrame, &textFrame, &prevFrame,
  1.9963 +                               letterFrames, &stopLooking);
  1.9964 +  if (parentFrame) {
  1.9965 +    if (parentFrame == aBlockFrame) {
  1.9966 +      // Take textFrame out of the block's frame list and substitute the
  1.9967 +      // letter frame(s) instead.
  1.9968 +      aBlockFrames.DestroyFrame(textFrame);
  1.9969 +      aBlockFrames.InsertFrames(nullptr, prevFrame, letterFrames);
  1.9970 +    }
  1.9971 +    else {
  1.9972 +      // Take the old textFrame out of the inline parent's child list
  1.9973 +      RemoveFrame(kPrincipalList, textFrame);
  1.9974 +
  1.9975 +      // Insert in the letter frame(s)
  1.9976 +      parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
  1.9977 +    }
  1.9978 +  }
  1.9979 +}
  1.9980 +
  1.9981 +void
  1.9982 +nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
  1.9983 +  nsIFrame*                aBlockFrame,
  1.9984 +  nsIFrame*                aBlockContinuation,
  1.9985 +  nsIFrame*                aParentFrame,
  1.9986 +  nsIFrame*                aParentFrameList,
  1.9987 +  nsIFrame**               aModifiedParent,
  1.9988 +  nsIFrame**               aTextFrame,
  1.9989 +  nsIFrame**               aPrevFrame,
  1.9990 +  nsFrameItems&            aLetterFrames,
  1.9991 +  bool*                  aStopLooking)
  1.9992 +{
  1.9993 +  nsIFrame* prevFrame = nullptr;
  1.9994 +  nsIFrame* frame = aParentFrameList;
  1.9995 +
  1.9996 +  while (frame) {
  1.9997 +    nsIFrame* nextFrame = frame->GetNextSibling();
  1.9998 +
  1.9999 +    nsIAtom* frameType = frame->GetType();
 1.10000 +    if (nsGkAtoms::textFrame == frameType) {
 1.10001 +      // Wrap up first-letter content in a letter frame
 1.10002 +      nsIContent* textContent = frame->GetContent();
 1.10003 +      if (IsFirstLetterContent(textContent)) {
 1.10004 +        // Create letter frame to wrap up the text
 1.10005 +        CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
 1.10006 +                          aParentFrame, aLetterFrames);
 1.10007 +
 1.10008 +        // Provide adjustment information for parent
 1.10009 +        *aModifiedParent = aParentFrame;
 1.10010 +        *aTextFrame = frame;
 1.10011 +        *aPrevFrame = prevFrame;
 1.10012 +        *aStopLooking = true;
 1.10013 +        return;
 1.10014 +      }
 1.10015 +    }
 1.10016 +    else if (IsInlineFrame(frame) && frameType != nsGkAtoms::brFrame) {
 1.10017 +      nsIFrame* kids = frame->GetFirstPrincipalChild();
 1.10018 +      WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation, frame,
 1.10019 +                                   kids, aModifiedParent, aTextFrame,
 1.10020 +                                   aPrevFrame, aLetterFrames, aStopLooking);
 1.10021 +      if (*aStopLooking) {
 1.10022 +        return;
 1.10023 +      }
 1.10024 +    }
 1.10025 +    else {
 1.10026 +      // This will stop us looking to create more letter frames. For
 1.10027 +      // example, maybe the frame-type is "letterFrame" or
 1.10028 +      // "placeholderFrame". This keeps us from creating extra letter
 1.10029 +      // frames, and also prevents us from creating letter frames when
 1.10030 +      // the first real content child of a block is not text (e.g. an
 1.10031 +      // image, hr, etc.)
 1.10032 +      *aStopLooking = true;
 1.10033 +      break;
 1.10034 +    }
 1.10035 +
 1.10036 +    prevFrame = frame;
 1.10037 +    frame = nextFrame;
 1.10038 +  }
 1.10039 +}
 1.10040 +
 1.10041 +static nsIFrame*
 1.10042 +FindFirstLetterFrame(nsIFrame* aFrame, nsIFrame::ChildListID aListID)
 1.10043 +{
 1.10044 +  nsFrameList list = aFrame->GetChildList(aListID);
 1.10045 +  for (nsFrameList::Enumerator e(list); !e.AtEnd(); e.Next()) {
 1.10046 +    if (nsGkAtoms::letterFrame == e.get()->GetType()) {
 1.10047 +      return e.get();
 1.10048 +    }
 1.10049 +  }
 1.10050 +  return nullptr;
 1.10051 +}
 1.10052 +
 1.10053 +nsresult
 1.10054 +nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
 1.10055 +  nsPresContext* aPresContext,
 1.10056 +  nsIPresShell* aPresShell,
 1.10057 +  nsIFrame* aBlockFrame,
 1.10058 +  bool* aStopLooking)
 1.10059 +{
 1.10060 +  // Look for the first letter frame on the kFloatList, then kPushedFloatsList.
 1.10061 +  nsIFrame* floatFrame =
 1.10062 +    ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kFloatList);
 1.10063 +  if (!floatFrame) {
 1.10064 +    floatFrame =
 1.10065 +      ::FindFirstLetterFrame(aBlockFrame, nsIFrame::kPushedFloatsList);
 1.10066 +    if (!floatFrame) {
 1.10067 +      return NS_OK;
 1.10068 +    }
 1.10069 +  }
 1.10070 +
 1.10071 +  // Take the text frame away from the letter frame (so it isn't
 1.10072 +  // destroyed when we destroy the letter frame).
 1.10073 +  nsIFrame* textFrame = floatFrame->GetFirstPrincipalChild();
 1.10074 +  if (!textFrame) {
 1.10075 +    return NS_OK;
 1.10076 +  }
 1.10077 +
 1.10078 +  // Discover the placeholder frame for the letter frame
 1.10079 +  nsIFrame* parentFrame;
 1.10080 +  nsPlaceholderFrame* placeholderFrame = GetPlaceholderFrameFor(floatFrame);
 1.10081 +
 1.10082 +  if (!placeholderFrame) {
 1.10083 +    // Somethings really wrong
 1.10084 +    return NS_OK;
 1.10085 +  }
 1.10086 +  parentFrame = placeholderFrame->GetParent();
 1.10087 +  if (!parentFrame) {
 1.10088 +    // Somethings really wrong
 1.10089 +    return NS_OK;
 1.10090 +  }
 1.10091 +
 1.10092 +  // Create a new text frame with the right style context that maps
 1.10093 +  // all of the content that was previously part of the letter frame
 1.10094 +  // (and probably continued elsewhere).
 1.10095 +  nsStyleContext* parentSC = parentFrame->StyleContext();
 1.10096 +  nsIContent* textContent = textFrame->GetContent();
 1.10097 +  if (!textContent) {
 1.10098 +    return NS_OK;
 1.10099 +  }
 1.10100 +  nsRefPtr<nsStyleContext> newSC;
 1.10101 +  newSC = aPresShell->StyleSet()->ResolveStyleForNonElement(parentSC);
 1.10102 +  nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
 1.10103 +  newTextFrame->Init(textContent, parentFrame, nullptr);
 1.10104 +
 1.10105 +  // Destroy the old text frame's continuations (the old text frame
 1.10106 +  // will be destroyed when its letter frame is destroyed).
 1.10107 +  nsIFrame* frameToDelete = textFrame->LastContinuation();
 1.10108 +  while (frameToDelete != textFrame) {
 1.10109 +    nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
 1.10110 +    RemoveFrame(kPrincipalList, frameToDelete);
 1.10111 +    frameToDelete = nextFrameToDelete;
 1.10112 +  }
 1.10113 +
 1.10114 +  nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
 1.10115 +
 1.10116 +  // Now that everything is set...
 1.10117 +#ifdef NOISY_FIRST_LETTER
 1.10118 +  printf("RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p newTextFrame=%p\n",
 1.10119 +         textContent.get(), textFrame, newTextFrame);
 1.10120 +#endif
 1.10121 +
 1.10122 +  // Remove placeholder frame and the float
 1.10123 +  RemoveFrame(kPrincipalList, placeholderFrame);
 1.10124 +
 1.10125 +  // Now that the old frames are gone, we can start pointing to our
 1.10126 +  // new primary frame.
 1.10127 +  textContent->SetPrimaryFrame(newTextFrame);
 1.10128 +
 1.10129 +  // Wallpaper bug 822910.
 1.10130 +  bool offsetsNeedFixing =
 1.10131 +    prevSibling && prevSibling->GetType() == nsGkAtoms::textFrame;
 1.10132 +  if (offsetsNeedFixing) {
 1.10133 +    prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
 1.10134 +  }
 1.10135 +
 1.10136 +  // Insert text frame in its place
 1.10137 +  nsFrameList textList(newTextFrame, newTextFrame);
 1.10138 +  InsertFrames(parentFrame, kPrincipalList, prevSibling, textList);
 1.10139 +
 1.10140 +  if (offsetsNeedFixing) {
 1.10141 +    prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
 1.10142 +  }
 1.10143 +
 1.10144 +  return NS_OK;
 1.10145 +}
 1.10146 +
 1.10147 +nsresult
 1.10148 +nsCSSFrameConstructor::RemoveFirstLetterFrames(nsPresContext* aPresContext,
 1.10149 +                                               nsIPresShell* aPresShell,
 1.10150 +                                               nsIFrame* aFrame,
 1.10151 +                                               nsIFrame* aBlockFrame,
 1.10152 +                                               bool* aStopLooking)
 1.10153 +{
 1.10154 +  nsIFrame* prevSibling = nullptr;
 1.10155 +  nsIFrame* kid = aFrame->GetFirstPrincipalChild();
 1.10156 +
 1.10157 +  while (kid) {
 1.10158 +    if (nsGkAtoms::letterFrame == kid->GetType()) {
 1.10159 +      // Bingo. Found it. First steal away the text frame.
 1.10160 +      nsIFrame* textFrame = kid->GetFirstPrincipalChild();
 1.10161 +      if (!textFrame) {
 1.10162 +        break;
 1.10163 +      }
 1.10164 +
 1.10165 +      // Create a new textframe
 1.10166 +      nsStyleContext* parentSC = aFrame->StyleContext();
 1.10167 +      if (!parentSC) {
 1.10168 +        break;
 1.10169 +      }
 1.10170 +      nsIContent* textContent = textFrame->GetContent();
 1.10171 +      if (!textContent) {
 1.10172 +        break;
 1.10173 +      }
 1.10174 +      nsRefPtr<nsStyleContext> newSC;
 1.10175 +      newSC = aPresShell->StyleSet()->ResolveStyleForNonElement(parentSC);
 1.10176 +      textFrame = NS_NewTextFrame(aPresShell, newSC);
 1.10177 +      textFrame->Init(textContent, aFrame, nullptr);
 1.10178 +
 1.10179 +      // Next rip out the kid and replace it with the text frame
 1.10180 +      RemoveFrame(kPrincipalList, kid);
 1.10181 +
 1.10182 +      // Now that the old frames are gone, we can start pointing to our
 1.10183 +      // new primary frame.
 1.10184 +      textContent->SetPrimaryFrame(textFrame);
 1.10185 +
 1.10186 +      // Wallpaper bug 822910.
 1.10187 +      bool offsetsNeedFixing =
 1.10188 +        prevSibling && prevSibling->GetType() == nsGkAtoms::textFrame;
 1.10189 +      if (offsetsNeedFixing) {
 1.10190 +        prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
 1.10191 +      }
 1.10192 +
 1.10193 +      // Insert text frame in its place
 1.10194 +      nsFrameList textList(textFrame, textFrame);
 1.10195 +      InsertFrames(aFrame, kPrincipalList, prevSibling, textList);
 1.10196 +
 1.10197 +      if (offsetsNeedFixing) {
 1.10198 +        prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
 1.10199 +      }
 1.10200 +
 1.10201 +      *aStopLooking = true;
 1.10202 +      NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
 1.10203 +                   "should have the first continuation here");
 1.10204 +      aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
 1.10205 +      break;
 1.10206 +    }
 1.10207 +    else if (IsInlineFrame(kid)) {
 1.10208 +      // Look inside child inline frame for the letter frame
 1.10209 +      RemoveFirstLetterFrames(aPresContext, aPresShell,
 1.10210 +                              kid, aBlockFrame, aStopLooking);
 1.10211 +      if (*aStopLooking) {
 1.10212 +        break;
 1.10213 +      }
 1.10214 +    }
 1.10215 +    prevSibling = kid;
 1.10216 +    kid = kid->GetNextSibling();
 1.10217 +  }
 1.10218 +
 1.10219 +  return NS_OK;
 1.10220 +}
 1.10221 +
 1.10222 +nsresult
 1.10223 +nsCSSFrameConstructor::RemoveLetterFrames(nsPresContext* aPresContext,
 1.10224 +                                          nsIPresShell* aPresShell,
 1.10225 +                                          nsIFrame* aBlockFrame)
 1.10226 +{
 1.10227 +  aBlockFrame = aBlockFrame->FirstContinuation();
 1.10228 +  nsIFrame* continuation = aBlockFrame;
 1.10229 +
 1.10230 +  bool stopLooking = false;
 1.10231 +  nsresult rv;
 1.10232 +  do {
 1.10233 +    rv = RemoveFloatingFirstLetterFrames(aPresContext, aPresShell,
 1.10234 +                                         continuation, &stopLooking);
 1.10235 +    if (NS_SUCCEEDED(rv) && !stopLooking) {
 1.10236 +      rv = RemoveFirstLetterFrames(aPresContext, aPresShell,
 1.10237 +                                   continuation, aBlockFrame, &stopLooking);
 1.10238 +    }
 1.10239 +    if (stopLooking) {
 1.10240 +      break;
 1.10241 +    }
 1.10242 +    continuation = continuation->GetNextContinuation();
 1.10243 +  }  while (continuation);
 1.10244 +  return rv;
 1.10245 +}
 1.10246 +
 1.10247 +// Fixup the letter frame situation for the given block
 1.10248 +void
 1.10249 +nsCSSFrameConstructor::RecoverLetterFrames(nsIFrame* aBlockFrame)
 1.10250 +{
 1.10251 +  aBlockFrame = aBlockFrame->FirstContinuation();
 1.10252 +  nsIFrame* continuation = aBlockFrame;
 1.10253 +
 1.10254 +  nsIFrame* parentFrame = nullptr;
 1.10255 +  nsIFrame* textFrame = nullptr;
 1.10256 +  nsIFrame* prevFrame = nullptr;
 1.10257 +  nsFrameItems letterFrames;
 1.10258 +  bool stopLooking = false;
 1.10259 +  do {
 1.10260 +    // XXX shouldn't this bit be set already (bug 408493), assert instead?
 1.10261 +    continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
 1.10262 +    WrapFramesInFirstLetterFrame(aBlockFrame, continuation, continuation,
 1.10263 +                                 continuation->GetFirstPrincipalChild(),
 1.10264 +                                 &parentFrame, &textFrame, &prevFrame,
 1.10265 +                                 letterFrames, &stopLooking);
 1.10266 +    if (stopLooking) {
 1.10267 +      break;
 1.10268 +    }
 1.10269 +    continuation = continuation->GetNextContinuation();
 1.10270 +  } while (continuation);
 1.10271 +
 1.10272 +  if (parentFrame) {
 1.10273 +    // Take the old textFrame out of the parents child list
 1.10274 +    RemoveFrame(kPrincipalList, textFrame);
 1.10275 +
 1.10276 +    // Insert in the letter frame(s)
 1.10277 +    parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
 1.10278 +  }
 1.10279 +}
 1.10280 +
 1.10281 +//----------------------------------------------------------------------
 1.10282 +
 1.10283 +// listbox Widget Routines
 1.10284 +
 1.10285 +nsresult
 1.10286 +nsCSSFrameConstructor::CreateListBoxContent(nsPresContext* aPresContext,
 1.10287 +                                            nsIFrame*       aParentFrame,
 1.10288 +                                            nsIFrame*       aPrevFrame,
 1.10289 +                                            nsIContent*     aChild,
 1.10290 +                                            nsIFrame**      aNewFrame,
 1.10291 +                                            bool            aIsAppend,
 1.10292 +                                            bool            aIsScrollbar,
 1.10293 +                                            nsILayoutHistoryState* aFrameState)
 1.10294 +{
 1.10295 +#ifdef MOZ_XUL
 1.10296 +  nsresult rv = NS_OK;
 1.10297 +
 1.10298 +  // Construct a new frame
 1.10299 +  if (nullptr != aParentFrame) {
 1.10300 +    nsFrameItems            frameItems;
 1.10301 +    nsFrameConstructorState state(mPresShell, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
 1.10302 +                                  GetAbsoluteContainingBlock(aParentFrame, ABS_POS),
 1.10303 +                                  GetFloatContainingBlock(aParentFrame),
 1.10304 +                                  mTempFrameTreeState);
 1.10305 +
 1.10306 +    // If we ever initialize the ancestor filter on |state|, make sure
 1.10307 +    // to push the right parent!
 1.10308 +
 1.10309 +    nsRefPtr<nsStyleContext> styleContext;
 1.10310 +    styleContext = ResolveStyleContext(aParentFrame, aChild, &state);
 1.10311 +
 1.10312 +    // Pre-check for display "none" - only if we find that, do we create
 1.10313 +    // any frame at all
 1.10314 +    const nsStyleDisplay* display = styleContext->StyleDisplay();
 1.10315 +
 1.10316 +    if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
 1.10317 +      *aNewFrame = nullptr;
 1.10318 +      return NS_OK;
 1.10319 +    }
 1.10320 +
 1.10321 +    BeginUpdate();
 1.10322 +
 1.10323 +    FrameConstructionItemList items;
 1.10324 +    AddFrameConstructionItemsInternal(state, aChild, aParentFrame,
 1.10325 +                                      aChild->Tag(), aChild->GetNameSpaceID(),
 1.10326 +                                      true, styleContext,
 1.10327 +                                      ITEM_ALLOW_XBL_BASE, nullptr, items);
 1.10328 +    ConstructFramesFromItemList(state, items, aParentFrame, frameItems);
 1.10329 +
 1.10330 +    nsIFrame* newFrame = frameItems.FirstChild();
 1.10331 +    *aNewFrame = newFrame;
 1.10332 +
 1.10333 +    if (newFrame) {
 1.10334 +      // Notify the parent frame
 1.10335 +      if (aIsAppend)
 1.10336 +        rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems);
 1.10337 +      else
 1.10338 +        rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems);
 1.10339 +    }
 1.10340 +
 1.10341 +    EndUpdate();
 1.10342 +
 1.10343 +#ifdef ACCESSIBILITY
 1.10344 +    if (newFrame) {
 1.10345 +      nsAccessibilityService* accService = nsIPresShell::AccService();
 1.10346 +      if (accService) {
 1.10347 +        accService->ContentRangeInserted(mPresShell, aChild->GetParent(),
 1.10348 +                                         aChild, aChild->GetNextSibling());
 1.10349 +      }
 1.10350 +    }
 1.10351 +#endif
 1.10352 +  }
 1.10353 +
 1.10354 +  return rv;
 1.10355 +#else
 1.10356 +  return NS_ERROR_FAILURE;
 1.10357 +#endif
 1.10358 +}
 1.10359 +
 1.10360 +//----------------------------------------
 1.10361 +
 1.10362 +void
 1.10363 +nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
 1.10364 +                                      const nsStyleDisplay*    aDisplay,
 1.10365 +                                      nsIContent*              aContent,
 1.10366 +                                      nsIFrame*                aParentFrame,
 1.10367 +                                      nsIFrame*                aContentParentFrame,
 1.10368 +                                      nsStyleContext*          aStyleContext,
 1.10369 +                                      nsIFrame**               aNewFrame,
 1.10370 +                                      nsFrameItems&            aFrameItems,
 1.10371 +                                      nsIFrame*                aPositionedFrameForAbsPosContainer,
 1.10372 +                                      PendingBinding*          aPendingBinding)
 1.10373 +{
 1.10374 +  // Create column wrapper if necessary
 1.10375 +  nsIFrame* blockFrame = *aNewFrame;
 1.10376 +  NS_ASSERTION(blockFrame->GetType() == nsGkAtoms::blockFrame, "not a block frame?");
 1.10377 +  nsIFrame* parent = aParentFrame;
 1.10378 +  nsRefPtr<nsStyleContext> blockStyle = aStyleContext;
 1.10379 +  const nsStyleColumn* columns = aStyleContext->StyleColumn();
 1.10380 +
 1.10381 +  if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
 1.10382 +      || columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
 1.10383 +    nsIFrame* columnSetFrame = nullptr;
 1.10384 +    columnSetFrame =
 1.10385 +      NS_NewColumnSetFrame(mPresShell, aStyleContext, nsFrameState(0));
 1.10386 +
 1.10387 +    InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetFrame);
 1.10388 +    blockStyle = mPresShell->StyleSet()->
 1.10389 +      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::columnContent, aStyleContext);
 1.10390 +    parent = columnSetFrame;
 1.10391 +    *aNewFrame = columnSetFrame;
 1.10392 +
 1.10393 +    SetInitialSingleChild(columnSetFrame, blockFrame);
 1.10394 +  }
 1.10395 +
 1.10396 +  blockFrame->SetStyleContextWithoutNotification(blockStyle);
 1.10397 +  InitAndRestoreFrame(aState, aContent, parent, blockFrame);
 1.10398 +
 1.10399 +  aState.AddChild(*aNewFrame, aFrameItems, aContent, aStyleContext,
 1.10400 +                  aContentParentFrame ? aContentParentFrame :
 1.10401 +                                        aParentFrame);
 1.10402 +  if (!mRootElementFrame) {
 1.10403 +    // The frame we're constructing will be the root element frame.
 1.10404 +    // Set mRootElementFrame before processing children.
 1.10405 +    mRootElementFrame = *aNewFrame;
 1.10406 +  }
 1.10407 +
 1.10408 +  // We should make the outer frame be the absolute containing block,
 1.10409 +  // if one is required. We have to do this because absolute
 1.10410 +  // positioning must be computed with respect to the CSS dimensions
 1.10411 +  // of the element, which are the dimensions of the outer block. But
 1.10412 +  // we can't really do that because only blocks can have absolute
 1.10413 +  // children. So use the block and try to compensate with hacks
 1.10414 +  // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
 1.10415 +  nsFrameConstructorSaveState absoluteSaveState;
 1.10416 +  (*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
 1.10417 +  if (aPositionedFrameForAbsPosContainer) {
 1.10418 +    //    NS_ASSERTION(aRelPos, "should have made area frame for this");
 1.10419 +    aState.PushAbsoluteContainingBlock(*aNewFrame, aPositionedFrameForAbsPosContainer, absoluteSaveState);
 1.10420 +  }
 1.10421 +
 1.10422 +  // Process the child content
 1.10423 +  nsFrameItems childItems;
 1.10424 +  ProcessChildren(aState, aContent, aStyleContext, blockFrame, true,
 1.10425 +                  childItems, true, aPendingBinding);
 1.10426 +
 1.10427 +  // Set the frame's initial child list
 1.10428 +  blockFrame->SetInitialChildList(kPrincipalList, childItems);
 1.10429 +}
 1.10430 +
 1.10431 +nsIFrame*
 1.10432 +nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
 1.10433 +                                       FrameConstructionItem&   aItem,
 1.10434 +                                       nsIFrame*                aParentFrame,
 1.10435 +                                       const nsStyleDisplay*    aDisplay,
 1.10436 +                                       nsFrameItems&            aFrameItems)
 1.10437 +{
 1.10438 +  // If an inline frame has non-inline kids, then we chop up the child list
 1.10439 +  // into runs of blocks and runs of inlines, create anonymous block frames to
 1.10440 +  // contain the runs of blocks, inline frames with our style context for the
 1.10441 +  // runs of inlines, and put all these frames, in order, into aFrameItems.  We
 1.10442 +  // return the the first one.  The whole setup is called an {ib}
 1.10443 +  // split; in what follows "frames in the split" refers to the anonymous blocks
 1.10444 +  // and inlines that contain our children.
 1.10445 +  //
 1.10446 +  // {ib} splits maintain the following invariants:
 1.10447 +  // 1) All frames in the split have the NS_FRAME_PART_OF_IBSPLIT bit
 1.10448 +  //    set.
 1.10449 +  // 2) Each frame in the split has the nsIFrame::IBSplitSibling
 1.10450 +  //    property pointing to the next frame in the split, except for the last
 1.10451 +  //    one, which does not have it set.
 1.10452 +  // 3) Each frame in the split has the nsIFrame::IBSplitPrevSibling
 1.10453 +  //    property pointing to the previous frame in the split, except for the
 1.10454 +  //    first one, which does not have it set.
 1.10455 +  // 4) The first and last frame in the split are always inlines.
 1.10456 +  //
 1.10457 +  // An invariant that is NOT maintained is that the wrappers are actually
 1.10458 +  // linked via GetNextSibling linkage.  A simple example is an inline
 1.10459 +  // containing an inline that contains a block.  The three parts of the inner
 1.10460 +  // inline end up with three different parents.
 1.10461 +  //
 1.10462 +  // For example, this HTML:
 1.10463 +  // <span>
 1.10464 +  //   <div>a</div>
 1.10465 +  //   <span>
 1.10466 +  //     b
 1.10467 +  //     <div>c</div>
 1.10468 +  //   </span>
 1.10469 +  //   d
 1.10470 +  //   <div>e</div>
 1.10471 +  //   f
 1.10472 +  //  </span>
 1.10473 +  // Gives the following frame tree:
 1.10474 +  //
 1.10475 +  // Inline (outer span)
 1.10476 +  // Block (anonymous, outer span)
 1.10477 +  //   Block (div)
 1.10478 +  //     Text("a")
 1.10479 +  // Inline (outer span)
 1.10480 +  //   Inline (inner span)
 1.10481 +  //     Text("b")
 1.10482 +  // Block (anonymous, outer span)
 1.10483 +  //   Block (anonymous, inner span)
 1.10484 +  //     Block (div)
 1.10485 +  //       Text("c")
 1.10486 +  // Inline (outer span)
 1.10487 +  //   Inline (inner span)
 1.10488 +  //   Text("d")
 1.10489 +  // Block (anonymous, outer span)
 1.10490 +  //   Block (div)
 1.10491 +  //     Text("e")
 1.10492 +  // Inline (outer span)
 1.10493 +  //   Text("f")
 1.10494 +
 1.10495 +  nsIContent* const content = aItem.mContent;
 1.10496 +  nsStyleContext* const styleContext = aItem.mStyleContext;
 1.10497 +
 1.10498 +  bool positioned =
 1.10499 +    NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay &&
 1.10500 +    aDisplay->IsRelativelyPositionedStyle() &&
 1.10501 +    !aParentFrame->IsSVGText();
 1.10502 +
 1.10503 +  nsIFrame* newFrame = NS_NewInlineFrame(mPresShell, styleContext);
 1.10504 +
 1.10505 +  // Initialize the frame
 1.10506 +  InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
 1.10507 +
 1.10508 +  // Inline frames can always have generated content
 1.10509 +  newFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT);
 1.10510 +
 1.10511 +  nsFrameConstructorSaveState absoluteSaveState;  // definition cannot be inside next block
 1.10512 +                                                  // because the object's destructor is significant
 1.10513 +                                                  // this is part of the fix for bug 42372
 1.10514 +
 1.10515 +  newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
 1.10516 +  if (positioned) {
 1.10517 +    // Relatively positioned frames becomes a container for child
 1.10518 +    // frames that are positioned
 1.10519 +    aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
 1.10520 +  }
 1.10521 +
 1.10522 +  // Process the child content
 1.10523 +  nsFrameItems childItems;
 1.10524 +  ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame, childItems);
 1.10525 +
 1.10526 +  nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childItems);
 1.10527 +  if (!aItem.mIsAllInline) {
 1.10528 +    FindFirstBlock(firstBlockEnumerator);
 1.10529 +  }
 1.10530 +
 1.10531 +  if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) {
 1.10532 +    // This part is easy.  We either already know we have no non-inline kids,
 1.10533 +    // or haven't found any when constructing actual frames (the latter can
 1.10534 +    // happen only if out-of-flows that we thought had no containing block
 1.10535 +    // acquired one when ancestor inline frames and {ib} splits got
 1.10536 +    // constructed).  Just put all the kids into the single inline frame and
 1.10537 +    // bail.
 1.10538 +    newFrame->SetInitialChildList(kPrincipalList, childItems);
 1.10539 +    aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
 1.10540 +    return newFrame;
 1.10541 +  }
 1.10542 +
 1.10543 +  // This inline frame contains several types of children. Therefore this frame
 1.10544 +  // has to be chopped into several pieces, as described above.
 1.10545 +
 1.10546 +  // Grab the first inline's kids
 1.10547 +  nsFrameList firstInlineKids = childItems.ExtractHead(firstBlockEnumerator);
 1.10548 +  newFrame->SetInitialChildList(kPrincipalList, firstInlineKids);
 1.10549 +
 1.10550 +  aFrameItems.AddChild(newFrame);
 1.10551 +
 1.10552 +  CreateIBSiblings(aState, newFrame, positioned, childItems, aFrameItems);
 1.10553 +
 1.10554 +  return newFrame;
 1.10555 +}
 1.10556 +
 1.10557 +void
 1.10558 +nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
 1.10559 +                                        nsIFrame* aInitialInline,
 1.10560 +                                        bool aIsPositioned,
 1.10561 +                                        nsFrameItems& aChildItems,
 1.10562 +                                        nsFrameItems& aSiblings)
 1.10563 +{
 1.10564 +  nsIContent* content = aInitialInline->GetContent();
 1.10565 +  nsStyleContext* styleContext = aInitialInline->StyleContext();
 1.10566 +  nsIFrame* parentFrame = aInitialInline->GetParent();
 1.10567 +
 1.10568 +  // Resolve the right style context for our anonymous blocks.
 1.10569 +  // The distinction in styles is needed because of CSS 2.1, section
 1.10570 +  // 9.2.1.1, which says:
 1.10571 +  //   When such an inline box is affected by relative positioning, any
 1.10572 +  //   resulting translation also affects the block-level box contained
 1.10573 +  //   in the inline box.
 1.10574 +  nsRefPtr<nsStyleContext> blockSC =
 1.10575 +    mPresShell->StyleSet()->
 1.10576 +      ResolveAnonymousBoxStyle(aIsPositioned ?
 1.10577 +                                 nsCSSAnonBoxes::mozAnonymousPositionedBlock :
 1.10578 +                                 nsCSSAnonBoxes::mozAnonymousBlock,
 1.10579 +                               styleContext);
 1.10580 +
 1.10581 +  nsIFrame* lastNewInline = aInitialInline->FirstContinuation();
 1.10582 +  do {
 1.10583 +    // On entry to this loop aChildItems is not empty and the first frame in it
 1.10584 +    // is block-level.
 1.10585 +    NS_PRECONDITION(aChildItems.NotEmpty(), "Should have child items");
 1.10586 +    NS_PRECONDITION(!aChildItems.FirstChild()->IsInlineOutside(),
 1.10587 +                    "Must have list starting with block");
 1.10588 +
 1.10589 +    // The initial run of blocks belongs to an anonymous block that we create
 1.10590 +    // right now. The anonymous block will be the parent of these block
 1.10591 +    // children of the inline.
 1.10592 +    nsIFrame* blockFrame;
 1.10593 +    blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
 1.10594 +
 1.10595 +    InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
 1.10596 +
 1.10597 +    // Find the first non-block child which defines the end of our block kids
 1.10598 +    // and the start of our next inline's kids
 1.10599 +    nsFrameList::FrameLinkEnumerator firstNonBlock =
 1.10600 +      FindFirstNonBlock(aChildItems);
 1.10601 +    nsFrameList blockKids = aChildItems.ExtractHead(firstNonBlock);
 1.10602 +
 1.10603 +    MoveChildrenTo(aState.mPresContext, aInitialInline, blockFrame, blockKids);
 1.10604 +
 1.10605 +    SetFrameIsIBSplit(lastNewInline, blockFrame);
 1.10606 +    aSiblings.AddChild(blockFrame);
 1.10607 +
 1.10608 +    // Now grab the initial inlines in aChildItems and put them into an inline
 1.10609 +    // frame
 1.10610 +    nsIFrame* inlineFrame = NS_NewInlineFrame(mPresShell, styleContext);
 1.10611 +
 1.10612 +    InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
 1.10613 +
 1.10614 +    inlineFrame->AddStateBits(NS_FRAME_MAY_HAVE_GENERATED_CONTENT |
 1.10615 +                              NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
 1.10616 +    if (aIsPositioned) {
 1.10617 +      inlineFrame->MarkAsAbsoluteContainingBlock();
 1.10618 +    }
 1.10619 +
 1.10620 +    if (aChildItems.NotEmpty()) {
 1.10621 +      nsFrameList::FrameLinkEnumerator firstBlock(aChildItems);
 1.10622 +      FindFirstBlock(firstBlock);
 1.10623 +      nsFrameList inlineKids = aChildItems.ExtractHead(firstBlock);
 1.10624 +
 1.10625 +      MoveChildrenTo(aState.mPresContext, aInitialInline, inlineFrame,
 1.10626 +                     inlineKids);
 1.10627 +    }
 1.10628 +
 1.10629 +    SetFrameIsIBSplit(blockFrame, inlineFrame);
 1.10630 +    aSiblings.AddChild(inlineFrame);
 1.10631 +    lastNewInline = inlineFrame;
 1.10632 +  } while (aChildItems.NotEmpty());
 1.10633 +
 1.10634 +  SetFrameIsIBSplit(lastNewInline, nullptr);
 1.10635 +}
 1.10636 +
 1.10637 +void
 1.10638 +nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
 1.10639 +                                             FrameConstructionItem& aParentItem,
 1.10640 +                                             bool aItemIsWithinSVGText,
 1.10641 +                                             bool aItemAllowsTextPathChild)
 1.10642 +{
 1.10643 +  // XXXbz should we preallocate aParentItem.mChildItems to some sane
 1.10644 +  // length?  Maybe even to parentContent->GetChildCount()?
 1.10645 +  nsFrameConstructorState::PendingBindingAutoPusher
 1.10646 +    pusher(aState, aParentItem.mPendingBinding);
 1.10647 +
 1.10648 +  nsStyleContext* const parentStyleContext = aParentItem.mStyleContext;
 1.10649 +  nsIContent* const parentContent = aParentItem.mContent;
 1.10650 +
 1.10651 +  TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
 1.10652 +  if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
 1.10653 +    ancestorPusher.PushAncestorAndStyleScope(parentContent->AsElement());
 1.10654 +  } else {
 1.10655 +    ancestorPusher.PushStyleScope(parentContent->AsElement());
 1.10656 +  }
 1.10657 +
 1.10658 +  if (!aItemIsWithinSVGText) {
 1.10659 +    // Probe for generated content before
 1.10660 +    CreateGeneratedContentItem(aState, nullptr, parentContent, parentStyleContext,
 1.10661 +                               nsCSSPseudoElements::ePseudo_before,
 1.10662 +                               aParentItem.mChildItems);
 1.10663 +  }
 1.10664 +
 1.10665 +  uint32_t flags = ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK;
 1.10666 +  if (aItemIsWithinSVGText) {
 1.10667 +    flags |= ITEM_IS_WITHIN_SVG_TEXT;
 1.10668 +  }
 1.10669 +  if (aItemAllowsTextPathChild && aParentItem.mIsForSVGAElement) {
 1.10670 +    flags |= ITEM_ALLOWS_TEXT_PATH_CHILD;
 1.10671 +  }
 1.10672 +
 1.10673 +  if (!aParentItem.mAnonChildren.IsEmpty()) {
 1.10674 +    // Use the anon-children list instead of the content tree child list so
 1.10675 +    // that we use any special style context that should be associated with
 1.10676 +    // the children, and so that we won't try to construct grandchildren frame
 1.10677 +    // constructor items before the frame is available for their parent.
 1.10678 +    AddFCItemsForAnonymousContent(aState, nullptr, aParentItem.mAnonChildren,
 1.10679 +                                  aParentItem.mChildItems, flags);
 1.10680 +  } else {
 1.10681 +    // Use the content tree child list:
 1.10682 +    FlattenedChildIterator iter(parentContent);
 1.10683 +    for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
 1.10684 +      // Get the parent of the content and check if it is a XBL children element
 1.10685 +      // (if the content is a children element then contentParent != parentContent because the
 1.10686 +      // FlattenedChildIterator will transitively iterate through <xbl:children>
 1.10687 +      // for default content). Push the children element as an ancestor here because
 1.10688 +      // it does not have a frame and would not otherwise be pushed as an ancestor.
 1.10689 +      nsIContent* contentParent = content->GetParent();
 1.10690 +      MOZ_ASSERT(contentParent, "Parent must be non-null because we are iterating children.");
 1.10691 +      TreeMatchContext::AutoAncestorPusher insertionPointPusher(aState.mTreeMatchContext);
 1.10692 +      if (contentParent != parentContent && contentParent->IsElement()) {
 1.10693 +        if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
 1.10694 +          insertionPointPusher.PushAncestorAndStyleScope(contentParent->AsElement());
 1.10695 +        } else {
 1.10696 +          insertionPointPusher.PushStyleScope(contentParent->AsElement());
 1.10697 +        }
 1.10698 +      }
 1.10699 +
 1.10700 +      // Manually check for comments/PIs, since we don't have a frame to pass to
 1.10701 +      // AddFrameConstructionItems.  We know our parent is a non-replaced inline,
 1.10702 +      // so there is no need to do the NeedFrameFor check.
 1.10703 +      content->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
 1.10704 +      if (content->IsNodeOfType(nsINode::eCOMMENT) ||
 1.10705 +          content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
 1.10706 +        continue;
 1.10707 +      }
 1.10708 +      if (content->IsElement()) {
 1.10709 +        // See comment explaining why we need to remove the "is possible
 1.10710 +        // restyle root" flags in AddFrameConstructionItems.  But note
 1.10711 +        // that we can remove all restyle flags, just like in
 1.10712 +        // ProcessChildren and for the same reason.
 1.10713 +        content->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
 1.10714 +      }
 1.10715 +
 1.10716 +      nsRefPtr<nsStyleContext> childContext =
 1.10717 +        ResolveStyleContext(parentStyleContext, content, &aState);
 1.10718 +
 1.10719 +      AddFrameConstructionItemsInternal(aState, content, nullptr, content->Tag(),
 1.10720 +                                        content->GetNameSpaceID(),
 1.10721 +                                        iter.XBLInvolved(), childContext,
 1.10722 +                                        flags, nullptr,
 1.10723 +                                        aParentItem.mChildItems);
 1.10724 +    }
 1.10725 +  }
 1.10726 +
 1.10727 +  if (!aItemIsWithinSVGText) {
 1.10728 +    // Probe for generated content after
 1.10729 +    CreateGeneratedContentItem(aState, nullptr, parentContent, parentStyleContext,
 1.10730 +                               nsCSSPseudoElements::ePseudo_after,
 1.10731 +                               aParentItem.mChildItems);
 1.10732 +  }
 1.10733 +
 1.10734 +  aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
 1.10735 +}
 1.10736 +
 1.10737 +// return whether it's ok to append (in the AppendFrames sense) to
 1.10738 +// aParentFrame if our nextSibling is aNextSibling.  aParentFrame must
 1.10739 +// be an ib-split inline.
 1.10740 +static bool
 1.10741 +IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame, nsIFrame* aNextSibling)
 1.10742 +{
 1.10743 +  NS_PRECONDITION(IsInlineFrame(aParentFrame),
 1.10744 +                  "Must have an inline parent here");
 1.10745 +  do {
 1.10746 +    NS_ASSERTION(IsFramePartOfIBSplit(aParentFrame),
 1.10747 +                 "How is this not part of an ib-split?");
 1.10748 +    if (aNextSibling || aParentFrame->GetNextContinuation() ||
 1.10749 +        GetIBSplitSibling(aParentFrame)) {
 1.10750 +      return false;
 1.10751 +    }
 1.10752 +
 1.10753 +    aNextSibling = aParentFrame->GetNextSibling();
 1.10754 +    aParentFrame = aParentFrame->GetParent();
 1.10755 +  } while (IsInlineFrame(aParentFrame));
 1.10756 +
 1.10757 +  return true;
 1.10758 +}
 1.10759 +
 1.10760 +bool
 1.10761 +nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
 1.10762 +                                           nsIFrame* aContainingBlock,
 1.10763 +                                           nsIFrame* aFrame,
 1.10764 +                                           FrameConstructionItemList& aItems,
 1.10765 +                                           bool aIsAppend,
 1.10766 +                                           nsIFrame* aPrevSibling)
 1.10767 +{
 1.10768 +  if (aItems.IsEmpty()) {
 1.10769 +    return false;
 1.10770 +  }
 1.10771 +
 1.10772 +  // Before we go and append the frames, we must check for several
 1.10773 +  // special situations.
 1.10774 +
 1.10775 +  // Situation #1 is a XUL frame that contains frames that are required
 1.10776 +  // to be wrapped in blocks.
 1.10777 +  if (aFrame->IsBoxFrame() &&
 1.10778 +      !(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
 1.10779 +      aItems.AnyItemsNeedBlockParent()) {
 1.10780 +    RecreateFramesForContent(aFrame->GetContent(), true);
 1.10781 +    return true;
 1.10782 +  }
 1.10783 +
 1.10784 +  nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
 1.10785 +
 1.10786 +  // Situation #2 is a flex container frame into which we're inserting new
 1.10787 +  // inline non-replaced children, adjacent to an existing anonymous flex item.
 1.10788 +  if (aFrame->GetType() == nsGkAtoms::flexContainerFrame) {
 1.10789 +    FCItemIterator iter(aItems);
 1.10790 +
 1.10791 +    // Check if we're adding to-be-wrapped content right *after* an existing
 1.10792 +    // anonymous flex item (which would need to absorb this content).
 1.10793 +    if (aPrevSibling && IsAnonymousFlexItem(aPrevSibling) &&
 1.10794 +        iter.item().NeedsAnonFlexItem(aState)) {
 1.10795 +      RecreateFramesForContent(aFrame->GetContent(), true);
 1.10796 +      return true;
 1.10797 +    }
 1.10798 +
 1.10799 +    // Check if we're adding to-be-wrapped content right *before* an existing
 1.10800 +    // anonymous flex item (which would need to absorb this content).
 1.10801 +    if (nextSibling && IsAnonymousFlexItem(nextSibling)) {
 1.10802 +      // Jump to the last entry in the list
 1.10803 +      iter.SetToEnd();
 1.10804 +      iter.Prev();
 1.10805 +      if (iter.item().NeedsAnonFlexItem(aState)) {
 1.10806 +        RecreateFramesForContent(aFrame->GetContent(), true);
 1.10807 +        return true;
 1.10808 +      }
 1.10809 +    }
 1.10810 +  }
 1.10811 +
 1.10812 +  // Situation #3 is an anonymous flex item that's getting new children who
 1.10813 +  // don't want to be wrapped.
 1.10814 +  if (IsAnonymousFlexItem(aFrame)) {
 1.10815 +    nsIFrame* flexContainerFrame = aFrame->GetParent();
 1.10816 +    NS_ABORT_IF_FALSE(flexContainerFrame &&
 1.10817 +                      flexContainerFrame->GetType() == nsGkAtoms::flexContainerFrame,
 1.10818 +                      "anonymous flex items should only exist as children "
 1.10819 +                      "of flex container frames");
 1.10820 +
 1.10821 +    // We need to push a null float containing block to be sure that
 1.10822 +    // "NeedsAnonFlexItem" will know we're not honoring floats for this
 1.10823 +    // inserted content. (In particular, this is necessary in order for
 1.10824 +    // NeedsAnonFlexItem's "GetGeometricParent" call to return the correct
 1.10825 +    // result.) We're not honoring floats on this content because it has the
 1.10826 +    // _flex container_ as its parent in the content tree.
 1.10827 +    nsFrameConstructorSaveState floatSaveState;
 1.10828 +    aState.PushFloatContainingBlock(nullptr, floatSaveState);
 1.10829 +
 1.10830 +    FCItemIterator iter(aItems);
 1.10831 +    // Skip over things that _do_ need an anonymous flex item, because
 1.10832 +    // they're perfectly happy to go here -- they won't cause a reframe.
 1.10833 +    if (!iter.SkipItemsThatNeedAnonFlexItem(aState)) {
 1.10834 +      // We hit something that _doesn't_ need an anonymous flex item!
 1.10835 +      // Rebuild the flex container to bust it out.
 1.10836 +      RecreateFramesForContent(flexContainerFrame->GetContent(), true);
 1.10837 +      return true;
 1.10838 +    }
 1.10839 +
 1.10840 +    // If we get here, then everything in |aItems| needs to be wrapped in
 1.10841 +    // an anonymous flex item.  That's where it's already going - good!
 1.10842 +  }
 1.10843 +
 1.10844 +  // Situation #4 is a case when table pseudo-frames don't work out right
 1.10845 +  ParentType parentType = GetParentType(aFrame);
 1.10846 +  // If all the kids want a parent of the type that aFrame is, then we're all
 1.10847 +  // set to go.  Indeed, there won't be any table pseudo-frames created between
 1.10848 +  // aFrame and the kids, so those won't need to be merged with any table
 1.10849 +  // pseudo-frames that might already be kids of aFrame.  If aFrame itself is a
 1.10850 +  // table pseudo-frame, then all the kids in this list would have wanted a
 1.10851 +  // frame of that type wrapping them anyway, so putting them inside it is ok.
 1.10852 +  if (!aItems.AllWantParentType(parentType)) {
 1.10853 +    // Don't give up yet.  If parentType is not eTypeBlock and the parent is
 1.10854 +    // not a generated content frame, then try filtering whitespace out of the
 1.10855 +    // list.
 1.10856 +    if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
 1.10857 +      // For leading whitespace followed by a kid that wants our parent type,
 1.10858 +      // there are four cases:
 1.10859 +      // 1) We have a previous sibling which is not a table pseudo.  That means
 1.10860 +      //    that previous sibling wanted a (non-block) parent of the type we're
 1.10861 +      //    looking at.  Then the whitespace comes between two table-internal
 1.10862 +      //    elements, so should be collapsed out.
 1.10863 +      // 2) We have a previous sibling which is a table pseudo.  It might have
 1.10864 +      //    kids who want this whitespace, so we need to reframe.
 1.10865 +      // 3) We have no previous sibling and our parent frame is not a table
 1.10866 +      //    pseudo.  That means that we'll be at the beginning of our actual
 1.10867 +      //    non-block-type parent, and the whitespace is OK to collapse out.
 1.10868 +      //    If something is ever inserted before us, it'll find our own parent
 1.10869 +      //    as its parent and if it's something that would care about the
 1.10870 +      //    whitespace it'll want a block parent, so it'll trigger a reframe at
 1.10871 +      //    that point.
 1.10872 +      // 4) We have no previous sibling and our parent frame is a table pseudo.
 1.10873 +      //    Need to reframe.
 1.10874 +      // All that is predicated on finding the correct previous sibling.  We
 1.10875 +      // might have to walk backwards along continuations from aFrame to do so.
 1.10876 +      //
 1.10877 +      // It's always OK to drop whitespace between any two items that want a
 1.10878 +      // parent of type parentType.
 1.10879 +      //
 1.10880 +      // For trailing whitespace preceded by a kid that wants our parent type,
 1.10881 +      // there are four cases:
 1.10882 +      // 1) We have a next sibling which is not a table pseudo.  That means
 1.10883 +      //    that next sibling wanted a (non-block) parent of the type we're
 1.10884 +      //    looking at.  Then the whitespace comes between two table-internal
 1.10885 +      //    elements, so should be collapsed out.
 1.10886 +      // 2) We have a next sibling which is a table pseudo.  It might have
 1.10887 +      //    kids who want this whitespace, so we need to reframe.
 1.10888 +      // 3) We have no next sibling and our parent frame is not a table
 1.10889 +      //    pseudo.  That means that we'll be at the end of our actual
 1.10890 +      //    non-block-type parent, and the whitespace is OK to collapse out.
 1.10891 +      //    If something is ever inserted after us, it'll find our own parent
 1.10892 +      //    as its parent and if it's something that would care about the
 1.10893 +      //    whitespace it'll want a block parent, so it'll trigger a reframe at
 1.10894 +      //    that point.
 1.10895 +      // 4) We have no next sibling and our parent frame is a table pseudo.
 1.10896 +      //    Need to reframe.
 1.10897 +      // All that is predicated on finding the correct next sibling.  We might
 1.10898 +      // have to walk forward along continuations from aFrame to do so.  That
 1.10899 +      // said, in the case when nextSibling is null at this point and aIsAppend
 1.10900 +      // is true, we know we're in case 3.  Furthermore, in that case we don't
 1.10901 +      // even have to worry about the table pseudo situation; we know our
 1.10902 +      // parent is not a table pseudo there.
 1.10903 +      FCItemIterator iter(aItems);
 1.10904 +      FCItemIterator start(iter);
 1.10905 +      do {
 1.10906 +        if (iter.SkipItemsWantingParentType(parentType)) {
 1.10907 +          break;
 1.10908 +        }
 1.10909 +
 1.10910 +        // iter points to an item that wants a different parent.  If it's not
 1.10911 +        // whitespace, we're done; no more point scanning the list.
 1.10912 +        if (!iter.item().IsWhitespace(aState)) {
 1.10913 +          break;
 1.10914 +        }
 1.10915 +
 1.10916 +        if (iter == start) {
 1.10917 +          // Leading whitespace.  How to handle this depends on our
 1.10918 +          // previous sibling and aFrame.  See the long comment above.
 1.10919 +          nsIFrame* prevSibling = aPrevSibling;
 1.10920 +          if (!prevSibling) {
 1.10921 +            // Try to find one after all
 1.10922 +            nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
 1.10923 +            while (parentPrevCont) {
 1.10924 +              prevSibling = parentPrevCont->GetLastChild(kPrincipalList);
 1.10925 +              if (prevSibling) {
 1.10926 +                break;
 1.10927 +              }
 1.10928 +              parentPrevCont = parentPrevCont->GetPrevContinuation();
 1.10929 +            }
 1.10930 +          };
 1.10931 +          if (prevSibling) {
 1.10932 +            if (IsTablePseudo(prevSibling)) {
 1.10933 +              // need to reframe
 1.10934 +              break;
 1.10935 +            }
 1.10936 +          } else if (IsTablePseudo(aFrame)) {
 1.10937 +            // need to reframe
 1.10938 +            break;
 1.10939 +          }
 1.10940 +        }
 1.10941 +
 1.10942 +        FCItemIterator spaceEndIter(iter);
 1.10943 +        // Advance spaceEndIter past any whitespace
 1.10944 +        bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
 1.10945 +
 1.10946 +        bool okToDrop;
 1.10947 +        if (trailingSpaces) {
 1.10948 +          // Trailing whitespace.  How to handle this depeds on aIsAppend, our
 1.10949 +          // next sibling and aFrame.  See the long comment above.
 1.10950 +          okToDrop = aIsAppend && !nextSibling;
 1.10951 +          if (!okToDrop) {
 1.10952 +            if (!nextSibling) {
 1.10953 +              // Try to find one after all
 1.10954 +              nsIFrame* parentNextCont = aFrame->GetNextContinuation();
 1.10955 +              while (parentNextCont) {
 1.10956 +                nextSibling = parentNextCont->GetFirstPrincipalChild();
 1.10957 +                if (nextSibling) {
 1.10958 +                  break;
 1.10959 +                }
 1.10960 +                parentNextCont = parentNextCont->GetNextContinuation();
 1.10961 +              }
 1.10962 +            }
 1.10963 +
 1.10964 +            okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
 1.10965 +                       (!nextSibling && !IsTablePseudo(aFrame));
 1.10966 +          }
 1.10967 +#ifdef DEBUG
 1.10968 +          else {
 1.10969 +            NS_ASSERTION(!IsTablePseudo(aFrame), "How did that happen?");
 1.10970 +          }
 1.10971 +#endif
 1.10972 +        } else {
 1.10973 +          okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
 1.10974 +        }
 1.10975 +
 1.10976 +        if (okToDrop) {
 1.10977 +          iter.DeleteItemsTo(spaceEndIter);
 1.10978 +        } else {
 1.10979 +          // We're done: we don't want to drop the whitespace, and it has the
 1.10980 +          // wrong parent type.
 1.10981 +          break;
 1.10982 +        }
 1.10983 +
 1.10984 +        // Now loop, since |iter| points to item right after the whitespace we
 1.10985 +        // removed.
 1.10986 +      } while (!iter.IsDone());
 1.10987 +    }
 1.10988 +
 1.10989 +    // We might be able to figure out some sort of optimizations here, but they
 1.10990 +    // would have to depend on having a correct aPrevSibling and a correct next
 1.10991 +    // sibling.  For example, we can probably avoid reframing if none of
 1.10992 +    // aFrame, aPrevSibling, and next sibling are table pseudo-frames.  But it
 1.10993 +    // doesn't seem worth it to worry about that for now, especially since we
 1.10994 +    // in fact do not have a reliable aPrevSibling, nor any next sibling, in
 1.10995 +    // this method.
 1.10996 +
 1.10997 +    // aItems might have changed, so recheck the parent type thing.  In fact,
 1.10998 +    // it might be empty, so recheck that too.
 1.10999 +    if (aItems.IsEmpty()) {
 1.11000 +      return false;
 1.11001 +    }
 1.11002 +
 1.11003 +    if (!aItems.AllWantParentType(parentType)) {
 1.11004 +      // Reframing aFrame->GetContent() is good enough, since the content of
 1.11005 +      // table pseudo-frames is the ancestor content.
 1.11006 +      RecreateFramesForContent(aFrame->GetContent(), true);
 1.11007 +      return true;
 1.11008 +    }
 1.11009 +  }
 1.11010 +
 1.11011 +  // Now we have several cases involving {ib} splits.  Put them all in a
 1.11012 +  // do/while with breaks to take us to the "go and reconstruct" code.
 1.11013 +  do {
 1.11014 +    if (IsInlineFrame(aFrame)) {
 1.11015 +      if (aItems.AreAllItemsInline()) {
 1.11016 +        // We can just put the kids in.
 1.11017 +        return false;
 1.11018 +      }
 1.11019 +
 1.11020 +      if (!IsFramePartOfIBSplit(aFrame)) {
 1.11021 +        // Need to go ahead and reconstruct.
 1.11022 +        break;
 1.11023 +      }
 1.11024 +
 1.11025 +      // Now we're adding kids including some blocks to an inline part of an
 1.11026 +      // {ib} split.  If we plan to call AppendFrames, and don't have a next
 1.11027 +      // sibling for the new frames, and our parent is the last continuation of
 1.11028 +      // the last part of the {ib} split, and the same is true of all our
 1.11029 +      // ancestor inlines (they have no following continuations and they're the
 1.11030 +      // last part of their {ib} splits and we'd be adding to the end for all
 1.11031 +      // of them), then AppendFrames will handle things for us.  Bail out in
 1.11032 +      // that case.
 1.11033 +      if (aIsAppend && IsSafeToAppendToIBSplitInline(aFrame, nextSibling)) {
 1.11034 +        return false;
 1.11035 +      }
 1.11036 +
 1.11037 +      // Need to reconstruct.
 1.11038 +      break;
 1.11039 +    }
 1.11040 +
 1.11041 +    // Now we know we have a block parent.  If it's not part of an
 1.11042 +    // ib-split, we're all set.
 1.11043 +    if (!IsFramePartOfIBSplit(aFrame)) {
 1.11044 +      return false;
 1.11045 +    }
 1.11046 +
 1.11047 +    // We're adding some kids to a block part of an {ib} split.  If all the
 1.11048 +    // kids are blocks, we don't need to reconstruct.
 1.11049 +    if (aItems.AreAllItemsBlock()) {
 1.11050 +      return false;
 1.11051 +    }
 1.11052 +
 1.11053 +    // We might have some inline kids for this block.  Just reconstruct.
 1.11054 +    break;
 1.11055 +  } while (0);
 1.11056 +
 1.11057 +  // If we don't have a containing block, start with aFrame and look for one.
 1.11058 +  if (!aContainingBlock) {
 1.11059 +    aContainingBlock = aFrame;
 1.11060 +  }
 1.11061 +
 1.11062 +  // To find the right block to reframe, just walk up the tree until we find a
 1.11063 +  // frame that is:
 1.11064 +  // 1)  Not part of an IB split
 1.11065 +  // 2)  Not a pseudo-frame
 1.11066 +  // 3)  Not an inline frame
 1.11067 +  // We're guaranteed to find one, since nsStyleContext::ApplyStyleFixups
 1.11068 +  // enforces that the root is display:none, display:table, or display:block.
 1.11069 +  // Note that walking up "too far" is OK in terms of correctness, even if it
 1.11070 +  // might be a little inefficient.  This is why we walk out of all
 1.11071 +  // pseudo-frames -- telling which ones are or are not OK to walk out of is
 1.11072 +  // too hard (and I suspect that we do in fact need to walk out of all of
 1.11073 +  // them).
 1.11074 +  while (IsFramePartOfIBSplit(aContainingBlock) ||
 1.11075 +         aContainingBlock->IsInlineOutside() ||
 1.11076 +         aContainingBlock->StyleContext()->GetPseudo()) {
 1.11077 +    aContainingBlock = aContainingBlock->GetParent();
 1.11078 +    NS_ASSERTION(aContainingBlock,
 1.11079 +                 "Must have non-inline, non-ib-split, non-pseudo frame as "
 1.11080 +                 "root (or child of root, for a table root)!");
 1.11081 +  }
 1.11082 +
 1.11083 +  // Tell parent of the containing block to reformulate the
 1.11084 +  // entire block. This is painful and definitely not optimal
 1.11085 +  // but it will *always* get the right answer.
 1.11086 +
 1.11087 +  nsIContent *blockContent = aContainingBlock->GetContent();
 1.11088 +#ifdef DEBUG
 1.11089 +  if (gNoisyContentUpdates) {
 1.11090 +    printf("nsCSSFrameConstructor::WipeContainingBlock: blockContent=%p\n",
 1.11091 +           static_cast<void*>(blockContent));
 1.11092 +  }
 1.11093 +#endif
 1.11094 +  RecreateFramesForContent(blockContent, true);
 1.11095 +  return true;
 1.11096 +}
 1.11097 +
 1.11098 +nsresult
 1.11099 +nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame)
 1.11100 +{
 1.11101 +
 1.11102 +#ifdef DEBUG
 1.11103 +  // ReframeContainingBlock is a NASTY routine, it causes terrible performance problems
 1.11104 +  // so I want to see when it is happening!  Unfortunately, it is happening way to often because
 1.11105 +  // so much content on the web causes block-in-inline frame situations and we handle them
 1.11106 +  // very poorly
 1.11107 +  if (gNoisyContentUpdates) {
 1.11108 +    printf("nsCSSFrameConstructor::ReframeContainingBlock frame=%p\n",
 1.11109 +           static_cast<void*>(aFrame));
 1.11110 +  }
 1.11111 +#endif
 1.11112 +
 1.11113 +  // XXXbz how exactly would we get here while isReflowing anyway?  Should this
 1.11114 +  // whole test be ifdef DEBUG?
 1.11115 +  if (mPresShell->IsReflowLocked()) {
 1.11116 +    // don't ReframeContainingBlock, this will result in a crash
 1.11117 +    // if we remove a tree that's in reflow - see bug 121368 for testcase
 1.11118 +    NS_ERROR("Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a Reflow!!!");
 1.11119 +    return NS_OK;
 1.11120 +  }
 1.11121 +
 1.11122 +  // Get the first "normal" ancestor of the target frame.
 1.11123 +  nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
 1.11124 +  if (containingBlock) {
 1.11125 +    // From here we look for the containing block in case the target
 1.11126 +    // frame is already a block (which can happen when an inline frame
 1.11127 +    // wraps some of its content in an anonymous block; see
 1.11128 +    // ConstructInline)
 1.11129 +
 1.11130 +    // NOTE: We used to get the FloatContainingBlock here, but it was often wrong.
 1.11131 +    // GetIBContainingBlock works much better and provides the correct container in all cases
 1.11132 +    // so GetFloatContainingBlock(aFrame) has been removed
 1.11133 +
 1.11134 +    // And get the containingBlock's content
 1.11135 +    nsCOMPtr<nsIContent> blockContent = containingBlock->GetContent();
 1.11136 +    if (blockContent) {
 1.11137 +#ifdef DEBUG
 1.11138 +      if (gNoisyContentUpdates) {
 1.11139 +        printf("  ==> blockContent=%p\n", static_cast<void*>(blockContent));
 1.11140 +      }
 1.11141 +#endif
 1.11142 +      return RecreateFramesForContent(blockContent, true);
 1.11143 +    }
 1.11144 +  }
 1.11145 +
 1.11146 +  // If we get here, we're screwed!
 1.11147 +  return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
 1.11148 +				  true);
 1.11149 +}
 1.11150 +
 1.11151 +nsresult
 1.11152 +nsCSSFrameConstructor::GenerateChildFrames(nsIFrame* aFrame)
 1.11153 +{
 1.11154 +  {
 1.11155 +    nsAutoScriptBlocker scriptBlocker;
 1.11156 +    BeginUpdate();
 1.11157 +
 1.11158 +    nsFrameItems childItems;
 1.11159 +    nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
 1.11160 +    // We don't have a parent frame with a pending binding constructor here,
 1.11161 +    // so no need to worry about ordering of the kids' constructors with it.
 1.11162 +    // Pass null for the PendingBinding.
 1.11163 +    ProcessChildren(state, aFrame->GetContent(), aFrame->StyleContext(),
 1.11164 +                    aFrame, false, childItems, false,
 1.11165 +                    nullptr);
 1.11166 +
 1.11167 +    aFrame->SetInitialChildList(kPrincipalList, childItems);
 1.11168 +
 1.11169 +    EndUpdate();
 1.11170 +  }
 1.11171 +
 1.11172 +#ifdef ACCESSIBILITY
 1.11173 +  nsAccessibilityService* accService = nsIPresShell::AccService();
 1.11174 +  if (accService) {
 1.11175 +    nsIContent* container = aFrame->GetContent();
 1.11176 +    nsIContent* child = container->GetFirstChild();
 1.11177 +    if (child) {
 1.11178 +      accService->ContentRangeInserted(mPresShell, container, child, nullptr);
 1.11179 +    }
 1.11180 +  }
 1.11181 +#endif
 1.11182 +
 1.11183 +  // call XBL constructors after the frames are created
 1.11184 +  mPresShell->GetDocument()->BindingManager()->ProcessAttachedQueue();
 1.11185 +
 1.11186 +  return NS_OK;
 1.11187 +}
 1.11188 +
 1.11189 +//////////////////////////////////////////////////////////
 1.11190 +// nsCSSFrameConstructor::FrameConstructionItem methods //
 1.11191 +//////////////////////////////////////////////////////////
 1.11192 +bool
 1.11193 +nsCSSFrameConstructor::
 1.11194 +FrameConstructionItem::IsWhitespace(nsFrameConstructorState& aState) const
 1.11195 +{
 1.11196 +  NS_PRECONDITION(aState.mCreatingExtraFrames ||
 1.11197 +                  !mContent->GetPrimaryFrame(), "How did that happen?");
 1.11198 +  if (!mIsText) {
 1.11199 +    return false;
 1.11200 +  }
 1.11201 +  mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
 1.11202 +                     NS_REFRAME_IF_WHITESPACE);
 1.11203 +  return mContent->TextIsOnlyWhitespace();
 1.11204 +}
 1.11205 +
 1.11206 +//////////////////////////////////////////////////////////////
 1.11207 +// nsCSSFrameConstructor::FrameConstructionItemList methods //
 1.11208 +//////////////////////////////////////////////////////////////
 1.11209 +void
 1.11210 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11211 +AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta)
 1.11212 +{
 1.11213 +  NS_PRECONDITION(aDelta == 1 || aDelta == -1, "Unexpected delta");
 1.11214 +  mItemCount += aDelta;
 1.11215 +  if (aItem->mIsAllInline) {
 1.11216 +    mInlineCount += aDelta;
 1.11217 +  }
 1.11218 +  if (aItem->mIsBlock) {
 1.11219 +    mBlockCount += aDelta;
 1.11220 +  }
 1.11221 +  if (aItem->mIsLineParticipant) {
 1.11222 +    mLineParticipantCount += aDelta;
 1.11223 +  }
 1.11224 +  mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
 1.11225 +}
 1.11226 +
 1.11227 +////////////////////////////////////////////////////////////////////////
 1.11228 +// nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
 1.11229 +////////////////////////////////////////////////////////////////////////
 1.11230 +inline bool
 1.11231 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11232 +Iterator::SkipItemsWantingParentType(ParentType aParentType)
 1.11233 +{
 1.11234 +  NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
 1.11235 +  while (item().DesiredParentType() == aParentType) {
 1.11236 +    Next();
 1.11237 +    if (IsDone()) {
 1.11238 +      return true;
 1.11239 +    }
 1.11240 +  }
 1.11241 +  return false;
 1.11242 +}
 1.11243 +
 1.11244 +bool
 1.11245 +nsCSSFrameConstructor::FrameConstructionItem::
 1.11246 +  NeedsAnonFlexItem(const nsFrameConstructorState& aState)
 1.11247 +{
 1.11248 +  if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) {
 1.11249 +    // This will be an inline non-replaced box.
 1.11250 +    return true;
 1.11251 +  }
 1.11252 +
 1.11253 +  if (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
 1.11254 +      aState.GetGeometricParent(mStyleContext->StyleDisplay(), nullptr)) {
 1.11255 +    // We're abspos or fixedpos, which means we'll spawn a placeholder which
 1.11256 +    // we'll need to wrap in an anonymous flex item.  So, we just treat
 1.11257 +    // _this_ frame as if _it_ needs to be wrapped in an anonymous flex item,
 1.11258 +    // and then when we spawn the placeholder, it'll end up in the right spot.
 1.11259 +    return true;
 1.11260 +  }
 1.11261 +
 1.11262 +  return false;
 1.11263 +}
 1.11264 +
 1.11265 +inline bool
 1.11266 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11267 +Iterator::SkipItemsThatNeedAnonFlexItem(
 1.11268 +  const nsFrameConstructorState& aState)
 1.11269 +{
 1.11270 +  NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
 1.11271 +  while (item().NeedsAnonFlexItem(aState)) {
 1.11272 +    Next();
 1.11273 +    if (IsDone()) {
 1.11274 +      return true;
 1.11275 +    }
 1.11276 +  }
 1.11277 +  return false;
 1.11278 +}
 1.11279 +
 1.11280 +inline bool
 1.11281 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11282 +Iterator::SkipItemsThatDontNeedAnonFlexItem(
 1.11283 +  const nsFrameConstructorState& aState)
 1.11284 +{
 1.11285 +  NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
 1.11286 +  while (!(item().NeedsAnonFlexItem(aState))) {
 1.11287 +    Next();
 1.11288 +    if (IsDone()) {
 1.11289 +      return true;
 1.11290 +    }
 1.11291 +  }
 1.11292 +  return false;
 1.11293 +}
 1.11294 +
 1.11295 +inline bool
 1.11296 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11297 +Iterator::SkipWhitespace(nsFrameConstructorState& aState)
 1.11298 +{
 1.11299 +  NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
 1.11300 +  NS_PRECONDITION(item().IsWhitespace(aState), "Not pointing to whitespace?");
 1.11301 +  do {
 1.11302 +    Next();
 1.11303 +    if (IsDone()) {
 1.11304 +      return true;
 1.11305 +    }
 1.11306 +  } while (item().IsWhitespace(aState));
 1.11307 +
 1.11308 +  return false;
 1.11309 +}
 1.11310 +
 1.11311 +void
 1.11312 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11313 +Iterator::AppendItemToList(FrameConstructionItemList& aTargetList)
 1.11314 +{
 1.11315 +  NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
 1.11316 +  NS_PRECONDITION(!IsDone(), "should not be done");
 1.11317 +
 1.11318 +  FrameConstructionItem* item = ToItem(mCurrent);
 1.11319 +  Next();
 1.11320 +  PR_REMOVE_LINK(item);
 1.11321 +  PR_APPEND_LINK(item, &aTargetList.mItems);
 1.11322 +
 1.11323 +  mList.AdjustCountsForItem(item, -1);
 1.11324 +  aTargetList.AdjustCountsForItem(item, 1);
 1.11325 +}
 1.11326 +
 1.11327 +void
 1.11328 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11329 +Iterator::AppendItemsToList(const Iterator& aEnd,
 1.11330 +                            FrameConstructionItemList& aTargetList)
 1.11331 +{
 1.11332 +  NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
 1.11333 +  NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
 1.11334 +
 1.11335 +  // We can't just move our guts to the other list if it already has
 1.11336 +  // some information or if we're not moving our entire list.
 1.11337 +  if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty() ||
 1.11338 +      !aTargetList.mUndisplayedItems.IsEmpty()) {
 1.11339 +    do {
 1.11340 +      AppendItemToList(aTargetList);
 1.11341 +    } while (*this != aEnd);
 1.11342 +    return;
 1.11343 +  }
 1.11344 +
 1.11345 +  // move over the list of items
 1.11346 +  PR_INSERT_AFTER(&aTargetList.mItems, &mList.mItems);
 1.11347 +  // Need to init when we remove to makd ~FrameConstructionItemList work right.
 1.11348 +  PR_REMOVE_AND_INIT_LINK(&mList.mItems);
 1.11349 +
 1.11350 +  // Copy over the various counters
 1.11351 +  aTargetList.mInlineCount = mList.mInlineCount;
 1.11352 +  aTargetList.mBlockCount = mList.mBlockCount;
 1.11353 +  aTargetList.mLineParticipantCount = mList.mLineParticipantCount;
 1.11354 +  aTargetList.mItemCount = mList.mItemCount;
 1.11355 +  memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
 1.11356 +         sizeof(aTargetList.mDesiredParentCounts));
 1.11357 +
 1.11358 +  // Swap out undisplayed item arrays, before we nuke the array on our end
 1.11359 +  aTargetList.mUndisplayedItems.SwapElements(mList.mUndisplayedItems);
 1.11360 +
 1.11361 +  // reset mList
 1.11362 +  mList.~FrameConstructionItemList();
 1.11363 +  new (&mList) FrameConstructionItemList();
 1.11364 +
 1.11365 +  // Point ourselves to aEnd, as advertised
 1.11366 +  mCurrent = mEnd = &mList.mItems;
 1.11367 +  NS_POSTCONDITION(*this == aEnd, "How did that happen?");
 1.11368 +}
 1.11369 +
 1.11370 +void
 1.11371 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11372 +Iterator::InsertItem(FrameConstructionItem* aItem)
 1.11373 +{
 1.11374 +  // Just insert the item before us.  There's no magic here.
 1.11375 +  PR_INSERT_BEFORE(aItem, mCurrent);
 1.11376 +  mList.AdjustCountsForItem(aItem, 1);
 1.11377 +
 1.11378 +  NS_POSTCONDITION(PR_NEXT_LINK(aItem) == mCurrent, "How did that happen?");
 1.11379 +}
 1.11380 +
 1.11381 +void
 1.11382 +nsCSSFrameConstructor::FrameConstructionItemList::
 1.11383 +Iterator::DeleteItemsTo(const Iterator& aEnd)
 1.11384 +{
 1.11385 +  NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
 1.11386 +  NS_PRECONDITION(*this != aEnd, "Shouldn't be at aEnd yet");
 1.11387 +
 1.11388 +  do {
 1.11389 +    NS_ASSERTION(!IsDone(), "Ran off end of list?");
 1.11390 +    FrameConstructionItem* item = ToItem(mCurrent);
 1.11391 +    Next();
 1.11392 +    PR_REMOVE_LINK(item);
 1.11393 +    mList.AdjustCountsForItem(item, -1);
 1.11394 +    delete item;
 1.11395 +  } while (*this != aEnd);
 1.11396 +}

mercurial