Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp
Warning:line 7522, column 7
Value stored to 'parentType' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_layout_base1.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/layout/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/layout/base -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/layout/forms -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/layout/mathml -I /var/lib/jenkins/workspace/firefox-scan-build/layout/painting -I /var/lib/jenkins/workspace/firefox-scan-build/layout/printing -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/layout/tables -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul/tree -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/html -I /var/lib/jenkins/workspace/firefox-scan-build/dom/svg -I /var/lib/jenkins/workspace/firefox-scan-build/dom/xul -I /var/lib/jenkins/workspace/firefox-scan-build/view -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ Unified_cpp_layout_base1.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7/*
8 * construction of a frame tree that is nearly isomorphic to the content
9 * tree and updating of that tree in response to dynamic changes
10 */
11
12#include "nsCSSFrameConstructor.h"
13
14#include "ActiveLayerTracker.h"
15#include "ChildIterator.h"
16#include "mozilla/AutoRestore.h"
17#include "mozilla/ComputedStyleInlines.h"
18#include "mozilla/DebugOnly.h"
19#include "mozilla/dom/BindContext.h"
20#include "mozilla/dom/BrowsingContext.h"
21#include "mozilla/dom/CharacterData.h"
22#include "mozilla/dom/Document.h"
23#include "mozilla/dom/DocumentInlines.h"
24#include "mozilla/dom/Element.h"
25#include "mozilla/dom/ElementInlines.h"
26#include "mozilla/dom/GeneratedImageContent.h"
27#include "mozilla/dom/HTMLInputElement.h"
28#include "mozilla/dom/HTMLSelectElement.h"
29#include "mozilla/dom/HTMLSharedListElement.h"
30#include "mozilla/dom/HTMLSummaryElement.h"
31#include "mozilla/ErrorResult.h"
32#include "mozilla/Likely.h"
33#include "mozilla/LinkedList.h"
34#include "mozilla/ManualNAC.h"
35#include "mozilla/MemoryReporting.h"
36#include "mozilla/PresShell.h"
37#include "mozilla/PresShellInlines.h"
38#include "mozilla/PrintedSheetFrame.h"
39#include "mozilla/ProfilerLabels.h"
40#include "mozilla/ProfilerMarkers.h"
41#include "mozilla/RestyleManager.h"
42#include "mozilla/ScopeExit.h"
43#include "mozilla/ScrollContainerFrame.h"
44#include "mozilla/ServoBindings.h"
45#include "mozilla/ServoStyleSetInlines.h"
46#include "mozilla/StaticPrefs_browser.h"
47#include "mozilla/StaticPrefs_layout.h"
48#include "mozilla/StaticPrefs_mathml.h"
49#include "mozilla/SVGGradientFrame.h"
50#include "mozilla/Unused.h"
51#include "nsAbsoluteContainingBlock.h"
52#include "nsAtom.h"
53#include "nsAutoLayoutPhase.h"
54#include "nsBackdropFrame.h"
55#include "nsBlockFrame.h"
56#include "nsCanvasFrame.h"
57#include "nsCheckboxRadioFrame.h"
58#include "nsComboboxControlFrame.h"
59#include "nsContainerFrame.h"
60#include "nsContentUtils.h"
61#include "nsCRT.h"
62#include "nsCSSAnonBoxes.h"
63#include "nsCSSPseudoElements.h"
64#include "nsError.h"
65#include "nsFieldSetFrame.h"
66#include "nsFirstLetterFrame.h"
67#include "nsFlexContainerFrame.h"
68#include "nsGkAtoms.h"
69#include "nsGridContainerFrame.h"
70#include "nsHTMLParts.h"
71#include "nsIAnonymousContentCreator.h"
72#include "nsIFormControl.h"
73#include "nsIFrameInlines.h"
74#include "nsImageFrame.h"
75#include "nsInlineFrame.h"
76#include "nsIObjectLoadingContent.h"
77#include "nsIPopupContainer.h"
78#include "nsIScriptError.h"
79#include "nsLayoutUtils.h"
80#include "nsListControlFrame.h"
81#include "nsMathMLParts.h"
82#include "nsNameSpaceManager.h"
83#include "nsPageContentFrame.h"
84#include "nsPageFrame.h"
85#include "nsPageSequenceFrame.h"
86#include "nsPlaceholderFrame.h"
87#include "nsPresContext.h"
88#include "nsRefreshDriver.h"
89#include "nsRubyBaseContainerFrame.h"
90#include "nsRubyBaseFrame.h"
91#include "nsRubyFrame.h"
92#include "nsRubyTextContainerFrame.h"
93#include "nsRubyTextFrame.h"
94#include "nsStyleConsts.h"
95#include "nsStyleStructInlines.h"
96#include "nsTableCellFrame.h"
97#include "nsTableColFrame.h"
98#include "nsTableFrame.h"
99#include "nsTableRowFrame.h"
100#include "nsTableRowGroupFrame.h"
101#include "nsTableWrapperFrame.h"
102#include "nsTArray.h"
103#include "nsTextFragment.h"
104#include "nsTextNode.h"
105#include "nsTransitionManager.h"
106#include "nsUnicharUtils.h"
107#include "nsViewManager.h"
108#include "nsXULElement.h"
109#include "RetainedDisplayListBuilder.h"
110#include "RubyUtils.h"
111#include "StickyScrollContainer.h"
112
113#ifdef XP_MACOSX
114# include "nsIDocShell.h"
115#endif
116
117#ifdef ACCESSIBILITY1
118# include "nsAccessibilityService.h"
119#endif
120
121#undef NOISY_FIRST_LETTER
122
123using namespace mozilla;
124using namespace mozilla::dom;
125
126nsIFrame* NS_NewHTMLCanvasFrame(PresShell* aPresShell, ComputedStyle* aStyle);
127
128nsIFrame* NS_NewHTMLVideoFrame(PresShell* aPresShell, ComputedStyle* aStyle);
129nsIFrame* NS_NewHTMLAudioFrame(PresShell* aPresShell, ComputedStyle* aStyle);
130
131nsContainerFrame* NS_NewSVGOuterSVGFrame(PresShell* aPresShell,
132 ComputedStyle* aStyle);
133nsContainerFrame* NS_NewSVGOuterSVGAnonChildFrame(PresShell* aPresShell,
134 ComputedStyle* aStyle);
135nsIFrame* NS_NewSVGInnerSVGFrame(PresShell* aPresShell, ComputedStyle* aStyle);
136nsIFrame* NS_NewSVGGeometryFrame(PresShell* aPresShell, ComputedStyle* aStyle);
137nsIFrame* NS_NewSVGGFrame(PresShell* aPresShell, ComputedStyle* aStyle);
138nsContainerFrame* NS_NewSVGForeignObjectFrame(PresShell* aPresShell,
139 ComputedStyle* aStyle);
140nsIFrame* NS_NewSVGAFrame(PresShell* aPresShell, ComputedStyle* aStyle);
141nsIFrame* NS_NewSVGSwitchFrame(PresShell* aPresShell, ComputedStyle* aStyle);
142nsIFrame* NS_NewSVGSymbolFrame(PresShell* aPresShell, ComputedStyle* aStyle);
143nsIFrame* NS_NewSVGTextFrame(PresShell* aPresShell, ComputedStyle* aStyle);
144nsIFrame* NS_NewSVGContainerFrame(PresShell* aPresShell, ComputedStyle* aStyle);
145nsIFrame* NS_NewSVGUseFrame(PresShell* aPresShell, ComputedStyle* aStyle);
146nsIFrame* NS_NewSVGViewFrame(PresShell* aPresShell, ComputedStyle* aStyle);
147extern nsIFrame* NS_NewSVGLinearGradientFrame(PresShell* aPresShell,
148 ComputedStyle* aStyle);
149extern nsIFrame* NS_NewSVGRadialGradientFrame(PresShell* aPresShell,
150 ComputedStyle* aStyle);
151extern nsIFrame* NS_NewSVGStopFrame(PresShell* aPresShell,
152 ComputedStyle* aStyle);
153nsContainerFrame* NS_NewSVGMarkerFrame(PresShell* aPresShell,
154 ComputedStyle* aStyle);
155nsContainerFrame* NS_NewSVGMarkerAnonChildFrame(PresShell* aPresShell,
156 ComputedStyle* aStyle);
157extern nsIFrame* NS_NewSVGImageFrame(PresShell* aPresShell,
158 ComputedStyle* aStyle);
159nsIFrame* NS_NewSVGClipPathFrame(PresShell* aPresShell, ComputedStyle* aStyle);
160nsIFrame* NS_NewSVGFilterFrame(PresShell* aPresShell, ComputedStyle* aStyle);
161nsIFrame* NS_NewSVGPatternFrame(PresShell* aPresShell, ComputedStyle* aStyle);
162nsIFrame* NS_NewSVGMaskFrame(PresShell* aPresShell, ComputedStyle* aStyle);
163nsIFrame* NS_NewSVGFEContainerFrame(PresShell* aPresShell,
164 ComputedStyle* aStyle);
165nsIFrame* NS_NewSVGFELeafFrame(PresShell* aPresShell, ComputedStyle* aStyle);
166nsIFrame* NS_NewSVGFEImageFrame(PresShell* aPresShell, ComputedStyle* aStyle);
167nsIFrame* NS_NewSVGFEUnstyledLeafFrame(PresShell* aPresShell,
168 ComputedStyle* aStyle);
169nsIFrame* NS_NewFileControlLabelFrame(PresShell*, ComputedStyle*);
170nsIFrame* NS_NewComboboxLabelFrame(PresShell*, ComputedStyle*);
171nsIFrame* NS_NewMiddleCroppingLabelFrame(PresShell*, ComputedStyle*);
172
173#include "mozilla/dom/NodeInfo.h"
174#include "prenv.h"
175#include "nsNodeInfoManager.h"
176#include "nsContentCreatorFunctions.h"
177
178#ifdef DEBUG1
179// Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
180// more of the following flags (comma separated) for handy debug
181// output.
182static bool gNoisyContentUpdates = false;
183static bool gReallyNoisyContentUpdates = false;
184static bool gNoisyInlineConstruction = false;
185
186struct FrameCtorDebugFlags {
187 const char* name;
188 bool* on;
189};
190
191static FrameCtorDebugFlags gFlags[] = {
192 {"content-updates", &gNoisyContentUpdates},
193 {"really-noisy-content-updates", &gReallyNoisyContentUpdates},
194 {"noisy-inline", &gNoisyInlineConstruction}};
195
196# define NUM_DEBUG_FLAGS(sizeof(gFlags) / sizeof(gFlags[0])) (sizeof(gFlags) / sizeof(gFlags[0]))
197#endif
198
199//------------------------------------------------------------------
200
201nsIFrame* NS_NewLeafBoxFrame(PresShell* aPresShell, ComputedStyle* aStyle);
202
203nsIFrame* NS_NewRangeFrame(PresShell* aPresShell, ComputedStyle* aStyle);
204
205nsIFrame* NS_NewTextBoxFrame(PresShell* aPresShell, ComputedStyle* aStyle);
206
207nsIFrame* NS_NewSplitterFrame(PresShell* aPresShell, ComputedStyle* aStyle);
208
209nsIFrame* NS_NewMenuPopupFrame(PresShell* aPresShell, ComputedStyle* aStyle);
210
211nsIFrame* NS_NewTreeBodyFrame(PresShell* aPresShell, ComputedStyle* aStyle);
212
213nsIFrame* NS_NewSliderFrame(PresShell* aPresShell, ComputedStyle* aStyle);
214
215nsIFrame* NS_NewScrollbarFrame(PresShell* aPresShell, ComputedStyle* aStyle);
216
217nsIFrame* NS_NewScrollbarButtonFrame(PresShell*, ComputedStyle*);
218nsIFrame* NS_NewSimpleXULLeafFrame(PresShell*, ComputedStyle*);
219
220nsIFrame* NS_NewXULImageFrame(PresShell*, ComputedStyle*);
221nsIFrame* NS_NewImageFrameForContentProperty(PresShell*, ComputedStyle*);
222nsIFrame* NS_NewImageFrameForGeneratedContentIndex(PresShell*, ComputedStyle*);
223nsIFrame* NS_NewImageFrameForListStyleImage(PresShell*, ComputedStyle*);
224nsIFrame* NS_NewImageFrameForViewTransitionOld(PresShell*, ComputedStyle*);
225
226// Returns true if aFrame is an anonymous flex/grid item.
227static inline bool IsAnonymousItem(const nsIFrame* aFrame) {
228 return aFrame->Style()->GetPseudoType() == PseudoStyleType::anonymousItem;
229}
230
231// Returns true IFF the given nsIFrame is a nsFlexContainerFrame and represents
232// a -webkit-{inline-}box container.
233static inline bool IsFlexContainerForLegacyWebKitBox(const nsIFrame* aFrame) {
234 return aFrame->IsFlexContainerFrame() &&
235 aFrame->HasAnyStateBits(NS_STATE_FLEX_IS_EMULATING_LEGACY_WEBKIT_BOX);
236}
237
238#if DEBUG1
239static void AssertAnonymousFlexOrGridItemParent(const nsIFrame* aChild,
240 const nsIFrame* aParent) {
241 MOZ_ASSERT(IsAnonymousItem(aChild), "expected an anonymous item child frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsAnonymousItem(aChild))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsAnonymousItem(aChild)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsAnonymousItem(aChild)"
" (" "expected an anonymous item child frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsAnonymousItem(aChild)"
") (" "expected an anonymous item child frame" ")"); do { *(
(volatile int*)__null) = 241; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
242 MOZ_ASSERT(aParent, "expected a parent frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParent" " (" "expected a parent frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ") ("
"expected a parent frame" ")"); do { *((volatile int*)__null
) = 242; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
243 MOZ_ASSERT(aParent->IsFlexOrGridContainer(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->IsFlexOrGridContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent->IsFlexOrGridContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent->IsFlexOrGridContainer()" " (" "anonymous items should only exist as children of flex/grid "
"container frames" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsFlexOrGridContainer()"
") (" "anonymous items should only exist as children of flex/grid "
"container frames" ")"); do { *((volatile int*)__null) = 245
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
244 "anonymous items should only exist as children of flex/grid "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->IsFlexOrGridContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent->IsFlexOrGridContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent->IsFlexOrGridContainer()" " (" "anonymous items should only exist as children of flex/grid "
"container frames" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsFlexOrGridContainer()"
") (" "anonymous items should only exist as children of flex/grid "
"container frames" ")"); do { *((volatile int*)__null) = 245
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
245 "container frames")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->IsFlexOrGridContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent->IsFlexOrGridContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent->IsFlexOrGridContainer()" " (" "anonymous items should only exist as children of flex/grid "
"container frames" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsFlexOrGridContainer()"
") (" "anonymous items should only exist as children of flex/grid "
"container frames" ")"); do { *((volatile int*)__null) = 245
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
246}
247#else
248# define AssertAnonymousFlexOrGridItemParent(x, y) PR_BEGIN_MACROdo { PR_END_MACRO} while (0)
249#endif
250
251#define ToCreationFunc(_func)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
_func(aPs, aStyle); }
\
252 [](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { \
253 return _func(aPs, aStyle); \
254 }
255
256/**
257 * True if aFrame is an actual inline frame in the sense of non-replaced
258 * display:inline CSS boxes. In other words, it can be affected by {ib}
259 * splitting and can contain first-letter frames. Basically, this is either an
260 * inline frame (positioned or otherwise) or an line frame (this last because
261 * it can contain first-letter and because inserting blocks in the middle of it
262 * needs to terminate it).
263 */
264static bool IsInlineFrame(const nsIFrame* aFrame) {
265 return aFrame->IsLineParticipant();
266}
267
268/**
269 * True for display: contents elements.
270 */
271static inline bool IsDisplayContents(const Element* aElement) {
272 return aElement->IsDisplayContents();
273}
274
275static inline bool IsDisplayContents(const nsIContent* aContent) {
276 return aContent->IsElement() && IsDisplayContents(aContent->AsElement());
277}
278
279/**
280 * True if aFrame is an instance of an SVG frame class or is an inline/block
281 * frame being used for SVG text.
282 */
283static bool IsFrameForSVG(const nsIFrame* aFrame) {
284 return aFrame->IsSVGFrame() || aFrame->IsInSVGTextSubtree();
285}
286
287static bool IsLastContinuationForColumnContent(const nsIFrame* aFrame) {
288 MOZ_ASSERT(aFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ")")
; do { *((volatile int*)__null) = 288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
289 return aFrame->Style()->GetPseudoType() == PseudoStyleType::columnContent &&
290 !aFrame->GetNextContinuation();
291}
292
293/**
294 * Returns true iff aFrame explicitly prevents its descendants from floating
295 * (at least, down to the level of descendants which themselves are
296 * float-containing blocks -- those will manage the floating status of any
297 * lower-level descendents inside them, of course).
298 */
299static bool ShouldSuppressFloatingOfDescendants(nsIFrame* aFrame) {
300 return aFrame->IsFlexOrGridContainer() || aFrame->IsMathMLFrame();
301}
302
303// Return true if column-span descendants should be suppressed under aFrame's
304// subtree (until a multi-column container re-establishing a block formatting
305// context). Basically, this is testing whether aFrame establishes a new block
306// formatting context or not.
307static bool ShouldSuppressColumnSpanDescendants(nsIFrame* aFrame) {
308 if (aFrame->Style()->GetPseudoType() == PseudoStyleType::columnContent) {
309 // Never suppress column-span under ::-moz-column-content frames.
310 return false;
311 }
312
313 if (aFrame->IsInlineFrame()) {
314 // Allow inline frames to have column-span block children.
315 return false;
316 }
317
318 if (!aFrame->IsBlockFrameOrSubclass() ||
319 aFrame->HasAnyStateBits(NS_BLOCK_BFC | NS_FRAME_OUT_OF_FLOW) ||
320 aFrame->IsFixedPosContainingBlock()) {
321 // Need to suppress column-span if we:
322 // - Are a different block formatting context,
323 // - Are an out-of-flow frame, OR
324 // - Establish a containing block for fixed-position descendants
325 //
326 // For example, the children of a column-span never need to be further
327 // processed even if there is a nested column-span child. Because a
328 // column-span always creates its own block formatting context, a nested
329 // column-span child won't be in the same block formatting context with the
330 // nearest multi-column ancestor. This is the same case as if the
331 // column-span is outside of a multi-column hierarchy.
332 return true;
333 }
334
335 return false;
336}
337
338// Reparent a frame into a wrapper frame that is a child of its old parent.
339static void ReparentFrame(RestyleManager* aRestyleManager,
340 nsContainerFrame* aNewParentFrame, nsIFrame* aFrame,
341 bool aForceStyleReparent) {
342 aFrame->SetParent(aNewParentFrame);
343 // We reparent frames for two reasons: to put them inside ::first-line, and to
344 // put them inside some wrapper anonymous boxes.
345 if (aForceStyleReparent) {
346 aRestyleManager->ReparentComputedStyleForFirstLine(aFrame);
347 }
348}
349
350static void ReparentFrames(nsCSSFrameConstructor* aFrameConstructor,
351 nsContainerFrame* aNewParentFrame,
352 const nsFrameList& aFrameList,
353 bool aForceStyleReparent) {
354 RestyleManager* restyleManager = aFrameConstructor->RestyleManager();
355 for (nsIFrame* f : aFrameList) {
356 ReparentFrame(restyleManager, aNewParentFrame, f, aForceStyleReparent);
357 }
358}
359
360//----------------------------------------------------------------------
361//
362// When inline frames get weird and have block frames in them, we
363// annotate them to help us respond to incremental content changes
364// more easily.
365
366static inline bool IsFramePartOfIBSplit(nsIFrame* aFrame) {
367 bool result = aFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT);
368 MOZ_ASSERT(!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!result || static_cast<nsBlockFrame*>(do_QueryFrame
(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(
aFrame)))>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(!result || static_cast<nsBlockFrame
*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*
>(do_QueryFrame(aFrame))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(aFrame))"
" (" "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(aFrame))"
") (" "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT"
")"); do { *((volatile int*)__null) = 370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
369 static_cast<nsInlineFrame*>(do_QueryFrame(aFrame)),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!result || static_cast<nsBlockFrame*>(do_QueryFrame
(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(
aFrame)))>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(!result || static_cast<nsBlockFrame
*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*
>(do_QueryFrame(aFrame))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(aFrame))"
" (" "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(aFrame))"
") (" "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT"
")"); do { *((volatile int*)__null) = 370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
370 "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!result || static_cast<nsBlockFrame*>(do_QueryFrame
(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(
aFrame)))>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(!result || static_cast<nsBlockFrame
*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*
>(do_QueryFrame(aFrame))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(aFrame))"
" (" "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!result || static_cast<nsBlockFrame*>(do_QueryFrame(aFrame)) || static_cast<nsInlineFrame*>(do_QueryFrame(aFrame))"
") (" "only block/inline frames can have NS_FRAME_PART_OF_IBSPLIT"
")"); do { *((volatile int*)__null) = 370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
371 return result;
372}
373
374static nsContainerFrame* GetIBSplitSibling(nsIFrame* aFrame) {
375 MOZ_ASSERT(IsFramePartOfIBSplit(aFrame), "Shouldn't call this")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFramePartOfIBSplit(aFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFramePartOfIBSplit(aFrame)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsFramePartOfIBSplit(aFrame)" " (" "Shouldn't call this" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "Shouldn't call this" ")"); do { *((volatile int*)__null
) = 375; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
376
377 // We only store the "ib-split sibling" annotation with the first
378 // frame in the continuation chain. Walk back to find that frame now.
379 return aFrame->FirstContinuation()->GetProperty(nsIFrame::IBSplitSibling());
380}
381
382static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame) {
383 MOZ_ASSERT(IsFramePartOfIBSplit(aFrame), "Shouldn't call this")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFramePartOfIBSplit(aFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFramePartOfIBSplit(aFrame)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsFramePartOfIBSplit(aFrame)" " (" "Shouldn't call this" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 383); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "Shouldn't call this" ")"); do { *((volatile int*)__null
) = 383; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
384
385 // We only store the ib-split sibling annotation with the first
386 // frame in the continuation chain. Walk back to find that frame now.
387 return aFrame->FirstContinuation()->GetProperty(
388 nsIFrame::IBSplitPrevSibling());
389}
390
391static nsContainerFrame* GetLastIBSplitSibling(nsIFrame* aFrame) {
392 for (nsIFrame *frame = aFrame, *next;; frame = next) {
393 next = GetIBSplitSibling(frame);
394 if (!next) {
395 return static_cast<nsContainerFrame*>(frame);
396 }
397 }
398 MOZ_ASSERT_UNREACHABLE("unreachable code")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"unreachable code" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 398); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unreachable code" ")"); do { *((
volatile int*)__null) = 398; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
399 return nullptr;
400}
401
402static void SetFrameIsIBSplit(nsContainerFrame* aFrame,
403 nsContainerFrame* aIBSplitSibling) {
404 MOZ_ASSERT(aFrame, "bad args!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "bad args!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"bad args!" ")"); do { *((volatile int*)__null) = 404; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
405
406 // We should be the only continuation
407 NS_ASSERTION(!aFrame->GetPrevContinuation(),do { if (!(!aFrame->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "assigning ib-split sibling to other than first continuation!"
, "!aFrame->GetPrevContinuation()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 408); MOZ_PretendNoReturn(); } } while (0)
408 "assigning ib-split sibling to other than first continuation!")do { if (!(!aFrame->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "assigning ib-split sibling to other than first continuation!"
, "!aFrame->GetPrevContinuation()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 408); MOZ_PretendNoReturn(); } } while (0)
;
409 NS_ASSERTION(!aFrame->GetNextContinuation() ||do { if (!(!aFrame->GetNextContinuation() || IsFramePartOfIBSplit
(aFrame->GetNextContinuation()))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "should have no non-ib-split continuations here", "!aFrame->GetNextContinuation() || IsFramePartOfIBSplit(aFrame->GetNextContinuation())"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 411); MOZ_PretendNoReturn(); } } while (0)
410 IsFramePartOfIBSplit(aFrame->GetNextContinuation()),do { if (!(!aFrame->GetNextContinuation() || IsFramePartOfIBSplit
(aFrame->GetNextContinuation()))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "should have no non-ib-split continuations here", "!aFrame->GetNextContinuation() || IsFramePartOfIBSplit(aFrame->GetNextContinuation())"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 411); MOZ_PretendNoReturn(); } } while (0)
411 "should have no non-ib-split continuations here")do { if (!(!aFrame->GetNextContinuation() || IsFramePartOfIBSplit
(aFrame->GetNextContinuation()))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "should have no non-ib-split continuations here", "!aFrame->GetNextContinuation() || IsFramePartOfIBSplit(aFrame->GetNextContinuation())"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 411); MOZ_PretendNoReturn(); } } while (0)
;
412
413 // Mark the frame as ib-split.
414 aFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
415
416 if (aIBSplitSibling) {
417 NS_ASSERTION(!aIBSplitSibling->GetPrevContinuation(),do { if (!(!aIBSplitSibling->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "assigning something other than the first continuation as the "
"ib-split sibling", "!aIBSplitSibling->GetPrevContinuation()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 419); MOZ_PretendNoReturn(); } } while (0)
418 "assigning something other than the first continuation as the "do { if (!(!aIBSplitSibling->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "assigning something other than the first continuation as the "
"ib-split sibling", "!aIBSplitSibling->GetPrevContinuation()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 419); MOZ_PretendNoReturn(); } } while (0)
419 "ib-split sibling")do { if (!(!aIBSplitSibling->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "assigning something other than the first continuation as the "
"ib-split sibling", "!aIBSplitSibling->GetPrevContinuation()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 419); MOZ_PretendNoReturn(); } } while (0)
;
420
421 // Store the ib-split sibling (if we were given one) with the
422 // first frame in the flow.
423 aFrame->SetProperty(nsIFrame::IBSplitSibling(), aIBSplitSibling);
424 aIBSplitSibling->SetProperty(nsIFrame::IBSplitPrevSibling(), aFrame);
425 }
426}
427
428static nsIFrame* GetIBContainingBlockFor(nsIFrame* aFrame) {
429 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFramePartOfIBSplit(aFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFramePartOfIBSplit(aFrame)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsFramePartOfIBSplit(aFrame)" " (" "GetIBContainingBlockFor() should only be called on known IB frames"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "GetIBContainingBlockFor() should only be called on known IB frames"
")"); do { *((volatile int*)__null) = 431; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
430 IsFramePartOfIBSplit(aFrame),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFramePartOfIBSplit(aFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFramePartOfIBSplit(aFrame)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsFramePartOfIBSplit(aFrame)" " (" "GetIBContainingBlockFor() should only be called on known IB frames"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "GetIBContainingBlockFor() should only be called on known IB frames"
")"); do { *((volatile int*)__null) = 431; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
431 "GetIBContainingBlockFor() should only be called on known IB frames")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFramePartOfIBSplit(aFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFramePartOfIBSplit(aFrame)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsFramePartOfIBSplit(aFrame)" " (" "GetIBContainingBlockFor() should only be called on known IB frames"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFramePartOfIBSplit(aFrame)"
") (" "GetIBContainingBlockFor() should only be called on known IB frames"
")"); do { *((volatile int*)__null) = 431; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
432
433 // Get the first "normal" ancestor of the target frame.
434 nsIFrame* parentFrame;
435 do {
436 parentFrame = aFrame->GetParent();
437
438 if (!parentFrame) {
439 NS_ERROR("no unsplit block frame in IB hierarchy")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "no unsplit block frame in IB hierarchy"
, "Error", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 439); MOZ_PretendNoReturn(); } while (0)
;
440 return aFrame;
441 }
442
443 // Note that we ignore non-ib-split frames which have a pseudo on their
444 // ComputedStyle -- they're not the frames we're looking for! In
445 // particular, they may be hiding a real parent that _is_ in an ib-split.
446 if (!IsFramePartOfIBSplit(parentFrame) &&
447 !parentFrame->Style()->IsPseudoOrAnonBox()) {
448 break;
449 }
450
451 aFrame = parentFrame;
452 } while (true);
453
454 // post-conditions
455 NS_ASSERTION(parentFrame,do { if (!(parentFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "no normal ancestor found for ib-split frame "
"in GetIBContainingBlockFor", "parentFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 457); MOZ_PretendNoReturn(); } } while (0)
456 "no normal ancestor found for ib-split frame "do { if (!(parentFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "no normal ancestor found for ib-split frame "
"in GetIBContainingBlockFor", "parentFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 457); MOZ_PretendNoReturn(); } } while (0)
457 "in GetIBContainingBlockFor")do { if (!(parentFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "no normal ancestor found for ib-split frame "
"in GetIBContainingBlockFor", "parentFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 457); MOZ_PretendNoReturn(); } } while (0)
;
458 NS_ASSERTION(parentFrame != aFrame,do { if (!(parentFrame != aFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "parentFrame is actually the child frame - bogus reslt", "parentFrame != aFrame"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 459); MOZ_PretendNoReturn(); } } while (0)
459 "parentFrame is actually the child frame - bogus reslt")do { if (!(parentFrame != aFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "parentFrame is actually the child frame - bogus reslt", "parentFrame != aFrame"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 459); MOZ_PretendNoReturn(); } } while (0)
;
460
461 return parentFrame;
462}
463
464// Find the multicol containing block suitable for reframing.
465//
466// Note: this function may not return a ColumnSetWrapperFrame. For example, if
467// the multicol containing block has "overflow:scroll" style,
468// ScrollContainerFrame is returned because ColumnSetWrapperFrame is the
469// scrolled frame which has the -moz-scrolled-content pseudo style. We may walk
470// up "too far", but in terms of correctness of reframing, it's OK.
471static nsContainerFrame* GetMultiColumnContainingBlockFor(nsIFrame* aFrame) {
472 MOZ_ASSERT(aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
" (" "Should only be called if the frame has a multi-column ancestor!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Should only be called if the frame has a multi-column ancestor!"
")"); do { *((volatile int*)__null) = 473; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
473 "Should only be called if the frame has a multi-column ancestor!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
" (" "Should only be called if the frame has a multi-column ancestor!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Should only be called if the frame has a multi-column ancestor!"
")"); do { *((volatile int*)__null) = 473; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
474
475 nsContainerFrame* current = aFrame->GetParent();
476 while (current &&
477 (current->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) ||
478 current->Style()->IsPseudoOrAnonBox())) {
479 current = current->GetParent();
480 }
481
482 MOZ_ASSERT(current,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(current)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(current))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("current" " (" "No multicol containing block in a valid column hierarchy?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "current" ") ("
"No multicol containing block in a valid column hierarchy?" ")"
); do { *((volatile int*)__null) = 483; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
483 "No multicol containing block in a valid column hierarchy?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(current)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(current))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("current" " (" "No multicol containing block in a valid column hierarchy?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "current" ") ("
"No multicol containing block in a valid column hierarchy?" ")"
); do { *((volatile int*)__null) = 483; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
484
485 return current;
486}
487
488static bool InsertSeparatorBeforeAccessKey() {
489 static bool sInitialized = false;
490 static bool sValue = false;
491 if (!sInitialized) {
492 sInitialized = true;
493
494 const char* prefName = "intl.menuitems.insertseparatorbeforeaccesskeys";
495 nsAutoString val;
496 Preferences::GetLocalizedString(prefName, val);
497 sValue = val.EqualsLiteral("true");
498 }
499 return sValue;
500}
501
502static bool AlwaysAppendAccessKey() {
503 static bool sInitialized = false;
504 static bool sValue = false;
505 if (!sInitialized) {
506 sInitialized = true;
507 const char* prefName = "intl.menuitems.alwaysappendaccesskeys";
508 nsAutoString val;
509 Preferences::GetLocalizedString(prefName, val);
510 sValue = val.EqualsLiteral("true");
511 }
512 return sValue;
513}
514
515//----------------------------------------------------------------------
516
517// Block/inline frame construction logic. We maintain a few invariants here:
518//
519// 1. Block frames contain block and inline frames.
520//
521// 2. Inline frames only contain inline frames. If an inline parent has a block
522// child then the block child is migrated upward until it lands in a block
523// parent (the inline frames containing block is where it will end up).
524
525inline void SetInitialSingleChild(nsContainerFrame* aParent, nsIFrame* aFrame) {
526 MOZ_ASSERT(!aFrame->GetNextSibling(), "Should be using a frame list")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->GetNextSibling()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->GetNextSibling()" " (" "Should be using a frame list"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 526); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->GetNextSibling()"
") (" "Should be using a frame list" ")"); do { *((volatile int
*)__null) = 526; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
527 aParent->SetInitialChildList(FrameChildListID::Principal,
528 nsFrameList(aFrame, aFrame));
529}
530
531// -----------------------------------------------------------
532
533// Structure used when constructing formatting object trees. Contains
534// state information needed for absolutely positioned elements
535namespace mozilla {
536struct AbsoluteFrameList final : public nsFrameList {
537 // Containing block for absolutely positioned elements.
538 nsContainerFrame* mContainingBlock;
539
540 explicit AbsoluteFrameList(nsContainerFrame* aContainingBlock = nullptr)
541 : mContainingBlock(aContainingBlock) {}
542
543 // Transfer frames in aOther to this list. aOther becomes empty after this
544 // operation.
545 AbsoluteFrameList(AbsoluteFrameList&& aOther) = default;
546 AbsoluteFrameList& operator=(AbsoluteFrameList&& aOther) = default;
547
548#ifdef DEBUG1
549 // XXXbz Does this need a debug-only assignment operator that nulls out the
550 // childList in the AbsoluteFrameList we're copying? Introducing a difference
551 // between debug and non-debug behavior seems bad, so I guess not...
552 ~AbsoluteFrameList() {
553 NS_ASSERTION(!FirstChild(),do { if (!(!FirstChild())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Dangling child list. Someone forgot to insert it?", "!FirstChild()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 554); MOZ_PretendNoReturn(); } } while (0)
554 "Dangling child list. Someone forgot to insert it?")do { if (!(!FirstChild())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Dangling child list. Someone forgot to insert it?", "!FirstChild()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 554); MOZ_PretendNoReturn(); } } while (0)
;
555 }
556#endif
557};
558} // namespace mozilla
559
560// -----------------------------------------------------------
561
562// Structure for saving the existing state when pushing/poping containing
563// blocks. The destructor restores the state to its previous state
564class MOZ_STACK_CLASS nsFrameConstructorSaveState {
565 public:
566 ~nsFrameConstructorSaveState();
567
568 private:
569 // Pointer to struct whose data we save/restore.
570 AbsoluteFrameList* mList = nullptr;
571
572 // The saved pointer to the fixed list.
573 AbsoluteFrameList* mSavedFixedList = nullptr;
574
575 // Copy of original frame list. This can be the original absolute list or a
576 // float list.
577 AbsoluteFrameList mSavedList;
578
579 // The name of the child list in which our frames would belong.
580 mozilla::FrameChildListID mChildListID = FrameChildListID::Principal;
581 nsFrameConstructorState* mState = nullptr;
582
583 friend class nsFrameConstructorState;
584};
585
586// Structure used for maintaining state information during the
587// frame construction process
588class MOZ_STACK_CLASS nsFrameConstructorState {
589 public:
590 nsPresContext* mPresContext;
591 PresShell* mPresShell;
592 nsCSSFrameConstructor* mFrameConstructor;
593
594 // Containing block information for out-of-flow frames.
595 //
596 // Floats are easy. Whatever is our float CB.
597 //
598 // Regular abspos elements are easy too. Its containing block can be the
599 // nearest abspos element, or the ICB (the canvas frame).
600 //
601 // Top layer abspos elements are always children of the ICB, but we can get
602 // away with having two different lists (mAbsoluteList and
603 // mTopLayerAbsoluteList), because because top layer frames cause
604 // non-top-layer frames to be contained inside (so any descendants of a top
605 // layer abspos can never share containing block with it, unless they're also
606 // in the top layer).
607 //
608 // Regular fixed elements however are trickier. Fixed elements can be
609 // contained in one of three lists:
610 //
611 // * mAbsoluteList, if our abspos cb is also a fixpos cb (e.g., is
612 // transformed or has a filter).
613 //
614 // * mAncestorFixedList, if the fixpos cb is an ancestor element other than
615 // the viewport frame, (so, a transformed / filtered
616 // ancestor).
617 //
618 // * mRealFixedList, which is also the fixed list used for the top layer
619 // fixed items, which is the fixed list of the viewport
620 // frame.
621 //
622 // It is important that mRealFixedList is shared between regular and top layer
623 // fixpos elements, since no-top-layer descendants of top layer fixed elements
624 // could share ICB and vice versa, so without that there would be no guarantee
625 // of layout ordering between them.
626 AbsoluteFrameList mFloatedList;
627 AbsoluteFrameList mAbsoluteList;
628 AbsoluteFrameList mTopLayerAbsoluteList;
629 AbsoluteFrameList mAncestorFixedList;
630 AbsoluteFrameList mRealFixedList;
631
632 // Never null, always pointing to one of the lists documented above.
633 AbsoluteFrameList* mFixedList;
634
635 // What `page: auto` resolves to. This is the used page-name of the parent
636 // frame. Updated by AutoFrameConstructionPageName.
637 const nsAtom* mAutoPageNameValue = nullptr;
638
639 nsCOMPtr<nsILayoutHistoryState> mFrameState;
640 // These bits will be added to the state bits of any frame we construct
641 // using this state.
642 nsFrameState mAdditionalStateBits{0};
643
644 // If false (which is the default) then call SetPrimaryFrame() as needed
645 // during frame construction. If true, don't make any SetPrimaryFrame()
646 // calls, except for generated content which doesn't have a primary frame
647 // yet. The mCreatingExtraFrames == true mode is meant to be used for
648 // construction of random "extra" frames for elements via normal frame
649 // construction APIs (e.g. replication of things across pages in paginated
650 // mode).
651 bool mCreatingExtraFrames;
652
653 // This keeps track of whether we have found a "rendered legend" for
654 // the current FieldSetFrame.
655 bool mHasRenderedLegend;
656
657 nsTArray<RefPtr<nsIContent>> mGeneratedContentWithInitializer;
658
659#ifdef DEBUG1
660 // Record the float containing block candidate passed into
661 // MaybePushFloatContainingBlock() to keep track that we've call the method to
662 // handle the float CB scope before processing the CB's children. It is reset
663 // in ConstructFramesFromItemList().
664 nsContainerFrame* mFloatCBCandidate = nullptr;
665#endif
666
667 // Constructor
668 // Use the passed-in history state.
669 nsFrameConstructorState(
670 PresShell* aPresShell, nsContainerFrame* aFixedContainingBlock,
671 nsContainerFrame* aAbsoluteContainingBlock,
672 nsContainerFrame* aFloatContainingBlock,
673 already_AddRefed<nsILayoutHistoryState> aHistoryState);
674 // Get the history state from the pres context's pres shell.
675 nsFrameConstructorState(PresShell* aPresShell,
676 nsContainerFrame* aFixedContainingBlock,
677 nsContainerFrame* aAbsoluteContainingBlock,
678 nsContainerFrame* aFloatContainingBlock);
679
680 ~nsFrameConstructorState();
681
682 // Process the frame insertions for all the out-of-flow nsAbsoluteItems.
683 void ProcessFrameInsertionsForAllLists();
684
685 // Function to push the existing absolute containing block state and
686 // create a new scope. Code that uses this function should get matching
687 // logic in GetAbsoluteContainingBlock.
688 // Also makes aNewAbsoluteContainingBlock the containing block for
689 // fixed-pos elements if necessary.
690 // aPositionedFrame is the frame whose style actually makes
691 // aNewAbsoluteContainingBlock a containing block. E.g. for a scrollable
692 // element aPositionedFrame is the element's primary frame and
693 // aNewAbsoluteContainingBlock is the scrolled frame.
694 void PushAbsoluteContainingBlock(
695 nsContainerFrame* aNewAbsoluteContainingBlock, nsIFrame* aPositionedFrame,
696 nsFrameConstructorSaveState& aSaveState);
697
698 // Function to forbid floats descendants under aFloatCBCandidate, or open a
699 // new float containing block scope for aFloatCBCandidate. The current
700 // state is saved in aSaveState if a new scope is pushed.
701 void MaybePushFloatContainingBlock(nsContainerFrame* aFloatCBCandidate,
702 nsFrameConstructorSaveState& aSaveState);
703
704 // Helper function for MaybePushFloatContainingBlock().
705 void PushFloatContainingBlock(nsContainerFrame* aNewFloatContainingBlock,
706 nsFrameConstructorSaveState& aSaveState);
707
708 // Function to return the proper geometric parent for a frame with display
709 // struct given by aStyleDisplay and parent's frame given by
710 // aContentParentFrame.
711 nsContainerFrame* GetGeometricParent(
712 const nsStyleDisplay& aStyleDisplay,
713 nsContainerFrame* aContentParentFrame) const;
714
715 // Collect absolute frames in mAbsoluteList which are proper descendants
716 // of aNewParent, and reparent them to aNewParent.
717 //
718 // Note: This function does something unusual that moves absolute items
719 // after their frames are constructed under a column hierarchy which has
720 // column-span elements. Do not use this if you're not dealing with
721 // columns.
722 void ReparentAbsoluteItems(nsContainerFrame* aNewParent);
723
724 // Collect floats in mFloatedList which are proper descendants of aNewParent,
725 // and reparent them to aNewParent.
726 //
727 // Note: This function does something unusual that moves floats after their
728 // frames are constructed under a column hierarchy which has column-span
729 // elements. Do not use this if you're not dealing with columns.
730 void ReparentFloats(nsContainerFrame* aNewParent);
731
732 /**
733 * Function to add a new frame to the right frame list. This MUST be called
734 * on frames before their children have been processed if the frames might
735 * conceivably be out-of-flow; otherwise cleanup in error cases won't work
736 * right. Also, this MUST be called on frames after they have been
737 * initialized.
738 * @param aNewFrame the frame to add
739 * @param aFrameList the list to add in-flow frames to
740 * @param aContent the content pointer for aNewFrame
741 * @param aParentFrame the parent frame for the content if it were in-flow
742 * @param aCanBePositioned pass false if the frame isn't allowed to be
743 * positioned
744 * @param aCanBeFloated pass false if the frame isn't allowed to be
745 * floated
746 */
747 void AddChild(nsIFrame* aNewFrame, nsFrameList& aFrameList,
748 nsIContent* aContent, nsContainerFrame* aParentFrame,
749 bool aCanBePositioned = true, bool aCanBeFloated = true,
750 bool aInsertAfter = false,
751 nsIFrame* aInsertAfterFrame = nullptr);
752
753 /**
754 * Function to return the fixed-pos element list. Normally this will just
755 * hand back the fixed-pos element list, but in case we're dealing with a
756 * transformed element that's acting as an abs-pos and fixed-pos container,
757 * we'll hand back the abs-pos list. Callers should use this function if they
758 * want to get the list acting as the fixed-pos item parent.
759 */
760 AbsoluteFrameList& GetFixedList() { return *mFixedList; }
761 const AbsoluteFrameList& GetFixedList() const { return *mFixedList; }
762
763 protected:
764 friend class nsFrameConstructorSaveState;
765
766 /**
767 * ProcessFrameInsertions takes the frames in aFrameList and adds them as
768 * kids to the aChildListID child list of |aFrameList.containingBlock|.
769 */
770 void ProcessFrameInsertions(AbsoluteFrameList& aFrameList,
771 mozilla::FrameChildListID aChildListID);
772
773 /**
774 * GetOutOfFlowFrameList selects the out-of-flow frame list the new
775 * frame should be added to. If the frame shouldn't be added to any
776 * out-of-flow list, it returns nullptr. The corresponding type of
777 * placeholder is also returned via the aPlaceholderType parameter
778 * if this method doesn't return nullptr. The caller should check
779 * whether the returned list really has a containing block.
780 */
781 AbsoluteFrameList* GetOutOfFlowFrameList(nsIFrame* aNewFrame,
782 bool aCanBePositioned,
783 bool aCanBeFloated,
784 nsFrameState* aPlaceholderType);
785
786 void ConstructBackdropFrameFor(nsIContent* aContent, nsIFrame* aFrame);
787};
788
789nsFrameConstructorState::nsFrameConstructorState(
790 PresShell* aPresShell, nsContainerFrame* aFixedContainingBlock,
791 nsContainerFrame* aAbsoluteContainingBlock,
792 nsContainerFrame* aFloatContainingBlock,
793 already_AddRefed<nsILayoutHistoryState> aHistoryState)
794 : mPresContext(aPresShell->GetPresContext()),
795 mPresShell(aPresShell),
796 mFrameConstructor(aPresShell->FrameConstructor()),
797 mFloatedList(aFloatContainingBlock),
798 mAbsoluteList(aAbsoluteContainingBlock),
799 mTopLayerAbsoluteList(mFrameConstructor->GetCanvasFrame()),
800 mAncestorFixedList(aFixedContainingBlock),
801 mRealFixedList(
802 static_cast<nsContainerFrame*>(mFrameConstructor->GetRootFrame())),
803 // See PushAbsoluteContaningBlock below
804 mFrameState(aHistoryState),
805 mCreatingExtraFrames(false),
806 mHasRenderedLegend(false) {
807 MOZ_COUNT_CTOR(nsFrameConstructorState)do { static_assert(std::is_class_v<nsFrameConstructorState
>, "Token '" "nsFrameConstructorState" "' is not a class type."
); static_assert(!std::is_base_of<nsISupports, nsFrameConstructorState
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "nsFrameConstructorState"
, sizeof(*this)); } while (0)
;
808 mFixedList = [&] {
809 if (aFixedContainingBlock == aAbsoluteContainingBlock) {
810 return &mAbsoluteList;
811 }
812 if (aAbsoluteContainingBlock == mRealFixedList.mContainingBlock) {
813 return &mRealFixedList;
814 }
815 return &mAncestorFixedList;
816 }();
817}
818
819nsFrameConstructorState::nsFrameConstructorState(
820 PresShell* aPresShell, nsContainerFrame* aFixedContainingBlock,
821 nsContainerFrame* aAbsoluteContainingBlock,
822 nsContainerFrame* aFloatContainingBlock)
823 : nsFrameConstructorState(
824 aPresShell, aFixedContainingBlock, aAbsoluteContainingBlock,
825 aFloatContainingBlock,
826 aPresShell->GetDocument()->GetLayoutHistoryState()) {}
827
828nsFrameConstructorState::~nsFrameConstructorState() {
829 MOZ_COUNT_DTOR(nsFrameConstructorState)do { static_assert(std::is_class_v<nsFrameConstructorState
>, "Token '" "nsFrameConstructorState" "' is not a class type."
); static_assert(!std::is_base_of<nsISupports, nsFrameConstructorState
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "nsFrameConstructorState"
, sizeof(*this)); } while (0)
;
830 ProcessFrameInsertionsForAllLists();
831 for (auto& content : Reversed(mGeneratedContentWithInitializer)) {
832 content->RemoveProperty(nsGkAtoms::genConInitializerProperty);
833 }
834}
835
836void nsFrameConstructorState::ProcessFrameInsertionsForAllLists() {
837 ProcessFrameInsertions(mFloatedList, FrameChildListID::Float);
838 ProcessFrameInsertions(mAbsoluteList, FrameChildListID::Absolute);
839 ProcessFrameInsertions(mTopLayerAbsoluteList, FrameChildListID::Absolute);
840 ProcessFrameInsertions(*mFixedList, FrameChildListID::Fixed);
841 ProcessFrameInsertions(mRealFixedList, FrameChildListID::Fixed);
842}
843
844void nsFrameConstructorState::PushAbsoluteContainingBlock(
845 nsContainerFrame* aNewAbsoluteContainingBlock, nsIFrame* aPositionedFrame,
846 nsFrameConstructorSaveState& aSaveState) {
847 MOZ_ASSERT(!!aNewAbsoluteContainingBlock == !!aPositionedFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!!aNewAbsoluteContainingBlock == !!aPositionedFrame)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!!aNewAbsoluteContainingBlock == !!aPositionedFrame)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!!aNewAbsoluteContainingBlock == !!aPositionedFrame"
" (" "We should have both or none" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!!aNewAbsoluteContainingBlock == !!aPositionedFrame"
") (" "We should have both or none" ")"); do { *((volatile int
*)__null) = 848; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
848 "We should have both or none")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!!aNewAbsoluteContainingBlock == !!aPositionedFrame)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!!aNewAbsoluteContainingBlock == !!aPositionedFrame)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!!aNewAbsoluteContainingBlock == !!aPositionedFrame"
" (" "We should have both or none" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!!aNewAbsoluteContainingBlock == !!aPositionedFrame"
") (" "We should have both or none" ")"); do { *((volatile int
*)__null) = 848; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
849 aSaveState.mList = &mAbsoluteList;
850 aSaveState.mChildListID = FrameChildListID::Absolute;
851 aSaveState.mState = this;
852 aSaveState.mSavedList = std::move(mAbsoluteList);
853 aSaveState.mSavedFixedList = mFixedList;
854 mAbsoluteList = AbsoluteFrameList(aNewAbsoluteContainingBlock);
855 mFixedList = [&] {
856 if (!aPositionedFrame || aPositionedFrame->IsFixedPosContainingBlock()) {
857 // See if we need to treat abspos and fixedpos the same. This happens if
858 // we're a transformed/filtered/etc element, or if we force a null abspos
859 // containing block (for mathml for example).
860 return &mAbsoluteList;
861 }
862 if (aPositionedFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Auto) {
863 // If our new CB is in the top layer, and isn't a fixed CB itself, we also
864 // escape the usual containment.
865 return &mRealFixedList;
866 }
867 if (mFixedList == &mAbsoluteList) {
868 // If we were pointing to our old absolute list, keep pointing to it.
869 return &aSaveState.mSavedList;
870 }
871 // Otherwise keep pointing to the current thing (another ancestor's
872 // absolute list, or the real fixed list, doesn't matter).
873 return mFixedList;
874 }();
875
876 if (aNewAbsoluteContainingBlock) {
877 aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
878 }
879}
880
881void nsFrameConstructorState::MaybePushFloatContainingBlock(
882 nsContainerFrame* aFloatCBCandidate,
883 nsFrameConstructorSaveState& aSaveState) {
884 // The logic here needs to match the logic in GetFloatContainingBlock().
885 if (ShouldSuppressFloatingOfDescendants(aFloatCBCandidate)) {
886 // Pushing a null float containing block forbids any frames from being
887 // floated until a new float containing block is pushed. See implementation
888 // of nsFrameConstructorState::AddChild().
889 //
890 // XXX we should get rid of null float containing blocks and teach the
891 // various frame classes to deal with floats instead.
892 PushFloatContainingBlock(nullptr, aSaveState);
893 } else if (aFloatCBCandidate->IsFloatContainingBlock()) {
894 PushFloatContainingBlock(aFloatCBCandidate, aSaveState);
895 }
896
897#ifdef DEBUG1
898 mFloatCBCandidate = aFloatCBCandidate;
899#endif
900}
901
902void nsFrameConstructorState::PushFloatContainingBlock(
903 nsContainerFrame* aNewFloatContainingBlock,
904 nsFrameConstructorSaveState& aSaveState) {
905 MOZ_ASSERT(!aNewFloatContainingBlock ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aNewFloatContainingBlock || aNewFloatContainingBlock
->IsFloatContainingBlock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aNewFloatContainingBlock ||
aNewFloatContainingBlock->IsFloatContainingBlock()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
" (" "Please push a real float containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
") (" "Please push a real float containing block!" ")"); do {
*((volatile int*)__null) = 907; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
906 aNewFloatContainingBlock->IsFloatContainingBlock(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aNewFloatContainingBlock || aNewFloatContainingBlock
->IsFloatContainingBlock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aNewFloatContainingBlock ||
aNewFloatContainingBlock->IsFloatContainingBlock()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
" (" "Please push a real float containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
") (" "Please push a real float containing block!" ")"); do {
*((volatile int*)__null) = 907; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
907 "Please push a real float containing block!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aNewFloatContainingBlock || aNewFloatContainingBlock
->IsFloatContainingBlock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aNewFloatContainingBlock ||
aNewFloatContainingBlock->IsFloatContainingBlock()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
" (" "Please push a real float containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFloatContainingBlock || aNewFloatContainingBlock->IsFloatContainingBlock()"
") (" "Please push a real float containing block!" ")"); do {
*((volatile int*)__null) = 907; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
908 NS_ASSERTION(do { if (!(!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants
(aNewFloatContainingBlock))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should not push a frame that is supposed to _suppress_ "
"floats as a float containing block!", "!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 912); MOZ_PretendNoReturn(); } } while (0)
909 !aNewFloatContainingBlock ||do { if (!(!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants
(aNewFloatContainingBlock))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should not push a frame that is supposed to _suppress_ "
"floats as a float containing block!", "!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 912); MOZ_PretendNoReturn(); } } while (0)
910 !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock),do { if (!(!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants
(aNewFloatContainingBlock))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should not push a frame that is supposed to _suppress_ "
"floats as a float containing block!", "!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 912); MOZ_PretendNoReturn(); } } while (0)
911 "We should not push a frame that is supposed to _suppress_ "do { if (!(!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants
(aNewFloatContainingBlock))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should not push a frame that is supposed to _suppress_ "
"floats as a float containing block!", "!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 912); MOZ_PretendNoReturn(); } } while (0)
912 "floats as a float containing block!")do { if (!(!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants
(aNewFloatContainingBlock))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "We should not push a frame that is supposed to _suppress_ "
"floats as a float containing block!", "!aNewFloatContainingBlock || !ShouldSuppressFloatingOfDescendants(aNewFloatContainingBlock)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 912); MOZ_PretendNoReturn(); } } while (0)
;
913 aSaveState.mList = &mFloatedList;
914 aSaveState.mSavedList = std::move(mFloatedList);
915 aSaveState.mChildListID = FrameChildListID::Float;
916 aSaveState.mState = this;
917 mFloatedList = AbsoluteFrameList(aNewFloatContainingBlock);
918}
919
920nsContainerFrame* nsFrameConstructorState::GetGeometricParent(
921 const nsStyleDisplay& aStyleDisplay,
922 nsContainerFrame* aContentParentFrame) const {
923 // If there is no container for a fixed, absolute, or floating root
924 // frame, we will ignore the positioning. This hack is originally
925 // brought to you by the letter T: tables, since other roots don't
926 // even call into this code. See bug 178855.
927 //
928 // XXX Disabling positioning in this case is a hack. If one was so inclined,
929 // one could support this either by (1) inserting a dummy block between the
930 // table and the canvas or (2) teaching the canvas how to reflow positioned
931 // elements. (1) has the usual problems when multiple frames share the same
932 // content (notice all the special cases in this file dealing with inner
933 // tables and table wrappers which share the same content). (2) requires some
934 // work and possible factoring.
935 //
936 // XXXbz couldn't we just force position to "static" on roots and
937 // float to "none"? That's OK per CSS 2.1, as far as I can tell.
938
939 if (aContentParentFrame && aContentParentFrame->IsInSVGTextSubtree()) {
940 return aContentParentFrame;
941 }
942
943 if (aStyleDisplay.IsFloatingStyle() && mFloatedList.mContainingBlock) {
944 NS_ASSERTION(!aStyleDisplay.IsAbsolutelyPositionedStyle(),do { if (!(!aStyleDisplay.IsAbsolutelyPositionedStyle())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Absolutely positioned _and_ floating?",
"!aStyleDisplay.IsAbsolutelyPositionedStyle()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 945); MOZ_PretendNoReturn(); } } while (0)
945 "Absolutely positioned _and_ floating?")do { if (!(!aStyleDisplay.IsAbsolutelyPositionedStyle())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Absolutely positioned _and_ floating?",
"!aStyleDisplay.IsAbsolutelyPositionedStyle()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 945); MOZ_PretendNoReturn(); } } while (0)
;
946 return mFloatedList.mContainingBlock;
947 }
948
949 if (aStyleDisplay.mTopLayer != StyleTopLayer::None) {
950 MOZ_ASSERT(aStyleDisplay.mTopLayer == StyleTopLayer::Auto,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.mTopLayer == StyleTopLayer::Auto)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStyleDisplay.mTopLayer == StyleTopLayer::Auto))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aStyleDisplay.mTopLayer == StyleTopLayer::Auto"
" (" "-moz-top-layer should be either none or auto" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.mTopLayer == StyleTopLayer::Auto"
") (" "-moz-top-layer should be either none or auto" ")"); do
{ *((volatile int*)__null) = 951; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
951 "-moz-top-layer should be either none or auto")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.mTopLayer == StyleTopLayer::Auto)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStyleDisplay.mTopLayer == StyleTopLayer::Auto))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aStyleDisplay.mTopLayer == StyleTopLayer::Auto"
" (" "-moz-top-layer should be either none or auto" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.mTopLayer == StyleTopLayer::Auto"
") (" "-moz-top-layer should be either none or auto" ")"); do
{ *((volatile int*)__null) = 951; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
952 MOZ_ASSERT(aStyleDisplay.IsAbsolutelyPositionedStyle(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.IsAbsolutelyPositionedStyle())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aStyleDisplay.IsAbsolutelyPositionedStyle()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aStyleDisplay.IsAbsolutelyPositionedStyle()"
" (" "Top layer items should always be absolutely positioned"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.IsAbsolutelyPositionedStyle()"
") (" "Top layer items should always be absolutely positioned"
")"); do { *((volatile int*)__null) = 953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
953 "Top layer items should always be absolutely positioned")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.IsAbsolutelyPositionedStyle())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aStyleDisplay.IsAbsolutelyPositionedStyle()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aStyleDisplay.IsAbsolutelyPositionedStyle()"
" (" "Top layer items should always be absolutely positioned"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.IsAbsolutelyPositionedStyle()"
") (" "Top layer items should always be absolutely positioned"
")"); do { *((volatile int*)__null) = 953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
954 if (aStyleDisplay.mPosition == StylePositionProperty::Fixed) {
955 MOZ_ASSERT(mRealFixedList.mContainingBlock, "No root frame?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRealFixedList.mContainingBlock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRealFixedList.mContainingBlock
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mRealFixedList.mContainingBlock" " (" "No root frame?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRealFixedList.mContainingBlock"
") (" "No root frame?" ")"); do { *((volatile int*)__null) =
955; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false)
;
956 return mRealFixedList.mContainingBlock;
957 }
958 MOZ_ASSERT(aStyleDisplay.mPosition == StylePositionProperty::Absolute)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyleDisplay.mPosition == StylePositionProperty::Absolute
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStyleDisplay.mPosition == StylePositionProperty::Absolute
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aStyleDisplay.mPosition == StylePositionProperty::Absolute",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyleDisplay.mPosition == StylePositionProperty::Absolute"
")"); do { *((volatile int*)__null) = 958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
959 MOZ_ASSERT(mTopLayerAbsoluteList.mContainingBlock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTopLayerAbsoluteList.mContainingBlock)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mTopLayerAbsoluteList.mContainingBlock))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mTopLayerAbsoluteList.mContainingBlock"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTopLayerAbsoluteList.mContainingBlock"
")"); do { *((volatile int*)__null) = 959; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
960 return mTopLayerAbsoluteList.mContainingBlock;
961 }
962
963 if (aStyleDisplay.mPosition == StylePositionProperty::Absolute &&
964 mAbsoluteList.mContainingBlock) {
965 return mAbsoluteList.mContainingBlock;
966 }
967
968 if (aStyleDisplay.mPosition == StylePositionProperty::Fixed &&
969 mFixedList->mContainingBlock) {
970 return mFixedList->mContainingBlock;
971 }
972
973 return aContentParentFrame;
974}
975
976void nsFrameConstructorState::ReparentAbsoluteItems(
977 nsContainerFrame* aNewParent) {
978 // Bug 1491727: This function might not conform to the spec. See
979 // https://github.com/w3c/csswg-drafts/issues/1894.
980
981 MOZ_ASSERT(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
" (" "Restrict the usage under column hierarchy." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 982; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
982 "Restrict the usage under column hierarchy.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
" (" "Restrict the usage under column hierarchy." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 982; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
983
984 AbsoluteFrameList newAbsoluteItems(aNewParent);
985
986 nsIFrame* current = mAbsoluteList.FirstChild();
987 while (current) {
988 nsIFrame* placeholder = current->GetPlaceholderFrame();
989
990 if (nsLayoutUtils::IsProperAncestorFrame(aNewParent, placeholder)) {
991 nsIFrame* next = current->GetNextSibling();
992 mAbsoluteList.RemoveFrame(current);
993 newAbsoluteItems.AppendFrame(aNewParent, current);
994 current = next;
995 } else {
996 current = current->GetNextSibling();
997 }
998 }
999
1000 if (newAbsoluteItems.NotEmpty()) {
1001 // ~nsFrameConstructorSaveState() will move newAbsoluteItems to
1002 // aNewParent's absolute child list.
1003 nsFrameConstructorSaveState absoluteSaveState;
1004
1005 // It doesn't matter whether aNewParent has position style or not. Caller
1006 // won't call us if we can't have absolute children.
1007 PushAbsoluteContainingBlock(aNewParent, aNewParent, absoluteSaveState);
1008 mAbsoluteList = std::move(newAbsoluteItems);
1009 }
1010}
1011
1012void nsFrameConstructorState::ReparentFloats(nsContainerFrame* aNewParent) {
1013 MOZ_ASSERT(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
" (" "Restrict the usage under column hierarchy." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 1014; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1014 "Restrict the usage under column hierarchy.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
" (" "Restrict the usage under column hierarchy." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)"
") (" "Restrict the usage under column hierarchy." ")"); do {
*((volatile int*)__null) = 1014; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1015 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->IsFloatContainingBlock())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aNewParent->IsFloatContainingBlock()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewParent->IsFloatContainingBlock()"
" (" "Why calling this method if aNewParent is not a float containing block?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->IsFloatContainingBlock()"
") (" "Why calling this method if aNewParent is not a float containing block?"
")"); do { *((volatile int*)__null) = 1017; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1016 aNewParent->IsFloatContainingBlock(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->IsFloatContainingBlock())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aNewParent->IsFloatContainingBlock()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewParent->IsFloatContainingBlock()"
" (" "Why calling this method if aNewParent is not a float containing block?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->IsFloatContainingBlock()"
") (" "Why calling this method if aNewParent is not a float containing block?"
")"); do { *((volatile int*)__null) = 1017; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1017 "Why calling this method if aNewParent is not a float containing block?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewParent->IsFloatContainingBlock())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aNewParent->IsFloatContainingBlock()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewParent->IsFloatContainingBlock()"
" (" "Why calling this method if aNewParent is not a float containing block?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewParent->IsFloatContainingBlock()"
") (" "Why calling this method if aNewParent is not a float containing block?"
")"); do { *((volatile int*)__null) = 1017; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1018
1019 // Gather floats that should reparent under aNewParent.
1020 AbsoluteFrameList floats(aNewParent);
1021 nsIFrame* current = mFloatedList.FirstChild();
1022 while (current) {
1023 nsIFrame* placeholder = current->GetPlaceholderFrame();
1024 nsIFrame* next = current->GetNextSibling();
1025 if (nsLayoutUtils::IsProperAncestorFrame(aNewParent, placeholder)) {
1026 mFloatedList.RemoveFrame(current);
1027 floats.AppendFrame(aNewParent, current);
1028 }
1029 current = next;
1030 }
1031
1032 if (floats.NotEmpty()) {
1033 // Make floats move into aNewParent's float child list in
1034 // ~nsFrameConstructorSaveState() when destructing floatSaveState.
1035 nsFrameConstructorSaveState floatSaveState;
1036 PushFloatContainingBlock(aNewParent, floatSaveState);
1037 mFloatedList = std::move(floats);
1038 }
1039}
1040
1041AbsoluteFrameList* nsFrameConstructorState::GetOutOfFlowFrameList(
1042 nsIFrame* aNewFrame, bool aCanBePositioned, bool aCanBeFloated,
1043 nsFrameState* aPlaceholderType) {
1044 const nsStyleDisplay* disp = aNewFrame->StyleDisplay();
1045 if (aCanBeFloated && disp->IsFloatingStyle()) {
1046 *aPlaceholderType = PLACEHOLDER_FOR_FLOAT;
1047 return &mFloatedList;
1048 }
1049
1050 if (aCanBePositioned) {
1051 if (disp->mTopLayer != StyleTopLayer::None) {
1052 *aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER;
1053 if (disp->mPosition == StylePositionProperty::Fixed) {
1054 *aPlaceholderType |= PLACEHOLDER_FOR_FIXEDPOS;
1055 return &mRealFixedList;
1056 }
1057 *aPlaceholderType |= PLACEHOLDER_FOR_ABSPOS;
1058 return &mTopLayerAbsoluteList;
1059 }
1060 if (disp->mPosition == StylePositionProperty::Absolute) {
1061 *aPlaceholderType = PLACEHOLDER_FOR_ABSPOS;
1062 return &mAbsoluteList;
1063 }
1064 if (disp->mPosition == StylePositionProperty::Fixed) {
1065 *aPlaceholderType = PLACEHOLDER_FOR_FIXEDPOS;
1066 return mFixedList;
1067 }
1068 }
1069 return nullptr;
1070}
1071
1072void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
1073 nsIFrame* aFrame) {
1074 MOZ_ASSERT(aFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Auto)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->StyleDisplay()->mTopLayer == StyleTopLayer
::Auto)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->StyleDisplay()->mTopLayer == StyleTopLayer
::Auto))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Auto"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->StyleDisplay()->mTopLayer == StyleTopLayer::Auto"
")"); do { *((volatile int*)__null) = 1074; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1075 nsContainerFrame* frame = do_QueryFrame(aFrame);
1076 if (!frame) {
1077 NS_WARNING("Cannot create backdrop frame for non-container frame")NS_DebugBreak(NS_DEBUG_WARNING, "Cannot create backdrop frame for non-container frame"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1077)
;
1078 return;
1079 }
1080
1081 ComputedStyle* parentStyle = nsLayoutUtils::GetStyleFrame(aFrame)->Style();
1082 RefPtr<ComputedStyle> style =
1083 mPresShell->StyleSet()->ResolvePseudoElementStyle(
1084 *aContent->AsElement(), PseudoStyleType::backdrop, nullptr,
1085 parentStyle);
1086 MOZ_ASSERT(style->StyleDisplay()->mTopLayer == StyleTopLayer::Auto)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(style->StyleDisplay()->mTopLayer == StyleTopLayer
::Auto)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(style->StyleDisplay()->mTopLayer == StyleTopLayer
::Auto))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("style->StyleDisplay()->mTopLayer == StyleTopLayer::Auto"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "style->StyleDisplay()->mTopLayer == StyleTopLayer::Auto"
")"); do { *((volatile int*)__null) = 1086; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1087 nsContainerFrame* parentFrame =
1088 GetGeometricParent(*style->StyleDisplay(), nullptr);
1089
1090 nsBackdropFrame* backdropFrame =
1091 new (mPresShell) nsBackdropFrame(style, mPresShell->GetPresContext());
1092 backdropFrame->Init(aContent, parentFrame, nullptr);
1093
1094 nsFrameState placeholderType;
1095 AbsoluteFrameList* frameList =
1096 GetOutOfFlowFrameList(backdropFrame, true, true, &placeholderType);
1097 MOZ_ASSERT(placeholderType & PLACEHOLDER_FOR_TOPLAYER)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(placeholderType & PLACEHOLDER_FOR_TOPLAYER)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(placeholderType & PLACEHOLDER_FOR_TOPLAYER))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("placeholderType & PLACEHOLDER_FOR_TOPLAYER"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1097); AnnotateMozCrashReason("MOZ_ASSERT" "(" "placeholderType & PLACEHOLDER_FOR_TOPLAYER"
")"); do { *((volatile int*)__null) = 1097; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1098
1099 nsIFrame* placeholder = nsCSSFrameConstructor::CreatePlaceholderFrameFor(
1100 mPresShell, aContent, backdropFrame, frame, nullptr, placeholderType);
1101 frame->SetInitialChildList(FrameChildListID::Backdrop,
1102 nsFrameList(placeholder, placeholder));
1103
1104 frameList->AppendFrame(nullptr, backdropFrame);
1105}
1106
1107void nsFrameConstructorState::AddChild(
1108 nsIFrame* aNewFrame, nsFrameList& aFrameList, nsIContent* aContent,
1109 nsContainerFrame* aParentFrame, bool aCanBePositioned, bool aCanBeFloated,
1110 bool aInsertAfter, nsIFrame* aInsertAfterFrame) {
1111 MOZ_ASSERT(!aNewFrame->GetNextSibling(), "Shouldn't happen")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aNewFrame->GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aNewFrame->GetNextSibling
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aNewFrame->GetNextSibling()" " (" "Shouldn't happen" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aNewFrame->GetNextSibling()"
") (" "Shouldn't happen" ")"); do { *((volatile int*)__null)
= 1111; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1112
1113 nsFrameState placeholderType;
1114 AbsoluteFrameList* outOfFlowFrameList = GetOutOfFlowFrameList(
1115 aNewFrame, aCanBePositioned, aCanBeFloated, &placeholderType);
1116
1117 // The comments in GetGeometricParent regarding root table frames
1118 // all apply here, unfortunately. Thus, we need to check whether
1119 // the returned frame items really has containing block.
1120 nsFrameList* frameList;
1121 if (outOfFlowFrameList && outOfFlowFrameList->mContainingBlock) {
1122 MOZ_ASSERT(aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewFrame->GetParent() == outOfFlowFrameList->
mContainingBlock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewFrame->GetParent() ==
outOfFlowFrameList->mContainingBlock))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock"
" (" "Parent of the frame is not the containing block?" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock"
") (" "Parent of the frame is not the containing block?" ")"
); do { *((volatile int*)__null) = 1123; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1123 "Parent of the frame is not the containing block?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewFrame->GetParent() == outOfFlowFrameList->
mContainingBlock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewFrame->GetParent() ==
outOfFlowFrameList->mContainingBlock))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock"
" (" "Parent of the frame is not the containing block?" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame->GetParent() == outOfFlowFrameList->mContainingBlock"
") (" "Parent of the frame is not the containing block?" ")"
); do { *((volatile int*)__null) = 1123; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1124 frameList = outOfFlowFrameList;
1125 } else {
1126 frameList = &aFrameList;
1127 placeholderType = nsFrameState(0);
1128 }
1129
1130 if (placeholderType) {
1131 NS_ASSERTION(frameList != &aFrameList,do { if (!(frameList != &aFrameList)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Putting frame in-flow _and_ want a placeholder?", "frameList != &aFrameList"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1132); MOZ_PretendNoReturn(); } } while (0)
1132 "Putting frame in-flow _and_ want a placeholder?")do { if (!(frameList != &aFrameList)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Putting frame in-flow _and_ want a placeholder?", "frameList != &aFrameList"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1132); MOZ_PretendNoReturn(); } } while (0)
;
1133 nsIFrame* placeholderFrame =
1134 nsCSSFrameConstructor::CreatePlaceholderFrameFor(
1135 mPresShell, aContent, aNewFrame, aParentFrame, nullptr,
1136 placeholderType);
1137
1138 placeholderFrame->AddStateBits(mAdditionalStateBits);
1139 // Add the placeholder frame to the flow
1140 aFrameList.AppendFrame(nullptr, placeholderFrame);
1141
1142 if (placeholderType & PLACEHOLDER_FOR_TOPLAYER) {
1143 ConstructBackdropFrameFor(aContent, aNewFrame);
1144 }
1145 }
1146#ifdef DEBUG1
1147 else {
1148 NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,do { if (!(aNewFrame->GetParent() == aParentFrame)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "In-flow frame has wrong parent", "aNewFrame->GetParent() == aParentFrame"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1149); MOZ_PretendNoReturn(); } } while (0)
1149 "In-flow frame has wrong parent")do { if (!(aNewFrame->GetParent() == aParentFrame)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "In-flow frame has wrong parent", "aNewFrame->GetParent() == aParentFrame"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1149); MOZ_PretendNoReturn(); } } while (0)
;
1150 }
1151#endif
1152
1153 if (aInsertAfter) {
1154 frameList->InsertFrame(nullptr, aInsertAfterFrame, aNewFrame);
1155 } else {
1156 frameList->AppendFrame(nullptr, aNewFrame);
1157 }
1158}
1159
1160// Some of this function's callers recurse 1000 levels deep in crashtests. On
1161// platforms where stack limits are low, we can't afford to incorporate this
1162// function's `AutoTArray`s into its callers' stack frames, so disable inlining.
1163MOZ_NEVER_INLINE__attribute__((noinline)) void nsFrameConstructorState::ProcessFrameInsertions(
1164 AbsoluteFrameList& aFrameList, FrameChildListID aChildListID) {
1165 MOZ_ASSERT(&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1166 &aFrameList == &mTopLayerAbsoluteList ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1167 &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1168 &aFrameList == &mRealFixedList)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(&aFrameList == &mFloatedList || &aFrameList
== &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList
|| &aFrameList == &mAncestorFixedList || &aFrameList
== mFixedList || &aFrameList == &mRealFixedList))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&aFrameList == &mFloatedList || &aFrameList == &mAbsoluteList || &aFrameList == &mTopLayerAbsoluteList || &aFrameList == &mAncestorFixedList || &aFrameList == mFixedList || &aFrameList == &mRealFixedList"
")"); do { *((volatile int*)__null) = 1168; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1169 MOZ_ASSERT_IF(&aFrameList == &mFloatedList,do { if (&aFrameList == &mFloatedList) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aChildListID
== FrameChildListID::Float)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Float))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Float", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Float"
")"); do { *((volatile int*)__null) = 1170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1170 aChildListID == FrameChildListID::Float)do { if (&aFrameList == &mFloatedList) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aChildListID
== FrameChildListID::Float)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Float))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Float", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1170); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Float"
")"); do { *((volatile int*)__null) = 1170; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1171 MOZ_ASSERT_IF(&aFrameList == &mAbsoluteList || &aFrameList == mFixedList,do { if (&aFrameList == &mAbsoluteList || &aFrameList
== mFixedList) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aChildListID == FrameChildListID::Absolute || aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Absolute || aChildListID == FrameChildListID::Fixed))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1172 aChildListID == FrameChildListID::Absolute ||do { if (&aFrameList == &mAbsoluteList || &aFrameList
== mFixedList) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aChildListID == FrameChildListID::Absolute || aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Absolute || aChildListID == FrameChildListID::Fixed))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1173 aChildListID == FrameChildListID::Fixed)do { if (&aFrameList == &mAbsoluteList || &aFrameList
== mFixedList) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aChildListID == FrameChildListID::Absolute || aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Absolute || aChildListID == FrameChildListID::Fixed))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute || aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1174 MOZ_ASSERT_IF(&aFrameList == &mTopLayerAbsoluteList,do { if (&aFrameList == &mTopLayerAbsoluteList) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(aChildListID == FrameChildListID::Absolute)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Absolute))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Absolute", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute"
")"); do { *((volatile int*)__null) = 1175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1175 aChildListID == FrameChildListID::Absolute)do { if (&aFrameList == &mTopLayerAbsoluteList) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(aChildListID == FrameChildListID::Absolute)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Absolute))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Absolute", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Absolute"
")"); do { *((volatile int*)__null) = 1175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1176 MOZ_ASSERT_IF(&aFrameList == mFixedList && &aFrameList != &mAbsoluteList,do { if (&aFrameList == mFixedList && &aFrameList
!= &mAbsoluteList) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aChildListID == FrameChildListID
::Fixed)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChildListID == FrameChildListID::Fixed))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aChildListID == FrameChildListID::Fixed"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1177; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1177 aChildListID == FrameChildListID::Fixed)do { if (&aFrameList == mFixedList && &aFrameList
!= &mAbsoluteList) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aChildListID == FrameChildListID
::Fixed)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChildListID == FrameChildListID::Fixed))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aChildListID == FrameChildListID::Fixed"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1177; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1178 MOZ_ASSERT_IF(&aFrameList == &mAncestorFixedList,do { if (&aFrameList == &mAncestorFixedList) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Fixed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Fixed", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1179 aChildListID == FrameChildListID::Fixed)do { if (&aFrameList == &mAncestorFixedList) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Fixed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Fixed", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1179; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1180 MOZ_ASSERT_IF(&aFrameList == &mRealFixedList,do { if (&aFrameList == &mRealFixedList) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Fixed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Fixed", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1181; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1181 aChildListID == FrameChildListID::Fixed)do { if (&aFrameList == &mRealFixedList) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aChildListID
== FrameChildListID::Fixed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildListID == FrameChildListID
::Fixed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChildListID == FrameChildListID::Fixed", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildListID == FrameChildListID::Fixed"
")"); do { *((volatile int*)__null) = 1181; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1182
1183 if (aFrameList.IsEmpty()) {
1184 return;
1185 }
1186
1187 nsContainerFrame* containingBlock = aFrameList.mContainingBlock;
1188
1189 NS_ASSERTION(containingBlock, "Child list without containing block?")do { if (!(containingBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Child list without containing block?", "containingBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1189); MOZ_PretendNoReturn(); } } while (0)
;
1190
1191 if (aChildListID == FrameChildListID::Fixed) {
1192 // Put this frame on the transformed-frame's abs-pos list instead, if
1193 // it has abs-pos children instead of fixed-pos children.
1194 aChildListID = containingBlock->GetAbsoluteListID();
1195 }
1196
1197 // Insert the frames hanging out in aItems. We can use SetInitialChildList()
1198 // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
1199 // is set) and doesn't have any frames in the aChildListID child list yet.
1200 const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
1201 if (childList.IsEmpty() &&
1202 containingBlock->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
1203 // If we're injecting absolutely positioned frames, inject them on the
1204 // absolute containing block
1205 if (aChildListID == containingBlock->GetAbsoluteListID()) {
1206 containingBlock->GetAbsoluteContainingBlock()->SetInitialChildList(
1207 containingBlock, aChildListID, std::move(aFrameList));
1208 } else {
1209 containingBlock->SetInitialChildList(aChildListID, std::move(aFrameList));
1210 }
1211 } else if (aChildListID == FrameChildListID::Fixed ||
1212 aChildListID == FrameChildListID::Absolute) {
1213 // The order is not important for abs-pos/fixed-pos frame list, just
1214 // append the frame items to the list directly.
1215 mFrameConstructor->AppendFrames(containingBlock, aChildListID,
1216 std::move(aFrameList));
1217 } else {
1218 // Note that whether the frame construction context is doing an append or
1219 // not is not helpful here, since it could be appending to some frame in
1220 // the middle of the document, which means we're not necessarily
1221 // appending to the children of the containing block.
1222 //
1223 // We need to make sure the 'append to the end of document' case is fast.
1224 // So first test the last child of the containing block
1225 nsIFrame* lastChild = childList.LastChild();
1226
1227 // CompareTreePosition uses placeholder hierarchy for out of flow frames,
1228 // so this will make out-of-flows respect the ordering of placeholders,
1229 // which is great because it takes care of anonymous content.
1230 nsIFrame* firstNewFrame = aFrameList.FirstChild();
1231
1232 // Cache the ancestor chain so that we can reuse it if needed.
1233 AutoTArray<nsIFrame*, 20> firstNewFrameAncestors;
1234 nsIFrame* notCommonAncestor = nullptr;
1235 if (lastChild) {
1236 notCommonAncestor = nsLayoutUtils::FillAncestors(
1237 firstNewFrame, containingBlock, &firstNewFrameAncestors);
1238 }
1239
1240 if (!lastChild || nsLayoutUtils::CompareTreePosition(
1241 lastChild, firstNewFrame, firstNewFrameAncestors,
1242 notCommonAncestor ? containingBlock : nullptr) < 0) {
1243 // no lastChild, or lastChild comes before the new children, so just
1244 // append
1245 mFrameConstructor->AppendFrames(containingBlock, aChildListID,
1246 std::move(aFrameList));
1247 } else {
1248 // Try the other children. First collect them to an array so that a
1249 // reasonable fast binary search can be used to find the insertion point.
1250 AutoTArray<nsIFrame*, 128> children;
1251 for (nsIFrame* f = childList.FirstChild(); f != lastChild;
1252 f = f->GetNextSibling()) {
1253 children.AppendElement(f);
1254 }
1255
1256 nsIFrame* insertionPoint = nullptr;
1257 int32_t imin = 0;
1258 int32_t max = children.Length();
1259 while (max > imin) {
1260 int32_t imid = imin + ((max - imin) / 2);
1261 nsIFrame* f = children[imid];
1262 int32_t compare = nsLayoutUtils::CompareTreePosition(
1263 f, firstNewFrame, firstNewFrameAncestors,
1264 notCommonAncestor ? containingBlock : nullptr);
1265 if (compare > 0) {
1266 // f is after the new frame.
1267 max = imid;
1268 insertionPoint = imid > 0 ? children[imid - 1] : nullptr;
1269 } else if (compare < 0) {
1270 // f is before the new frame.
1271 imin = imid + 1;
1272 insertionPoint = f;
1273 } else {
1274 // This is for the old behavior. Should be removed once it is
1275 // guaranteed that CompareTreePosition can't return 0!
1276 // See bug 928645.
1277 NS_WARNING("Something odd happening???")NS_DebugBreak(NS_DEBUG_WARNING, "Something odd happening???",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1277)
;
1278 insertionPoint = nullptr;
1279 for (uint32_t i = 0; i < children.Length(); ++i) {
1280 nsIFrame* f = children[i];
1281 if (nsLayoutUtils::CompareTreePosition(
1282 f, firstNewFrame, firstNewFrameAncestors,
1283 notCommonAncestor ? containingBlock : nullptr) > 0) {
1284 break;
1285 }
1286 insertionPoint = f;
1287 }
1288 break;
1289 }
1290 }
1291 mFrameConstructor->InsertFrames(containingBlock, aChildListID,
1292 insertionPoint, std::move(aFrameList));
1293 }
1294 }
1295
1296 MOZ_ASSERT(aFrameList.IsEmpty(), "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrameList.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFrameList.IsEmpty()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aFrameList.IsEmpty()"
" (" "How did that happen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrameList.IsEmpty()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 1296; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
1297}
1298
1299nsFrameConstructorSaveState::~nsFrameConstructorSaveState() {
1300 // Restore the state
1301 if (mList) {
1302 MOZ_ASSERT(mState, "Can't have mList set without having a state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mState)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(mState))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mState" " (" "Can't have mList set without having a state!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mState" ") ("
"Can't have mList set without having a state!" ")"); do { *(
(volatile int*)__null) = 1302; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1303 mState->ProcessFrameInsertions(*mList, mChildListID);
1304
1305 if (mList == &mState->mAbsoluteList) {
1306 mState->mAbsoluteList = std::move(mSavedList);
1307 mState->mFixedList = mSavedFixedList;
1308 } else {
1309 mState->mFloatedList = std::move(mSavedList);
1310 }
1311
1312 MOZ_ASSERT(mSavedList.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSavedList.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSavedList.IsEmpty()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mSavedList.IsEmpty()"
" (" "Frames in mSavedList should've moved back into mState!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSavedList.IsEmpty()"
") (" "Frames in mSavedList should've moved back into mState!"
")"); do { *((volatile int*)__null) = 1313; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1313 "Frames in mSavedList should've moved back into mState!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mSavedList.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mSavedList.IsEmpty()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mSavedList.IsEmpty()"
" (" "Frames in mSavedList should've moved back into mState!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mSavedList.IsEmpty()"
") (" "Frames in mSavedList should've moved back into mState!"
")"); do { *((volatile int*)__null) = 1313; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1314 MOZ_ASSERT(!mList->LastChild() || !mList->LastChild()->GetNextSibling(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mList->LastChild() || !mList->LastChild()->
GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mList->LastChild() || !mList
->LastChild()->GetNextSibling()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mList->LastChild() || !mList->LastChild()->GetNextSibling()"
" (" "Something corrupted our list!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mList->LastChild() || !mList->LastChild()->GetNextSibling()"
") (" "Something corrupted our list!" ")"); do { *((volatile
int*)__null) = 1315; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1315 "Something corrupted our list!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mList->LastChild() || !mList->LastChild()->
GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mList->LastChild() || !mList
->LastChild()->GetNextSibling()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mList->LastChild() || !mList->LastChild()->GetNextSibling()"
" (" "Something corrupted our list!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mList->LastChild() || !mList->LastChild()->GetNextSibling()"
") (" "Something corrupted our list!" ")"); do { *((volatile
int*)__null) = 1315; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1316 }
1317}
1318
1319/**
1320 * Moves aFrameList from aOldParent to aNewParent. This updates the parent
1321 * pointer of the frames in the list, and reparents their views as needed.
1322 * nsIFrame::SetParent sets the NS_FRAME_HAS_VIEW bit on aNewParent and its
1323 * ancestors as needed. Then it sets the list as the initial child list
1324 * on aNewParent, unless aNewParent either already has kids or has been
1325 * reflowed; in that case it appends the new frames. Note that this
1326 * method differs from ReparentFrames in that it doesn't change the kids'
1327 * style.
1328 */
1329// XXXbz Since this is only used for {ib} splits, could we just copy the view
1330// bits from aOldParent to aNewParent and then use the
1331// nsFrameList::ApplySetParent? That would still leave us doing two passes
1332// over the list, of course; if we really wanted to we could factor out the
1333// relevant part of ReparentFrameViewList, I suppose... Or just get rid of
1334// views, which would make most of this function go away.
1335static void MoveChildrenTo(nsIFrame* aOldParent, nsContainerFrame* aNewParent,
1336 nsFrameList& aFrameList) {
1337#ifdef DEBUG1
1338 bool sameGrandParent = aOldParent->GetParent() == aNewParent->GetParent();
1339
1340 if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) {
1341 // Move the frames into the new view
1342 nsContainerFrame::ReparentFrameViewList(aFrameList, aOldParent, aNewParent);
1343 }
1344#endif
1345
1346 aFrameList.ApplySetParent(aNewParent);
1347
1348 if (aNewParent->PrincipalChildList().IsEmpty() &&
1349 aNewParent->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
1350 aNewParent->SetInitialChildList(FrameChildListID::Principal,
1351 std::move(aFrameList));
1352 } else {
1353 aNewParent->AppendFrames(FrameChildListID::Principal,
1354 std::move(aFrameList));
1355 }
1356}
1357
1358static void EnsureAutoPageName(nsFrameConstructorState& aState,
1359 const nsContainerFrame* const aFrame) {
1360 // Check if we need to figure out our used page name.
1361 // When building the entire document, this should only happen for the
1362 // root, which will mean the loop will immediately end. Either way, this will
1363 // only happen once for each time the frame constructor is run.
1364 if (aState.mAutoPageNameValue) {
1365 return;
1366 }
1367
1368 for (const nsContainerFrame* frame = aFrame; frame;
1369 frame = frame->GetParent()) {
1370 if (const nsAtom* maybePageName = frame->GetStylePageName()) {
1371 aState.mAutoPageNameValue = maybePageName;
1372 return;
1373 }
1374 }
1375 // Ensure that a root with `page: auto` gets an empty page name
1376 // https://drafts.csswg.org/css-page-3/#using-named-pages
1377 aState.mAutoPageNameValue = nsGkAtoms::_empty;
1378}
1379
1380nsCSSFrameConstructor::AutoFrameConstructionPageName::
1381 AutoFrameConstructionPageName(nsFrameConstructorState& aState,
1382 nsIFrame* const aFrame)
1383 : mState(aState), mNameToRestore(nullptr) {
1384 if (!aState.mPresContext->IsPaginated()) {
1385 MOZ_ASSERT(!aState.mAutoPageNameValue,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aState.mAutoPageNameValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aState.mAutoPageNameValue))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aState.mAutoPageNameValue"
" (" "Page name should not have been set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aState.mAutoPageNameValue"
") (" "Page name should not have been set" ")"); do { *((volatile
int*)__null) = 1386; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1386 "Page name should not have been set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aState.mAutoPageNameValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aState.mAutoPageNameValue))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aState.mAutoPageNameValue"
" (" "Page name should not have been set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aState.mAutoPageNameValue"
") (" "Page name should not have been set" ")"); do { *((volatile
int*)__null) = 1386; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1387 return;
1388 }
1389#ifdef DEBUG1
1390 MOZ_ASSERT(!aFrame->mWasVisitedByAutoFrameConstructionPageName,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->mWasVisitedByAutoFrameConstructionPageName
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aFrame->mWasVisitedByAutoFrameConstructionPageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->mWasVisitedByAutoFrameConstructionPageName" " ("
"Frame should only have been visited once" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should only have been visited once" ")"); do { *
((volatile int*)__null) = 1391; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1391 "Frame should only have been visited once")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->mWasVisitedByAutoFrameConstructionPageName
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aFrame->mWasVisitedByAutoFrameConstructionPageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->mWasVisitedByAutoFrameConstructionPageName" " ("
"Frame should only have been visited once" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should only have been visited once" ")"); do { *
((volatile int*)__null) = 1391; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1392 aFrame->mWasVisitedByAutoFrameConstructionPageName = true;
1393#endif
1394
1395 EnsureAutoPageName(aState, aFrame->GetParent());
1396 mNameToRestore = aState.mAutoPageNameValue;
1397
1398 MOZ_ASSERT(mNameToRestore,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mNameToRestore)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mNameToRestore))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mNameToRestore"
" (" "Page name should have been found by EnsureAutoPageName"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mNameToRestore"
") (" "Page name should have been found by EnsureAutoPageName"
")"); do { *((volatile int*)__null) = 1399; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1399 "Page name should have been found by EnsureAutoPageName")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mNameToRestore)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mNameToRestore))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mNameToRestore"
" (" "Page name should have been found by EnsureAutoPageName"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1399); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mNameToRestore"
") (" "Page name should have been found by EnsureAutoPageName"
")"); do { *((volatile int*)__null) = 1399; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1400 if (const nsAtom* maybePageName = aFrame->GetStylePageName()) {
1401 aState.mAutoPageNameValue = maybePageName;
1402 }
1403 aFrame->SetAutoPageValue(aState.mAutoPageNameValue);
1404}
1405
1406nsCSSFrameConstructor::AutoFrameConstructionPageName::
1407 ~AutoFrameConstructionPageName() {
1408 // This isn't actually useful when not in paginated layout, but it's very
1409 // likely cheaper to unconditionally write this pointer than to test for
1410 // paginated layout and then branch on the result.
1411 mState.mAutoPageNameValue = mNameToRestore;
1412}
1413
1414//----------------------------------------------------------------------
1415
1416nsCSSFrameConstructor::nsCSSFrameConstructor(Document* aDocument,
1417 PresShell* aPresShell)
1418 : nsFrameManager(aPresShell),
1419 mDocument(aDocument),
1420 mFirstFreeFCItem(nullptr),
1421 mFCItemsInUse(0),
1422 mCurrentDepth(0),
1423 mQuotesDirty(false),
1424 mCountersDirty(false),
1425 mAlwaysCreateFramesForIgnorableWhitespace(false),
1426 mRemovingContent(false) {
1427#ifdef DEBUG1
1428 static bool gFirstTime = true;
1429 if (gFirstTime) {
1430 gFirstTime = false;
1431 char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
1432 if (flags) {
1433 bool error = false;
1434 for (;;) {
1435 char* comma = strchr(flags, ',');
1436 if (comma) *comma = '\0';
1437
1438 bool found = false;
1439 FrameCtorDebugFlags* flag = gFlags;
1440 FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS(sizeof(gFlags) / sizeof(gFlags[0]));
1441 while (flag < limit) {
1442 if (nsCRT::strcasecmp(flag->name, flags) == 0) {
1443 *(flag->on) = true;
1444 printf("nsCSSFrameConstructor: setting %s debug flag on\n",
1445 flag->name);
1446 found = true;
1447 break;
1448 }
1449 ++flag;
1450 }
1451
1452 if (!found) error = true;
1453
1454 if (!comma) break;
1455
1456 *comma = ',';
1457 flags = comma + 1;
1458 }
1459
1460 if (error) {
1461 printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
1462 FrameCtorDebugFlags* flag = gFlags;
1463 FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS(sizeof(gFlags) / sizeof(gFlags[0]));
1464 while (flag < limit) {
1465 printf(" %s\n", flag->name);
1466 ++flag;
1467 }
1468 printf(
1469 "Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of "
1470 "flag\n");
1471 printf("names (no whitespace)\n");
1472 }
1473 }
1474 }
1475#endif
1476}
1477
1478void nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame) {
1479 if (aFrame->StyleDisplay()->IsContainStyle()) {
1480 mContainStyleScopeManager.DestroyScopesFor(aFrame);
1481 }
1482
1483 if (aFrame->HasAnyStateBits(NS_FRAME_GENERATED_CONTENT) &&
1484 mContainStyleScopeManager.DestroyQuoteNodesFor(aFrame)) {
1485 QuotesDirty();
1486 }
1487
1488 if (aFrame->HasAnyStateBits(NS_FRAME_HAS_CSS_COUNTER_STYLE) &&
1489 mContainStyleScopeManager.DestroyCounterNodesFor(aFrame)) {
1490 // Technically we don't need to update anything if we destroyed only
1491 // USE nodes. However, this is unlikely to happen in the real world
1492 // since USE nodes generally go along with INCREMENT nodes.
1493 CountersDirty();
1494 }
1495
1496 RestyleManager()->NotifyDestroyingFrame(aFrame);
1497}
1498
1499struct nsGenConInitializer {
1500 UniquePtr<nsGenConNode> mNode;
1501 nsGenConList* mList;
1502 void (nsCSSFrameConstructor::*mDirtyAll)();
1503
1504 nsGenConInitializer(UniquePtr<nsGenConNode> aNode, nsGenConList* aList,
1505 void (nsCSSFrameConstructor::*aDirtyAll)())
1506 : mNode(std::move(aNode)), mList(aList), mDirtyAll(aDirtyAll) {}
1507};
1508
1509already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGenConTextNode(
1510 nsFrameConstructorState& aState, const nsAString& aString,
1511 UniquePtr<nsGenConInitializer> aInitializer) {
1512 RefPtr<nsTextNode> content = new (mDocument->NodeInfoManager())
1513 nsTextNode(mDocument->NodeInfoManager());
1514 content->SetText(aString, false);
1515 if (aInitializer) {
1516 aInitializer->mNode->mText = content;
1517 content->SetProperty(nsGkAtoms::genConInitializerProperty,
1518 aInitializer.release(),
1519 nsINode::DeleteProperty<nsGenConInitializer>);
1520 aState.mGeneratedContentWithInitializer.AppendElement(content);
1521 }
1522 return content.forget();
1523}
1524
1525void nsCSSFrameConstructor::CreateGeneratedContent(
1526 nsFrameConstructorState& aState, Element& aOriginatingElement,
1527 ComputedStyle& aPseudoStyle, const StyleContentItem& aItem,
1528 size_t aContentIndex, const FunctionRef<void(nsIContent*)> aAddChild) {
1529 using Type = StyleContentItem::Tag;
1530 // Get the content value
1531 const Type type = aItem.tag;
1532
1533 switch (type) {
1534 case Type::Image: {
1535 RefPtr c = GeneratedImageContent::Create(*mDocument, aContentIndex);
1536 aAddChild(c);
1537 return;
1538 }
1539
1540 case Type::String: {
1541 const auto string = aItem.AsString().AsString();
1542 if (string.IsEmpty()) {
1543 return;
1544 }
1545 RefPtr text =
1546 CreateGenConTextNode(aState, NS_ConvertUTF8toUTF16(string), nullptr);
1547 aAddChild(text);
1548 return;
1549 }
1550
1551 case Type::Attr: {
1552 const auto& attr = aItem.AsAttr();
1553 RefPtr<nsAtom> attrName = attr.attribute.AsAtom();
1554 int32_t attrNameSpace = kNameSpaceID_None;
1555 RefPtr<nsAtom> ns = attr.namespace_url.AsAtom();
1556 if (!ns->IsEmpty()) {
1557 nsresult rv = nsNameSpaceManager::GetInstance()->RegisterNameSpace(
1558 ns.forget(), attrNameSpace);
1559 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1559); return; } } while (false)
;
1560 }
1561
1562 if (mDocument->IsHTMLDocument() && aOriginatingElement.IsHTMLElement()) {
1563 ToLowerCaseASCII(attrName);
1564 }
1565
1566 RefPtr<nsAtom> fallback = attr.fallback.AsAtom();
1567
1568 nsCOMPtr<nsIContent> content;
1569 NS_NewAttributeContent(mDocument->NodeInfoManager(), attrNameSpace,
1570 attrName, fallback, getter_AddRefs(content));
1571 aAddChild(content);
1572 return;
1573 }
1574
1575 case Type::Counter:
1576 case Type::Counters: {
1577 RefPtr<nsAtom> name;
1578 const StyleCounterStyle* style;
1579 nsString separator;
1580 if (type == Type::Counter) {
1581 const auto& counter = aItem.AsCounter();
1582 name = counter._0.AsAtom();
1583 style = &counter._1;
1584 } else {
1585 const auto& counters = aItem.AsCounters();
1586 name = counters._0.AsAtom();
1587 CopyUTF8toUTF16(counters._1.AsString(), separator);
1588 style = &counters._2;
1589 }
1590
1591 auto* counterList = mContainStyleScopeManager.GetOrCreateCounterList(
1592 aOriginatingElement, name);
1593 auto node = MakeUnique<nsCounterUseNode>(
1594 *style, std::move(separator), aContentIndex,
1595 /* aAllCounters = */ type == Type::Counters);
1596
1597 auto initializer = MakeUnique<nsGenConInitializer>(
1598 std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
1599 RefPtr c = CreateGenConTextNode(aState, u""_ns, std::move(initializer));
1600 aAddChild(c);
1601 return;
1602 }
1603 case Type::OpenQuote:
1604 case Type::CloseQuote:
1605 case Type::NoOpenQuote:
1606 case Type::NoCloseQuote: {
1607 auto node = MakeUnique<nsQuoteNode>(type, aContentIndex);
1608 auto* quoteList =
1609 mContainStyleScopeManager.QuoteListFor(aOriginatingElement);
1610 auto initializer = MakeUnique<nsGenConInitializer>(
1611 std::move(node), quoteList, &nsCSSFrameConstructor::QuotesDirty);
1612 RefPtr c = CreateGenConTextNode(aState, u""_ns, std::move(initializer));
1613 aAddChild(c);
1614 return;
1615 }
1616
1617 case Type::MozLabelContent: {
1618 nsAutoString accesskey;
1619 if (!aOriginatingElement.GetAttr(nsGkAtoms::accesskey, accesskey) ||
1620 accesskey.IsEmpty() || !LookAndFeel::GetMenuAccessKey()) {
1621 // Easy path: just return a regular value attribute content.
1622 nsCOMPtr<nsIContent> content;
1623 NS_NewAttributeContent(mDocument->NodeInfoManager(), kNameSpaceID_None,
1624 nsGkAtoms::value, nsGkAtoms::_empty,
1625 getter_AddRefs(content));
1626 aAddChild(content);
1627 return;
1628 }
1629
1630 nsAutoString value;
1631 aOriginatingElement.GetAttr(nsGkAtoms::value, value);
1632
1633 auto AppendAccessKeyLabel = [&] {
1634 // Always append accesskey text in uppercase, see bug 1806167.
1635 ToUpperCase(accesskey);
1636 nsAutoString accessKeyLabel = u"("_ns + accesskey + u")"_ns;
1637 if (!StringEndsWith(value, accessKeyLabel)) {
1638 if (InsertSeparatorBeforeAccessKey() && !value.IsEmpty() &&
1639 !NS_IS_SPACE(value.Last())) {
1640 value.Append(' ');
1641 }
1642 value.Append(accessKeyLabel);
1643 }
1644 };
1645 if (AlwaysAppendAccessKey()) {
1646 AppendAccessKeyLabel();
1647 RefPtr c = CreateGenConTextNode(aState, value, nullptr);
1648 aAddChild(c);
1649 return;
1650 }
1651
1652 const auto accessKeyStart = [&]() -> Maybe<size_t> {
1653 nsAString::const_iterator start, end;
1654 value.BeginReading(start);
1655 value.EndReading(end);
1656
1657 const auto originalStart = start;
1658 // not appending access key - do case-sensitive search
1659 // first
1660 bool found = true;
1661 if (!FindInReadable(accesskey, start, end)) {
1662 start = originalStart;
1663 // didn't find it - perform a case-insensitive search
1664 found = FindInReadable(accesskey, start, end,
1665 nsCaseInsensitiveStringComparator);
1666 }
1667 if (!found) {
1668 return Nothing();
1669 }
1670 return Some(Distance(originalStart, start));
1671 }();
1672
1673 if (accessKeyStart.isNothing()) {
1674 AppendAccessKeyLabel();
1675 RefPtr c = CreateGenConTextNode(aState, value, nullptr);
1676 aAddChild(c);
1677 return;
1678 }
1679
1680 if (*accessKeyStart != 0) {
1681 RefPtr beginning = CreateGenConTextNode(
1682 aState, Substring(value, 0, *accessKeyStart), nullptr);
1683 aAddChild(beginning);
1684 }
1685
1686 {
1687 RefPtr accessKeyText = CreateGenConTextNode(
1688 aState, Substring(value, *accessKeyStart, accesskey.Length()),
1689 nullptr);
1690 RefPtr<nsIContent> underline =
1691 mDocument->CreateHTMLElement(nsGkAtoms::u);
1692 underline->AppendChildTo(accessKeyText, /* aNotify = */ false,
1693 IgnoreErrors());
1694 aAddChild(underline);
1695 }
1696
1697 size_t accessKeyEnd = *accessKeyStart + accesskey.Length();
1698 if (accessKeyEnd != value.Length()) {
1699 RefPtr valueEnd = CreateGenConTextNode(
1700 aState, Substring(value, *accessKeyStart + accesskey.Length()),
1701 nullptr);
1702 aAddChild(valueEnd);
1703 }
1704 break;
1705 }
1706 case Type::MozAltContent: {
1707 // Use the "alt" attribute; if that fails and the node is an HTML
1708 // <input>, try the value attribute and then fall back to some default
1709 // localized text we have.
1710 // XXX what if the 'alt' attribute is added later, how will we
1711 // detect that and do the right thing here?
1712 if (aOriginatingElement.HasAttr(nsGkAtoms::alt)) {
1713 nsCOMPtr<nsIContent> content;
1714 NS_NewAttributeContent(mDocument->NodeInfoManager(), kNameSpaceID_None,
1715 nsGkAtoms::alt, nsGkAtoms::_empty,
1716 getter_AddRefs(content));
1717 aAddChild(content);
1718 return;
1719 }
1720
1721 if (aOriginatingElement.IsHTMLElement(nsGkAtoms::input)) {
1722 if (aOriginatingElement.HasAttr(nsGkAtoms::value)) {
1723 nsCOMPtr<nsIContent> content;
1724 NS_NewAttributeContent(mDocument->NodeInfoManager(),
1725 kNameSpaceID_None, nsGkAtoms::value,
1726 nsGkAtoms::_empty, getter_AddRefs(content));
1727 aAddChild(content);
1728 return;
1729 }
1730
1731 nsAutoString temp;
1732 nsContentUtils::GetMaybeLocalizedString(
1733 nsContentUtils::eFORMS_PROPERTIES, "Submit", mDocument, temp);
1734 RefPtr c = CreateGenConTextNode(aState, temp, nullptr);
1735 aAddChild(c);
1736 return;
1737 }
1738 break;
1739 }
1740 }
1741}
1742
1743void nsCSSFrameConstructor::CreateGeneratedContentFromListStyle(
1744 nsFrameConstructorState& aState, Element& aOriginatingElement,
1745 const ComputedStyle& aPseudoStyle,
1746 const FunctionRef<void(nsIContent*)> aAddChild) {
1747 const nsStyleList* styleList = aPseudoStyle.StyleList();
1748 if (!styleList->mListStyleImage.IsNone()) {
1749 RefPtr<nsIContent> child =
1750 GeneratedImageContent::CreateForListStyleImage(*mDocument);
1751 aAddChild(child);
1752 child = CreateGenConTextNode(aState, u" "_ns, nullptr);
1753 aAddChild(child);
1754 return;
1755 }
1756 CreateGeneratedContentFromListStyleType(aState, aOriginatingElement,
1757 aPseudoStyle, aAddChild);
1758}
1759
1760void nsCSSFrameConstructor::CreateGeneratedContentFromListStyleType(
1761 nsFrameConstructorState& aState, Element& aOriginatingElement,
1762 const ComputedStyle& aPseudoStyle,
1763 const FunctionRef<void(nsIContent*)> aAddChild) {
1764 using Tag = StyleCounterStyle::Tag;
1765 const auto& styleType = aPseudoStyle.StyleList()->mListStyleType;
1766 switch (styleType.tag) {
1767 case Tag::None:
1768 return;
1769 case Tag::String: {
1770 nsDependentAtomString string(styleType.AsString().AsAtom());
1771 RefPtr<nsIContent> child = CreateGenConTextNode(aState, string, nullptr);
1772 aAddChild(child);
1773 return;
1774 }
1775 case Tag::Name:
1776 case Tag::Symbols:
1777 break;
1778 }
1779
1780 auto node = MakeUnique<nsCounterUseNode>(nsCounterUseNode::ForLegacyBullet,
1781 styleType);
1782 if (styleType.IsName()) {
1783 nsAtom* name = styleType.AsName().AsAtom();
1784 if (name == nsGkAtoms::disc || name == nsGkAtoms::circle ||
1785 name == nsGkAtoms::square || name == nsGkAtoms::disclosure_closed ||
1786 name == nsGkAtoms::disclosure_open) {
1787 // We don't need a use node inserted for these.
1788 CounterStyle* counterStyle = mPresShell->GetPresContext()
1789 ->CounterStyleManager()
1790 ->ResolveCounterStyle(name);
1791 nsAutoString text;
1792 node->GetText(WritingMode(&aPseudoStyle), counterStyle, text);
1793 // Note that we're done with 'node' in this case. It's not inserted into
1794 // any list so it's deleted when we return.
1795 RefPtr<nsIContent> child = CreateGenConTextNode(aState, text, nullptr);
1796 aAddChild(child);
1797 return;
1798 }
1799 }
1800
1801 auto* counterList = mContainStyleScopeManager.GetOrCreateCounterList(
1802 aOriginatingElement, nsGkAtoms::list_item);
1803 auto initializer = MakeUnique<nsGenConInitializer>(
1804 std::move(node), counterList, &nsCSSFrameConstructor::CountersDirty);
1805 RefPtr<nsIContent> child =
1806 CreateGenConTextNode(aState, EmptyString(), std::move(initializer));
1807 aAddChild(child);
1808}
1809
1810// Frames for these may not be leaves in the proper sense, but we still don't
1811// want to expose generated content on them. For the purposes of the page they
1812// should be leaves.
1813static bool HasUAWidget(const Element& aOriginatingElement) {
1814 const ShadowRoot* sr = aOriginatingElement.GetShadowRoot();
1815 return sr && sr->IsUAWidget();
1816}
1817
1818/*
1819 * aParentFrame - the frame that should be the parent of the generated
1820 * content. This is the frame for the corresponding content node,
1821 * which must not be a leaf frame.
1822 *
1823 * Any items created are added to aItems.
1824 *
1825 * We create an XML element (tag _moz_generated_content_before/after/marker)
1826 * representing the pseudoelement. We create a DOM node for each 'content'
1827 * item and make those nodes the children of the XML element. Then we create
1828 * a frame subtree for the XML element as if it were a regular child of
1829 * aParentFrame/aParentContent, giving the XML element the ::before, ::after
1830 * or ::marker style.
1831 */
1832void nsCSSFrameConstructor::CreateGeneratedContentItem(
1833 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
1834 Element& aOriginatingElement, ComputedStyle& aStyle,
1835 PseudoStyleType aPseudoElement, FrameConstructionItemList& aItems,
1836 ItemFlags aExtraFlags) {
1837 MOZ_ASSERT(aPseudoElement == PseudoStyleType::before ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPseudoElement == PseudoStyleType::before || aPseudoElement
== PseudoStyleType::after || aPseudoElement == PseudoStyleType
::marker)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aPseudoElement == PseudoStyleType::before
|| aPseudoElement == PseudoStyleType::after || aPseudoElement
== PseudoStyleType::marker))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
" (" "unexpected aPseudoElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1840; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1838 aPseudoElement == PseudoStyleType::after ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPseudoElement == PseudoStyleType::before || aPseudoElement
== PseudoStyleType::after || aPseudoElement == PseudoStyleType
::marker)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aPseudoElement == PseudoStyleType::before
|| aPseudoElement == PseudoStyleType::after || aPseudoElement
== PseudoStyleType::marker))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
" (" "unexpected aPseudoElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1840; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1839 aPseudoElement == PseudoStyleType::marker,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPseudoElement == PseudoStyleType::before || aPseudoElement
== PseudoStyleType::after || aPseudoElement == PseudoStyleType
::marker)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aPseudoElement == PseudoStyleType::before
|| aPseudoElement == PseudoStyleType::after || aPseudoElement
== PseudoStyleType::marker))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
" (" "unexpected aPseudoElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1840; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1840 "unexpected aPseudoElement")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPseudoElement == PseudoStyleType::before || aPseudoElement
== PseudoStyleType::after || aPseudoElement == PseudoStyleType
::marker)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(aPseudoElement == PseudoStyleType::before
|| aPseudoElement == PseudoStyleType::after || aPseudoElement
== PseudoStyleType::marker))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
" (" "unexpected aPseudoElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPseudoElement == PseudoStyleType::before || aPseudoElement == PseudoStyleType::after || aPseudoElement == PseudoStyleType::marker"
") (" "unexpected aPseudoElement" ")"); do { *((volatile int
*)__null) = 1840; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1841
1842 if (HasUAWidget(aOriginatingElement) &&
1843 !aOriginatingElement.IsHTMLElement(nsGkAtoms::details)) {
1844 return;
1845 }
1846
1847 ServoStyleSet* styleSet = mPresShell->StyleSet();
1848
1849 // Probe for the existence of the pseudo-element.
1850 // |ProbePseudoElementStyle| checks the relevant properties for the pseudo.
1851 // It only returns a non-null value if the pseudo should exist.
1852 RefPtr<ComputedStyle> pseudoStyle = styleSet->ProbePseudoElementStyle(
1853 aOriginatingElement, aPseudoElement, nullptr, &aStyle);
1854 if (!pseudoStyle) {
1855 return;
1856 }
1857
1858 nsAtom* elemName = nullptr;
1859 nsAtom* property = nullptr;
1860 switch (aPseudoElement) {
1861 case PseudoStyleType::before:
1862 elemName = nsGkAtoms::mozgeneratedcontentbefore;
1863 property = nsGkAtoms::beforePseudoProperty;
1864 break;
1865 case PseudoStyleType::after:
1866 elemName = nsGkAtoms::mozgeneratedcontentafter;
1867 property = nsGkAtoms::afterPseudoProperty;
1868 break;
1869 case PseudoStyleType::marker:
1870 // We want to get a marker style even if we match no rules, but we still
1871 // want to check the result of GeneratedContentPseudoExists.
1872 elemName = nsGkAtoms::mozgeneratedcontentmarker;
1873 property = nsGkAtoms::markerPseudoProperty;
1874 break;
1875 default:
1876 MOZ_ASSERT_UNREACHABLE("unexpected aPseudoElement")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"unexpected aPseudoElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 1876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected aPseudoElement" ")");
do { *((volatile int*)__null) = 1876; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1877 }
1878
1879 RefPtr<NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
1880 elemName, nullptr, kNameSpaceID_None, nsINode::ELEMENT_NODE);
1881 RefPtr<Element> container;
1882 nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
1883 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1884 return;
1885 }
1886
1887 // Cleared when the pseudo is unbound from the tree, so no need to store a
1888 // strong reference, nor a destructor.
1889 aOriginatingElement.SetProperty(property, container.get());
1890
1891 container->SetIsNativeAnonymousRoot();
1892 container->SetPseudoElementType(aPseudoElement);
1893
1894 BindContext context(aOriginatingElement, BindContext::ForNativeAnonymous);
1895 rv = container->BindToTree(context, aOriginatingElement);
1896 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1897 container->UnbindFromTree();
1898 return;
1899 }
1900
1901 if (mDocument->DevToolsAnonymousAndShadowEventsEnabled()) {
1902 container->QueueDevtoolsAnonymousEvent(/* aIsRemove = */ false);
1903 }
1904
1905 // Servo has already eagerly computed the style for the container, so we can
1906 // just stick the style on the element and avoid an additional traversal.
1907 //
1908 // We don't do this for pseudos that may trigger animations or transitions,
1909 // since those need to be kicked off by the traversal machinery.
1910 //
1911 // Note that when a pseudo-element animates, we flag the originating element,
1912 // so we check that flag, but we could also a more expensive (but exhaustive)
1913 // check using EffectSet::GetEffectSet, for example.
1914 if (!Servo_ComputedValues_SpecifiesAnimationsOrTransitions(pseudoStyle) &&
1915 !aOriginatingElement.MayHaveAnimations()) {
1916 Servo_SetExplicitStyle(container, pseudoStyle);
1917 } else {
1918 // If animations are involved, we avoid the SetExplicitStyle optimization
1919 // above. We need to grab style with animations from the pseudo element and
1920 // replace old one.
1921 mPresShell->StyleSet()->StyleNewSubtree(container);
1922 pseudoStyle = ServoStyleSet::ResolveServoStyle(*container);
1923 }
1924
1925 auto AppendChild = [&container, this](nsIContent* aChild) {
1926 // We don't strictly have to set NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE
1927 // here; it would get set under AppendChildTo. But AppendChildTo might
1928 // think that we're going from not being anonymous to being anonymous and
1929 // do some extra work; setting the flag here avoids that.
1930 aChild->SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
1931 container->AppendChildTo(aChild, false, IgnoreErrors());
1932 if (auto* childElement = Element::FromNode(aChild)) {
1933 // If we created any children elements, Servo needs to traverse them, but
1934 // the root is already set up.
1935 mPresShell->StyleSet()->StyleNewSubtree(childElement);
1936 }
1937 };
1938 auto items = pseudoStyle->StyleContent()->NonAltContentItems();
1939 size_t index = 0;
1940 for (const auto& item : items) {
1941 CreateGeneratedContent(aState, aOriginatingElement, *pseudoStyle, item,
1942 index++, AppendChild);
1943 }
1944 // If a ::marker has no 'content' then generate it from its 'list-style-*'.
1945 if (index == 0 && aPseudoElement == PseudoStyleType::marker) {
1946 CreateGeneratedContentFromListStyle(aState, aOriginatingElement,
1947 *pseudoStyle, AppendChild);
1948 }
1949 auto flags = ItemFlags{ItemFlag::IsGeneratedContent} + aExtraFlags;
1950 AddFrameConstructionItemsInternal(aState, container, aParentFrame, true,
1951 pseudoStyle, flags, aItems);
1952}
1953
1954/****************************************************
1955 ** BEGIN TABLE SECTION
1956 ****************************************************/
1957
1958// The term pseudo frame is being used instead of anonymous frame, since
1959// anonymous frame has been used elsewhere to refer to frames that have
1960// generated content
1961
1962// Return whether the given frame is a table pseudo-frame. Note that
1963// cell-content and table-outer frames have pseudo-types, but are always
1964// created, even for non-anonymous cells and tables respectively. So for those
1965// we have to examine the cell or table frame to see whether it's a pseudo
1966// frame. In particular, a lone table caption will have a table wrapper as its
1967// parent, but will also trigger construction of an empty inner table, which
1968// will be the one we can examine to see whether the wrapper was a pseudo-frame.
1969static bool IsTablePseudo(nsIFrame* aFrame) {
1970 auto pseudoType = aFrame->Style()->GetPseudoType();
1971 if (pseudoType == PseudoStyleType::NotPseudo) {
1972 return false;
1973 }
1974 return pseudoType == PseudoStyleType::table ||
1975 pseudoType == PseudoStyleType::inlineTable ||
1976 pseudoType == PseudoStyleType::tableColGroup ||
1977 pseudoType == PseudoStyleType::tableRowGroup ||
1978 pseudoType == PseudoStyleType::tableRow ||
1979 pseudoType == PseudoStyleType::tableCell ||
1980 (pseudoType == PseudoStyleType::cellContent &&
1981 aFrame->GetParent()->Style()->GetPseudoType() ==
1982 PseudoStyleType::tableCell) ||
1983 (pseudoType == PseudoStyleType::tableWrapper &&
1984 aFrame->PrincipalChildList()
1985 .FirstChild()
1986 ->Style()
1987 ->IsPseudoOrAnonBox());
1988}
1989
1990static bool IsRubyPseudo(nsIFrame* aFrame) {
1991 return RubyUtils::IsRubyPseudo(aFrame->Style()->GetPseudoType());
1992}
1993
1994// Note that this is (subtly) different to ParentIsWrapperAnonBox, since
1995// ParentIsWrapperAnonBox is really just about restyles, but there are wrapper
1996// anon boxes that don't need to return true for that...
1997// FIXME(emilio): This should be less complicated, ParentIsWrapperAnonBox should
1998// probably be renamed to something else, and this should just use
1999// IsWrapperAnonBox or similar...
2000static bool IsWrapperPseudo(nsIFrame* aFrame) {
2001 auto pseudoType = aFrame->Style()->GetPseudoType();
2002 if (!PseudoStyle::IsAnonBox(pseudoType)) {
2003 return false;
2004 }
2005 return PseudoStyle::IsWrapperAnonBox(pseudoType) || IsTablePseudo(aFrame);
2006}
2007
2008/* static */
2009nsCSSFrameConstructor::ParentType nsCSSFrameConstructor::GetParentType(
2010 LayoutFrameType aFrameType) {
2011 if (aFrameType == LayoutFrameType::Table) {
2012 return eTypeTable;
2013 }
2014 if (aFrameType == LayoutFrameType::TableRowGroup) {
2015 return eTypeRowGroup;
2016 }
2017 if (aFrameType == LayoutFrameType::TableRow) {
2018 return eTypeRow;
2019 }
2020 if (aFrameType == LayoutFrameType::TableColGroup) {
2021 return eTypeColGroup;
2022 }
2023 if (aFrameType == LayoutFrameType::RubyBaseContainer) {
2024 return eTypeRubyBaseContainer;
2025 }
2026 if (aFrameType == LayoutFrameType::RubyTextContainer) {
2027 return eTypeRubyTextContainer;
2028 }
2029 if (aFrameType == LayoutFrameType::Ruby) {
2030 return eTypeRuby;
2031 }
2032
2033 return eTypeBlock;
2034}
2035
2036// Pull all the captions present in aItems out into aCaptions.
2037static void PullOutCaptionFrames(nsFrameList& aList, nsFrameList& aCaptions) {
2038 nsIFrame* child = aList.FirstChild();
2039 while (child) {
2040 nsIFrame* nextSibling = child->GetNextSibling();
2041 if (child->StyleDisplay()->mDisplay == StyleDisplay::TableCaption) {
2042 aList.RemoveFrame(child);
2043 aCaptions.AppendFrame(nullptr, child);
2044 }
2045 child = nextSibling;
2046 }
2047}
2048
2049// Construct the outer, inner table frames and the children frames for the
2050// table.
2051// XXX Page break frames for pseudo table frames are not constructed to avoid
2052// the risk associated with revising the pseudo frame mechanism. The long term
2053// solution of having frames handle page-break-before/after will solve the
2054// problem.
2055nsIFrame* nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
2056 FrameConstructionItem& aItem,
2057 nsContainerFrame* aParentFrame,
2058 const nsStyleDisplay* aDisplay,
2059 nsFrameList& aFrameList) {
2060 MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::Table ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::Table || aDisplay
->mDisplay == StyleDisplay::InlineTable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::Table || aDisplay->mDisplay == StyleDisplay::InlineTable
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
" (" "Unexpected call" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2062; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
2061 aDisplay->mDisplay == StyleDisplay::InlineTable,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::Table || aDisplay
->mDisplay == StyleDisplay::InlineTable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::Table || aDisplay->mDisplay == StyleDisplay::InlineTable
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
" (" "Unexpected call" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2062; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
2062 "Unexpected call")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::Table || aDisplay
->mDisplay == StyleDisplay::InlineTable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::Table || aDisplay->mDisplay == StyleDisplay::InlineTable
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
" (" "Unexpected call" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::Table || aDisplay->mDisplay == StyleDisplay::InlineTable"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2062; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2063
2064 nsIContent* const content = aItem.mContent;
2065 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2066 const bool isMathMLContent = content->IsMathMLElement();
2067
2068 // create the pseudo SC for the table wrapper as a child of the inner SC
2069 RefPtr<ComputedStyle> outerComputedStyle =
2070 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
2071 PseudoStyleType::tableWrapper, computedStyle);
2072
2073 // Create the table wrapper frame which holds the caption and inner table
2074 // frame
2075 nsContainerFrame* newFrame;
2076 if (isMathMLContent) {
2077 newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerComputedStyle);
2078 } else {
2079 newFrame = NS_NewTableWrapperFrame(mPresShell, outerComputedStyle);
2080 }
2081
2082 nsContainerFrame* geometricParent = aState.GetGeometricParent(
2083 *outerComputedStyle->StyleDisplay(), aParentFrame);
2084
2085 // Init the table wrapper frame
2086 InitAndRestoreFrame(aState, content, geometricParent, newFrame);
2087
2088 // Create the inner table frame
2089 nsContainerFrame* innerFrame;
2090 if (isMathMLContent) {
2091 innerFrame = NS_NewMathMLmtableFrame(mPresShell, computedStyle);
2092 } else {
2093 innerFrame = NS_NewTableFrame(mPresShell, computedStyle);
2094 }
2095
2096 InitAndRestoreFrame(aState, content, newFrame, innerFrame);
2097 innerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2098
2099 // Put the newly created frames into the right child list
2100 SetInitialSingleChild(newFrame, innerFrame);
2101
2102 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
2103
2104 if (!mRootElementFrame) {
2105 mRootElementFrame = newFrame;
2106 }
2107
2108 nsFrameList childList;
2109
2110 // Process children
2111 nsFrameConstructorSaveState absoluteSaveState;
2112
2113 // Mark the table frame as an absolute container if needed
2114 newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2115 if (newFrame->IsAbsPosContainingBlock()) {
2116 aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
2117 }
2118
2119 nsFrameConstructorSaveState floatSaveState;
2120 aState.MaybePushFloatContainingBlock(innerFrame, floatSaveState);
2121
2122 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
2123 ConstructFramesFromItemList(
2124 aState, aItem.mChildItems, innerFrame,
2125 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
2126 } else {
2127 ProcessChildren(aState, content, computedStyle, innerFrame, true, childList,
2128 false);
2129 }
2130
2131 nsFrameList captionList;
2132 PullOutCaptionFrames(childList, captionList);
2133
2134 // Set the inner table frame's initial primary list
2135 innerFrame->SetInitialChildList(FrameChildListID::Principal,
2136 std::move(childList));
2137
2138 // Set the table wrapper frame's secondary childlist lists
2139 if (captionList.NotEmpty()) {
2140 captionList.ApplySetParent(newFrame);
2141 newFrame->SetInitialChildList(FrameChildListID::Caption,
2142 std::move(captionList));
2143 }
2144
2145 return newFrame;
2146}
2147
2148static void MakeTablePartAbsoluteContainingBlock(
2149 nsFrameConstructorState& aState, nsFrameConstructorSaveState& aAbsSaveState,
2150 nsContainerFrame* aFrame) {
2151 // If we're positioned, then we need to become an absolute containing block
2152 // for any absolutely positioned children.
2153 aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2154 if (aFrame->IsAbsPosContainingBlock()) {
2155 aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
2156 }
2157}
2158
2159nsIFrame* nsCSSFrameConstructor::ConstructTableRowOrRowGroup(
2160 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
2161 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
2162 nsFrameList& aFrameList) {
2163 MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableRow ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay
->mDisplay == StyleDisplay::TableRowGroup || aDisplay->
mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay
== StyleDisplay::TableHeaderGroup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup
|| aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
aDisplay->mDisplay == StyleDisplay::TableHeaderGroup))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
" (" "Not a row or row group" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
") (" "Not a row or row group" ")"); do { *((volatile int*)__null
) = 2167; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2164 aDisplay->mDisplay == StyleDisplay::TableRowGroup ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay
->mDisplay == StyleDisplay::TableRowGroup || aDisplay->
mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay
== StyleDisplay::TableHeaderGroup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup
|| aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
aDisplay->mDisplay == StyleDisplay::TableHeaderGroup))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
" (" "Not a row or row group" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
") (" "Not a row or row group" ")"); do { *((volatile int*)__null
) = 2167; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2165 aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay
->mDisplay == StyleDisplay::TableRowGroup || aDisplay->
mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay
== StyleDisplay::TableHeaderGroup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup
|| aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
aDisplay->mDisplay == StyleDisplay::TableHeaderGroup))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
" (" "Not a row or row group" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
") (" "Not a row or row group" ")"); do { *((volatile int*)__null
) = 2167; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2166 aDisplay->mDisplay == StyleDisplay::TableHeaderGroup,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay
->mDisplay == StyleDisplay::TableRowGroup || aDisplay->
mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay
== StyleDisplay::TableHeaderGroup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup
|| aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
aDisplay->mDisplay == StyleDisplay::TableHeaderGroup))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
" (" "Not a row or row group" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
") (" "Not a row or row group" ")"); do { *((volatile int*)__null
) = 2167; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2167 "Not a row or row group")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay
->mDisplay == StyleDisplay::TableRowGroup || aDisplay->
mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay
== StyleDisplay::TableHeaderGroup)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDisplay->mDisplay == StyleDisplay
::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup
|| aDisplay->mDisplay == StyleDisplay::TableFooterGroup ||
aDisplay->mDisplay == StyleDisplay::TableHeaderGroup))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
" (" "Not a row or row group" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableRow || aDisplay->mDisplay == StyleDisplay::TableRowGroup || aDisplay->mDisplay == StyleDisplay::TableFooterGroup || aDisplay->mDisplay == StyleDisplay::TableHeaderGroup"
") (" "Not a row or row group" ")"); do { *((volatile int*)__null
) = 2167; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2168 MOZ_ASSERT(aItem.mComputedStyle->StyleDisplay() == aDisplay,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aItem.mComputedStyle->StyleDisplay() == aDisplay)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aItem.mComputedStyle->StyleDisplay() == aDisplay)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aItem.mComputedStyle->StyleDisplay() == aDisplay"
" (" "Display style doesn't match style" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem.mComputedStyle->StyleDisplay() == aDisplay"
") (" "Display style doesn't match style" ")"); do { *((volatile
int*)__null) = 2169; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2169 "Display style doesn't match style")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aItem.mComputedStyle->StyleDisplay() == aDisplay)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aItem.mComputedStyle->StyleDisplay() == aDisplay)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aItem.mComputedStyle->StyleDisplay() == aDisplay"
" (" "Display style doesn't match style" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem.mComputedStyle->StyleDisplay() == aDisplay"
") (" "Display style doesn't match style" ")"); do { *((volatile
int*)__null) = 2169; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2170 nsIContent* const content = aItem.mContent;
2171 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2172
2173 nsContainerFrame* newFrame;
2174 if (aDisplay->mDisplay == StyleDisplay::TableRow) {
2175 if (content->IsMathMLElement()) {
2176 newFrame = NS_NewMathMLmtrFrame(mPresShell, computedStyle);
2177 } else {
2178 newFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
2179 }
2180 } else {
2181 newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
2182 }
2183
2184 InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
2185
2186 nsFrameConstructorSaveState absoluteSaveState;
2187 MakeTablePartAbsoluteContainingBlock(aState, absoluteSaveState, newFrame);
2188
2189 nsFrameConstructorSaveState floatSaveState;
2190 aState.MaybePushFloatContainingBlock(newFrame, floatSaveState);
2191
2192 nsFrameList childList;
2193 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
2194 ConstructFramesFromItemList(
2195 aState, aItem.mChildItems, newFrame,
2196 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
2197 } else {
2198 ProcessChildren(aState, content, computedStyle, newFrame, true, childList,
2199 false);
2200 }
2201
2202 newFrame->SetInitialChildList(FrameChildListID::Principal,
2203 std::move(childList));
2204 aFrameList.AppendFrame(nullptr, newFrame);
2205 return newFrame;
2206}
2207
2208nsIFrame* nsCSSFrameConstructor::ConstructTableCol(
2209 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
2210 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
2211 nsFrameList& aFrameList) {
2212 nsIContent* const content = aItem.mContent;
2213 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2214
2215 nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, computedStyle);
2216 InitAndRestoreFrame(aState, content, aParentFrame, colFrame);
2217
2218 NS_ASSERTION(colFrame->Style() == computedStyle, "Unexpected style")do { if (!(colFrame->Style() == computedStyle)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Unexpected style", "colFrame->Style() == computedStyle"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2218); MOZ_PretendNoReturn(); } } while (0)
;
2219
2220 aFrameList.AppendFrame(nullptr, colFrame);
2221
2222 // construct additional col frames if the col frame has a span > 1
2223 int32_t span = colFrame->GetSpan();
2224 for (int32_t spanX = 1; spanX < span; spanX++) {
2225 nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, computedStyle);
2226 InitAndRestoreFrame(aState, content, aParentFrame, newCol, false);
2227 aFrameList.LastChild()->SetNextContinuation(newCol);
2228 newCol->SetPrevContinuation(aFrameList.LastChild());
2229 aFrameList.AppendFrame(nullptr, newCol);
2230 newCol->SetColType(eColAnonymousCol);
2231 }
2232
2233 return colFrame;
2234}
2235
2236nsIFrame* nsCSSFrameConstructor::ConstructTableCell(
2237 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
2238 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
2239 nsFrameList& aFrameList) {
2240 MOZ_ASSERT(aDisplay->mDisplay == StyleDisplay::TableCell, "Unexpected call")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplay->mDisplay == StyleDisplay::TableCell)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aDisplay->mDisplay == StyleDisplay::TableCell))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aDisplay->mDisplay == StyleDisplay::TableCell"
" (" "Unexpected call" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplay->mDisplay == StyleDisplay::TableCell"
") (" "Unexpected call" ")"); do { *((volatile int*)__null) =
2240; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
2241
2242 nsIContent* const content = aItem.mContent;
2243 ComputedStyle* const computedStyle = aItem.mComputedStyle;
2244 const bool isMathMLContent = content->IsMathMLElement();
2245
2246 nsTableFrame* tableFrame =
2247 static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
2248 nsContainerFrame* cellFrame;
2249 // <mtable> is border separate in mathml.css and the MathML code doesn't
2250 // implement border collapse. For those users who style <mtable> with border
2251 // collapse, give them the default non-MathML table frames that understand
2252 // border collapse. This won't break us because MathML table frames are all
2253 // subclasses of the default table code, and so we can freely mix <mtable>
2254 // with <mtr> or <tr>, <mtd> or <td>. What will happen is just that non-MathML
2255 // frames won't understand MathML attributes and will therefore miss the
2256 // special handling that the MathML code does.
2257 if (isMathMLContent && !tableFrame->IsBorderCollapse()) {
2258 cellFrame = NS_NewMathMLmtdFrame(mPresShell, computedStyle, tableFrame);
2259 } else {
2260 // Warning: If you change this and add a wrapper frame around table cell
2261 // frames, make sure Bug 368554 doesn't regress!
2262 // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
2263 cellFrame = NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
2264 }
2265
2266 // Initialize the table cell frame
2267 InitAndRestoreFrame(aState, content, aParentFrame, cellFrame);
2268 cellFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2269
2270 // Resolve pseudo style and initialize the body cell frame
2271 RefPtr<ComputedStyle> innerPseudoStyle =
2272 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
2273 PseudoStyleType::cellContent, computedStyle);
2274
2275 nsContainerFrame* cellInnerFrame;
2276 nsContainerFrame* scrollFrame = nullptr;
2277 bool isScrollable = false;
2278 // Create a block frame that will format the cell's content
2279 if (isMathMLContent) {
2280 cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
2281 } else {
2282 isScrollable = innerPseudoStyle->StyleDisplay()->IsScrollableOverflow() &&
2283 !aState.mPresContext->IsPaginated() &&
2284 StaticPrefs::layout_tables_scrollable_cells();
2285 if (isScrollable) {
2286 innerPseudoStyle = BeginBuildingScrollContainerFrame(
2287 aState, content, innerPseudoStyle, cellFrame,
2288 PseudoStyleType::scrolledContent, false, scrollFrame);
2289 }
2290 cellInnerFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle);
2291 }
2292 auto* parent = scrollFrame ? scrollFrame : cellFrame;
2293 InitAndRestoreFrame(aState, content, parent, cellInnerFrame);
2294
2295 nsFrameConstructorSaveState absoluteSaveState;
2296 MakeTablePartAbsoluteContainingBlock(aState, absoluteSaveState, cellFrame);
2297
2298 nsFrameConstructorSaveState floatSaveState;
2299 aState.MaybePushFloatContainingBlock(cellInnerFrame, floatSaveState);
2300
2301 nsFrameList childList;
2302 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
2303 AutoFrameConstructionPageName pageNameTracker(aState, cellInnerFrame);
2304 ConstructFramesFromItemList(
2305 aState, aItem.mChildItems, cellInnerFrame,
2306 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
2307 } else {
2308 // Process the child content
2309 ProcessChildren(aState, content, computedStyle, cellInnerFrame, true,
2310 childList, !isMathMLContent);
2311 }
2312
2313 cellInnerFrame->SetInitialChildList(FrameChildListID::Principal,
2314 std::move(childList));
2315
2316 if (isScrollable) {
2317 FinishBuildingScrollContainerFrame(scrollFrame, cellInnerFrame);
2318 }
2319 SetInitialSingleChild(cellFrame, scrollFrame ? scrollFrame : cellInnerFrame);
2320 aFrameList.AppendFrame(nullptr, cellFrame);
2321 return cellFrame;
2322}
2323
2324static inline bool NeedFrameFor(const nsFrameConstructorState& aState,
2325 nsContainerFrame* aParentFrame,
2326 nsIContent* aChildContent) {
2327 // XXX the GetContent() != aChildContent check is needed due to bug 135040.
2328 // Remove it once that's fixed.
2329 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
" (" "Why did we get called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2332; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2330 !aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
" (" "Why did we get called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2332; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2331 aChildContent->GetPrimaryFrame()->GetContent() != aChildContent,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
" (" "Why did we get called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2332; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2332 "Why did we get called?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aChildContent->GetPrimaryFrame()->GetContent() != aChildContent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
" (" "Why did we get called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChildContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aChildContent->GetPrimaryFrame()->GetContent() != aChildContent"
") (" "Why did we get called?" ")"); do { *((volatile int*)__null
) = 2332; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2333
2334 // don't create a whitespace frame if aParentFrame doesn't want it.
2335 // always create frames for children in generated content. counter(),
2336 // quotes, and attr() content can easily change dynamically and we don't
2337 // want to be reconstructing frames. It's not even clear that these
2338 // should be considered ignorable just because they evaluate to
2339 // whitespace.
2340
2341 // We could handle all this in CreateNeededPseudoContainers or some other
2342 // place after we build our frame construction items, but that would involve
2343 // creating frame construction items for whitespace kids that ignores
2344 // white-space, where we know we'll be dropping them all anyway, and involve
2345 // an extra walk down the frame construction item list.
2346 auto excludesIgnorableWhitespace = [](nsIFrame* aParentFrame) {
2347 return aParentFrame->IsMathMLFrame();
2348 };
2349 if (!aParentFrame || !excludesIgnorableWhitespace(aParentFrame) ||
2350 aParentFrame->IsGeneratedContentFrame() || !aChildContent->IsText()) {
2351 return true;
2352 }
2353
2354 aChildContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
2355 NS_REFRAME_IF_WHITESPACE);
2356 return !aChildContent->TextIsOnlyWhitespace();
2357}
2358
2359/***********************************************
2360 * END TABLE SECTION
2361 ***********************************************/
2362
2363nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
2364 Element* aDocElement) {
2365 MOZ_ASSERT(GetRootFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetRootFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetRootFrame()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("GetRootFrame()"
" (" "No viewport? Someone forgot to call ConstructRootFrame!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetRootFrame()"
") (" "No viewport? Someone forgot to call ConstructRootFrame!"
")"); do { *((volatile int*)__null) = 2366; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2366 "No viewport? Someone forgot to call ConstructRootFrame!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetRootFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetRootFrame()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("GetRootFrame()"
" (" "No viewport? Someone forgot to call ConstructRootFrame!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetRootFrame()"
") (" "No viewport? Someone forgot to call ConstructRootFrame!"
")"); do { *((volatile int*)__null) = 2366; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2367 MOZ_ASSERT(!mDocElementContainingBlock,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDocElementContainingBlock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDocElementContainingBlock)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDocElementContainingBlock"
" (" "Shouldn't have a doc element containing block here" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDocElementContainingBlock"
") (" "Shouldn't have a doc element containing block here" ")"
); do { *((volatile int*)__null) = 2368; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2368 "Shouldn't have a doc element containing block here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDocElementContainingBlock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDocElementContainingBlock)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mDocElementContainingBlock"
" (" "Shouldn't have a doc element containing block here" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDocElementContainingBlock"
") (" "Shouldn't have a doc element containing block here" ")"
); do { *((volatile int*)__null) = 2368; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2369
2370 // Resolve a new style for the viewport since it may be affected by a new root
2371 // element style (e.g. a propagated 'direction').
2372 //
2373 // @see ComputedStyle::ApplyStyleFixups
2374 {
2375 RefPtr<ComputedStyle> sc =
2376 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
2377 PseudoStyleType::viewport, nullptr);
2378 GetRootFrame()->SetComputedStyleWithoutNotification(sc);
2379 }
2380
2381 // Ensure the document element is styled at this point.
2382 if (!aDocElement->HasServoData()) {
2383 mPresShell->StyleSet()->StyleNewSubtree(aDocElement);
2384 }
2385 aDocElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
2386
2387 // Make sure to call UpdateViewportScrollStylesOverride before
2388 // SetUpDocElementContainingBlock, since it sets up our scrollbar state
2389 // properly.
2390 DebugOnly<nsIContent*> propagatedScrollFrom;
2391 if (nsPresContext* presContext = mPresShell->GetPresContext()) {
2392 propagatedScrollFrom = presContext->UpdateViewportScrollStylesOverride();
2393 }
2394
2395 SetUpDocElementContainingBlock(aDocElement);
2396
2397 // This has the side-effect of getting `mFrameTreeState` from our docshell.
2398 //
2399 // FIXME(emilio): There may be a more sensible time to do this.
2400 if (!mFrameTreeState) {
2401 mPresShell->CaptureHistoryState(getter_AddRefs(mFrameTreeState));
2402 }
2403
2404 NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now")do { if (!(mDocElementContainingBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should have parent by now", "mDocElementContainingBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2404); MOZ_PretendNoReturn(); } } while (0)
;
2405 nsFrameConstructorState state(
2406 mPresShell,
2407 GetAbsoluteContainingBlock(mDocElementContainingBlock, FIXED_POS),
2408 nullptr, nullptr, do_AddRef(mFrameTreeState));
2409
2410 RefPtr<ComputedStyle> computedStyle =
2411 ServoStyleSet::ResolveServoStyle(*aDocElement);
2412
2413 const nsStyleDisplay* display = computedStyle->StyleDisplay();
2414
2415 // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
2416
2417 NS_ASSERTION(!display->IsScrollableOverflow() ||do { if (!(!display->IsScrollableOverflow() || state.mPresContext
->IsPaginated() || propagatedScrollFrom == aDocElement)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Scrollbars should have been propagated to the viewport"
, "!display->IsScrollableOverflow() || state.mPresContext->IsPaginated() || propagatedScrollFrom == aDocElement"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0)
2418 state.mPresContext->IsPaginated() ||do { if (!(!display->IsScrollableOverflow() || state.mPresContext
->IsPaginated() || propagatedScrollFrom == aDocElement)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Scrollbars should have been propagated to the viewport"
, "!display->IsScrollableOverflow() || state.mPresContext->IsPaginated() || propagatedScrollFrom == aDocElement"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0)
2419 propagatedScrollFrom == aDocElement,do { if (!(!display->IsScrollableOverflow() || state.mPresContext
->IsPaginated() || propagatedScrollFrom == aDocElement)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Scrollbars should have been propagated to the viewport"
, "!display->IsScrollableOverflow() || state.mPresContext->IsPaginated() || propagatedScrollFrom == aDocElement"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0)
2420 "Scrollbars should have been propagated to the viewport")do { if (!(!display->IsScrollableOverflow() || state.mPresContext
->IsPaginated() || propagatedScrollFrom == aDocElement)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Scrollbars should have been propagated to the viewport"
, "!display->IsScrollableOverflow() || state.mPresContext->IsPaginated() || propagatedScrollFrom == aDocElement"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0)
;
2421
2422 if (MOZ_UNLIKELY(display->mDisplay == StyleDisplay::None)(__builtin_expect(!!(display->mDisplay == StyleDisplay::None
), 0))
) {
2423 return nullptr;
2424 }
2425
2426 // This implements "The Principal Writing Mode".
2427 // https://drafts.csswg.org/css-writing-modes-3/#principal-flow
2428 //
2429 // If there's a <body> element in an HTML document, its writing-mode,
2430 // direction, and text-orientation override the root element's used value.
2431 //
2432 // We need to copy <body>'s WritingMode to mDocElementContainingBlock before
2433 // construct mRootElementFrame so that anonymous internal frames such as
2434 // <html> with table style can copy their parent frame's mWritingMode in
2435 // nsIFrame::Init().
2436 MOZ_ASSERT(!mRootElementFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRootElementFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRootElementFrame))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mRootElementFrame"
" (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")"); do { *((volatile int
*)__null) = 2438; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2437 "We need to copy <body>'s principal writing-mode before "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRootElementFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRootElementFrame))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mRootElementFrame"
" (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")"); do { *((volatile int
*)__null) = 2438; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2438 "constructing mRootElementFrame.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRootElementFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRootElementFrame))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mRootElementFrame"
" (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "We need to copy <body>'s principal writing-mode before "
"constructing mRootElementFrame." ")"); do { *((volatile int
*)__null) = 2438; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2439
2440 const WritingMode propagatedWM = [&] {
2441 const WritingMode rootWM(computedStyle);
2442 if (computedStyle->StyleDisplay()->IsContainAny()) {
2443 return rootWM;
2444 }
2445 Element* body = mDocument->GetBodyElement();
2446 if (!body) {
2447 return rootWM;
2448 }
2449 RefPtr<ComputedStyle> bodyStyle = ResolveComputedStyle(body);
2450 if (bodyStyle->StyleDisplay()->IsContainAny()) {
2451 return rootWM;
2452 }
2453 const WritingMode bodyWM(bodyStyle);
2454 if (bodyWM != rootWM) {
2455 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "Layout"_ns,
2456 mDocument,
2457 nsContentUtils::eLAYOUT_PROPERTIES,
2458 "PrincipalWritingModePropagationWarning");
2459 }
2460 return bodyWM;
2461 }();
2462
2463 mDocElementContainingBlock->PropagateWritingModeToSelfAndAncestors(
2464 propagatedWM);
2465
2466 // Push the absolute containing block now so we can absolutely position the
2467 // root element
2468 nsFrameConstructorSaveState canvasCbSaveState;
2469 mCanvasFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2470
2471 state.PushAbsoluteContainingBlock(mCanvasFrame, mCanvasFrame,
2472 canvasCbSaveState);
2473
2474 nsFrameConstructorSaveState docElementCbSaveState;
2475 if (mCanvasFrame != mDocElementContainingBlock) {
2476 mDocElementContainingBlock->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2477 state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
2478 mDocElementContainingBlock,
2479 docElementCbSaveState);
2480 }
2481
2482 // The rules from CSS 2.1, section 9.2.4, have already been applied
2483 // by the style system, so we can assume that display->mDisplay is
2484 // either NONE, BLOCK, or TABLE.
2485
2486 // contentFrame is the primary frame for the root element. frameList contains
2487 // the children of the initial containing block.
2488 //
2489 // The first of those frames is usually `contentFrame`, but it can be
2490 // different, in particular if the root frame is positioned, in which case
2491 // contentFrame is the out-of-flow frame and frameList.FirstChild() is the
2492 // placeholder.
2493 //
2494 // The rest of the frames in frameList are the anonymous content of the canvas
2495 // frame.
2496 nsContainerFrame* contentFrame;
2497 nsFrameList frameList;
2498 bool processChildren = false;
2499
2500 nsFrameConstructorSaveState absoluteSaveState;
2501
2502 if (aDocElement->IsSVGElement()) {
2503 if (!aDocElement->IsSVGElement(nsGkAtoms::svg)) {
2504 return nullptr;
2505 }
2506 // We're going to call the right function ourselves, so no need to give a
2507 // function to this FrameConstructionData.
2508
2509 // XXXbz on the other hand, if we converted this whole function to
2510 // FrameConstructionData/Item, then we'd need the right function
2511 // here... but would probably be able to get away with less code in this
2512 // function in general.
2513 static constexpr FrameConstructionData rootSVGData;
2514 AutoFrameConstructionItem item(this, &rootSVGData, aDocElement,
2515 do_AddRef(computedStyle), true);
2516
2517 contentFrame = static_cast<nsContainerFrame*>(ConstructOuterSVG(
2518 state, item, mDocElementContainingBlock, display, frameList));
2519 } else if (display->mDisplay == StyleDisplay::Flex ||
2520 display->mDisplay == StyleDisplay::WebkitBox ||
2521 display->mDisplay == StyleDisplay::Grid) {
2522 auto func = [&] {
2523 if (display->mDisplay == StyleDisplay::Grid) {
2524 return NS_NewGridContainerFrame;
2525 }
2526 return NS_NewFlexContainerFrame;
2527 }();
2528 contentFrame = func(mPresShell, computedStyle);
2529 InitAndRestoreFrame(
2530 state, aDocElement,
2531 state.GetGeometricParent(*display, mDocElementContainingBlock),
2532 contentFrame);
2533 state.AddChild(contentFrame, frameList, aDocElement,
2534 mDocElementContainingBlock);
2535 processChildren = true;
2536
2537 contentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2538 if (contentFrame->IsAbsPosContainingBlock()) {
2539 state.PushAbsoluteContainingBlock(contentFrame, contentFrame,
2540 absoluteSaveState);
2541 }
2542 } else if (display->mDisplay == StyleDisplay::Table) {
2543 // We're going to call the right function ourselves, so no need to give a
2544 // function to this FrameConstructionData.
2545
2546 // XXXbz on the other hand, if we converted this whole function to
2547 // FrameConstructionData/Item, then we'd need the right function
2548 // here... but would probably be able to get away with less code in this
2549 // function in general.
2550 static constexpr FrameConstructionData rootTableData;
2551 AutoFrameConstructionItem item(this, &rootTableData, aDocElement,
2552 do_AddRef(computedStyle), true);
2553
2554 // if the document is a table then just populate it.
2555 contentFrame = static_cast<nsContainerFrame*>(ConstructTable(
2556 state, item, mDocElementContainingBlock, display, frameList));
2557 } else if (display->DisplayInside() == StyleDisplayInside::Ruby) {
2558 static constexpr FrameConstructionData data(
2559 &nsCSSFrameConstructor::ConstructBlockRubyFrame);
2560 AutoFrameConstructionItem item(this, &data, aDocElement,
2561 do_AddRef(computedStyle), true);
2562 contentFrame = static_cast<nsContainerFrame*>(ConstructBlockRubyFrame(
2563 state, item,
2564 state.GetGeometricParent(*display, mDocElementContainingBlock), display,
2565 frameList));
2566 } else {
2567 MOZ_ASSERT(display->mDisplay == StyleDisplay::Block ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(display->mDisplay == StyleDisplay::Block || display
->mDisplay == StyleDisplay::FlowRoot)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(display->mDisplay == StyleDisplay
::Block || display->mDisplay == StyleDisplay::FlowRoot))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
" (" "Unhandled display type for root element" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
") (" "Unhandled display type for root element" ")"); do { *
((volatile int*)__null) = 2569; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2568 display->mDisplay == StyleDisplay::FlowRoot,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(display->mDisplay == StyleDisplay::Block || display
->mDisplay == StyleDisplay::FlowRoot)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(display->mDisplay == StyleDisplay
::Block || display->mDisplay == StyleDisplay::FlowRoot))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
" (" "Unhandled display type for root element" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
") (" "Unhandled display type for root element" ")"); do { *
((volatile int*)__null) = 2569; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2569 "Unhandled display type for root element")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(display->mDisplay == StyleDisplay::Block || display
->mDisplay == StyleDisplay::FlowRoot)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(display->mDisplay == StyleDisplay
::Block || display->mDisplay == StyleDisplay::FlowRoot))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
" (" "Unhandled display type for root element" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "display->mDisplay == StyleDisplay::Block || display->mDisplay == StyleDisplay::FlowRoot"
") (" "Unhandled display type for root element" ")"); do { *
((volatile int*)__null) = 2569; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2570 contentFrame = NS_NewBlockFrame(mPresShell, computedStyle);
2571 ConstructBlock(
2572 state, aDocElement,
2573 state.GetGeometricParent(*display, mDocElementContainingBlock),
2574 mDocElementContainingBlock, computedStyle, &contentFrame, frameList,
2575 contentFrame->IsAbsPosContainingBlock() ? contentFrame : nullptr);
2576 }
2577
2578 MOZ_ASSERT(frameList.FirstChild())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(frameList.FirstChild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(frameList.FirstChild()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("frameList.FirstChild()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "frameList.FirstChild()"
")"); do { *((volatile int*)__null) = 2578; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2579 MOZ_ASSERT(frameList.FirstChild()->GetContent() == aDocElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(frameList.FirstChild()->GetContent() == aDocElement
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(frameList.FirstChild()->GetContent() == aDocElement
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"frameList.FirstChild()->GetContent() == aDocElement", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "frameList.FirstChild()->GetContent() == aDocElement"
")"); do { *((volatile int*)__null) = 2579; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2580 MOZ_ASSERT(contentFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(contentFrame))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("contentFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentFrame"
")"); do { *((volatile int*)__null) = 2580; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2581
2582 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(processChildren ? !mRootElementFrame : mRootElementFrame
== contentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(processChildren ? !mRootElementFrame
: mRootElementFrame == contentFrame))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
" (" "unexpected mRootElementFrame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
") (" "unexpected mRootElementFrame" ")"); do { *((volatile int
*)__null) = 2584; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2583 processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(processChildren ? !mRootElementFrame : mRootElementFrame
== contentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(processChildren ? !mRootElementFrame
: mRootElementFrame == contentFrame))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
" (" "unexpected mRootElementFrame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
") (" "unexpected mRootElementFrame" ")"); do { *((volatile int
*)__null) = 2584; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2584 "unexpected mRootElementFrame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(processChildren ? !mRootElementFrame : mRootElementFrame
== contentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(processChildren ? !mRootElementFrame
: mRootElementFrame == contentFrame))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
" (" "unexpected mRootElementFrame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "processChildren ? !mRootElementFrame : mRootElementFrame == contentFrame"
") (" "unexpected mRootElementFrame" ")"); do { *((volatile int
*)__null) = 2584; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2585 if (processChildren) {
2586 mRootElementFrame = contentFrame;
2587 }
2588
2589 // Figure out which frame has the main style for the document element,
2590 // assigning it to mRootElementStyleFrame.
2591 // Backgrounds should be propagated from that frame to the viewport.
2592 contentFrame->GetParentComputedStyle(&mRootElementStyleFrame);
2593 bool isChild = mRootElementStyleFrame &&
2594 mRootElementStyleFrame->GetParent() == contentFrame;
2595 if (!isChild) {
2596 mRootElementStyleFrame = mRootElementFrame;
2597 }
2598
2599 if (processChildren) {
2600 // Still need to process the child content
2601 nsFrameList childList;
2602
2603 NS_ASSERTION(do { if (!(!contentFrame->IsBlockFrameOrSubclass() &&
!contentFrame->IsSVGFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Only XUL frames should reach here", "!contentFrame->IsBlockFrameOrSubclass() && !contentFrame->IsSVGFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2605); MOZ_PretendNoReturn(); } } while (0)
2604 !contentFrame->IsBlockFrameOrSubclass() && !contentFrame->IsSVGFrame(),do { if (!(!contentFrame->IsBlockFrameOrSubclass() &&
!contentFrame->IsSVGFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Only XUL frames should reach here", "!contentFrame->IsBlockFrameOrSubclass() && !contentFrame->IsSVGFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2605); MOZ_PretendNoReturn(); } } while (0)
2605 "Only XUL frames should reach here")do { if (!(!contentFrame->IsBlockFrameOrSubclass() &&
!contentFrame->IsSVGFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Only XUL frames should reach here", "!contentFrame->IsBlockFrameOrSubclass() && !contentFrame->IsSVGFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2605); MOZ_PretendNoReturn(); } } while (0)
;
2606
2607 nsFrameConstructorSaveState floatSaveState;
2608 state.MaybePushFloatContainingBlock(contentFrame, floatSaveState);
2609
2610 ProcessChildren(state, aDocElement, computedStyle, contentFrame, true,
2611 childList, false);
2612
2613 // Set the initial child lists
2614 contentFrame->SetInitialChildList(FrameChildListID::Principal,
2615 std::move(childList));
2616 }
2617
2618 nsIFrame* newFrame = frameList.FirstChild();
2619 // set the primary frame
2620 aDocElement->SetPrimaryFrame(contentFrame);
2621 mDocElementContainingBlock->AppendFrames(FrameChildListID::Principal,
2622 std::move(frameList));
2623
2624 // NOTE(emilio): This is in the reverse order compared to normal anonymous
2625 // children. We usually generate anonymous kids first, then non-anonymous,
2626 // but we generate the doc element frame the other way around. This is fine
2627 // either way, but generating anonymous children in a different order requires
2628 // changing nsCanvasFrame (and a whole lot of other potentially unknown code)
2629 // to look at the last child to find the root frame rather than the first
2630 // child.
2631 ConstructAnonymousContentForCanvas(
2632 state, mCanvasFrame, mRootElementFrame->GetContent(), frameList);
2633 mCanvasFrame->AppendFrames(FrameChildListID::Principal, std::move(frameList));
2634
2635 return newFrame;
2636}
2637
2638RestyleManager* nsCSSFrameConstructor::RestyleManager() const {
2639 return mPresShell->GetPresContext()->RestyleManager();
2640}
2641
2642ViewportFrame* nsCSSFrameConstructor::ConstructRootFrame() {
2643 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ConstructRootFrame",mozilla::AutoProfilerLabelHot raiiObject2644( "nsCSSFrameConstructor::ConstructRootFrame"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
2644 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject2644( "nsCSSFrameConstructor::ConstructRootFrame"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
2645 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
2646
2647 ServoStyleSet* styleSet = mPresShell->StyleSet();
2648
2649 // --------- BUILD VIEWPORT -----------
2650 RefPtr<ComputedStyle> viewportPseudoStyle =
2651 styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::viewport,
2652 nullptr);
2653 ViewportFrame* viewportFrame =
2654 NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
2655
2656 // XXXbz do we _have_ to pass a null content pointer to that frame?
2657 // Would it really kill us to pass in the root element or something?
2658 // What would that break?
2659 viewportFrame->Init(nullptr, nullptr, nullptr);
2660
2661 viewportFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2662
2663 // Bind the viewport frame to the root view
2664 if (nsView* rootView = mPresShell->GetViewManager()->GetRootView()) {
2665 viewportFrame->SetView(rootView);
2666 viewportFrame->SyncFrameViewProperties(rootView);
2667 rootView->SetNeedsWindowPropertiesSync();
2668 }
2669
2670 // Make it an absolute container for fixed-pos elements
2671 viewportFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2672 viewportFrame->MarkAsAbsoluteContainingBlock();
2673
2674 return viewportFrame;
2675}
2676
2677void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
2678 nsIContent* aDocElement) {
2679 MOZ_ASSERT(aDocElement, "No element?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocElement))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aDocElement" " ("
"No element?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement"
") (" "No element?" ")"); do { *((volatile int*)__null) = 2679
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2680 MOZ_ASSERT(!aDocElement->GetParent(), "Not root content?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aDocElement->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aDocElement->GetParent()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aDocElement->GetParent()" " (" "Not root content?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2680); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aDocElement->GetParent()"
") (" "Not root content?" ")"); do { *((volatile int*)__null
) = 2680; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2681 MOZ_ASSERT(aDocElement->GetUncomposedDoc(), "Not in a document?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocElement->GetUncomposedDoc())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocElement->GetUncomposedDoc
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aDocElement->GetUncomposedDoc()" " (" "Not in a document?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement->GetUncomposedDoc()"
") (" "Not in a document?" ")"); do { *((volatile int*)__null
) = 2681; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2682 MOZ_ASSERT(aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocElement->GetUncomposedDoc()->GetRootElement
() == aDocElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocElement->GetUncomposedDoc
()->GetRootElement() == aDocElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement"
" (" "Not the root of the document?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement"
") (" "Not the root of the document?" ")"); do { *((volatile
int*)__null) = 2683; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
2683 "Not the root of the document?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocElement->GetUncomposedDoc()->GetRootElement
() == aDocElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocElement->GetUncomposedDoc
()->GetRootElement() == aDocElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement"
" (" "Not the root of the document?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocElement->GetUncomposedDoc()->GetRootElement() == aDocElement"
") (" "Not the root of the document?" ")"); do { *((volatile
int*)__null) = 2683; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2684
2685 /*
2686 how the root frame hierarchy should look
2687
2688 Galley presentation, with scrolling:
2689
2690 ViewportFrame [fixed-cb]
2691 ScrollContainerFrame (if needed)
2692 nsCanvasFrame [abs-cb]
2693 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2694 nsTableWrapperFrame, nsPlaceholderFrame,
2695 nsFlexContainerFrame, nsGridContainerFrame)
2696
2697 Print presentation, non-XUL
2698
2699 ViewportFrame
2700 nsCanvasFrame
2701 nsPageSequenceFrame
2702 PrintedSheetFrame
2703 nsPageFrame
2704 nsPageContentFrame [fixed-cb]
2705 nsCanvasFrame [abs-cb]
2706 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2707 nsTableWrapperFrame, nsPlaceholderFrame,
2708 nsFlexContainerFrame,
2709 nsGridContainerFrame)
2710
2711 Print-preview presentation, non-XUL
2712
2713 ViewportFrame
2714 ScrollContainerFrame
2715 nsCanvasFrame
2716 nsPageSequenceFrame
2717 PrintedSheetFrame
2718 nsPageFrame
2719 nsPageContentFrame [fixed-cb]
2720 nsCanvasFrame [abs-cb]
2721 root element frame (nsBlockFrame, SVGOuterSVGFrame,
2722 nsTableWrapperFrame,
2723 nsPlaceholderFrame,
2724 nsFlexContainerFrame,
2725 nsGridContainerFrame)
2726
2727 Print/print preview of XUL is not supported.
2728 [fixed-cb]: the default containing block for fixed-pos content
2729 [abs-cb]: the default containing block for abs-pos content
2730
2731 Meaning of nsCSSFrameConstructor fields:
2732 mRootElementFrame is "root element frame". This is the primary frame for
2733 the root element.
2734 mDocElementContainingBlock is the parent of mRootElementFrame
2735 (i.e. nsCanvasFrame)
2736 mPageSequenceFrame is the nsPageSequenceFrame, or null if there isn't
2737 one
2738 */
2739
2740 // --------- CREATE ROOT FRAME -------
2741
2742 // Create the root frame. The document element's frame is a child of the
2743 // root frame.
2744 //
2745 // The root frame serves two purposes:
2746 // - reserves space for any margins needed for the document element's frame
2747 // - renders the document element's background. This ensures the background
2748 // covers the entire canvas as specified by the CSS2 spec
2749
2750 nsPresContext* presContext = mPresShell->GetPresContext();
2751 const bool isPaginated = presContext->IsRootPaginatedDocument();
2752
2753 const bool isHTML = aDocElement->IsHTMLElement();
2754 const bool isXUL = !isHTML && aDocElement->IsXULElement();
2755
2756 const bool isScrollable = [&] {
2757 if (isPaginated) {
2758 return presContext->HasPaginatedScrolling();
2759 }
2760 // Never create scrollbars for XUL documents or top level XHTML documents
2761 // that disable scrolling.
2762 if (isXUL) {
2763 return false;
2764 }
2765 if (aDocElement->OwnerDoc()->ChromeRulesEnabled() &&
2766 aDocElement->AsElement()->AttrValueIs(
2767 kNameSpaceID_None, nsGkAtoms::scrolling, nsGkAtoms::_false,
2768 eCaseMatters)) {
2769 return false;
2770 }
2771 return true;
2772 }();
2773
2774 nsContainerFrame* viewportFrame =
2775 static_cast<nsContainerFrame*>(GetRootFrame());
2776 ComputedStyle* viewportPseudoStyle = viewportFrame->Style();
2777
2778 nsCanvasFrame* rootCanvasFrame =
2779 NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
2780 PseudoStyleType rootPseudo = PseudoStyleType::canvas;
2781 mCanvasFrame = rootCanvasFrame;
2782 mDocElementContainingBlock = rootCanvasFrame;
2783
2784 // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
2785
2786 // If the device supports scrolling (e.g., in galley mode on the screen and
2787 // for print-preview, but not when printing), then create a scroll frame that
2788 // will act as the scrolling mechanism for the viewport.
2789 // XXX Do we even need a viewport when printing to a printer?
2790
2791 // We no longer need to do overflow propagation here. It's taken care of
2792 // when we construct frames for the element whose overflow might be
2793 // propagated
2794 NS_ASSERTION(!isScrollable || !isXUL,do { if (!(!isScrollable || !isXUL)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "XUL documents should never be scrollable - see above", "!isScrollable || !isXUL"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2795); MOZ_PretendNoReturn(); } } while (0)
2795 "XUL documents should never be scrollable - see above")do { if (!(!isScrollable || !isXUL)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "XUL documents should never be scrollable - see above", "!isScrollable || !isXUL"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2795); MOZ_PretendNoReturn(); } } while (0)
;
2796
2797 nsContainerFrame* newFrame = rootCanvasFrame;
2798 RefPtr<ComputedStyle> rootPseudoStyle;
2799 // we must create a state because if the scrollbars are GFX it needs the
2800 // state to build the scrollbar frames.
2801 nsFrameConstructorState state(mPresShell, nullptr, nullptr, nullptr);
2802
2803 // Start off with the viewport as parent; we'll adjust it as needed.
2804 nsContainerFrame* parentFrame = viewportFrame;
2805
2806 ServoStyleSet* styleSet = mPresShell->StyleSet();
2807 // If paginated, make sure we don't put scrollbars in
2808 if (!isScrollable) {
2809 rootPseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
2810 rootPseudo, viewportPseudoStyle);
2811 } else {
2812 rootPseudo = PseudoStyleType::scrolledCanvas;
2813
2814 // Build the frame. We give it the content we are wrapping which is the
2815 // document element, the root frame, the parent view port frame, and we
2816 // should get back the new frame and the scrollable view if one was
2817 // created.
2818
2819 // resolve a context for the scrollframe
2820 RefPtr<ComputedStyle> computedStyle =
2821 styleSet->ResolveInheritingAnonymousBoxStyle(
2822 PseudoStyleType::viewportScroll, viewportPseudoStyle);
2823
2824 // Note that the viewport scrollframe is always built with
2825 // overflow:auto style. This forces the scroll frame to create
2826 // anonymous content for both scrollbars. This is necessary even
2827 // if the HTML or BODY elements are overriding the viewport
2828 // scroll style to 'hidden' --- dynamic style changes might put
2829 // scrollbars back on the viewport and we don't want to have to
2830 // reframe the viewport to create the scrollbar content.
2831 newFrame = nullptr;
2832 rootPseudoStyle = BeginBuildingScrollContainerFrame(
2833 state, aDocElement, computedStyle, viewportFrame, rootPseudo, true,
2834 newFrame);
2835 parentFrame = newFrame;
2836 }
2837
2838 rootCanvasFrame->SetComputedStyleWithoutNotification(rootPseudoStyle);
2839 rootCanvasFrame->Init(aDocElement, parentFrame, nullptr);
2840
2841 if (isScrollable) {
2842 FinishBuildingScrollContainerFrame(parentFrame, rootCanvasFrame);
2843 }
2844
2845 if (isPaginated) {
2846 // Create a page sequence frame
2847 {
2848 RefPtr<ComputedStyle> pageSequenceStyle =
2849 styleSet->ResolveInheritingAnonymousBoxStyle(
2850 PseudoStyleType::pageSequence, viewportPseudoStyle);
2851 mPageSequenceFrame =
2852 NS_NewPageSequenceFrame(mPresShell, pageSequenceStyle);
2853 mPageSequenceFrame->Init(aDocElement, rootCanvasFrame, nullptr);
2854 SetInitialSingleChild(rootCanvasFrame, mPageSequenceFrame);
2855 }
2856
2857 // Create the first printed sheet frame, as the sole child (for now) of our
2858 // page sequence frame (mPageSequenceFrame).
2859 auto* printedSheetFrame =
2860 ConstructPrintedSheetFrame(mPresShell, mPageSequenceFrame, nullptr);
2861 SetInitialSingleChild(mPageSequenceFrame, printedSheetFrame);
2862
2863 MOZ_ASSERT(!mNextPageContentFramePageName,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mNextPageContentFramePageName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mNextPageContentFramePageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mNextPageContentFramePageName" " (" "Next page name should not have been set."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNextPageContentFramePageName"
") (" "Next page name should not have been set." ")"); do { *
((volatile int*)__null) = 2864; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
2864 "Next page name should not have been set.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mNextPageContentFramePageName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mNextPageContentFramePageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mNextPageContentFramePageName" " (" "Next page name should not have been set."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mNextPageContentFramePageName"
") (" "Next page name should not have been set." ")"); do { *
((volatile int*)__null) = 2864; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
2865
2866 // Create the first page, as the sole child (for now) of the printed sheet
2867 // frame that we just created.
2868 nsCanvasFrame* canvasFrame;
2869 nsContainerFrame* pageFrame =
2870 ConstructPageFrame(mPresShell, printedSheetFrame, nullptr, canvasFrame);
2871 pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2872 SetInitialSingleChild(printedSheetFrame, pageFrame);
2873
2874 // The eventual parent of the document element frame.
2875 // XXX should this be set for every new page (in ConstructPageFrame)?
2876 mDocElementContainingBlock = canvasFrame;
2877 }
2878
2879 if (viewportFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
2880 SetInitialSingleChild(viewportFrame, newFrame);
2881 } else {
2882 viewportFrame->AppendFrames(FrameChildListID::Principal,
2883 nsFrameList(newFrame, newFrame));
2884 }
2885}
2886
2887void nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(
2888 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
2889 nsIContent* aDocElement, nsFrameList& aFrameList) {
2890 NS_ASSERTION(aFrame->IsCanvasFrame(), "aFrame should be canvas frame!")do { if (!(aFrame->IsCanvasFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aFrame should be canvas frame!", "aFrame->IsCanvasFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2890); MOZ_PretendNoReturn(); } } while (0)
;
2891 MOZ_ASSERT(mRootElementFrame->GetContent() == aDocElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRootElementFrame->GetContent() == aDocElement)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRootElementFrame->GetContent() == aDocElement)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mRootElementFrame->GetContent() == aDocElement"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRootElementFrame->GetContent() == aDocElement"
")"); do { *((volatile int*)__null) = 2891; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2892
2893 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
2894 GetAnonymousContent(aDocElement, aFrame, anonymousItems);
2895 if (anonymousItems.IsEmpty()) {
2896 return;
2897 }
2898
2899 AutoFrameConstructionItemList itemsToConstruct(this);
2900 AutoFrameConstructionPageName pageNameTracker(aState, aFrame);
2901 AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
2902 itemsToConstruct, pageNameTracker);
2903 ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
2904 /* aParentIsWrapperAnonBox = */ false,
2905 aFrameList);
2906}
2907
2908PrintedSheetFrame* nsCSSFrameConstructor::ConstructPrintedSheetFrame(
2909 PresShell* aPresShell, nsContainerFrame* aParentFrame,
2910 nsIFrame* aPrevSheetFrame) {
2911 RefPtr<ComputedStyle> printedSheetPseudoStyle =
2912 aPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
2913 PseudoStyleType::printedSheet);
2914
2915 auto* printedSheetFrame =
2916 NS_NewPrintedSheetFrame(aPresShell, printedSheetPseudoStyle);
2917
2918 printedSheetFrame->Init(nullptr, aParentFrame, aPrevSheetFrame);
2919
2920 return printedSheetFrame;
2921}
2922
2923nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
2924 PresShell* aPresShell, nsContainerFrame* aParentFrame,
2925 nsIFrame* aPrevPageFrame, nsCanvasFrame*& aCanvasFrame) {
2926 ServoStyleSet* styleSet = aPresShell->StyleSet();
2927
2928 RefPtr<ComputedStyle> pagePseudoStyle =
2929 styleSet->ResolveNonInheritingAnonymousBoxStyle(PseudoStyleType::page);
2930
2931 nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
2932
2933 // Initialize the page frame and force it to have a view. This makes printing
2934 // of the pages easier and faster.
2935 pageFrame->Init(nullptr, aParentFrame, aPrevPageFrame);
2936
2937 RefPtr<const nsAtom> pageName;
2938 if (mNextPageContentFramePageName) {
2939 pageName = mNextPageContentFramePageName.forget();
2940 } else if (aPrevPageFrame) {
2941 pageName = aPrevPageFrame->ComputePageValue();
2942 MOZ_ASSERT(pageName,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pageName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pageName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pageName" " (" "Page name from prev-in-flow should not have been null"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pageName" ") ("
"Page name from prev-in-flow should not have been null" ")")
; do { *((volatile int*)__null) = 2943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2943 "Page name from prev-in-flow should not have been null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pageName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(pageName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("pageName" " (" "Page name from prev-in-flow should not have been null"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pageName" ") ("
"Page name from prev-in-flow should not have been null" ")")
; do { *((volatile int*)__null) = 2943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2944 }
2945 RefPtr<ComputedStyle> pageContentPseudoStyle =
2946 styleSet->ResolvePageContentStyle(pageName,
2947 StylePagePseudoClassFlags::NONE);
2948
2949 nsContainerFrame* pageContentFrame = NS_NewPageContentFrame(
2950 aPresShell, pageContentPseudoStyle, pageName.forget());
2951
2952 nsPageContentFrame* prevPageContentFrame = nullptr;
2953 if (aPrevPageFrame) {
2954 MOZ_ASSERT(aPrevPageFrame->IsPageFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrevPageFrame->IsPageFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrevPageFrame->IsPageFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPrevPageFrame->IsPageFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevPageFrame->IsPageFrame()"
")"); do { *((volatile int*)__null) = 2954; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2955 prevPageContentFrame =
2956 static_cast<nsPageFrame*>(aPrevPageFrame)->PageContentFrame();
2957 }
2958 pageContentFrame->Init(nullptr, pageFrame, prevPageContentFrame);
2959 if (!prevPageContentFrame) {
2960 // The canvas is an inheriting anon box, so needs to be "owned" by the page
2961 // content.
2962 pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
2963 }
2964 SetInitialSingleChild(pageFrame, pageContentFrame);
2965 // Make it an absolute container for fixed-pos elements
2966 pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
2967 pageContentFrame->MarkAsAbsoluteContainingBlock();
2968
2969 RefPtr<ComputedStyle> canvasPseudoStyle =
2970 styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::canvas,
2971 pageContentPseudoStyle);
2972
2973 aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
2974
2975 nsIFrame* prevCanvasFrame = nullptr;
2976 if (prevPageContentFrame) {
2977 prevCanvasFrame = prevPageContentFrame->PrincipalChildList().FirstChild();
2978 NS_ASSERTION(prevCanvasFrame, "missing canvas frame")do { if (!(prevCanvasFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "missing canvas frame", "prevCanvasFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 2978); MOZ_PretendNoReturn(); } } while (0)
;
2979 }
2980 aCanvasFrame->Init(nullptr, pageContentFrame, prevCanvasFrame);
2981 SetInitialSingleChild(pageContentFrame, aCanvasFrame);
2982 return pageFrame;
2983}
2984
2985/* static */
2986nsIFrame* nsCSSFrameConstructor::CreatePlaceholderFrameFor(
2987 PresShell* aPresShell, nsIContent* aContent, nsIFrame* aFrame,
2988 nsContainerFrame* aParentFrame, nsIFrame* aPrevInFlow,
2989 nsFrameState aTypeBit) {
2990 RefPtr<ComputedStyle> placeholderStyle =
2991 aPresShell->StyleSet()->ResolveStyleForPlaceholder();
2992
2993 // The placeholder frame gets a pseudo style.
2994 nsPlaceholderFrame* placeholderFrame =
2995 NS_NewPlaceholderFrame(aPresShell, placeholderStyle, aTypeBit);
2996
2997 placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
2998
2999 // Associate the placeholder/out-of-flow with each other.
3000 placeholderFrame->SetOutOfFlowFrame(aFrame);
3001 aFrame->SetProperty(nsIFrame::PlaceholderFrameProperty(), placeholderFrame);
3002
3003 aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
3004
3005 return placeholderFrame;
3006}
3007
3008// Clears any lazy bits set in the range [aStartContent, aEndContent). If
3009// aEndContent is null, that means to clear bits in all siblings starting with
3010// aStartContent. aStartContent must not be null unless aEndContent is also
3011// null. We do this so that when new children are inserted under elements whose
3012// frame is a leaf the new children don't cause us to try to construct frames
3013// for the existing children again.
3014static inline void ClearLazyBits(nsIContent* aStartContent,
3015 nsIContent* aEndContent) {
3016 MOZ_ASSERT(aStartContent || !aEndContent,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStartContent || !aEndContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStartContent || !aEndContent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aStartContent || !aEndContent" " (" "Must have start child if we have an end child"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartContent || !aEndContent"
") (" "Must have start child if we have an end child" ")"); do
{ *((volatile int*)__null) = 3017; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
3017 "Must have start child if we have an end child")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStartContent || !aEndContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStartContent || !aEndContent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aStartContent || !aEndContent" " (" "Must have start child if we have an end child"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartContent || !aEndContent"
") (" "Must have start child if we have an end child" ")"); do
{ *((volatile int*)__null) = 3017; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3018
3019 for (nsIContent* cur = aStartContent; cur != aEndContent;
3020 cur = cur->GetNextSibling()) {
3021 cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
3022 }
3023}
3024
3025/* static */
3026const nsCSSFrameConstructor::FrameConstructionData*
3027nsCSSFrameConstructor::FindSelectData(const Element& aElement,
3028 ComputedStyle& aStyle) {
3029 // Construct a frame-based listbox or combobox
3030 const auto* sel = dom::HTMLSelectElement::FromNode(aElement);
3031 MOZ_ASSERT(sel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sel)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(sel))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("sel", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sel" ")"); do
{ *((volatile int*)__null) = 3031; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
3032 if (sel->IsCombobox()) {
3033 static constexpr FrameConstructionData sComboboxData{
3034 ToCreationFunc(NS_NewComboboxControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewComboboxControlFrame(aPs, aStyle); }
, 0,
3035 PseudoStyleType::buttonContent};
3036 return &sComboboxData;
3037 }
3038 // FIXME: Can we simplify this to avoid needing ConstructListboxSelectFrame,
3039 // and reuse ConstructScrollableBlock or so?
3040 static constexpr FrameConstructionData sListBoxData{
3041 &nsCSSFrameConstructor::ConstructListBoxSelectFrame};
3042 return &sListBoxData;
3043}
3044
3045nsIFrame* nsCSSFrameConstructor::ConstructListBoxSelectFrame(
3046 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3047 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3048 nsFrameList& aFrameList) {
3049 nsIContent* const content = aItem.mContent;
3050 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3051
3052 // Listbox, not combobox
3053 nsContainerFrame* listFrame =
3054 NS_NewListControlFrame(mPresShell, computedStyle);
3055
3056 nsContainerFrame* scrolledFrame =
3057 NS_NewSelectsAreaFrame(mPresShell, computedStyle);
3058
3059 // ******* this code stolen from Initialze ScrollFrame ********
3060 // please adjust this code to use BuildScrollFrame.
3061
3062 InitializeListboxSelect(aState, listFrame, scrolledFrame, content,
3063 aParentFrame, computedStyle, aFrameList);
3064
3065 return listFrame;
3066}
3067
3068void nsCSSFrameConstructor::InitializeListboxSelect(
3069 nsFrameConstructorState& aState, nsContainerFrame* scrollFrame,
3070 nsContainerFrame* scrolledFrame, nsIContent* aContent,
3071 nsContainerFrame* aParentFrame, ComputedStyle* aComputedStyle,
3072 nsFrameList& aFrameList) {
3073 // Initialize it
3074 nsContainerFrame* geometricParent =
3075 aState.GetGeometricParent(*aComputedStyle->StyleDisplay(), aParentFrame);
3076
3077 // We don't call InitAndRestoreFrame for scrollFrame because we can only
3078 // restore the frame state after its parts have been created (in particular,
3079 // the scrollable view). So we have to split Init and Restore.
3080
3081 scrollFrame->Init(aContent, geometricParent, nullptr);
3082 aState.AddChild(scrollFrame, aFrameList, aContent, aParentFrame);
3083 BuildScrollContainerFrame(aState, aContent, aComputedStyle, scrolledFrame,
3084 geometricParent, scrollFrame);
3085 if (aState.mFrameState) {
3086 // Restore frame state for the scroll frame
3087 RestoreFrameStateFor(scrollFrame, aState.mFrameState);
3088 }
3089
3090 nsFrameConstructorSaveState floatSaveState;
3091 aState.MaybePushFloatContainingBlock(scrolledFrame, floatSaveState);
3092
3093 // Process children
3094 nsFrameList childList;
3095
3096 ProcessChildren(aState, aContent, aComputedStyle, scrolledFrame, false,
3097 childList, false);
3098
3099 // Set the scrolled frame's initial child lists
3100 scrolledFrame->SetInitialChildList(FrameChildListID::Principal,
3101 std::move(childList));
3102}
3103
3104nsIFrame* nsCSSFrameConstructor::ConstructFieldSetFrame(
3105 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3106 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3107 nsFrameList& aFrameList) {
3108 AutoRestore<bool> savedHasRenderedLegend(aState.mHasRenderedLegend);
3109 aState.mHasRenderedLegend = false;
3110 nsIContent* const content = aItem.mContent;
3111 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3112
3113 nsContainerFrame* fieldsetFrame =
3114 NS_NewFieldSetFrame(mPresShell, computedStyle);
3115
3116 // Initialize it
3117 InitAndRestoreFrame(aState, content,
3118 aState.GetGeometricParent(*aStyleDisplay, aParentFrame),
3119 fieldsetFrame);
3120
3121 fieldsetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3122
3123 // Resolve style and initialize the frame
3124 RefPtr<ComputedStyle> fieldsetContentStyle =
3125 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3126 PseudoStyleType::fieldsetContent, computedStyle);
3127
3128 const nsStyleDisplay* fieldsetContentDisplay =
3129 fieldsetContentStyle->StyleDisplay();
3130 const bool isScrollable = fieldsetContentDisplay->IsScrollableOverflow();
3131 nsContainerFrame* scrollFrame = nullptr;
3132 if (isScrollable) {
3133 fieldsetContentStyle = BeginBuildingScrollContainerFrame(
3134 aState, content, fieldsetContentStyle, fieldsetFrame,
3135 PseudoStyleType::scrolledContent, false, scrollFrame);
3136 }
3137
3138 // Create the inner ::-moz-fieldset-content frame.
3139 nsContainerFrame* contentFrameTop;
3140 nsContainerFrame* contentFrame;
3141 auto* parent = scrollFrame ? scrollFrame : fieldsetFrame;
3142 MOZ_ASSERT(fieldsetContentDisplay->DisplayOutside() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside
::Block)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside
::Block))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
")"); do { *((volatile int*)__null) = 3143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3143 StyleDisplayOutside::Block)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside
::Block)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside
::Block))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->DisplayOutside() == StyleDisplayOutside::Block"
")"); do { *((volatile int*)__null) = 3143; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3144 switch (fieldsetContentDisplay->DisplayInside()) {
3145 case StyleDisplayInside::Flex:
3146 contentFrame = NS_NewFlexContainerFrame(mPresShell, fieldsetContentStyle);
3147 InitAndRestoreFrame(aState, content, parent, contentFrame);
3148 contentFrameTop = contentFrame;
3149 break;
3150 case StyleDisplayInside::Grid:
3151 contentFrame = NS_NewGridContainerFrame(mPresShell, fieldsetContentStyle);
3152 InitAndRestoreFrame(aState, content, parent, contentFrame);
3153 contentFrameTop = contentFrame;
3154 break;
3155 default: {
3156 MOZ_ASSERT(fieldsetContentDisplay->mDisplay == StyleDisplay::Block,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fieldsetContentDisplay->mDisplay == StyleDisplay::
Block)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(fieldsetContentDisplay->mDisplay == StyleDisplay::
Block))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
" (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
") (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
); do { *((volatile int*)__null) = 3157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3157 "bug in StyleAdjuster::adjust_for_fieldset_content?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fieldsetContentDisplay->mDisplay == StyleDisplay::
Block)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(fieldsetContentDisplay->mDisplay == StyleDisplay::
Block))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
" (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fieldsetContentDisplay->mDisplay == StyleDisplay::Block"
") (" "bug in StyleAdjuster::adjust_for_fieldset_content?" ")"
); do { *((volatile int*)__null) = 3157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3158
3159 contentFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle);
3160 if (fieldsetContentStyle->StyleColumn()->IsColumnContainerStyle()) {
3161 contentFrameTop = BeginBuildingColumns(
3162 aState, content, parent, contentFrame, fieldsetContentStyle);
3163 } else {
3164 // No need to create column container. Initialize content frame.
3165 InitAndRestoreFrame(aState, content, parent, contentFrame);
3166 contentFrameTop = contentFrame;
3167 }
3168
3169 break;
3170 }
3171 }
3172
3173 aState.AddChild(fieldsetFrame, aFrameList, content, aParentFrame);
3174
3175 // Process children
3176 nsFrameConstructorSaveState absoluteSaveState;
3177 nsFrameList childList;
3178
3179 contentFrameTop->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3180 if (fieldsetFrame->IsAbsPosContainingBlock()) {
3181 aState.PushAbsoluteContainingBlock(contentFrameTop, fieldsetFrame,
3182 absoluteSaveState);
3183 }
3184
3185 nsFrameConstructorSaveState floatSaveState;
3186 aState.MaybePushFloatContainingBlock(contentFrame, floatSaveState);
3187
3188 ProcessChildren(aState, content, computedStyle, contentFrame, true, childList,
3189 true);
3190 nsFrameList fieldsetKids;
3191 fieldsetKids.AppendFrame(nullptr,
3192 scrollFrame ? scrollFrame : contentFrameTop);
3193
3194 if (!MayNeedToCreateColumnSpanSiblings(contentFrame, childList)) {
3195 // Set the inner frame's initial child lists.
3196 contentFrame->SetInitialChildList(FrameChildListID::Principal,
3197 std::move(childList));
3198 } else {
3199 // Extract any initial non-column-span kids, and put them in inner frame's
3200 // child list.
3201 nsFrameList initialNonColumnSpanKids =
3202 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
3203 contentFrame->SetInitialChildList(FrameChildListID::Principal,
3204 std::move(initialNonColumnSpanKids));
3205
3206 if (childList.NotEmpty()) {
3207 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
3208 aState, contentFrame, childList,
3209 // Column content should never be a absolute/fixed positioned
3210 // containing block. Pass nullptr as aPositionedFrame.
3211 nullptr);
3212 FinishBuildingColumns(aState, contentFrameTop, contentFrame,
3213 columnSpanSiblings);
3214 }
3215 }
3216
3217 if (isScrollable) {
3218 FinishBuildingScrollContainerFrame(scrollFrame, contentFrameTop);
3219 }
3220
3221 // We use AppendFrames here because the rendered legend will already
3222 // be present in the principal child list if it exists.
3223 fieldsetFrame->AppendFrames(FrameChildListID::NoReflowPrincipal,
3224 std::move(fieldsetKids));
3225
3226 return fieldsetFrame;
3227}
3228
3229const nsCSSFrameConstructor::FrameConstructionData*
3230nsCSSFrameConstructor::FindDetailsData(const Element& aElement,
3231 ComputedStyle& aStyle) {
3232 if (!StaticPrefs::layout_details_force_block_layout()) {
3233 return nullptr;
3234 }
3235 static constexpr FrameConstructionData sBlockData[2] = {
3236 {&nsCSSFrameConstructor::ConstructNonScrollableBlock},
3237 {&nsCSSFrameConstructor::ConstructScrollableBlock},
3238 };
3239 return &sBlockData[aStyle.StyleDisplay()->IsScrollableOverflow()];
3240}
3241
3242nsIFrame* nsCSSFrameConstructor::ConstructBlockRubyFrame(
3243 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
3244 nsContainerFrame* aParentFrame, const nsStyleDisplay* aStyleDisplay,
3245 nsFrameList& aFrameList) {
3246 nsIContent* const content = aItem.mContent;
3247 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3248
3249 nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, computedStyle);
3250 nsContainerFrame* newFrame = blockFrame;
3251 nsContainerFrame* geometricParent =
3252 aState.GetGeometricParent(*aStyleDisplay, aParentFrame);
3253 AutoFrameConstructionPageName pageNameTracker(aState, blockFrame);
3254 if ((aItem.mFCData->mBits & FCDATA_MAY_NEED_SCROLLFRAME0x80) &&
3255 aStyleDisplay->IsScrollableOverflow()) {
3256 nsContainerFrame* scrollframe = nullptr;
3257 BuildScrollContainerFrame(aState, content, computedStyle, blockFrame,
3258 geometricParent, scrollframe);
3259 newFrame = scrollframe;
3260 } else {
3261 InitAndRestoreFrame(aState, content, geometricParent, blockFrame);
3262 }
3263
3264 RefPtr<ComputedStyle> rubyStyle =
3265 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3266 PseudoStyleType::blockRubyContent, computedStyle);
3267 nsContainerFrame* rubyFrame = NS_NewRubyFrame(mPresShell, rubyStyle);
3268 InitAndRestoreFrame(aState, content, blockFrame, rubyFrame);
3269 SetInitialSingleChild(blockFrame, rubyFrame);
3270 blockFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3271
3272 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
3273
3274 if (!mRootElementFrame) {
3275 mRootElementFrame = newFrame;
3276 }
3277
3278 nsFrameConstructorSaveState absoluteSaveState;
3279 blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3280 if (newFrame->IsAbsPosContainingBlock()) {
3281 aState.PushAbsoluteContainingBlock(blockFrame, blockFrame,
3282 absoluteSaveState);
3283 }
3284 nsFrameConstructorSaveState floatSaveState;
3285 aState.MaybePushFloatContainingBlock(blockFrame, floatSaveState);
3286
3287 nsFrameList childList;
3288 ProcessChildren(aState, content, rubyStyle, rubyFrame, true, childList, false,
3289 nullptr);
3290 rubyFrame->SetInitialChildList(FrameChildListID::Principal,
3291 std::move(childList));
3292
3293 return newFrame;
3294}
3295
3296static nsIFrame* FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame) {
3297 for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
3298 NS_ASSERTION(f->IsGeneratedContentFrame(),do { if (!(f->IsGeneratedContentFrame())) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "should not have exited generated content"
, "f->IsGeneratedContentFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3299); MOZ_PretendNoReturn(); } } while (0)
3299 "should not have exited generated content")do { if (!(f->IsGeneratedContentFrame())) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "should not have exited generated content"
, "f->IsGeneratedContentFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3299); MOZ_PretendNoReturn(); } } while (0)
;
3300 auto pseudo = f->Style()->GetPseudoType();
3301 if (pseudo == PseudoStyleType::before || pseudo == PseudoStyleType::after ||
3302 pseudo == PseudoStyleType::marker) {
3303 return f;
3304 }
3305 }
3306 return nullptr;
3307}
3308
3309/* static */
3310const nsCSSFrameConstructor::FrameConstructionData*
3311nsCSSFrameConstructor::FindTextData(const Text& aTextContent,
3312 nsIFrame* aParentFrame) {
3313 if (aParentFrame && IsFrameForSVG(aParentFrame)) {
3314 if (!aParentFrame->IsInSVGTextSubtree()) {
3315 return nullptr;
3316 }
3317
3318 // FIXME(bug 1588477) Don't render stuff in display: contents / Shadow DOM
3319 // subtrees, because TextCorrespondenceRecorder in the SVG text code doesn't
3320 // really know how to deal with it. This kinda sucks. :(
3321 if (aParentFrame->GetContent() != aTextContent.GetParent()) {
3322 return nullptr;
3323 }
3324
3325 static constexpr FrameConstructionData sSVGTextData(
3326 NS_NewTextFrame, FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_IS_SVG_TEXT0x80000);
3327 return &sSVGTextData;
3328 }
3329
3330 static constexpr FrameConstructionData sTextData(NS_NewTextFrame,
3331 FCDATA_IS_LINE_PARTICIPANT0x2000);
3332 return &sTextData;
3333}
3334
3335void nsCSSFrameConstructor::ConstructTextFrame(
3336 const FrameConstructionData* aData, nsFrameConstructorState& aState,
3337 nsIContent* aContent, nsContainerFrame* aParentFrame,
3338 ComputedStyle* aComputedStyle, nsFrameList& aFrameList) {
3339 MOZ_ASSERT(aData, "Must have frame construction data")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aData)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aData))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aData" " (" "Must have frame construction data"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aData" ") ("
"Must have frame construction data" ")"); do { *((volatile int
*)__null) = 3339; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
3340
3341 nsIFrame* newFrame =
3342 (*aData->mFunc.mCreationFunc)(mPresShell, aComputedStyle);
3343
3344 InitAndRestoreFrame(aState, aContent, aParentFrame, newFrame);
3345
3346 // We never need to create a view for a text frame.
3347
3348 if (newFrame->IsGeneratedContentFrame()) {
3349 UniquePtr<nsGenConInitializer> initializer(
3350 static_cast<nsGenConInitializer*>(
3351 aContent->TakeProperty(nsGkAtoms::genConInitializerProperty)));
3352 if (initializer) {
3353 if (initializer->mNode.release()->InitTextFrame(
3354 initializer->mList,
3355 FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
3356 (this->*(initializer->mDirtyAll))();
3357 }
3358 }
3359 }
3360
3361 // Add the newly constructed frame to the flow
3362 aFrameList.AppendFrame(nullptr, newFrame);
3363
3364 if (!aState.mCreatingExtraFrames || (aContent->IsInNativeAnonymousSubtree() &&
3365 !aContent->GetPrimaryFrame())) {
3366 aContent->SetPrimaryFrame(newFrame);
3367 }
3368}
3369
3370/* static */
3371const nsCSSFrameConstructor::FrameConstructionData*
3372nsCSSFrameConstructor::FindDataByInt(int32_t aInt, const Element& aElement,
3373 ComputedStyle& aComputedStyle,
3374 const FrameConstructionDataByInt* aDataPtr,
3375 uint32_t aDataLength) {
3376 for (const FrameConstructionDataByInt *curData = aDataPtr,
3377 *endData = aDataPtr + aDataLength;
3378 curData != endData; ++curData) {
3379 if (curData->mInt == aInt) {
3380 const FrameConstructionData* data = &curData->mData;
3381 if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER0x2) {
3382 return data->mFunc.mDataGetter(aElement, aComputedStyle);
3383 }
3384
3385 return data;
3386 }
3387 }
3388
3389 return nullptr;
3390}
3391
3392/* static */
3393const nsCSSFrameConstructor::FrameConstructionData*
3394nsCSSFrameConstructor::FindDataByTag(const Element& aElement,
3395 ComputedStyle& aStyle,
3396 const FrameConstructionDataByTag* aDataPtr,
3397 uint32_t aDataLength) {
3398 const nsAtom* tag = aElement.NodeInfo()->NameAtom();
3399 for (const FrameConstructionDataByTag *curData = aDataPtr,
3400 *endData = aDataPtr + aDataLength;
3401 curData != endData; ++curData) {
3402 if (curData->mTag == tag) {
3403 const FrameConstructionData* data = &curData->mData;
3404 if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER0x2) {
3405 return data->mFunc.mDataGetter(aElement, aStyle);
3406 }
3407
3408 return data;
3409 }
3410 }
3411
3412 return nullptr;
3413}
3414
3415#define SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40) FrameConstructionData(nullptr, FCDATA_SUPPRESS_FRAME0x40)
3416#define SIMPLE_INT_CREATE(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3417 {int32_t(_int), FrameConstructionData(_func)}
3418#define SIMPLE_INT_CHAIN(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3419 {int32_t(_int), FrameConstructionData(_func)}
3420#define COMPLEX_INT_CREATE(_int, _func){int32_t(_int), FrameConstructionData(_func)} \
3421 {int32_t(_int), FrameConstructionData(_func)}
3422
3423#define SIMPLE_TAG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3424 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3425#define SIMPLE_TAG_CHAIN(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3426 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3427#define COMPLEX_TAG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData(_func)} \
3428 {nsGkAtoms::_tag, FrameConstructionData(_func)}
3429
3430static nsFieldSetFrame* GetFieldSetFrameFor(nsIFrame* aFrame) {
3431 auto pseudo = aFrame->Style()->GetPseudoType();
3432 if (pseudo == PseudoStyleType::fieldsetContent ||
3433 pseudo == PseudoStyleType::scrolledContent ||
3434 pseudo == PseudoStyleType::columnSet ||
3435 pseudo == PseudoStyleType::columnContent) {
3436 return GetFieldSetFrameFor(aFrame->GetParent());
3437 }
3438 return do_QueryFrame(aFrame);
3439}
3440
3441/* static */
3442const nsCSSFrameConstructor::FrameConstructionData*
3443nsCSSFrameConstructor::FindHTMLData(const Element& aElement,
3444 nsIFrame* aParentFrame,
3445 ComputedStyle& aStyle) {
3446 MOZ_ASSERT(aElement.IsHTMLElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement.IsHTMLElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement.IsHTMLElement()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement.IsHTMLElement()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3446); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsHTMLElement()"
")"); do { *((volatile int*)__null) = 3446; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3447 NS_ASSERTION(!aParentFrame ||do { if (!(!aParentFrame || aParentFrame->Style()->GetPseudoType
() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent
()->IsFieldSetFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected parent for fieldset content anon box", "!aParentFrame || aParentFrame->Style()->GetPseudoType() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent()->IsFieldSetFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3451); MOZ_PretendNoReturn(); } } while (0)
3448 aParentFrame->Style()->GetPseudoType() !=do { if (!(!aParentFrame || aParentFrame->Style()->GetPseudoType
() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent
()->IsFieldSetFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected parent for fieldset content anon box", "!aParentFrame || aParentFrame->Style()->GetPseudoType() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent()->IsFieldSetFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3451); MOZ_PretendNoReturn(); } } while (0)
3449 PseudoStyleType::fieldsetContent ||do { if (!(!aParentFrame || aParentFrame->Style()->GetPseudoType
() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent
()->IsFieldSetFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected parent for fieldset content anon box", "!aParentFrame || aParentFrame->Style()->GetPseudoType() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent()->IsFieldSetFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3451); MOZ_PretendNoReturn(); } } while (0)
3450 aParentFrame->GetParent()->IsFieldSetFrame(),do { if (!(!aParentFrame || aParentFrame->Style()->GetPseudoType
() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent
()->IsFieldSetFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected parent for fieldset content anon box", "!aParentFrame || aParentFrame->Style()->GetPseudoType() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent()->IsFieldSetFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3451); MOZ_PretendNoReturn(); } } while (0)
3451 "Unexpected parent for fieldset content anon box")do { if (!(!aParentFrame || aParentFrame->Style()->GetPseudoType
() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent
()->IsFieldSetFrame())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected parent for fieldset content anon box", "!aParentFrame || aParentFrame->Style()->GetPseudoType() != PseudoStyleType::fieldsetContent || aParentFrame->GetParent()->IsFieldSetFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3451); MOZ_PretendNoReturn(); } } while (0)
;
3452
3453 if (aElement.IsInNativeAnonymousSubtree()) {
3454 if (aElement.NodeInfo()->NameAtom() == nsGkAtoms::label && aParentFrame) {
3455 if (aParentFrame->IsFileControlFrame()) {
3456 static constexpr FrameConstructionData sFileLabelData(
3457 NS_NewFileControlLabelFrame);
3458 return &sFileLabelData;
3459 }
3460 if (aParentFrame->GetParent() &&
3461 aParentFrame->GetParent()->IsComboboxControlFrame()) {
3462 static constexpr FrameConstructionData sComboboxLabelData(
3463 NS_NewComboboxLabelFrame);
3464 return &sComboboxLabelData;
3465 }
3466 }
3467 if (aElement.GetPseudoElementType() == PseudoStyleType::viewTransitionOld) {
3468 static constexpr FrameConstructionData sViewTransitionOldData(
3469 NS_NewImageFrameForViewTransitionOld);
3470 return &sViewTransitionOldData;
3471 }
3472 }
3473
3474 static constexpr FrameConstructionDataByTag sHTMLData[] = {
3475 SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData){nsGkAtoms::img, FrameConstructionData(nsCSSFrameConstructor::
FindImgData)}
,
3476 SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,{nsGkAtoms::mozgeneratedcontentimage, FrameConstructionData(nsCSSFrameConstructor
::FindGeneratedImageData)}
3477 nsCSSFrameConstructor::FindGeneratedImageData){nsGkAtoms::mozgeneratedcontentimage, FrameConstructionData(nsCSSFrameConstructor
::FindGeneratedImageData)}
,
3478 {nsGkAtoms::br,
3479 {NS_NewBRFrame, FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_IS_LINE_BREAK0x4000}},
3480 SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame){nsGkAtoms::wbr, FrameConstructionData(NS_NewWBRFrame)},
3481 SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData){nsGkAtoms::input, FrameConstructionData(nsCSSFrameConstructor
::FindInputData)}
,
3482 SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame){nsGkAtoms::textarea, FrameConstructionData(NS_NewTextControlFrame
)}
,
3483 SIMPLE_TAG_CHAIN(select, nsCSSFrameConstructor::FindSelectData){nsGkAtoms::select, FrameConstructionData(nsCSSFrameConstructor
::FindSelectData)}
,
3484 SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData){nsGkAtoms::object, FrameConstructionData(nsCSSFrameConstructor
::FindObjectData)}
,
3485 SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData){nsGkAtoms::embed, FrameConstructionData(nsCSSFrameConstructor
::FindObjectData)}
,
3486 COMPLEX_TAG_CREATE(fieldset,{nsGkAtoms::fieldset, FrameConstructionData(&nsCSSFrameConstructor
::ConstructFieldSetFrame)}
3487 &nsCSSFrameConstructor::ConstructFieldSetFrame){nsGkAtoms::fieldset, FrameConstructionData(&nsCSSFrameConstructor
::ConstructFieldSetFrame)}
,
3488 SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame){nsGkAtoms::frameset, FrameConstructionData(NS_NewHTMLFramesetFrame
)}
,
3489 SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame){nsGkAtoms::iframe, FrameConstructionData(NS_NewSubDocumentFrame
)}
,
3490 {nsGkAtoms::button,
3491 {ToCreationFunc(NS_NewHTMLButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewHTMLButtonControlFrame(aPs, aStyle); }
,
3492 FCDATA_ALLOW_BLOCK_STYLES0x8000 | FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000,
3493 PseudoStyleType::buttonContent}},
3494 SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData){nsGkAtoms::canvas, FrameConstructionData(nsCSSFrameConstructor
::FindCanvasData)}
,
3495 SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame){nsGkAtoms::video, FrameConstructionData(NS_NewHTMLVideoFrame
)}
,
3496 SIMPLE_TAG_CREATE(audio, NS_NewHTMLAudioFrame){nsGkAtoms::audio, FrameConstructionData(NS_NewHTMLAudioFrame
)}
,
3497 SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame){nsGkAtoms::progress, FrameConstructionData(NS_NewProgressFrame
)}
,
3498 SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame){nsGkAtoms::meter, FrameConstructionData(NS_NewMeterFrame)},
3499 SIMPLE_TAG_CHAIN(details, nsCSSFrameConstructor::FindDetailsData){nsGkAtoms::details, FrameConstructionData(nsCSSFrameConstructor
::FindDetailsData)}
,
3500 };
3501
3502 return FindDataByTag(aElement, aStyle, sHTMLData, std::size(sHTMLData));
3503}
3504
3505/* static */
3506const nsCSSFrameConstructor::FrameConstructionData*
3507nsCSSFrameConstructor::FindGeneratedImageData(const Element& aElement,
3508 ComputedStyle&) {
3509 if (!aElement.IsInNativeAnonymousSubtree()) {
3510 return nullptr;
3511 }
3512
3513 auto& generatedContent = static_cast<const GeneratedImageContent&>(aElement);
3514 if (generatedContent.IsForListStyleImageMarker()) {
3515 static constexpr FrameConstructionData sImgData(
3516 NS_NewImageFrameForListStyleImage);
3517 return &sImgData;
3518 }
3519
3520 static constexpr FrameConstructionData sImgData(
3521 NS_NewImageFrameForGeneratedContentIndex);
3522 return &sImgData;
3523}
3524
3525/* static */
3526const nsCSSFrameConstructor::FrameConstructionData*
3527nsCSSFrameConstructor::FindImgData(const Element& aElement,
3528 ComputedStyle& aStyle) {
3529 if (nsImageFrame::ImageFrameTypeFor(aElement, aStyle) !=
3530 nsImageFrame::ImageFrameType::ForElementRequest) {
3531 // content: url gets handled by the generic code-path.
3532 return nullptr;
3533 }
3534
3535 static constexpr FrameConstructionData sImgData(NS_NewImageFrame);
3536 return &sImgData;
3537}
3538
3539/* static */
3540const nsCSSFrameConstructor::FrameConstructionData*
3541nsCSSFrameConstructor::FindImgControlData(const Element& aElement,
3542 ComputedStyle& aStyle) {
3543 if (nsImageFrame::ImageFrameTypeFor(aElement, aStyle) !=
3544 nsImageFrame::ImageFrameType::ForElementRequest) {
3545 return nullptr;
3546 }
3547
3548 static constexpr FrameConstructionData sImgControlData(
3549 NS_NewImageControlFrame);
3550 return &sImgControlData;
3551}
3552
3553/* static */
3554const nsCSSFrameConstructor::FrameConstructionData*
3555nsCSSFrameConstructor::FindSearchControlData(const Element& aElement,
3556 ComputedStyle& aStyle) {
3557 if (StaticPrefs::layout_forms_input_type_search_enabled()) {
3558 static constexpr FrameConstructionData sSearchControlData(
3559 NS_NewSearchControlFrame);
3560 return &sSearchControlData;
3561 }
3562
3563 static constexpr FrameConstructionData sTextControlData(
3564 NS_NewTextControlFrame);
3565 return &sTextControlData;
3566}
3567
3568/* static */
3569const nsCSSFrameConstructor::FrameConstructionData*
3570nsCSSFrameConstructor::FindInputData(const Element& aElement,
3571 ComputedStyle& aStyle) {
3572 static constexpr FrameConstructionDataByInt sInputData[] = {
3573 SIMPLE_INT_CREATE(FormControlType::InputCheckbox,{int32_t(FormControlType::InputCheckbox), FrameConstructionData
([](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
3574 ToCreationFunc(NS_NewCheckboxRadioFrame)){int32_t(FormControlType::InputCheckbox), FrameConstructionData
([](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
,
3575 SIMPLE_INT_CREATE(FormControlType::InputRadio,{int32_t(FormControlType::InputRadio), FrameConstructionData(
[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
3576 ToCreationFunc(NS_NewCheckboxRadioFrame)){int32_t(FormControlType::InputRadio), FrameConstructionData(
[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewCheckboxRadioFrame(aPs, aStyle); })}
,
3577 SIMPLE_INT_CREATE(FormControlType::InputFile, NS_NewFileControlFrame){int32_t(FormControlType::InputFile), FrameConstructionData(NS_NewFileControlFrame
)}
,
3578 SIMPLE_INT_CHAIN(FormControlType::InputImage,{int32_t(FormControlType::InputImage), FrameConstructionData(
nsCSSFrameConstructor::FindImgControlData)}
3579 nsCSSFrameConstructor::FindImgControlData){int32_t(FormControlType::InputImage), FrameConstructionData(
nsCSSFrameConstructor::FindImgControlData)}
,
3580 SIMPLE_INT_CREATE(FormControlType::InputEmail, NS_NewTextControlFrame){int32_t(FormControlType::InputEmail), FrameConstructionData(
NS_NewTextControlFrame)}
,
3581 SIMPLE_INT_CREATE(FormControlType::InputText, NS_NewTextControlFrame){int32_t(FormControlType::InputText), FrameConstructionData(NS_NewTextControlFrame
)}
,
3582 SIMPLE_INT_CREATE(FormControlType::InputTel, NS_NewTextControlFrame){int32_t(FormControlType::InputTel), FrameConstructionData(NS_NewTextControlFrame
)}
,
3583 SIMPLE_INT_CREATE(FormControlType::InputUrl, NS_NewTextControlFrame){int32_t(FormControlType::InputUrl), FrameConstructionData(NS_NewTextControlFrame
)}
,
3584 SIMPLE_INT_CREATE(FormControlType::InputRange, NS_NewRangeFrame){int32_t(FormControlType::InputRange), FrameConstructionData(
NS_NewRangeFrame)}
,
3585 SIMPLE_INT_CREATE(FormControlType::InputPassword, NS_NewTextControlFrame){int32_t(FormControlType::InputPassword), FrameConstructionData
(NS_NewTextControlFrame)}
,
3586 {int32_t(FormControlType::InputColor),
3587 {NS_NewColorControlFrame, 0, PseudoStyleType::buttonContent}},
3588
3589 SIMPLE_INT_CHAIN(FormControlType::InputSearch,{int32_t(FormControlType::InputSearch), FrameConstructionData
(nsCSSFrameConstructor::FindSearchControlData)}
3590 nsCSSFrameConstructor::FindSearchControlData){int32_t(FormControlType::InputSearch), FrameConstructionData
(nsCSSFrameConstructor::FindSearchControlData)}
,
3591 SIMPLE_INT_CREATE(FormControlType::InputNumber, NS_NewNumberControlFrame){int32_t(FormControlType::InputNumber), FrameConstructionData
(NS_NewNumberControlFrame)}
,
3592 SIMPLE_INT_CREATE(FormControlType::InputTime, NS_NewDateTimeControlFrame){int32_t(FormControlType::InputTime), FrameConstructionData(NS_NewDateTimeControlFrame
)}
,
3593 SIMPLE_INT_CREATE(FormControlType::InputDate, NS_NewDateTimeControlFrame){int32_t(FormControlType::InputDate), FrameConstructionData(NS_NewDateTimeControlFrame
)}
,
3594 SIMPLE_INT_CREATE(FormControlType::InputDatetimeLocal,{int32_t(FormControlType::InputDatetimeLocal), FrameConstructionData
(NS_NewDateTimeControlFrame)}
3595 NS_NewDateTimeControlFrame){int32_t(FormControlType::InputDatetimeLocal), FrameConstructionData
(NS_NewDateTimeControlFrame)}
,
3596 // TODO: this is temporary until a frame is written: bug 888320
3597 SIMPLE_INT_CREATE(FormControlType::InputMonth, NS_NewTextControlFrame){int32_t(FormControlType::InputMonth), FrameConstructionData(
NS_NewTextControlFrame)}
,
3598 // TODO: this is temporary until a frame is written: bug 888320
3599 SIMPLE_INT_CREATE(FormControlType::InputWeek, NS_NewTextControlFrame){int32_t(FormControlType::InputWeek), FrameConstructionData(NS_NewTextControlFrame
)}
,
3600 {int32_t(FormControlType::InputSubmit),
3601 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3602 PseudoStyleType::buttonContent}},
3603 {int32_t(FormControlType::InputReset),
3604 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3605 PseudoStyleType::buttonContent}},
3606 {int32_t(FormControlType::InputButton),
3607 {ToCreationFunc(NS_NewGfxButtonControlFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGfxButtonControlFrame(aPs, aStyle); }
, 0,
3608 PseudoStyleType::buttonContent}}
3609 // Keeping hidden inputs out of here on purpose for so they get frames by
3610 // display (in practice, none).
3611 };
3612
3613 auto controlType = HTMLInputElement::FromNode(aElement)->ControlType();
3614
3615 // radio and checkbox inputs with appearance:none should be constructed
3616 // by display type. (Note that we're not checking that appearance is
3617 // not (respectively) StyleAppearance::Radio and StyleAppearance::Checkbox.)
3618 if ((controlType == FormControlType::InputCheckbox ||
3619 controlType == FormControlType::InputRadio) &&
3620 !aStyle.StyleDisplay()->HasAppearance()) {
3621 return nullptr;
3622 }
3623
3624 return FindDataByInt(int32_t(controlType), aElement, aStyle, sInputData,
3625 std::size(sInputData));
3626}
3627
3628/* static */
3629const nsCSSFrameConstructor::FrameConstructionData*
3630nsCSSFrameConstructor::FindObjectData(const Element& aElement,
3631 ComputedStyle& aStyle) {
3632 uint32_t type;
3633 nsCOMPtr<nsIObjectLoadingContent> objContent =
3634 do_QueryInterface(const_cast<Element*>(&aElement));
3635 NS_ASSERTION(objContent,do { if (!(objContent)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "embed and object must implement "
"nsIObjectLoadingContent!", "objContent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3637); MOZ_PretendNoReturn(); } } while (0)
3636 "embed and object must implement "do { if (!(objContent)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "embed and object must implement "
"nsIObjectLoadingContent!", "objContent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3637); MOZ_PretendNoReturn(); } } while (0)
3637 "nsIObjectLoadingContent!")do { if (!(objContent)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "embed and object must implement "
"nsIObjectLoadingContent!", "objContent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3637); MOZ_PretendNoReturn(); } } while (0)
;
3638 objContent->GetDisplayedType(&type);
3639
3640 static constexpr FrameConstructionDataByInt sObjectData[] = {
3641 // TODO(emilio): Can we remove the NS_NewEmptyFrame case and just use a
3642 // subdocument frame here?
3643 SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,{int32_t(nsIObjectLoadingContent::TYPE_LOADING), FrameConstructionData
(NS_NewEmptyFrame)}
3644 NS_NewEmptyFrame){int32_t(nsIObjectLoadingContent::TYPE_LOADING), FrameConstructionData
(NS_NewEmptyFrame)}
,
3645 SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,{int32_t(nsIObjectLoadingContent::TYPE_DOCUMENT), FrameConstructionData
(NS_NewSubDocumentFrame)}
3646 NS_NewSubDocumentFrame){int32_t(nsIObjectLoadingContent::TYPE_DOCUMENT), FrameConstructionData
(NS_NewSubDocumentFrame)}
,
3647 // Nothing for TYPE_FALLBACK so we'll construct frames by display there
3648 };
3649
3650 return FindDataByInt((int32_t)type, aElement, aStyle, sObjectData,
3651 std::size(sObjectData));
3652}
3653
3654/* static */
3655const nsCSSFrameConstructor::FrameConstructionData*
3656nsCSSFrameConstructor::FindCanvasData(const Element& aElement,
3657 ComputedStyle& aStyle) {
3658 // We want to check whether script is enabled on the document that
3659 // could be painting to the canvas. That's the owner document of
3660 // the canvas, except when the owner document is a static document,
3661 // in which case it's the original document it was cloned from.
3662 Document* doc = aElement.OwnerDoc();
3663 if (doc->IsStaticDocument()) {
3664 doc = doc->GetOriginalDocument();
3665 }
3666 if (!doc->IsScriptEnabled()) {
3667 return nullptr;
3668 }
3669
3670 static constexpr FrameConstructionData sCanvasData(
3671 NS_NewHTMLCanvasFrame, 0, PseudoStyleType::htmlCanvasContent);
3672 return &sCanvasData;
3673}
3674
3675static MOZ_NEVER_INLINE__attribute__((noinline)) void DestroyFramesInList(PresShell* aPs,
3676 nsFrameList& aList) {
3677 nsIFrame::DestroyContext context(aPs);
3678 aList.DestroyFrames(context);
3679}
3680
3681void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
3682 FrameConstructionItem& aItem, nsFrameConstructorState& aState,
3683 nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
3684 const FrameConstructionData* data = aItem.mFCData;
3685 NS_ASSERTION(data, "Must have frame construction data")do { if (!(data)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Must have frame construction data"
, "data", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3685); MOZ_PretendNoReturn(); } } while (0)
;
3686
3687 uint32_t bits = data->mBits;
3688
3689 NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),do { if (!(!(bits & 0x2))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should have dealt with this inside the data finder", "!(bits & FCDATA_FUNC_IS_DATA_GETTER)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3690); MOZ_PretendNoReturn(); } } while (0)
3690 "Should have dealt with this inside the data finder")do { if (!(!(bits & 0x2))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should have dealt with this inside the data finder", "!(bits & FCDATA_FUNC_IS_DATA_GETTER)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3690); MOZ_PretendNoReturn(); } } while (0)
;
3691
3692 // Some sets of bits are not compatible with each other
3693#define CHECK_ONLY_ONE_BIT(_bit1, _bit2) \
3694 NS_ASSERTION(!(bits & _bit1) || !(bits & _bit2), \do { if (!(!(bits & _bit1) || !(bits & _bit2))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Only one of these bits should be set", "!(bits & _bit1) || !(bits & _bit2)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3695); MOZ_PretendNoReturn(); } } while (0)
3695 "Only one of these bits should be set")do { if (!(!(bits & _bit1) || !(bits & _bit2))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Only one of these bits should be set", "!(bits & _bit1) || !(bits & _bit2)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3695); MOZ_PretendNoReturn(); } } while (0)
3696 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3697 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10);
3698 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
3699 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_IS_POPUP0x100);
3700 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_SKIP_ABSPOS_PUSH0x200);
3701 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3702 FCDATA_DISALLOW_GENERATED_CONTENT0x400);
3703 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4, FCDATA_ALLOW_BLOCK_STYLES0x8000);
3704 CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR0x4,
3705 FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000);
3706 CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS0x20,
3707 FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000);
3708#undef CHECK_ONLY_ONE_BIT
3709 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(bits & 0x400000) || (bits & 0x10000))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(bits & 0x400000) || (bits & 0x10000)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!(bits & 0x400000) || (bits & 0x10000)"
" (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3710 !(bits & FCDATA_IS_WRAPPER_ANON_BOX) || (bits & FCDATA_USE_CHILD_ITEMS),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(bits & 0x400000) || (bits & 0x10000))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(bits & 0x400000) || (bits & 0x10000)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!(bits & 0x400000) || (bits & 0x10000)"
" (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3711 "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(bits & 0x400000) || (bits & 0x10000))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(bits & 0x400000) || (bits & 0x10000)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!(bits & 0x400000) || (bits & 0x10000)"
" (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x400000) || (bits & 0x10000)"
") (" "Wrapper anon boxes should always have FCDATA_USE_CHILD_ITEMS"
")"); do { *((volatile int*)__null) = 3711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3712 MOZ_ASSERT(!(bits & FCDATA_ALLOW_GRID_FLEX_COLUMN) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(bits & 0x200000) || (bits & 0x40000))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(bits & 0x200000) || (bits & 0x40000)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!(bits & 0x200000) || (bits & 0x40000)"
" (" "Need the block wrapper bit to create grid/flex/column."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3713 (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(bits & 0x200000) || (bits & 0x40000))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(bits & 0x200000) || (bits & 0x40000)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!(bits & 0x200000) || (bits & 0x40000)"
" (" "Need the block wrapper bit to create grid/flex/column."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3714 "Need the block wrapper bit to create grid/flex/column.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(bits & 0x200000) || (bits & 0x40000))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(bits & 0x200000) || (bits & 0x40000)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!(bits & 0x200000) || (bits & 0x40000)"
" (" "Need the block wrapper bit to create grid/flex/column."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(bits & 0x200000) || (bits & 0x40000)"
") (" "Need the block wrapper bit to create grid/flex/column."
")"); do { *((volatile int*)__null) = 3714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3715
3716 // Don't create a subdocument frame for iframes if we're creating extra frames
3717 if (aState.mCreatingExtraFrames &&
3718 aItem.mContent->IsHTMLElement(nsGkAtoms::iframe)) {
3719 return;
3720 }
3721
3722 nsIContent* const content = aItem.mContent;
3723 nsIFrame* newFrame;
3724 nsIFrame* primaryFrame;
3725 ComputedStyle* const computedStyle = aItem.mComputedStyle;
3726 const nsStyleDisplay* display = computedStyle->StyleDisplay();
3727 if (bits & FCDATA_FUNC_IS_FULL_CTOR0x4) {
3728 newFrame = (this->*(data->mFunc.mFullConstructor))(
3729 aState, aItem, aParentFrame, display, aFrameList);
3730 MOZ_ASSERT(newFrame, "Full constructor failed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("newFrame" " (" "Full constructor failed"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newFrame" ") ("
"Full constructor failed" ")"); do { *((volatile int*)__null
) = 3730; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
3731 primaryFrame = newFrame;
3732 } else {
3733 newFrame = (*data->mFunc.mCreationFunc)(mPresShell, computedStyle);
3734
3735 const bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW0x8);
3736 const bool isPopup = aItem.mIsPopup;
3737
3738 nsContainerFrame* geometricParent =
3739 (isPopup || allowOutOfFlow)
3740 ? aState.GetGeometricParent(*display, aParentFrame)
3741 : aParentFrame;
3742
3743 // In the non-scrollframe case, primaryFrame and newFrame are equal; in the
3744 // scrollframe case, newFrame is the scrolled frame while primaryFrame is
3745 // the scrollframe.
3746 if ((bits & FCDATA_MAY_NEED_SCROLLFRAME0x80) &&
3747 display->IsScrollableOverflow()) {
3748 nsContainerFrame* scrollframe = nullptr;
3749 BuildScrollContainerFrame(aState, content, computedStyle, newFrame,
3750 geometricParent, scrollframe);
3751 primaryFrame = scrollframe;
3752 } else {
3753 InitAndRestoreFrame(aState, content, geometricParent, newFrame);
3754 primaryFrame = newFrame;
3755 }
3756
3757 // If we need to create a block formatting context to wrap our
3758 // kids, do it now.
3759 nsIFrame* maybeAbsoluteContainingBlockStyleFrame = primaryFrame;
3760 nsIFrame* maybeAbsoluteContainingBlock = newFrame;
3761 nsIFrame* possiblyLeafFrame = newFrame;
3762 nsContainerFrame* outerFrame = nullptr;
3763 if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS0x40000) {
3764 RefPtr<ComputedStyle> outerStyle =
3765 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
3766 data->mAnonBoxPseudo, computedStyle);
3767#ifdef DEBUG1
3768 nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
3769 MOZ_ASSERT(containerFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(containerFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(containerFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("containerFrame"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containerFrame"
")"); do { *((volatile int*)__null) = 3769; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3770#endif
3771 nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
3772 nsContainerFrame* innerFrame;
3773 if (bits & FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000) {
3774 switch (display->DisplayInside()) {
3775 case StyleDisplayInside::Flex:
3776 outerFrame = NS_NewFlexContainerFrame(mPresShell, outerStyle);
3777 InitAndRestoreFrame(aState, content, container, outerFrame);
3778 innerFrame = outerFrame;
3779 break;
3780 case StyleDisplayInside::Grid:
3781 outerFrame = NS_NewGridContainerFrame(mPresShell, outerStyle);
3782 InitAndRestoreFrame(aState, content, container, outerFrame);
3783 innerFrame = outerFrame;
3784 break;
3785 default: {
3786 innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
3787 if (outerStyle->StyleColumn()->IsColumnContainerStyle()) {
3788 outerFrame = BeginBuildingColumns(aState, content, container,
3789 innerFrame, outerStyle);
3790 } else {
3791 // No need to create column container. Initialize innerFrame.
3792 InitAndRestoreFrame(aState, content, container, innerFrame);
3793 outerFrame = innerFrame;
3794 }
3795 break;
3796 }
3797 }
3798 } else {
3799 innerFrame = NS_NewBlockFrame(mPresShell, outerStyle);
3800 InitAndRestoreFrame(aState, content, container, innerFrame);
3801 outerFrame = innerFrame;
3802 }
3803
3804 SetInitialSingleChild(container, outerFrame);
3805
3806 container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
3807
3808 // Now figure out whether newFrame or outerFrame should be the
3809 // absolute container.
3810 if (outerFrame->IsAbsPosContainingBlock()) {
3811 maybeAbsoluteContainingBlock = outerFrame;
3812 maybeAbsoluteContainingBlockStyleFrame = outerFrame;
3813 innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3814 }
3815
3816 // Our kids should go into the innerFrame.
3817 newFrame = innerFrame;
3818 }
3819
3820 aState.AddChild(primaryFrame, aFrameList, content, aParentFrame,
3821 allowOutOfFlow, allowOutOfFlow);
3822
3823 nsContainerFrame* newFrameAsContainer = do_QueryFrame(newFrame);
3824 if (newFrameAsContainer) {
3825 // Process the child content if requested
3826 nsFrameList childList;
3827 nsFrameConstructorSaveState absoluteSaveState;
3828
3829 if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10) {
3830 aState.PushAbsoluteContainingBlock(nullptr, nullptr, absoluteSaveState);
3831 } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH0x200)) {
3832 maybeAbsoluteContainingBlock->AddStateBits(
3833 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
3834 if (maybeAbsoluteContainingBlockStyleFrame->IsAbsPosContainingBlock()) {
3835 auto* cf =
3836 static_cast<nsContainerFrame*>(maybeAbsoluteContainingBlock);
3837 aState.PushAbsoluteContainingBlock(
3838 cf, maybeAbsoluteContainingBlockStyleFrame, absoluteSaveState);
3839 }
3840 }
3841
3842 nsFrameConstructorSaveState floatSaveState;
3843 aState.MaybePushFloatContainingBlock(newFrameAsContainer, floatSaveState);
3844
3845 if (bits & FCDATA_USE_CHILD_ITEMS0x10000) {
3846 // At this point, we have not set up the auto value for this frame, and
3847 // no caller will have set it so it is not redundant and therefor will
3848 // not assert.
3849 AutoFrameConstructionPageName pageNameTracker(aState,
3850 newFrameAsContainer);
3851 ConstructFramesFromItemList(
3852 aState, aItem.mChildItems, newFrameAsContainer,
3853 bits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
3854 } else {
3855 // Process the child frames.
3856 ProcessChildren(aState, content, computedStyle, newFrameAsContainer,
3857 !(bits & FCDATA_DISALLOW_GENERATED_CONTENT0x400), childList,
3858 (bits & FCDATA_ALLOW_BLOCK_STYLES0x8000) != 0,
3859 possiblyLeafFrame);
3860 }
3861
3862 if (bits & FCDATA_WRAP_KIDS_IN_BLOCKS0x20) {
3863 nsFrameList newList;
3864 nsFrameList currentBlockList;
3865 nsIFrame* f;
3866 while ((f = childList.FirstChild()) != nullptr) {
3867 bool wrapFrame = IsInlineFrame(f) || IsFramePartOfIBSplit(f);
3868 if (!wrapFrame) {
3869 FlushAccumulatedBlock(aState, content, newFrameAsContainer,
3870 currentBlockList, newList);
3871 }
3872
3873 childList.RemoveFrame(f);
3874 if (wrapFrame) {
3875 currentBlockList.AppendFrame(nullptr, f);
3876 } else {
3877 newList.AppendFrame(nullptr, f);
3878 }
3879 }
3880 FlushAccumulatedBlock(aState, content, newFrameAsContainer,
3881 currentBlockList, newList);
3882
3883 if (childList.NotEmpty()) {
3884 // an error must have occurred, delete unprocessed frames
3885 DestroyFramesInList(mPresShell, childList);
3886 }
3887
3888 childList = std::move(newList);
3889 }
3890
3891 if (!(bits & FCDATA_ALLOW_GRID_FLEX_COLUMN0x200000) ||
3892 !MayNeedToCreateColumnSpanSiblings(newFrameAsContainer, childList)) {
3893 // Set the frame's initial child list. Note that MathML depends on this
3894 // being called even if childList is empty!
3895 newFrameAsContainer->SetInitialChildList(FrameChildListID::Principal,
3896 std::move(childList));
3897 } else {
3898 // Extract any initial non-column-span kids, and put them in inner
3899 // frame's child list.
3900 nsFrameList initialNonColumnSpanKids =
3901 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
3902 newFrameAsContainer->SetInitialChildList(
3903 FrameChildListID::Principal, std::move(initialNonColumnSpanKids));
3904
3905 if (childList.NotEmpty()) {
3906 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
3907 aState, newFrameAsContainer, childList,
3908 // Column content should never be a absolute/fixed positioned
3909 // containing block. Pass nullptr as aPositionedFrame.
3910 nullptr);
3911
3912 MOZ_ASSERT(outerFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outerFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outerFrame))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("outerFrame" " (" "outerFrame should be non-null if multi-column container "
"is created." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3914; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
3913 "outerFrame should be non-null if multi-column container "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outerFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outerFrame))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("outerFrame" " (" "outerFrame should be non-null if multi-column container "
"is created." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3914; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
3914 "is created.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outerFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outerFrame))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("outerFrame" " (" "outerFrame should be non-null if multi-column container "
"is created." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerFrame"
") (" "outerFrame should be non-null if multi-column container "
"is created." ")"); do { *((volatile int*)__null) = 3914; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
3915 FinishBuildingColumns(aState, outerFrame, newFrameAsContainer,
3916 columnSpanSiblings);
3917 }
3918 }
3919 }
3920 }
3921
3922 NS_ASSERTION(newFrame->IsLineParticipant() ==do { if (!(newFrame->IsLineParticipant() == ((bits & 0x2000
) != 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits"
, "newFrame->IsLineParticipant() == ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3924); MOZ_PretendNoReturn(); } } while (0)
3923 ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),do { if (!(newFrame->IsLineParticipant() == ((bits & 0x2000
) != 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits"
, "newFrame->IsLineParticipant() == ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3924); MOZ_PretendNoReturn(); } } while (0)
3924 "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits")do { if (!(newFrame->IsLineParticipant() == ((bits & 0x2000
) != 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits"
, "newFrame->IsLineParticipant() == ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3924); MOZ_PretendNoReturn(); } } while (0)
;
3925
3926 // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
3927 // generated content that doesn't have one yet. Note that we have to examine
3928 // the frame bit, because by this point mIsGeneratedContent has been cleared
3929 // on aItem.
3930 if ((!aState.mCreatingExtraFrames ||
3931 (aItem.mContent->IsRootOfNativeAnonymousSubtree() &&
3932 !aItem.mContent->GetPrimaryFrame())) &&
3933 !(bits & FCDATA_SKIP_FRAMESET0x1)) {
3934 aItem.mContent->SetPrimaryFrame(primaryFrame);
3935 ActiveLayerTracker::TransferActivityToFrame(aItem.mContent, primaryFrame);
3936 }
3937}
3938
3939static void GatherSubtreeElements(Element* aElement,
3940 nsTArray<Element*>& aElements) {
3941 aElements.AppendElement(aElement);
3942 StyleChildrenIterator iter(aElement);
3943 for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
3944 if (!c->IsElement()) {
3945 continue;
3946 }
3947 GatherSubtreeElements(c->AsElement(), aElements);
3948 }
3949}
3950
3951nsresult nsCSSFrameConstructor::GetAnonymousContent(
3952 nsIContent* aParent, nsIFrame* aParentFrame,
3953 nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent) {
3954 nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
3955 if (!creator) {
3956 return NS_OK;
3957 }
3958
3959 nsresult rv = creator->CreateAnonymousContent(aContent);
3960 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3961 // CreateAnonymousContent failed, e.g. because the page has a <use> loop.
3962 return rv;
3963 }
3964
3965 if (aContent.IsEmpty()) {
3966 return NS_OK;
3967 }
3968
3969 const bool devtoolsEventsEnabled =
3970 mDocument->DevToolsAnonymousAndShadowEventsEnabled();
3971
3972 MOZ_ASSERT(aParent->IsElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->IsElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent->IsElement()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aParent->IsElement()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 3972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsElement()"
")"); do { *((volatile int*)__null) = 3972; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3973 for (const auto& info : aContent) {
3974 // get our child's content and set its parent to our content
3975 nsIContent* content = info.mContent;
3976 content->SetIsNativeAnonymousRoot();
3977
3978 BindContext context(*aParent->AsElement(), BindContext::ForNativeAnonymous);
3979 rv = content->BindToTree(context, *aParent);
3980
3981 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3982 content->UnbindFromTree();
3983 return rv;
3984 }
3985
3986 if (devtoolsEventsEnabled) {
3987 content->QueueDevtoolsAnonymousEvent(/* aIsRemove = */ false);
3988 }
3989 }
3990
3991 // Some situations where we don't cache anonymous content styles:
3992 //
3993 // * when visibility or pointer-events is anything other than the initial
3994 // value; we rely on visibility and pointer-events inheriting into anonymous
3995 // content, but don't bother adding this state to the AnonymousContentKey,
3996 // since it's not so common. Note that with overlay scrollbars, scrollbars
3997 // always start off with pointer-events: none so we don't need to check for
3998 // that in that case.
3999 //
4000 // * when the medium is anything other than screen; some UA style sheet rules
4001 // apply in e.g. print medium, and will give different results from the
4002 // cached styles
4003 Maybe<bool> computedAllowStyleCaching;
4004 auto ComputeAllowStyleCaching = [&] {
4005 if (!StaticPrefs::layout_css_cached_scrollbar_styles_enabled()) {
4006 return false;
4007 }
4008 if (aParentFrame->StyleVisibility()->mVisible != StyleVisibility::Visible) {
4009 return false;
4010 }
4011 nsPresContext* pc = mPresShell->GetPresContext();
4012 if (!pc->UseOverlayScrollbars() &&
4013 aParentFrame->StyleUI()->ComputedPointerEvents() !=
4014 StylePointerEvents::Auto) {
4015 return false;
4016 }
4017 if (pc->Medium() != nsGkAtoms::screen) {
4018 return false;
4019 }
4020 return true;
4021 };
4022
4023 auto AllowStyleCaching = [&] {
4024 if (computedAllowStyleCaching.isNothing()) {
4025 computedAllowStyleCaching.emplace(ComputeAllowStyleCaching());
4026 }
4027 return computedAllowStyleCaching.value();
4028 };
4029
4030 // Compute styles for the anonymous content tree.
4031 ServoStyleSet* styleSet = mPresShell->StyleSet();
4032 for (auto& info : aContent) {
4033 Element* e = Element::FromNode(info.mContent);
4034 if (!e) {
4035 continue;
4036 }
4037
4038 if (info.mKey == AnonymousContentKey::None || !AllowStyleCaching()) {
4039 // Most NAC subtrees do not use caching of computed styles. Just go
4040 // ahead and eagerly style the subtree.
4041 styleSet->StyleNewSubtree(e);
4042 continue;
4043 }
4044
4045 // We have a NAC subtree for which we can use cached styles.
4046 AutoTArray<RefPtr<ComputedStyle>, 2> cachedStyles;
4047 AutoTArray<Element*, 2> elements;
4048
4049 GatherSubtreeElements(e, elements);
4050 styleSet->GetCachedAnonymousContentStyles(info.mKey, cachedStyles);
4051
4052 if (cachedStyles.IsEmpty()) {
4053 // We haven't stored cached styles for this kind of NAC subtree yet.
4054 // Eagerly compute those styles, then cache them for later.
4055 styleSet->StyleNewSubtree(e);
4056 for (Element* e : elements) {
4057 if (e->HasServoData()) {
4058 cachedStyles.AppendElement(ServoStyleSet::ResolveServoStyle(*e));
4059 } else {
4060 cachedStyles.AppendElement(nullptr);
4061 }
4062 }
4063 styleSet->PutCachedAnonymousContentStyles(info.mKey,
4064 std::move(cachedStyles));
4065 continue;
4066 }
4067
4068 // We previously stored cached styles for this kind of NAC subtree.
4069 // Iterate over them and set them on the subtree's elements.
4070 MOZ_ASSERT(cachedStyles.Length() == elements.Length(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cachedStyles.Length() == elements.Length())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(cachedStyles.Length() == elements.Length()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("cachedStyles.Length() == elements.Length()"
" (" "should always produce the same size NAC subtree" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles.Length() == elements.Length()"
") (" "should always produce the same size NAC subtree" ")")
; do { *((volatile int*)__null) = 4071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4071 "should always produce the same size NAC subtree")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cachedStyles.Length() == elements.Length())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(cachedStyles.Length() == elements.Length()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("cachedStyles.Length() == elements.Length()"
" (" "should always produce the same size NAC subtree" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles.Length() == elements.Length()"
") (" "should always produce the same size NAC subtree" ")")
; do { *((volatile int*)__null) = 4071; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4072 for (size_t i = 0, len = cachedStyles.Length(); i != len; ++i) {
4073 if (cachedStyles[i]) {
4074#ifdef DEBUG1
4075 // Assert that our cached style is the same as one we could compute.
4076 RefPtr<ComputedStyle> cs = styleSet->ResolveStyleLazily(*elements[i]);
4077 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
" (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4080; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4078 cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
" (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4080; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4079 "cached anonymous content styles should be identical to those we "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
" (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4080; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
4080 "would compute normally")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cachedStyles[i]->EqualForCachedAnonymousContentStyle
(*cs)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
" (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs)"
") (" "cached anonymous content styles should be identical to those we "
"would compute normally" ")"); do { *((volatile int*)__null)
= 4080; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4081 // All overlay scrollbars start off as inactive, so we can rely on their
4082 // pointer-events value being always none.
4083 MOZ_ASSERT(!mPresShell->GetPresContext()->UseOverlayScrollbars() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresShell->GetPresContext()->UseOverlayScrollbars
() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents
::None)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mPresShell->GetPresContext()->UseOverlayScrollbars
() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4084 cs->StyleUI()->ComputedPointerEvents() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresShell->GetPresContext()->UseOverlayScrollbars
() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents
::None)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mPresShell->GetPresContext()->UseOverlayScrollbars
() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4085 StylePointerEvents::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPresShell->GetPresContext()->UseOverlayScrollbars
() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents
::None)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mPresShell->GetPresContext()->UseOverlayScrollbars
() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents
::None))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPresShell->GetPresContext()->UseOverlayScrollbars() || cs->StyleUI()->ComputedPointerEvents() == StylePointerEvents::None"
")"); do { *((volatile int*)__null) = 4085; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4086#endif
4087 Servo_SetExplicitStyle(elements[i], cachedStyles[i]);
4088 }
4089 }
4090 }
4091
4092 return NS_OK;
4093}
4094
4095/* static */
4096const nsCSSFrameConstructor::FrameConstructionData*
4097nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
4098 ComputedStyle& aStyle) {
4099 MOZ_ASSERT(aElement.IsXULElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement.IsXULElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement.IsXULElement()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aElement.IsXULElement()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsXULElement()"
")"); do { *((volatile int*)__null) = 4099; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4100 static constexpr FrameConstructionData kPopupData(NS_NewMenuPopupFrame,
4101 FCDATA_IS_POPUP0x100);
4102
4103 static constexpr FrameConstructionDataByTag sXULTagData[] = {
4104 SIMPLE_TAG_CREATE(image, NS_NewXULImageFrame){nsGkAtoms::image, FrameConstructionData(NS_NewXULImageFrame)
}
,
4105 SIMPLE_TAG_CREATE(treechildren, NS_NewTreeBodyFrame){nsGkAtoms::treechildren, FrameConstructionData(NS_NewTreeBodyFrame
)}
,
4106 SIMPLE_TAG_CHAIN(label,{nsGkAtoms::label, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
4107 nsCSSFrameConstructor::FindXULLabelOrDescriptionData){nsGkAtoms::label, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
,
4108 SIMPLE_TAG_CHAIN(description,{nsGkAtoms::description, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
4109 nsCSSFrameConstructor::FindXULLabelOrDescriptionData){nsGkAtoms::description, FrameConstructionData(nsCSSFrameConstructor
::FindXULLabelOrDescriptionData)}
,
4110#ifdef XP_MACOSX
4111 SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData){nsGkAtoms::menubar, FrameConstructionData(nsCSSFrameConstructor
::FindXULMenubarData)}
,
4112#endif /* XP_MACOSX */
4113 SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame){nsGkAtoms::iframe, FrameConstructionData(NS_NewSubDocumentFrame
)}
,
4114 SIMPLE_TAG_CREATE(editor, NS_NewSubDocumentFrame){nsGkAtoms::editor, FrameConstructionData(NS_NewSubDocumentFrame
)}
,
4115 SIMPLE_TAG_CREATE(browser, NS_NewSubDocumentFrame){nsGkAtoms::browser, FrameConstructionData(NS_NewSubDocumentFrame
)}
,
4116 SIMPLE_TAG_CREATE(splitter, NS_NewSplitterFrame){nsGkAtoms::splitter, FrameConstructionData(NS_NewSplitterFrame
)}
,
4117 SIMPLE_TAG_CREATE(scrollbar, NS_NewScrollbarFrame){nsGkAtoms::scrollbar, FrameConstructionData(NS_NewScrollbarFrame
)}
,
4118 SIMPLE_TAG_CREATE(slider, NS_NewSliderFrame){nsGkAtoms::slider, FrameConstructionData(NS_NewSliderFrame)},
4119 SIMPLE_TAG_CREATE(thumb, NS_NewSimpleXULLeafFrame){nsGkAtoms::thumb, FrameConstructionData(NS_NewSimpleXULLeafFrame
)}
,
4120 SIMPLE_TAG_CREATE(scrollcorner, NS_NewSimpleXULLeafFrame){nsGkAtoms::scrollcorner, FrameConstructionData(NS_NewSimpleXULLeafFrame
)}
,
4121 SIMPLE_TAG_CREATE(resizer, NS_NewSimpleXULLeafFrame){nsGkAtoms::resizer, FrameConstructionData(NS_NewSimpleXULLeafFrame
)}
,
4122 SIMPLE_TAG_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame){nsGkAtoms::scrollbarbutton, FrameConstructionData(NS_NewScrollbarButtonFrame
)}
,
4123 {nsGkAtoms::panel, kPopupData},
4124 {nsGkAtoms::menupopup, kPopupData},
4125 {nsGkAtoms::tooltip, kPopupData},
4126 };
4127
4128 return FindDataByTag(aElement, aStyle, sXULTagData, std::size(sXULTagData));
4129}
4130
4131/* static */
4132const nsCSSFrameConstructor::FrameConstructionData*
4133nsCSSFrameConstructor::FindXULLabelOrDescriptionData(const Element& aElement,
4134 ComputedStyle&) {
4135 // Follow CSS display value if no value attribute
4136 if (!aElement.HasAttr(nsGkAtoms::value)) {
4137 return nullptr;
4138 }
4139
4140 // Follow CSS display if there's no crop="center".
4141 if (!aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::crop,
4142 nsGkAtoms::center, eCaseMatters)) {
4143 return nullptr;
4144 }
4145
4146 static constexpr FrameConstructionData sMiddleCroppingData(
4147 NS_NewMiddleCroppingLabelFrame);
4148 return &sMiddleCroppingData;
4149}
4150
4151#ifdef XP_MACOSX
4152/* static */
4153const nsCSSFrameConstructor::FrameConstructionData*
4154nsCSSFrameConstructor::FindXULMenubarData(const Element& aElement,
4155 ComputedStyle&) {
4156 if (aElement.OwnerDoc()->IsInChromeDocShell()) {
4157 BrowsingContext* bc = aElement.OwnerDoc()->GetBrowsingContext();
4158 bool isRoot = bc && !bc->GetParent();
4159 if (isRoot) {
4160 // This is the root. Suppress the menubar, since on Mac
4161 // window menus are not attached to the window.
4162 static constexpr FrameConstructionData sSuppressData = SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40);
4163 return &sSuppressData;
4164 }
4165 }
4166
4167 return nullptr;
4168}
4169#endif /* XP_MACOSX */
4170
4171already_AddRefed<ComputedStyle>
4172nsCSSFrameConstructor::BeginBuildingScrollContainerFrame(
4173 nsFrameConstructorState& aState, nsIContent* aContent,
4174 ComputedStyle* aContentStyle, nsContainerFrame* aParentFrame,
4175 PseudoStyleType aScrolledPseudo, bool aIsRoot,
4176 nsContainerFrame*& aNewFrame) {
4177 nsContainerFrame* scrollContainerFrame = aNewFrame;
4178
4179 if (!scrollContainerFrame) {
4180 scrollContainerFrame =
4181 NS_NewScrollContainerFrame(mPresShell, aContentStyle, aIsRoot);
4182 InitAndRestoreFrame(aState, aContent, aParentFrame, scrollContainerFrame);
4183 }
4184
4185 MOZ_ASSERT(scrollContainerFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(scrollContainerFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(scrollContainerFrame))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("scrollContainerFrame"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4185); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scrollContainerFrame"
")"); do { *((volatile int*)__null) = 4185; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4186
4187 // if there are any anonymous children for the scroll frame, create
4188 // frames for them.
4189 //
4190 // We can't take the normal ProcessChildren path, because the NAC needs to
4191 // be parented to the scrollframe, and everything else needs to be parented
4192 // to the scrolledframe.
4193 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> scrollNAC;
4194 DebugOnly<nsresult> rv =
4195 GetAnonymousContent(aContent, scrollContainerFrame, scrollNAC);
4196 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 4196; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4197 nsFrameList anonymousList;
4198 if (!scrollNAC.IsEmpty()) {
4199 nsFrameConstructorSaveState floatSaveState;
4200 aState.MaybePushFloatContainingBlock(scrollContainerFrame, floatSaveState);
4201
4202 AutoFrameConstructionItemList items(this);
4203 AutoFrameConstructionPageName pageNameTracker(aState, scrollContainerFrame);
4204 AddFCItemsForAnonymousContent(aState, scrollContainerFrame, scrollNAC,
4205 items, pageNameTracker);
4206 ConstructFramesFromItemList(aState, items, scrollContainerFrame,
4207 /* aParentIsWrapperAnonBox = */ false,
4208 anonymousList);
4209 }
4210
4211 aNewFrame = scrollContainerFrame;
4212 scrollContainerFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
4213
4214 // we used the style that was passed in. So resolve another one.
4215 ServoStyleSet* styleSet = mPresShell->StyleSet();
4216 RefPtr<ComputedStyle> scrolledChildStyle =
4217 styleSet->ResolveInheritingAnonymousBoxStyle(aScrolledPseudo,
4218 aContentStyle);
4219
4220 scrollContainerFrame->SetInitialChildList(FrameChildListID::Principal,
4221 std::move(anonymousList));
4222
4223 return scrolledChildStyle.forget();
4224}
4225
4226void nsCSSFrameConstructor::FinishBuildingScrollContainerFrame(
4227 nsContainerFrame* aScrollContainerFrame, nsIFrame* aScrolledFrame) {
4228 aScrollContainerFrame->AppendFrames(
4229 FrameChildListID::Principal, nsFrameList(aScrolledFrame, aScrolledFrame));
4230}
4231
4232void nsCSSFrameConstructor::BuildScrollContainerFrame(
4233 nsFrameConstructorState& aState, nsIContent* aContent,
4234 ComputedStyle* aContentStyle, nsIFrame* aScrolledFrame,
4235 nsContainerFrame* aParentFrame, nsContainerFrame*& aNewFrame) {
4236 RefPtr<ComputedStyle> scrolledContentStyle =
4237 BeginBuildingScrollContainerFrame(
4238 aState, aContent, aContentStyle, aParentFrame,
4239 PseudoStyleType::scrolledContent, false, aNewFrame);
4240
4241 aScrolledFrame->SetComputedStyleWithoutNotification(scrolledContentStyle);
4242 InitAndRestoreFrame(aState, aContent, aNewFrame, aScrolledFrame);
4243
4244 FinishBuildingScrollContainerFrame(aNewFrame, aScrolledFrame);
4245}
4246
4247const nsCSSFrameConstructor::FrameConstructionData*
4248nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
4249 const Element& aElement) {
4250 static_assert(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET28)),
4251 "Check eParentTypeCount should not overflow");
4252
4253 // The style system ensures that floated and positioned frames are
4254 // block-level.
4255 NS_ASSERTION(do { if (!(!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle
()) || aDisplay.IsBlockOutsideStyle())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Style system did not apply CSS2.1 section 9.7 fixups", "!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) || aDisplay.IsBlockOutsideStyle()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4258); MOZ_PretendNoReturn(); } } while (0)
4256 !(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) ||do { if (!(!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle
()) || aDisplay.IsBlockOutsideStyle())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Style system did not apply CSS2.1 section 9.7 fixups", "!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) || aDisplay.IsBlockOutsideStyle()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4258); MOZ_PretendNoReturn(); } } while (0)
4257 aDisplay.IsBlockOutsideStyle(),do { if (!(!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle
()) || aDisplay.IsBlockOutsideStyle())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Style system did not apply CSS2.1 section 9.7 fixups", "!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) || aDisplay.IsBlockOutsideStyle()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4258); MOZ_PretendNoReturn(); } } while (0)
4258 "Style system did not apply CSS2.1 section 9.7 fixups")do { if (!(!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle
()) || aDisplay.IsBlockOutsideStyle())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Style system did not apply CSS2.1 section 9.7 fixups", "!(aDisplay.IsFloatingStyle() || aDisplay.IsAbsolutelyPositionedStyle()) || aDisplay.IsBlockOutsideStyle()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4258); MOZ_PretendNoReturn(); } } while (0)
;
4259
4260 // If this is "body", try propagating its scroll style to the viewport
4261 // Note that we need to do this even if the body is NOT scrollable;
4262 // it might have dynamically changed from scrollable to not scrollable,
4263 // and that might need to be propagated.
4264 // XXXbz is this the right place to do this? If this code moves,
4265 // make this function static.
4266 bool propagatedScrollToViewport = false;
4267 if (aElement.IsHTMLElement(nsGkAtoms::body)) {
4268 if (nsPresContext* presContext = mPresShell->GetPresContext()) {
4269 propagatedScrollToViewport =
4270 presContext->UpdateViewportScrollStylesOverride() == &aElement;
4271 MOZ_ASSERT(!propagatedScrollToViewport ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!propagatedScrollToViewport || !mPresShell->GetPresContext
()->IsPaginated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propagatedScrollToViewport ||
!mPresShell->GetPresContext()->IsPaginated()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
" (" "Shouldn't propagate scroll in paginated contexts" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4272 !mPresShell->GetPresContext()->IsPaginated(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!propagatedScrollToViewport || !mPresShell->GetPresContext
()->IsPaginated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propagatedScrollToViewport ||
!mPresShell->GetPresContext()->IsPaginated()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
" (" "Shouldn't propagate scroll in paginated contexts" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4273 "Shouldn't propagate scroll in paginated contexts")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!propagatedScrollToViewport || !mPresShell->GetPresContext
()->IsPaginated())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!propagatedScrollToViewport ||
!mPresShell->GetPresContext()->IsPaginated()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
" (" "Shouldn't propagate scroll in paginated contexts" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!propagatedScrollToViewport || !mPresShell->GetPresContext()->IsPaginated()"
") (" "Shouldn't propagate scroll in paginated contexts" ")"
); do { *((volatile int*)__null) = 4273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4274 }
4275 }
4276
4277 switch (aDisplay.DisplayInside()) {
4278 case StyleDisplayInside::Flow:
4279 case StyleDisplayInside::FlowRoot: {
4280 if (aDisplay.IsInlineFlow()) {
4281 static constexpr FrameConstructionData data(
4282 &nsCSSFrameConstructor::ConstructInline,
4283 FCDATA_IS_INLINE0x1000 | FCDATA_IS_LINE_PARTICIPANT0x2000);
4284 return &data;
4285 }
4286
4287 // If the frame is a block-level frame and is scrollable, then wrap it in
4288 // a scroll frame. Except we don't want to do that for paginated contexts
4289 // for frames that are block-outside and aren't frames for native
4290 // anonymous stuff.
4291 // XXX Ignore tables for the time being (except caption)
4292 const uint32_t kCaptionCtorFlags =
4293 FCDATA_IS_TABLE_PART0x800 | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28);
4294 const bool caption = aDisplay.mDisplay == StyleDisplay::TableCaption;
4295 const bool needScrollFrame =
4296 aDisplay.IsScrollableOverflow() && !propagatedScrollToViewport;
4297 if (needScrollFrame) {
4298 const bool suppressScrollFrame =
4299 mPresShell->GetPresContext()->IsPaginated() &&
4300 aDisplay.IsBlockOutsideStyle() &&
4301 !aElement.IsInNativeAnonymousSubtree();
4302 if (!suppressScrollFrame) {
4303 static constexpr FrameConstructionData sScrollableBlockData[2] = {
4304 {&nsCSSFrameConstructor::ConstructScrollableBlock},
4305 {&nsCSSFrameConstructor::ConstructScrollableBlock,
4306 kCaptionCtorFlags}};
4307 return &sScrollableBlockData[caption];
4308 }
4309 }
4310
4311 // Handle various non-scrollable blocks.
4312 static constexpr FrameConstructionData sNonScrollableBlockData[2] = {
4313 {&nsCSSFrameConstructor::ConstructNonScrollableBlock},
4314 {&nsCSSFrameConstructor::ConstructNonScrollableBlock,
4315 kCaptionCtorFlags}};
4316 return &sNonScrollableBlockData[caption];
4317 }
4318 case StyleDisplayInside::Table: {
4319 static constexpr FrameConstructionData data(
4320 &nsCSSFrameConstructor::ConstructTable);
4321 return &data;
4322 }
4323 // NOTE: In the unlikely event that we add another table-part here that
4324 // has a desired-parent-type (& hence triggers table fixup), we'll need to
4325 // also update the flexbox chunk in ComputedStyle::ApplyStyleFixups().
4326 case StyleDisplayInside::TableRowGroup: {
4327 static constexpr FrameConstructionData data(
4328 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4329 FCDATA_IS_TABLE_PART0x800 |
4330 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4331 return &data;
4332 }
4333 case StyleDisplayInside::TableColumn: {
4334 static constexpr FrameConstructionData data(
4335 &nsCSSFrameConstructor::ConstructTableCol,
4336 FCDATA_IS_TABLE_PART0x800 |
4337 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup)(((uint32_t)(eTypeColGroup)) << 28));
4338 return &data;
4339 }
4340 case StyleDisplayInside::TableColumnGroup: {
4341 static constexpr FrameConstructionData data(
4342 ToCreationFunc(NS_NewTableColGroupFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewTableColGroupFrame(aPs, aStyle); }
,
4343 FCDATA_IS_TABLE_PART0x800 | FCDATA_DISALLOW_OUT_OF_FLOW0x8 |
4344 FCDATA_SKIP_ABSPOS_PUSH0x200 |
4345 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4346 return &data;
4347 }
4348 case StyleDisplayInside::TableHeaderGroup: {
4349 static constexpr FrameConstructionData data(
4350 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4351 FCDATA_IS_TABLE_PART0x800 |
4352 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4353 return &data;
4354 }
4355 case StyleDisplayInside::TableFooterGroup: {
4356 static constexpr FrameConstructionData data(
4357 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4358 FCDATA_IS_TABLE_PART0x800 |
4359 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28));
4360 return &data;
4361 }
4362 case StyleDisplayInside::TableRow: {
4363 static constexpr FrameConstructionData data(
4364 &nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
4365 FCDATA_IS_TABLE_PART0x800 |
4366 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup)(((uint32_t)(eTypeRowGroup)) << 28));
4367 return &data;
4368 }
4369 case StyleDisplayInside::TableCell: {
4370 static constexpr FrameConstructionData data(
4371 &nsCSSFrameConstructor::ConstructTableCell,
4372 FCDATA_IS_TABLE_PART0x800 | FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow)(((uint32_t)(eTypeRow)) << 28));
4373 return &data;
4374 }
4375 case StyleDisplayInside::Flex:
4376 case StyleDisplayInside::WebkitBox: {
4377 static constexpr FrameConstructionData nonScrollableData(
4378 ToCreationFunc(NS_NewFlexContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewFlexContainerFrame(aPs, aStyle); }
);
4379 static constexpr FrameConstructionData data(
4380 ToCreationFunc(NS_NewFlexContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewFlexContainerFrame(aPs, aStyle); }
,
4381 FCDATA_MAY_NEED_SCROLLFRAME0x80);
4382 return MOZ_UNLIKELY(propagatedScrollToViewport)(__builtin_expect(!!(propagatedScrollToViewport), 0)) ? &nonScrollableData
4383 : &data;
4384 }
4385 case StyleDisplayInside::Grid: {
4386 static constexpr FrameConstructionData nonScrollableData(
4387 ToCreationFunc(NS_NewGridContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGridContainerFrame(aPs, aStyle); }
);
4388 static constexpr FrameConstructionData data(
4389 ToCreationFunc(NS_NewGridContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewGridContainerFrame(aPs, aStyle); }
,
4390 FCDATA_MAY_NEED_SCROLLFRAME0x80);
4391 return MOZ_UNLIKELY(propagatedScrollToViewport)(__builtin_expect(!!(propagatedScrollToViewport), 0)) ? &nonScrollableData
4392 : &data;
4393 }
4394 case StyleDisplayInside::Ruby: {
4395 static constexpr FrameConstructionData data[] = {
4396 {&nsCSSFrameConstructor::ConstructBlockRubyFrame,
4397 FCDATA_MAY_NEED_SCROLLFRAME0x80},
4398 {ToCreationFunc(NS_NewRubyFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyFrame(aPs, aStyle); }
, FCDATA_IS_LINE_PARTICIPANT0x2000}};
4399 bool isInline = aDisplay.DisplayOutside() == StyleDisplayOutside::Inline;
4400 return &data[isInline];
4401 }
4402 case StyleDisplayInside::RubyBase: {
4403 static constexpr FrameConstructionData data(
4404 ToCreationFunc(NS_NewRubyBaseFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseFrame(aPs, aStyle); }
,
4405 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4406 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer)(((uint32_t)(eTypeRubyBaseContainer)) << 28));
4407 return &data;
4408 }
4409 case StyleDisplayInside::RubyBaseContainer: {
4410 static constexpr FrameConstructionData data(
4411 ToCreationFunc(NS_NewRubyBaseContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseContainerFrame(aPs, aStyle); }
,
4412 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4413 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28));
4414 return &data;
4415 }
4416 case StyleDisplayInside::RubyText: {
4417 static constexpr FrameConstructionData data(
4418 ToCreationFunc(NS_NewRubyTextFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextFrame(aPs, aStyle); }
,
4419 FCDATA_IS_LINE_PARTICIPANT0x2000 |
4420 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer)(((uint32_t)(eTypeRubyTextContainer)) << 28));
4421 return &data;
4422 }
4423 case StyleDisplayInside::RubyTextContainer: {
4424 static constexpr FrameConstructionData data(
4425 ToCreationFunc(NS_NewRubyTextContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextContainerFrame(aPs, aStyle); }
,
4426 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28));
4427 return &data;
4428 }
4429 default:
4430 MOZ_ASSERT_UNREACHABLE("unknown 'display' value")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"unknown 'display' value" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unknown 'display' value" ")"); do
{ *((volatile int*)__null) = 4430; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4431 return nullptr;
4432 }
4433}
4434
4435nsIFrame* nsCSSFrameConstructor::ConstructScrollableBlock(
4436 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4437 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4438 nsFrameList& aFrameList) {
4439 nsIContent* const content = aItem.mContent;
4440 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4441
4442 nsContainerFrame* newFrame = nullptr;
4443 RefPtr<ComputedStyle> scrolledContentStyle =
4444 BeginBuildingScrollContainerFrame(
4445 aState, content, computedStyle,
4446 aState.GetGeometricParent(*aDisplay, aParentFrame),
4447 PseudoStyleType::scrolledContent, false, newFrame);
4448
4449 // Create our block frame
4450 // pass a temporary stylecontext, the correct one will be set later
4451 nsContainerFrame* scrolledFrame = NS_NewBlockFrame(mPresShell, computedStyle);
4452
4453 // Make sure to AddChild before we call ConstructBlock so that we
4454 // end up before our descendants in fixed-pos lists as needed.
4455 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
4456
4457 nsFrameList blockList;
4458 ConstructBlock(aState, content, newFrame, newFrame, scrolledContentStyle,
4459 &scrolledFrame, blockList,
4460 newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
4461
4462 MOZ_ASSERT(blockList.OnlyChild() == scrolledFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(blockList.OnlyChild() == scrolledFrame)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(blockList.OnlyChild() == scrolledFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("blockList.OnlyChild() == scrolledFrame"
" (" "Scrollframe's frameList should be exactly the scrolled frame!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4463); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockList.OnlyChild() == scrolledFrame"
") (" "Scrollframe's frameList should be exactly the scrolled frame!"
")"); do { *((volatile int*)__null) = 4463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4463 "Scrollframe's frameList should be exactly the scrolled frame!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(blockList.OnlyChild() == scrolledFrame)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(blockList.OnlyChild() == scrolledFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("blockList.OnlyChild() == scrolledFrame"
" (" "Scrollframe's frameList should be exactly the scrolled frame!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4463); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockList.OnlyChild() == scrolledFrame"
") (" "Scrollframe's frameList should be exactly the scrolled frame!"
")"); do { *((volatile int*)__null) = 4463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4464 FinishBuildingScrollContainerFrame(newFrame, scrolledFrame);
4465
4466 return newFrame;
4467}
4468
4469nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlock(
4470 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4471 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4472 nsFrameList& aFrameList) {
4473 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4474 nsContainerFrame* newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
4475 ConstructBlock(aState, aItem.mContent,
4476 aState.GetGeometricParent(*aDisplay, aParentFrame),
4477 aParentFrame, computedStyle, &newFrame, aFrameList,
4478 newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
4479 return newFrame;
4480}
4481
4482void nsCSSFrameConstructor::InitAndRestoreFrame(
4483 const nsFrameConstructorState& aState, nsIContent* aContent,
4484 nsContainerFrame* aParentFrame, nsIFrame* aNewFrame, bool aAllowCounters) {
4485 MOZ_ASSERT(aNewFrame, "Null frame cannot be initialized")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNewFrame" " (" "Null frame cannot be initialized"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewFrame" ") ("
"Null frame cannot be initialized" ")"); do { *((volatile int
*)__null) = 4485; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4486
4487 // Initialize the frame
4488 aNewFrame->Init(aContent, aParentFrame, nullptr);
4489 aNewFrame->AddStateBits(aState.mAdditionalStateBits);
4490
4491 if (aState.mFrameState) {
4492 // Restore frame state for just the newly created frame.
4493 RestoreFrameStateFor(aNewFrame, aState.mFrameState);
4494 }
4495
4496 if (aAllowCounters &&
4497 mContainStyleScopeManager.AddCounterChanges(aNewFrame)) {
4498 CountersDirty();
4499 }
4500}
4501
4502already_AddRefed<ComputedStyle> nsCSSFrameConstructor::ResolveComputedStyle(
4503 nsIContent* aContent) {
4504 if (auto* element = Element::FromNode(aContent)) {
4505 return ServoStyleSet::ResolveServoStyle(*element);
4506 }
4507
4508 MOZ_ASSERT(aContent->IsText(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsText())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent->IsText()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aContent->IsText()"
" (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4509 "shouldn't waste time creating ComputedStyles for "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsText())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent->IsText()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aContent->IsText()"
" (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4510 "comments and processing instructions")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsText())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent->IsText()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aContent->IsText()"
" (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText()"
") (" "shouldn't waste time creating ComputedStyles for " "comments and processing instructions"
")"); do { *((volatile int*)__null) = 4510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4511
4512 Element* parent = aContent->GetFlattenedTreeParentElement();
4513 MOZ_ASSERT(parent, "Text out of the flattened tree?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(parent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("parent" " (" "Text out of the flattened tree?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ") ("
"Text out of the flattened tree?" ")"); do { *((volatile int
*)__null) = 4513; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4514
4515 // FIXME(emilio): The const_cast is unfortunate, but it's not worse than what
4516 // we did before.
4517 //
4518 // We could use ResolveServoStyle, but that would involve extra unnecessary
4519 // refcount traffic...
4520 auto* parentStyle =
4521 const_cast<ComputedStyle*>(Servo_Element_GetMaybeOutOfDateStyle(parent));
4522 MOZ_ASSERT(parentStyle,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parentStyle)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(parentStyle))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("parentStyle" " ("
"How are we inserting text frames in an unstyled element?" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentStyle"
") (" "How are we inserting text frames in an unstyled element?"
")"); do { *((volatile int*)__null) = 4523; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4523 "How are we inserting text frames in an unstyled element?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parentStyle)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(parentStyle))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("parentStyle" " ("
"How are we inserting text frames in an unstyled element?" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentStyle"
") (" "How are we inserting text frames in an unstyled element?"
")"); do { *((volatile int*)__null) = 4523; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4524 return mPresShell->StyleSet()->ResolveStyleForText(aContent, parentStyle);
4525}
4526
4527// MathML Mod - RBS
4528void nsCSSFrameConstructor::FlushAccumulatedBlock(
4529 nsFrameConstructorState& aState, nsIContent* aContent,
4530 nsContainerFrame* aParentFrame, nsFrameList& aBlockList,
4531 nsFrameList& aNewList) {
4532 if (aBlockList.IsEmpty()) {
4533 // Nothing to do
4534 return;
4535 }
4536
4537 auto anonPseudo = PseudoStyleType::mozMathMLAnonymousBlock;
4538
4539 ComputedStyle* parentContext =
4540 nsIFrame::CorrectStyleParentFrame(aParentFrame, anonPseudo)->Style();
4541 ServoStyleSet* styleSet = mPresShell->StyleSet();
4542 RefPtr<ComputedStyle> blockContext =
4543 styleSet->ResolveInheritingAnonymousBoxStyle(anonPseudo, parentContext);
4544
4545 // then, create a block frame that will wrap the child frames. Make it a
4546 // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
4547 // is not a suitable block.
4548 nsContainerFrame* blockFrame =
4549 NS_NewMathMLmathBlockFrame(mPresShell, blockContext);
4550
4551 InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
4552 ReparentFrames(this, blockFrame, aBlockList, false);
4553 // We have to walk over aBlockList before we hand it over to blockFrame.
4554 for (nsIFrame* f : aBlockList) {
4555 f->SetParentIsWrapperAnonBox();
4556 }
4557 // abs-pos and floats are disabled in MathML children so we don't have to
4558 // worry about messing up those.
4559 blockFrame->SetInitialChildList(FrameChildListID::Principal,
4560 std::move(aBlockList));
4561 aNewList.AppendFrame(nullptr, blockFrame);
4562}
4563
4564// Only <math> elements can be floated or positioned. All other MathML
4565// should be in-flow.
4566#define SIMPLE_MATHML_CREATE(_tag, _func){ nsGkAtoms::_tag, { _func, 0x8 | 0x10 | 0x20 } } \
4567 { \
4568 nsGkAtoms::_tag, { \
4569 _func, FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4570 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | \
4571 FCDATA_WRAP_KIDS_IN_BLOCKS0x20 \
4572 } \
4573 }
4574
4575/* static */
4576const nsCSSFrameConstructor::FrameConstructionData*
4577nsCSSFrameConstructor::FindMathMLData(const Element& aElement,
4578 ComputedStyle& aStyle) {
4579 MOZ_ASSERT(aElement.IsMathMLElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement.IsMathMLElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement.IsMathMLElement()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aElement.IsMathMLElement()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsMathMLElement()"
")"); do { *((volatile int*)__null) = 4579; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4580
4581 nsAtom* tag = aElement.NodeInfo()->NameAtom();
4582
4583 // Handle <math> specially, because it sometimes produces inlines
4584 if (tag == nsGkAtoms::math) {
4585 // The IsBlockOutsideStyle() check must match what
4586 // specified::Display::equivalent_block_display is checking for
4587 // already-block-outside things. Though the behavior here for the
4588 // display:table case is pretty weird...
4589 if (aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
4590 static constexpr FrameConstructionData sBlockMathData(
4591 ToCreationFunc(NS_NewMathMLmathBlockFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewMathMLmathBlockFrame(aPs, aStyle); }
,
4592 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
4593 return &sBlockMathData;
4594 }
4595
4596 static constexpr FrameConstructionData sInlineMathData(
4597 ToCreationFunc(NS_NewMathMLmathInlineFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewMathMLmathInlineFrame(aPs, aStyle); }
,
4598 FCDATA_FORCE_NULL_ABSPOS_CONTAINER0x10 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
4599 FCDATA_WRAP_KIDS_IN_BLOCKS0x20);
4600 return &sInlineMathData;
4601 }
4602
4603 static constexpr FrameConstructionDataByTag sMathMLData[] = {
4604 SIMPLE_MATHML_CREATE(annotation_, NS_NewMathMLTokenFrame){ nsGkAtoms::annotation_, { NS_NewMathMLTokenFrame, 0x8 | 0x10
| 0x20 } }
,
4605 SIMPLE_MATHML_CREATE(annotation_xml_, NS_NewMathMLmrowFrame){ nsGkAtoms::annotation_xml_, { NS_NewMathMLmrowFrame, 0x8 | 0x10
| 0x20 } }
,
4606 SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame){ nsGkAtoms::mi_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4607 SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame){ nsGkAtoms::mn_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4608 SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame){ nsGkAtoms::ms_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4609 SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame){ nsGkAtoms::mtext_, { NS_NewMathMLTokenFrame, 0x8 | 0x10 | 0x20
} }
,
4610 SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame){ nsGkAtoms::mo_, { NS_NewMathMLmoFrame, 0x8 | 0x10 | 0x20 } },
4611 SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame){ nsGkAtoms::mfrac_, { NS_NewMathMLmfracFrame, 0x8 | 0x10 | 0x20
} }
,
4612 SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msup_, { NS_NewMathMLmmultiscriptsFrame, 0x8 | 0x10
| 0x20 } }
,
4613 SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msub_, { NS_NewMathMLmmultiscriptsFrame, 0x8 | 0x10
| 0x20 } }
,
4614 SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::msubsup_, { NS_NewMathMLmmultiscriptsFrame, 0x8 |
0x10 | 0x20 } }
,
4615 SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::munder_, { NS_NewMathMLmunderoverFrame, 0x8 | 0x10
| 0x20 } }
,
4616 SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::mover_, { NS_NewMathMLmunderoverFrame, 0x8 | 0x10
| 0x20 } }
,
4617 SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame){ nsGkAtoms::munderover_, { NS_NewMathMLmunderoverFrame, 0x8 |
0x10 | 0x20 } }
,
4618 SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmrowFrame){ nsGkAtoms::mphantom_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 |
0x20 } }
,
4619 SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame){ nsGkAtoms::mpadded_, { NS_NewMathMLmpaddedFrame, 0x8 | 0x10
| 0x20 } }
,
4620 SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame){ nsGkAtoms::mspace_, { NS_NewMathMLmspaceFrame, 0x8 | 0x10 |
0x20 } }
,
4621 SIMPLE_MATHML_CREATE(none, NS_NewMathMLmrowFrame){ nsGkAtoms::none, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4622 SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmrowFrame){ nsGkAtoms::mprescripts_, { NS_NewMathMLmrowFrame, 0x8 | 0x10
| 0x20 } }
,
4623 SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmrowFrame){ nsGkAtoms::mfenced_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4624 SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame){ nsGkAtoms::mmultiscripts_, { NS_NewMathMLmmultiscriptsFrame
, 0x8 | 0x10 | 0x20 } }
,
4625 SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmrowFrame){ nsGkAtoms::mstyle_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4626 SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmrootFrame){ nsGkAtoms::msqrt_, { NS_NewMathMLmrootFrame, 0x8 | 0x10 | 0x20
} }
,
4627 SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame){ nsGkAtoms::mroot_, { NS_NewMathMLmrootFrame, 0x8 | 0x10 | 0x20
} }
,
4628 SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmrowFrame){ nsGkAtoms::maction_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4629 SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame){ nsGkAtoms::mrow_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4630 SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame){ nsGkAtoms::merror_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 | 0x20
} }
,
4631 SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame){ nsGkAtoms::menclose_, { NS_NewMathMLmencloseFrame, 0x8 | 0x10
| 0x20 } }
,
4632 SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLmrowFrame){ nsGkAtoms::semantics_, { NS_NewMathMLmrowFrame, 0x8 | 0x10 |
0x20 } }
};
4633
4634 return FindDataByTag(aElement, aStyle, sMathMLData, std::size(sMathMLData));
4635}
4636
4637nsContainerFrame* nsCSSFrameConstructor::ConstructFrameWithAnonymousChild(
4638 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4639 nsContainerFrame* aParentFrame, nsFrameList& aFrameList,
4640 ContainerFrameCreationFunc aConstructor,
4641 ContainerFrameCreationFunc aInnerConstructor, PseudoStyleType aInnerPseudo,
4642 bool aCandidateRootFrame) {
4643 nsIContent* const content = aItem.mContent;
4644 ComputedStyle* const computedStyle = aItem.mComputedStyle;
4645
4646 // Create the outer frame:
4647 nsContainerFrame* newFrame = aConstructor(mPresShell, computedStyle);
4648
4649 InitAndRestoreFrame(aState, content,
4650 aCandidateRootFrame
4651 ? aState.GetGeometricParent(
4652 *computedStyle->StyleDisplay(), aParentFrame)
4653 : aParentFrame,
4654 newFrame);
4655 newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
4656
4657 // Create the pseudo SC for the anonymous wrapper child as a child of the SC:
4658 RefPtr<ComputedStyle> scForAnon =
4659 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(aInnerPseudo,
4660 computedStyle);
4661
4662 // Create the anonymous inner wrapper frame
4663 nsContainerFrame* innerFrame = aInnerConstructor(mPresShell, scForAnon);
4664
4665 InitAndRestoreFrame(aState, content, newFrame, innerFrame);
4666
4667 // Put the newly created frames into the right child list
4668 SetInitialSingleChild(newFrame, innerFrame);
4669
4670 aState.AddChild(newFrame, aFrameList, content, aParentFrame,
4671 aCandidateRootFrame, aCandidateRootFrame);
4672
4673 if (!mRootElementFrame && aCandidateRootFrame) {
4674 mRootElementFrame = newFrame;
4675 }
4676
4677 nsFrameConstructorSaveState floatSaveState;
4678 aState.MaybePushFloatContainingBlock(innerFrame, floatSaveState);
4679
4680 nsFrameList childList;
4681
4682 // Process children
4683 if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS0x10000) {
4684 ConstructFramesFromItemList(
4685 aState, aItem.mChildItems, innerFrame,
4686 aItem.mFCData->mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000, childList);
4687 } else {
4688 ProcessChildren(aState, content, computedStyle, innerFrame, true, childList,
4689 false);
4690 }
4691
4692 // Set the inner wrapper frame's initial primary list
4693 innerFrame->SetInitialChildList(FrameChildListID::Principal,
4694 std::move(childList));
4695
4696 return newFrame;
4697}
4698
4699nsIFrame* nsCSSFrameConstructor::ConstructOuterSVG(
4700 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4701 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4702 nsFrameList& aFrameList) {
4703 return ConstructFrameWithAnonymousChild(
4704 aState, aItem, aParentFrame, aFrameList, NS_NewSVGOuterSVGFrame,
4705 NS_NewSVGOuterSVGAnonChildFrame, PseudoStyleType::mozSVGOuterSVGAnonChild,
4706 true);
4707}
4708
4709nsIFrame* nsCSSFrameConstructor::ConstructMarker(
4710 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
4711 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
4712 nsFrameList& aFrameList) {
4713 return ConstructFrameWithAnonymousChild(
4714 aState, aItem, aParentFrame, aFrameList, NS_NewSVGMarkerFrame,
4715 NS_NewSVGMarkerAnonChildFrame, PseudoStyleType::mozSVGMarkerAnonChild,
4716 false);
4717}
4718
4719// Only outer <svg> elements can be floated or positioned. All other SVG
4720// should be in-flow.
4721#define SIMPLE_SVG_FCDATA(_func)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8 | 0x200
| 0x400)
\
4722 FrameConstructionData(ToCreationFunc(_func)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
_func(aPs, aStyle); }
, \
4723 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | \
4724 FCDATA_SKIP_ABSPOS_PUSH0x200 | \
4725 FCDATA_DISALLOW_GENERATED_CONTENT0x400)
4726#define SIMPLE_SVG_CREATE(_tag, _func){nsGkAtoms::_tag, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8
| 0x200 | 0x400)}
\
4727 {nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return _func(aPs, aStyle); }, 0x8 | 0x200
| 0x400)
}
4728
4729/* static */
4730const nsCSSFrameConstructor::FrameConstructionData*
4731nsCSSFrameConstructor::FindSVGData(const Element& aElement,
4732 nsIFrame* aParentFrame,
4733 bool aIsWithinSVGText,
4734 bool aAllowsTextPathChild,
4735 ComputedStyle& aStyle) {
4736 MOZ_ASSERT(aElement.IsSVGElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement.IsSVGElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement.IsSVGElement()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aElement.IsSVGElement()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement.IsSVGElement()"
")"); do { *((volatile int*)__null) = 4736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4737
4738 static constexpr FrameConstructionData sSuppressData = SUPPRESS_FCDATA()FrameConstructionData(nullptr, 0x40);
4739 static constexpr FrameConstructionData sContainerData =
4740 SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame)FrameConstructionData([](PresShell* aPs, ComputedStyle* aStyle
) -> nsIFrame* { return NS_NewSVGContainerFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)
;
4741
4742 bool parentIsSVG = aIsWithinSVGText;
4743 nsIContent* parentContent =
4744 aParentFrame ? aParentFrame->GetContent() : nullptr;
4745
4746 nsAtom* tag = aElement.NodeInfo()->NameAtom();
4747
4748 // XXXbz should this really be based on the tag of the parent frame's content?
4749 // Should it not be based on the type of the parent frame (e.g. whether it's
4750 // an SVG frame)?
4751 if (parentContent) {
4752 // It's not clear whether the SVG spec intends to allow any SVG
4753 // content within svg:foreignObject at all (SVG 1.1, section
4754 // 23.2), but if it does, it better be svg:svg. So given that
4755 // we're allowing it, treat it as a non-SVG parent.
4756 parentIsSVG =
4757 parentContent->IsSVGElement() &&
4758 parentContent->NodeInfo()->NameAtom() != nsGkAtoms::foreignObject;
4759 }
4760
4761 if ((tag != nsGkAtoms::svg && !parentIsSVG) ||
4762 (tag == nsGkAtoms::desc || tag == nsGkAtoms::title ||
4763 tag == nsGkAtoms::metadata)) {
4764 // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
4765 // svg:svg not contained within svg:svg are incorrect, although they
4766 // don't seem to specify error handling. Ignore them, since many of
4767 // our frame classes can't deal. It *may* be that the document
4768 // should at that point be considered in error according to F.2, but
4769 // it's hard to tell.
4770 //
4771 // Style mutation can't change this situation, so don't bother
4772 // adding to the undisplayed content map.
4773 //
4774 // We don't currently handle any UI for desc/title/metadata
4775 return &sSuppressData;
4776 }
4777
4778 // We don't need frames for animation elements
4779 if (aElement.IsSVGAnimationElement()) {
4780 return &sSuppressData;
4781 }
4782
4783 if (tag == nsGkAtoms::svg && !parentIsSVG) {
4784 // We need outer <svg> elements to have an SVGOuterSVGFrame regardless
4785 // of whether they fail conditional processing attributes, since various
4786 // SVG frames assume that one exists. We handle the non-rendering
4787 // of failing outer <svg> element contents like <switch> statements,
4788 // and do the PassesConditionalProcessingTests call in
4789 // SVGOuterSVGFrame::Init.
4790 static constexpr FrameConstructionData sOuterSVGData(
4791 &nsCSSFrameConstructor::ConstructOuterSVG);
4792 return &sOuterSVGData;
4793 }
4794
4795 if (tag == nsGkAtoms::marker) {
4796 static constexpr FrameConstructionData sMarkerSVGData(
4797 &nsCSSFrameConstructor::ConstructMarker);
4798 return &sMarkerSVGData;
4799 }
4800
4801 if (!aElement.PassesConditionalProcessingTests()) {
4802 // Elements with failing conditional processing attributes never get
4803 // rendered. Note that this is not where we select which frame in a
4804 // <switch> to render! That happens in SVGSwitchFrame::PaintSVG.
4805 if (aIsWithinSVGText) {
4806 // SVGTextFrame doesn't handle conditional processing attributes,
4807 // so don't create frames for descendants of <text> with failing
4808 // attributes. We need frames not to be created so that text layout
4809 // is correct.
4810 return &sSuppressData;
4811 }
4812 // If we're not inside <text>, create an SVGContainerFrame (which is a
4813 // frame that doesn't render) so that paint servers can still be referenced,
4814 // even if they live inside an element with failing conditional processing
4815 // attributes.
4816 return &sContainerData;
4817 }
4818
4819 // Ensure that a stop frame is a child of a gradient and that gradients
4820 // can only have stop children.
4821 bool parentIsGradient = aParentFrame && static_cast<SVGGradientFrame*>(
4822 do_QueryFrame(aParentFrame));
4823 bool stop = (tag == nsGkAtoms::stop);
4824 if ((parentIsGradient && !stop) || (!parentIsGradient && stop)) {
4825 return &sSuppressData;
4826 }
4827
4828 // Prevent bad frame types being children of filters or parents of filter
4829 // primitives. If aParentFrame is null, we know that the frame that will
4830 // be created will be an nsInlineFrame, so it can never be a filter.
4831 bool parentIsFilter = aParentFrame && aParentFrame->IsSVGFilterFrame();
4832 if ((parentIsFilter && !aElement.IsSVGFilterPrimitiveElement()) ||
4833 (!parentIsFilter && aElement.IsSVGFilterPrimitiveElement())) {
4834 return &sSuppressData;
4835 }
4836
4837 // Prevent bad frame types being children of filter primitives or parents of
4838 // filter primitive children. If aParentFrame is null, we know that the frame
4839 // that will be created will be an nsInlineFrame, so it can never be a filter
4840 // primitive.
4841 bool parentIsFEContainerFrame =
4842 aParentFrame && aParentFrame->IsSVGFEContainerFrame();
4843 if ((parentIsFEContainerFrame &&
4844 !aElement.IsSVGFilterPrimitiveChildElement()) ||
4845 (!parentIsFEContainerFrame &&
4846 aElement.IsSVGFilterPrimitiveChildElement())) {
4847 return &sSuppressData;
4848 }
4849
4850 // Special cases for text/tspan/textPath, because the kind of frame
4851 // they get depends on the parent frame. We ignore 'a' elements when
4852 // determining the parent, however.
4853 if (aIsWithinSVGText) {
4854 // If aIsWithinSVGText is true, then we know that the "SVG text uses
4855 // CSS frames" pref was true when this SVG fragment was first constructed.
4856 //
4857 // FIXME(bug 1588477) Don't render stuff in display: contents / Shadow DOM
4858 // subtrees, because TextCorrespondenceRecorder in the SVG text code doesn't
4859 // really know how to deal with it. This kinda sucks. :(
4860 if (aParentFrame && aParentFrame->GetContent() != aElement.GetParent()) {
4861 return &sSuppressData;
4862 }
4863
4864 // We don't use ConstructInline because we want different behavior
4865 // for generated content.
4866 static constexpr FrameConstructionData sTSpanData(
4867 ToCreationFunc(NS_NewInlineFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewInlineFrame(aPs, aStyle); }
,
4868 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_SKIP_ABSPOS_PUSH0x200 |
4869 FCDATA_DISALLOW_GENERATED_CONTENT0x400 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
4870 FCDATA_IS_INLINE0x1000 | FCDATA_USE_CHILD_ITEMS0x10000);
4871 if (tag == nsGkAtoms::textPath) {
4872 if (aAllowsTextPathChild) {
4873 return &sTSpanData;
4874 }
4875 } else if (tag == nsGkAtoms::tspan || tag == nsGkAtoms::a) {
4876 return &sTSpanData;
4877 }
4878 return &sSuppressData;
4879 } else if (tag == nsGkAtoms::tspan || tag == nsGkAtoms::textPath) {
4880 return &sSuppressData;
4881 }
4882
4883 static constexpr FrameConstructionDataByTag sSVGData[] = {
4884 SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame){nsGkAtoms::svg, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGInnerSVGFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4885 SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame){nsGkAtoms::g, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4886 SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame){nsGkAtoms::svgSwitch, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGSwitchFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4887 SIMPLE_SVG_CREATE(symbol, NS_NewSVGSymbolFrame){nsGkAtoms::symbol, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGSymbolFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4888 SIMPLE_SVG_CREATE(polygon, NS_NewSVGGeometryFrame){nsGkAtoms::polygon, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4889 SIMPLE_SVG_CREATE(polyline, NS_NewSVGGeometryFrame){nsGkAtoms::polyline, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4890 SIMPLE_SVG_CREATE(circle, NS_NewSVGGeometryFrame){nsGkAtoms::circle, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4891 SIMPLE_SVG_CREATE(ellipse, NS_NewSVGGeometryFrame){nsGkAtoms::ellipse, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4892 SIMPLE_SVG_CREATE(line, NS_NewSVGGeometryFrame){nsGkAtoms::line, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4893 SIMPLE_SVG_CREATE(rect, NS_NewSVGGeometryFrame){nsGkAtoms::rect, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4894 SIMPLE_SVG_CREATE(path, NS_NewSVGGeometryFrame){nsGkAtoms::path, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGGeometryFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4895 SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame){nsGkAtoms::defs, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGContainerFrame(aPs
, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4896 {nsGkAtoms::text,
4897 {NS_NewSVGTextFrame,
4898 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_ALLOW_BLOCK_STYLES0x8000,
4899 PseudoStyleType::mozSVGText}},
4900 {nsGkAtoms::foreignObject,
4901 {ToCreationFunc(NS_NewSVGForeignObjectFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewSVGForeignObjectFrame(aPs, aStyle); }
,
4902 FCDATA_DISALLOW_OUT_OF_FLOW0x8, PseudoStyleType::mozSVGForeignContent}},
4903 SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame){nsGkAtoms::a, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGAFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4904 SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame){nsGkAtoms::linearGradient, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGLinearGradientFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4905 SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame){nsGkAtoms::radialGradient, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGRadialGradientFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4906 SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame){nsGkAtoms::stop, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGStopFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4907 SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame){nsGkAtoms::use, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGUseFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4908 SIMPLE_SVG_CREATE(view, NS_NewSVGViewFrame){nsGkAtoms::view, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGViewFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4909 SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame){nsGkAtoms::image, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGImageFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4910 SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame){nsGkAtoms::clipPath, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGClipPathFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4911 SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame){nsGkAtoms::filter, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGFilterFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4912 SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame){nsGkAtoms::pattern, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGPatternFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4913 SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame){nsGkAtoms::mask, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGMaskFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4914 SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feDistantLight, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4915 SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::fePointLight, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4916 SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feSpotLight, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4917 SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame){nsGkAtoms::feBlend, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4918 SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame){nsGkAtoms::feColorMatrix, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4919 SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncR, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4920 SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncG, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4921 SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncB, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4922 SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feFuncA, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4923 SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame){nsGkAtoms::feComposite, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4924 SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame){nsGkAtoms::feComponentTransfer, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4925 SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame){nsGkAtoms::feConvolveMatrix, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4926 SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame){nsGkAtoms::feDiffuseLighting, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4927 SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame){nsGkAtoms::feDisplacementMap, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4928 SIMPLE_SVG_CREATE(feDropShadow, NS_NewSVGFELeafFrame){nsGkAtoms::feDropShadow, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4929 SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame){nsGkAtoms::feFlood, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4930 SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame){nsGkAtoms::feGaussianBlur, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4931 SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame){nsGkAtoms::feImage, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEImageFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4932 SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame){nsGkAtoms::feMerge, FrameConstructionData([](PresShell* aPs,
ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4933 SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame){nsGkAtoms::feMergeNode, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEUnstyledLeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4934 SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame){nsGkAtoms::feMorphology, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4935 SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame){nsGkAtoms::feOffset, FrameConstructionData([](PresShell* aPs
, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4936 SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame){nsGkAtoms::feSpecularLighting, FrameConstructionData([](PresShell
* aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFEContainerFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
,
4937 SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame){nsGkAtoms::feTile, FrameConstructionData([](PresShell* aPs, ComputedStyle
* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame(aPs, aStyle
); }, 0x8 | 0x200 | 0x400)}
,
4938 SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame){nsGkAtoms::feTurbulence, FrameConstructionData([](PresShell*
aPs, ComputedStyle* aStyle) -> nsIFrame* { return NS_NewSVGFELeafFrame
(aPs, aStyle); }, 0x8 | 0x200 | 0x400)}
};
4939
4940 const FrameConstructionData* data =
4941 FindDataByTag(aElement, aStyle, sSVGData, std::size(sSVGData));
4942
4943 if (!data) {
4944 data = &sContainerData;
4945 }
4946
4947 return data;
4948}
4949
4950void nsCSSFrameConstructor::AppendPageBreakItem(
4951 nsIContent* aContent, FrameConstructionItemList& aItems) {
4952 RefPtr<ComputedStyle> pseudoStyle =
4953 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
4954 PseudoStyleType::pageBreak);
4955
4956 MOZ_ASSERT(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay
::Block)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay
::Block))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
" (" "Unexpected display" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
") (" "Unexpected display" ")"); do { *((volatile int*)__null
) = 4957; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
4957 "Unexpected display")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay
::Block)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay
::Block))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
" (" "Unexpected display" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "pseudoStyle->StyleDisplay()->mDisplay == StyleDisplay::Block"
") (" "Unexpected display" ")"); do { *((volatile int*)__null
) = 4957; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
4958
4959 static constexpr FrameConstructionData sPageBreakData(NS_NewPageBreakFrame,
4960 FCDATA_SKIP_FRAMESET0x1);
4961 aItems.AppendItem(this, &sPageBreakData, aContent, pseudoStyle.forget(),
4962 true);
4963}
4964
4965bool nsCSSFrameConstructor::ShouldCreateItemsForChild(
4966 nsFrameConstructorState& aState, nsIContent* aContent,
4967 nsContainerFrame* aParentFrame) {
4968 aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
4969 // XXX the GetContent() != aContent check is needed due to bug 135040.
4970 // Remove it once that's fixed.
4971 if (aContent->GetPrimaryFrame() &&
4972 aContent->GetPrimaryFrame()->GetContent() == aContent &&
4973 !aState.mCreatingExtraFrames) {
4974 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "asked to create frame construction item for a node that "
"already has a frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4975 "asked to create frame construction item for a node that "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "asked to create frame construction item for a node that "
"already has a frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4976 "already has a frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "asked to create frame construction item for a node that "
"already has a frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 4976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"asked to create frame construction item for a node that " "already has a frame"
")"); do { *((volatile int*)__null) = 4976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4977 return false;
4978 }
4979
4980 // don't create a whitespace frame if aParent doesn't want it
4981 if (!NeedFrameFor(aState, aParentFrame, aContent)) {
4982 return false;
4983 }
4984
4985 // never create frames for comments or PIs
4986 if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
4987 return false;
4988 }
4989
4990 return true;
4991}
4992
4993void nsCSSFrameConstructor::AddFrameConstructionItems(
4994 nsFrameConstructorState& aState, nsIContent* aContent,
4995 bool aSuppressWhiteSpaceOptimizations, const ComputedStyle& aParentStyle,
4996 const InsertionPoint& aInsertion, FrameConstructionItemList& aItems,
4997 ItemFlags aFlags) {
4998 nsContainerFrame* parentFrame = aInsertion.mParentFrame;
4999 if (!ShouldCreateItemsForChild(aState, aContent, parentFrame)) {
5000 return;
5001 }
5002 if (MOZ_UNLIKELY(aParentStyle.StyleContent()->mContent.IsNone())(__builtin_expect(!!(aParentStyle.StyleContent()->mContent
.IsNone()), 0))
&&
5003 StaticPrefs::layout_css_element_content_none_enabled()) {
5004 return;
5005 }
5006
5007 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
5008 auto flags = aFlags + ItemFlag::AllowPageBreak;
5009 if (parentFrame) {
5010 if (parentFrame->IsInSVGTextSubtree()) {
5011 flags += ItemFlag::IsWithinSVGText;
5012 }
5013 if (parentFrame->IsBlockFrame() && parentFrame->GetParent() &&
5014 parentFrame->GetParent()->IsSVGTextFrame()) {
5015 flags += ItemFlag::AllowTextPathChild;
5016 }
5017 }
5018 AddFrameConstructionItemsInternal(aState, aContent, parentFrame,
5019 aSuppressWhiteSpaceOptimizations,
5020 computedStyle, flags, aItems);
5021}
5022
5023// Whether we should suppress frames for a child under a <select> frame.
5024//
5025// Never create frames for non-option/optgroup kids of <select> and non-option
5026// kids of <optgroup> inside a <select>.
5027static bool ShouldSuppressFrameInSelect(const nsIContent* aParent,
5028 const nsIContent& aChild) {
5029 if (!aParent ||
5030 !aParent->IsAnyOfHTMLElements(nsGkAtoms::select, nsGkAtoms::optgroup,
5031 nsGkAtoms::option)) {
5032 return false;
5033 }
5034
5035 // Allow native anonymous content no matter what.
5036 if (aChild.IsRootOfNativeAnonymousSubtree()) {
5037 return false;
5038 }
5039
5040 // Options with labels have their label text added in ::before by forms.css.
5041 // Suppress frames for their child text.
5042 if (aParent->IsHTMLElement(nsGkAtoms::option)) {
5043 return aParent->AsElement()->HasNonEmptyAttr(nsGkAtoms::label);
5044 }
5045
5046 // If we're in any display: contents subtree, just suppress the frame.
5047 //
5048 // We can't be regular NAC, since display: contents has no frame to generate
5049 // them off.
5050 if (aChild.GetParent() != aParent) {
5051 return true;
5052 }
5053
5054 // Option is always fine.
5055 if (aChild.IsHTMLElement(nsGkAtoms::option)) {
5056 return false;
5057 }
5058
5059 // <optgroup> is OK in <select> but not in <optgroup>.
5060 if (aChild.IsHTMLElement(nsGkAtoms::optgroup) &&
5061 aParent->IsHTMLElement(nsGkAtoms::select)) {
5062 return false;
5063 }
5064
5065 // Anything else is not ok.
5066 return true;
5067}
5068
5069const nsCSSFrameConstructor::FrameConstructionData*
5070nsCSSFrameConstructor::FindDataForContent(nsIContent& aContent,
5071 ComputedStyle& aStyle,
5072 nsIFrame* aParentFrame,
5073 ItemFlags aFlags) {
5074 MOZ_ASSERT(aStyle.StyleDisplay()->mDisplay != StyleDisplay::None &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyle.StyleDisplay()->mDisplay != StyleDisplay::
None && aStyle.StyleDisplay()->mDisplay != StyleDisplay
::Contents)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(aStyle.StyleDisplay()->mDisplay !=
StyleDisplay::None && aStyle.StyleDisplay()->mDisplay
!= StyleDisplay::Contents))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aStyle.StyleDisplay()->mDisplay != StyleDisplay::None && aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents"
" (" "These two special display values should be handled earlier"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyle.StyleDisplay()->mDisplay != StyleDisplay::None && aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents"
") (" "These two special display values should be handled earlier"
")"); do { *((volatile int*)__null) = 5076; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5075 aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyle.StyleDisplay()->mDisplay != StyleDisplay::
None && aStyle.StyleDisplay()->mDisplay != StyleDisplay
::Contents)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(aStyle.StyleDisplay()->mDisplay !=
StyleDisplay::None && aStyle.StyleDisplay()->mDisplay
!= StyleDisplay::Contents))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aStyle.StyleDisplay()->mDisplay != StyleDisplay::None && aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents"
" (" "These two special display values should be handled earlier"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyle.StyleDisplay()->mDisplay != StyleDisplay::None && aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents"
") (" "These two special display values should be handled earlier"
")"); do { *((volatile int*)__null) = 5076; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5076 "These two special display values should be handled earlier")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStyle.StyleDisplay()->mDisplay != StyleDisplay::
None && aStyle.StyleDisplay()->mDisplay != StyleDisplay
::Contents)>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(aStyle.StyleDisplay()->mDisplay !=
StyleDisplay::None && aStyle.StyleDisplay()->mDisplay
!= StyleDisplay::Contents))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aStyle.StyleDisplay()->mDisplay != StyleDisplay::None && aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents"
" (" "These two special display values should be handled earlier"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStyle.StyleDisplay()->mDisplay != StyleDisplay::None && aStyle.StyleDisplay()->mDisplay != StyleDisplay::Contents"
") (" "These two special display values should be handled earlier"
")"); do { *((volatile int*)__null) = 5076; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5077
5078 if (auto* text = Text::FromNode(aContent)) {
5079 return FindTextData(*text, aParentFrame);
5080 }
5081
5082 return FindElementData(*aContent.AsElement(), aStyle, aParentFrame, aFlags);
5083}
5084
5085const nsCSSFrameConstructor::FrameConstructionData*
5086nsCSSFrameConstructor::FindElementData(const Element& aElement,
5087 ComputedStyle& aStyle,
5088 nsIFrame* aParentFrame,
5089 ItemFlags aFlags) {
5090 // Don't create frames for non-SVG element children of SVG elements.
5091 if (!aElement.IsSVGElement()) {
5092 if (aParentFrame && IsFrameForSVG(aParentFrame) &&
5093 !aParentFrame->IsSVGForeignObjectFrame()) {
5094 return nullptr;
5095 }
5096 if (aFlags.contains(ItemFlag::IsWithinSVGText)) {
5097 return nullptr;
5098 }
5099 }
5100
5101 if (auto* data = FindElementTagData(aElement, aStyle, aParentFrame, aFlags)) {
5102 return data;
5103 }
5104
5105 // Check for 'content: <image-url>' on the element (which makes us ignore
5106 // 'display' values other than 'none' or 'contents').
5107 if (nsImageFrame::ShouldCreateImageFrameForContentProperty(aElement,
5108 aStyle)) {
5109 static constexpr FrameConstructionData sImgData(
5110 NS_NewImageFrameForContentProperty);
5111 return &sImgData;
5112 }
5113
5114 const bool shouldBlockify = aFlags.contains(ItemFlag::IsForRenderedLegend) ||
5115 aFlags.contains(ItemFlag::IsForOutsideMarker);
5116 if (shouldBlockify && !aStyle.StyleDisplay()->IsBlockOutsideStyle()) {
5117 // Make a temp copy of StyleDisplay and blockify its mDisplay value.
5118 auto display = *aStyle.StyleDisplay();
5119 bool isRootElement = false;
5120 uint16_t rawDisplayValue =
5121 Servo_ComputedValues_BlockifiedDisplay(&aStyle, isRootElement);
5122 display.mDisplay = StyleDisplay{rawDisplayValue};
5123 return FindDisplayData(display, aElement);
5124 }
5125
5126 const auto& display = *aStyle.StyleDisplay();
5127 return FindDisplayData(display, aElement);
5128}
5129
5130const nsCSSFrameConstructor::FrameConstructionData*
5131nsCSSFrameConstructor::FindElementTagData(const Element& aElement,
5132 ComputedStyle& aStyle,
5133 nsIFrame* aParentFrame,
5134 ItemFlags aFlags) {
5135 switch (aElement.GetNameSpaceID()) {
5136 case kNameSpaceID_XHTML3:
5137 return FindHTMLData(aElement, aParentFrame, aStyle);
5138 case kNameSpaceID_MathML6:
5139 return FindMathMLData(aElement, aStyle);
5140 case kNameSpaceID_SVG9:
5141 return FindSVGData(aElement, aParentFrame,
5142 aFlags.contains(ItemFlag::IsWithinSVGText),
5143 aFlags.contains(ItemFlag::AllowTextPathChild), aStyle);
5144 case kNameSpaceID_XUL8:
5145 return FindXULTagData(aElement, aStyle);
5146 default:
5147 return nullptr;
5148 }
5149}
5150
5151void nsCSSFrameConstructor::AddFrameConstructionItemsInternal(
5152 nsFrameConstructorState& aState, nsIContent* aContent,
5153 nsContainerFrame* aParentFrame, bool aSuppressWhiteSpaceOptimizations,
5154 ComputedStyle* aComputedStyle, ItemFlags aFlags,
5155 FrameConstructionItemList& aItems) {
5156 MOZ_ASSERT(aContent->IsText() || aContent->IsElement(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsText() || aContent->IsElement())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aContent->IsText() || aContent->IsElement())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent->IsText() || aContent->IsElement()"
" (" "Shouldn't get anything else here!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText() || aContent->IsElement()"
") (" "Shouldn't get anything else here!" ")"); do { *((volatile
int*)__null) = 5157; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5157 "Shouldn't get anything else here!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsText() || aContent->IsElement())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aContent->IsText() || aContent->IsElement())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent->IsText() || aContent->IsElement()"
" (" "Shouldn't get anything else here!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsText() || aContent->IsElement()"
") (" "Shouldn't get anything else here!" ")"); do { *((volatile
int*)__null) = 5157; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5158 MOZ_ASSERT(aContent->IsInComposedDoc())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsInComposedDoc())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent->IsInComposedDoc
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aContent->IsInComposedDoc()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5158); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsInComposedDoc()"
")"); do { *((volatile int*)__null) = 5158; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5159 MOZ_ASSERT(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aContent->NodeInfo()->NameAtom() == nsGkAtoms::area
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aContent->NodeInfo()->NameAtom() == nsGkAtoms::area
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
")"); do { *((volatile int*)__null) = 5160; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5160 aContent->NodeInfo()->NameAtom() == nsGkAtoms::area)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aContent->NodeInfo()->NameAtom() == nsGkAtoms::area
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames
|| aContent->NodeInfo()->NameAtom() == nsGkAtoms::area
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame() || aState.mCreatingExtraFrames || aContent->NodeInfo()->NameAtom() == nsGkAtoms::area"
")"); do { *((volatile int*)__null) = 5160; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5161
5162 const bool withinSVGText = aFlags.contains(ItemFlag::IsWithinSVGText);
5163 const bool isGeneratedContent = aFlags.contains(ItemFlag::IsGeneratedContent);
5164 MOZ_ASSERT(!isGeneratedContent || aComputedStyle->IsPseudoElement(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isGeneratedContent || aComputedStyle->IsPseudoElement
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!isGeneratedContent || aComputedStyle->IsPseudoElement
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!isGeneratedContent || aComputedStyle->IsPseudoElement()"
" (" "Generated content should be a pseudo-element" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isGeneratedContent || aComputedStyle->IsPseudoElement()"
") (" "Generated content should be a pseudo-element" ")"); do
{ *((volatile int*)__null) = 5165; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5165 "Generated content should be a pseudo-element")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isGeneratedContent || aComputedStyle->IsPseudoElement
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!isGeneratedContent || aComputedStyle->IsPseudoElement
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!isGeneratedContent || aComputedStyle->IsPseudoElement()"
" (" "Generated content should be a pseudo-element" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isGeneratedContent || aComputedStyle->IsPseudoElement()"
") (" "Generated content should be a pseudo-element" ")"); do
{ *((volatile int*)__null) = 5165; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5166
5167 FrameConstructionItem* item = nullptr;
5168 auto cleanupGeneratedContent = mozilla::MakeScopeExit([&]() {
5169 if (isGeneratedContent && !item) {
5170 MOZ_ASSERT(!IsDisplayContents(aContent),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDisplayContents(aContent))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDisplayContents(aContent)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsDisplayContents(aContent)" " (" "This would need to change if we support display: contents "
"in generated content" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5172; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
5171 "This would need to change if we support display: contents "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDisplayContents(aContent))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDisplayContents(aContent)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsDisplayContents(aContent)" " (" "This would need to change if we support display: contents "
"in generated content" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5172; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
5172 "in generated content")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDisplayContents(aContent))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDisplayContents(aContent)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!IsDisplayContents(aContent)" " (" "This would need to change if we support display: contents "
"in generated content" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDisplayContents(aContent)"
") (" "This would need to change if we support display: contents "
"in generated content" ")"); do { *((volatile int*)__null) =
5172; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
5173 aContent->UnbindFromTree();
5174 }
5175 });
5176
5177 // 'display:none' elements never creates any frames at all.
5178 const nsStyleDisplay& display = *aComputedStyle->StyleDisplay();
5179 if (display.mDisplay == StyleDisplay::None) {
5180 return;
5181 }
5182
5183 if (display.mDisplay == StyleDisplay::Contents) {
5184 // See the mDisplay fixup code in StyleAdjuster::adjust.
5185 MOZ_ASSERT(!aContent->AsElement()->IsRootOfNativeAnonymousSubtree(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aContent->AsElement()->IsRootOfNativeAnonymousSubtree
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aContent->AsElement()->IsRootOfNativeAnonymousSubtree
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
" (" "display:contents on anonymous content is unsupported" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
") (" "display:contents on anonymous content is unsupported"
")"); do { *((volatile int*)__null) = 5186; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5186 "display:contents on anonymous content is unsupported")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aContent->AsElement()->IsRootOfNativeAnonymousSubtree
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aContent->AsElement()->IsRootOfNativeAnonymousSubtree
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
" (" "display:contents on anonymous content is unsupported" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->AsElement()->IsRootOfNativeAnonymousSubtree()"
") (" "display:contents on anonymous content is unsupported"
")"); do { *((volatile int*)__null) = 5186; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5187
5188 // FIXME(bug 1588477): <svg:text>'s TextNodeCorrespondenceRecorder has
5189 // trouble with everything that looks like display: contents.
5190 if (withinSVGText) {
5191 return;
5192 }
5193
5194 CreateGeneratedContentItem(aState, aParentFrame, *aContent->AsElement(),
5195 *aComputedStyle, PseudoStyleType::before,
5196 aItems);
5197
5198 FlattenedChildIterator iter(aContent);
5199 InsertionPoint insertion(aParentFrame, aContent);
5200 for (nsIContent* child = iter.GetNextChild(); child;
5201 child = iter.GetNextChild()) {
5202 AddFrameConstructionItems(aState, child, aSuppressWhiteSpaceOptimizations,
5203 *aComputedStyle, insertion, aItems, aFlags);
5204 }
5205 aItems.SetParentHasNoShadowDOM(!iter.ShadowDOMInvolved());
5206
5207 CreateGeneratedContentItem(aState, aParentFrame, *aContent->AsElement(),
5208 *aComputedStyle, PseudoStyleType::after, aItems);
5209 return;
5210 }
5211
5212 nsIContent* parent = aParentFrame ? aParentFrame->GetContent() : nullptr;
5213 if (ShouldSuppressFrameInSelect(parent, *aContent)) {
5214 return;
5215 }
5216
5217 if (aContent->IsHTMLElement(nsGkAtoms::legend) && aParentFrame) {
5218 const nsFieldSetFrame* const fs = GetFieldSetFrameFor(aParentFrame);
5219 if (fs && !fs->GetLegend() && !aState.mHasRenderedLegend &&
5220 !aComputedStyle->StyleDisplay()->IsFloatingStyle() &&
5221 !aComputedStyle->StyleDisplay()->IsAbsolutelyPositionedStyle()) {
5222 aState.mHasRenderedLegend = true;
5223 aFlags += ItemFlag::IsForRenderedLegend;
5224 }
5225 }
5226
5227 const FrameConstructionData* const data =
5228 FindDataForContent(*aContent, *aComputedStyle, aParentFrame, aFlags);
5229 if (!data || data->mBits & FCDATA_SUPPRESS_FRAME0x40) {
5230 return;
5231 }
5232
5233 const bool isPopup = data->mBits & FCDATA_IS_POPUP0x100;
5234
5235 const uint32_t bits = data->mBits;
5236
5237 // Inside colgroups, suppress everything except columns.
5238 if (aParentFrame && aParentFrame->IsTableColGroupFrame() &&
5239 (!(bits & FCDATA_IS_TABLE_PART0x800) ||
5240 display.mDisplay != StyleDisplay::TableColumn)) {
5241 return;
5242 }
5243
5244 const bool canHavePageBreak =
5245 aFlags.contains(ItemFlag::AllowPageBreak) &&
5246 aState.mPresContext->IsPaginated() &&
5247 !display.IsAbsolutelyPositionedStyle() &&
5248 !(aParentFrame && aParentFrame->IsFlexOrGridContainer()) &&
5249 !(bits & FCDATA_IS_TABLE_PART0x800) && !(bits & FCDATA_IS_SVG_TEXT0x80000);
5250 if (canHavePageBreak && display.BreakBefore()) {
5251 AppendPageBreakItem(aContent, aItems);
5252 }
5253
5254 if (!item) {
5255 item = aItems.AppendItem(this, data, aContent, do_AddRef(aComputedStyle),
5256 aSuppressWhiteSpaceOptimizations);
5257 if (aFlags.contains(ItemFlag::IsForRenderedLegend)) {
5258 item->mIsRenderedLegend = true;
5259 }
5260 }
5261 item->mIsText = !aContent->IsElement();
5262 item->mIsGeneratedContent = isGeneratedContent;
5263 if (isGeneratedContent) {
5264 // We need to keep this alive until the frame takes ownership.
5265 // This corresponds to the Release in ConstructFramesFromItem.
5266 item->mContent->AddRef();
5267 }
5268 item->mIsPopup = isPopup;
5269
5270 if (canHavePageBreak && display.BreakAfter()) {
5271 AppendPageBreakItem(aContent, aItems);
5272 }
5273
5274 if (bits & FCDATA_IS_INLINE0x1000) {
5275 // To correctly set item->mIsAllInline we need to build up our child items
5276 // right now.
5277 BuildInlineChildItems(aState, *item,
5278 aFlags.contains(ItemFlag::IsWithinSVGText),
5279 aFlags.contains(ItemFlag::AllowTextPathChild));
5280 item->mIsBlock = false;
5281 } else {
5282 // Compute a boolean isInline which is guaranteed to be false for blocks
5283 // (but may also be false for some inlines).
5284 const bool isInline =
5285 // Table-internal things are inline-outside if and only if they're kids
5286 // of inlines, since they'll trigger construction of inline-table
5287 // pseudos.
5288 ((bits & FCDATA_IS_TABLE_PART0x800) &&
5289 (!aParentFrame || // No aParentFrame means inline
5290 aParentFrame->StyleDisplay()->IsInlineFlow())) ||
5291 // Things that are inline-outside but aren't inline frames are inline
5292 display.IsInlineOutsideStyle() ||
5293 // Popups that are certainly out of flow.
5294 isPopup;
5295
5296 // Set mIsAllInline conservatively. It just might be that even an inline
5297 // that has mIsAllInline false doesn't need an {ib} split. So this is just
5298 // an optimization to keep from doing too much work in cases when we can
5299 // show that mIsAllInline is true..
5300 item->mIsAllInline =
5301 isInline ||
5302 // Figure out whether we're guaranteed this item will be out of flow.
5303 // This is not a precise test, since one of our ancestor inlines might
5304 // add an absolute containing block (if it's relatively positioned) when
5305 // there wasn't such a containing block before. But it's conservative
5306 // in the sense that anything that will really end up as an in-flow
5307 // non-inline will test false here. In other words, if this test is
5308 // true we're guaranteed to be inline; if it's false we don't know what
5309 // we'll end up as.
5310 //
5311 // If we make this test precise, we can remove some of the code dealing
5312 // with the imprecision in ConstructInline and adjust the comments on
5313 // mIsAllInline and mIsBlock in the header.
5314 (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW0x8) &&
5315 aState.GetGeometricParent(display, nullptr));
5316
5317 // Set mIsBlock conservatively. It's OK to set it false for some real
5318 // blocks, but not OK to set it true for things that aren't blocks. Since
5319 // isOutOfFlow might be false even in cases when the frame will end up
5320 // out-of-flow, we can't use it here. But we _can_ say that the frame will
5321 // for sure end up in-flow if it's not floated or absolutely positioned.
5322 item->mIsBlock = !isInline && !display.IsAbsolutelyPositionedStyle() &&
5323 !display.IsFloatingStyle() && !(bits & FCDATA_IS_SVG_TEXT0x80000);
5324 }
5325
5326 if (item->mIsAllInline) {
5327 aItems.InlineItemAdded();
5328 } else if (item->mIsBlock) {
5329 aItems.BlockItemAdded();
5330 }
5331}
5332
5333/**
5334 * Return true if the frame construction item pointed to by aIter will
5335 * create a frame adjacent to a line boundary in the frame tree, and that
5336 * line boundary is induced by a content node adjacent to the frame's
5337 * content node in the content tree. The latter condition is necessary so
5338 * that ContentAppended/ContentInserted/ContentWillBeRemoved can easily find any
5339 * text nodes that were suppressed here.
5340 */
5341bool nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter) {
5342 if (aIter.item().mSuppressWhiteSpaceOptimizations) {
5343 return false;
5344 }
5345
5346 if (aIter.AtStart()) {
5347 if (aIter.List()->HasLineBoundaryAtStart() &&
5348 !aIter.item().mContent->GetPreviousSibling()) {
5349 return true;
5350 }
5351 } else {
5352 FCItemIterator prev = aIter;
5353 prev.Prev();
5354 if (prev.item().IsLineBoundary() &&
5355 !prev.item().mSuppressWhiteSpaceOptimizations &&
5356 aIter.item().mContent->GetPreviousSibling() == prev.item().mContent) {
5357 return true;
5358 }
5359 }
5360
5361 FCItemIterator next = aIter;
5362 next.Next();
5363 if (next.IsDone()) {
5364 if (aIter.List()->HasLineBoundaryAtEnd() &&
5365 !aIter.item().mContent->GetNextSibling()) {
5366 return true;
5367 }
5368 } else {
5369 if (next.item().IsLineBoundary() &&
5370 !next.item().mSuppressWhiteSpaceOptimizations &&
5371 aIter.item().mContent->GetNextSibling() == next.item().mContent) {
5372 return true;
5373 }
5374 }
5375
5376 return false;
5377}
5378
5379void nsCSSFrameConstructor::ConstructFramesFromItem(
5380 nsFrameConstructorState& aState, FCItemIterator& aIter,
5381 nsContainerFrame* aParentFrame, nsFrameList& aFrameList) {
5382 FrameConstructionItem& item = aIter.item();
5383 ComputedStyle* computedStyle = item.mComputedStyle;
5384 if (item.mIsText) {
5385 // If this is collapsible whitespace next to a line boundary,
5386 // don't create a frame. item.IsWhitespace() also sets the
5387 // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
5388 // end up creating a frame, nsTextFrame::Init will clear the flag.)
5389 // We don't do this for generated content, because some generated
5390 // text content is empty text nodes that are about to be initialized.
5391 // (We check mAdditionalStateBits because only the generated content
5392 // container's frame construction item is marked with
5393 // mIsGeneratedContent, and we might not have an aParentFrame.)
5394 // We don't do it for content that may have Shadow DOM siblings / insertion
5395 // points, because they make it difficult to correctly create the frame due
5396 // to dynamic changes.
5397 // We don't do it for SVG text, since we might need to position and
5398 // measure the white space glyphs due to x/y/dx/dy attributes.
5399 if (AtLineBoundary(aIter) &&
5400 !computedStyle->StyleText()->WhiteSpaceOrNewlineIsSignificant() &&
5401 aIter.List()->ParentHasNoShadowDOM() &&
5402 !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
5403 (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT0x2000) &&
5404 !(item.mFCData->mBits & FCDATA_IS_SVG_TEXT0x80000) &&
5405 !mAlwaysCreateFramesForIgnorableWhitespace &&
5406 item.IsWhitespace(aState)) {
5407 return;
5408 }
5409
5410 ConstructTextFrame(item.mFCData, aState, item.mContent, aParentFrame,
5411 computedStyle, aFrameList);
5412 return;
5413 }
5414
5415 AutoRestore<nsFrameState> savedStateBits(aState.mAdditionalStateBits);
5416 if (item.mIsGeneratedContent) {
5417 // Ensure that frames created here are all tagged with
5418 // NS_FRAME_GENERATED_CONTENT.
5419 aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
5420 }
5421
5422 // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
5423 ConstructFrameFromItemInternal(item, aState, aParentFrame, aFrameList);
5424
5425 if (item.mIsGeneratedContent) {
5426 // This corresponds to the AddRef in AddFrameConstructionItemsInternal.
5427 // The frame owns the generated content now.
5428 item.mContent->Release();
5429
5430 // Now that we've passed ownership of item.mContent to the frame, unset
5431 // our generated content flag so we don't release or unbind it ourselves.
5432 item.mIsGeneratedContent = false;
5433 }
5434}
5435
5436nsContainerFrame* nsCSSFrameConstructor::GetAbsoluteContainingBlock(
5437 nsIFrame* aFrame, ContainingBlockType aType) {
5438 // Starting with aFrame, look for a frame that is absolutely positioned or
5439 // relatively positioned (and transformed, if aType is FIXED)
5440 for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
5441 if (frame->IsMathMLFrame()) {
5442 // If it's mathml, bail out -- no absolute positioning out from inside
5443 // mathml frames. Note that we don't make this part of the loop
5444 // condition because of the stuff at the end of this method...
5445 return nullptr;
5446 }
5447
5448 // Look for the ICB.
5449 if (aType == FIXED_POS) {
5450 LayoutFrameType t = frame->Type();
5451 if (t == LayoutFrameType::Viewport || t == LayoutFrameType::PageContent) {
5452 return static_cast<nsContainerFrame*>(frame);
5453 }
5454 }
5455
5456 // If the frame is positioned, we will probably return it as the containing
5457 // block (see the exceptions below). Otherwise, we'll start looking at the
5458 // parent frame, unless we're dealing with a scrollframe.
5459 // Scrollframes are special since they're not positioned, but their
5460 // scrolledframe might be. So, we need to check this special case to return
5461 // the correct containing block (the scrolledframe) in that case.
5462 // If we're looking for a fixed-pos containing block and the frame is
5463 // not transformed, skip it.
5464 if (!frame->IsAbsPosContainingBlock()) {
5465 continue;
5466 }
5467 if (aType == FIXED_POS && !frame->IsFixedPosContainingBlock()) {
5468 continue;
5469 }
5470 nsIFrame* absPosCBCandidate = frame;
5471 LayoutFrameType type = absPosCBCandidate->Type();
5472 if (type == LayoutFrameType::FieldSet) {
5473 absPosCBCandidate =
5474 static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
5475 if (!absPosCBCandidate) {
5476 continue;
5477 }
5478 type = absPosCBCandidate->Type();
5479 }
5480 if (type == LayoutFrameType::ScrollContainer) {
5481 ScrollContainerFrame* scrollContainerFrame =
5482 do_QueryFrame(absPosCBCandidate);
5483 absPosCBCandidate = scrollContainerFrame->GetScrolledFrame();
5484 if (!absPosCBCandidate) {
5485 continue;
5486 }
5487 type = absPosCBCandidate->Type();
5488 }
5489 // Only first continuations can be containing blocks.
5490 absPosCBCandidate = absPosCBCandidate->FirstContinuation();
5491 // Is the frame really an absolute container?
5492 if (!absPosCBCandidate->IsAbsoluteContainer()) {
5493 continue;
5494 }
5495
5496 // For tables, skip the inner frame and consider the table wrapper frame.
5497 if (type == LayoutFrameType::Table) {
5498 continue;
5499 }
5500 // For table wrapper frames, we can just return absPosCBCandidate.
5501 MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(absPosCBCandidate),do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nsContainerFrame*)do_QueryFrame(absPosCBCandidate))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nsContainerFrame*)do_QueryFrame(absPosCBCandidate))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
" (" "abs.pos. containing block must be nsContainerFrame sub-class"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
") (" "abs.pos. containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5502; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5502 "abs.pos. containing block must be nsContainerFrame sub-class")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nsContainerFrame*)do_QueryFrame(absPosCBCandidate))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nsContainerFrame*)do_QueryFrame(absPosCBCandidate))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
" (" "abs.pos. containing block must be nsContainerFrame sub-class"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(absPosCBCandidate)"
") (" "abs.pos. containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5502; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5503 return static_cast<nsContainerFrame*>(absPosCBCandidate);
5504 }
5505
5506 MOZ_ASSERT(aType != FIXED_POS, "no ICB in this frame tree?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aType != FIXED_POS)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aType != FIXED_POS))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aType != FIXED_POS"
" (" "no ICB in this frame tree?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aType != FIXED_POS"
") (" "no ICB in this frame tree?" ")"); do { *((volatile int
*)__null) = 5506; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5507
5508 // It is possible for the search for the containing block to fail, because
5509 // no absolute container can be found in the parent chain. In those cases,
5510 // we fall back to the document element's containing block.
5511 return mDocElementContainingBlock;
5512}
5513
5514nsContainerFrame* nsCSSFrameConstructor::GetFloatContainingBlock(
5515 nsIFrame* aFrame) {
5516 // Starting with aFrame, look for a frame that is a float containing block.
5517 // If we hit a frame which prevents its descendants from floating, bail out.
5518 // The logic here needs to match the logic in MaybePushFloatContainingBlock().
5519 for (nsIFrame* containingBlock = aFrame;
5520 containingBlock && !ShouldSuppressFloatingOfDescendants(containingBlock);
5521 containingBlock = containingBlock->GetParent()) {
5522 if (containingBlock->IsFloatContainingBlock()) {
5523 MOZ_ASSERT((nsContainerFrame*)do_QueryFrame(containingBlock),do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nsContainerFrame*)do_QueryFrame(containingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nsContainerFrame*)do_QueryFrame(containingBlock))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("(nsContainerFrame*)do_QueryFrame(containingBlock)"
" (" "float containing block must be nsContainerFrame sub-class"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(containingBlock)"
") (" "float containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5524; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5524 "float containing block must be nsContainerFrame sub-class")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((nsContainerFrame*)do_QueryFrame(containingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((nsContainerFrame*)do_QueryFrame(containingBlock))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("(nsContainerFrame*)do_QueryFrame(containingBlock)"
" (" "float containing block must be nsContainerFrame sub-class"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(nsContainerFrame*)do_QueryFrame(containingBlock)"
") (" "float containing block must be nsContainerFrame sub-class"
")"); do { *((volatile int*)__null) = 5524; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5525 return static_cast<nsContainerFrame*>(containingBlock);
5526 }
5527 }
5528
5529 // If we didn't find a containing block, then there just isn't
5530 // one.... return null
5531 return nullptr;
5532}
5533
5534/**
5535 * This function will get the previous sibling to use for an append operation.
5536 *
5537 * It takes a parent frame (must not be null) and the next insertion sibling, if
5538 * the parent content is display: contents or has ::after content (may be null).
5539 */
5540static nsIFrame* FindAppendPrevSibling(nsIFrame* aParentFrame,
5541 nsIFrame* aNextSibling) {
5542 aParentFrame->DrainSelfOverflowList();
5543
5544 if (aNextSibling) {
5545 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNextSibling->GetParent()->GetContentInsertionFrame
() == aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNextSibling->GetParent()
->GetContentInsertionFrame() == aParentFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
" (" "Wrong parent" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5547
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
5546 aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNextSibling->GetParent()->GetContentInsertionFrame
() == aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNextSibling->GetParent()
->GetContentInsertionFrame() == aParentFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
" (" "Wrong parent" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5547
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
5547 "Wrong parent")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNextSibling->GetParent()->GetContentInsertionFrame
() == aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNextSibling->GetParent()
->GetContentInsertionFrame() == aParentFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
" (" "Wrong parent" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNextSibling->GetParent()->GetContentInsertionFrame() == aParentFrame"
") (" "Wrong parent" ")"); do { *((volatile int*)__null) = 5547
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
5548 return aNextSibling->GetPrevSibling();
5549 }
5550
5551 return aParentFrame->PrincipalChildList().LastChild();
5552}
5553
5554/**
5555 * Finds the right parent frame to append content to aParentFrame.
5556 *
5557 * Cannot return or receive null.
5558 */
5559static nsContainerFrame* ContinuationToAppendTo(
5560 nsContainerFrame* aParentFrame) {
5561 MOZ_ASSERT(aParentFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParentFrame))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aParentFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame"
")"); do { *((volatile int*)__null) = 5561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5562
5563 if (IsFramePartOfIBSplit(aParentFrame)) {
5564 // If the frame we are manipulating is a ib-split frame (that is, one that's
5565 // been created as a result of a block-in-inline situation) then we need to
5566 // append to the last ib-split sibling, not to the frame itself.
5567 //
5568 // Always make sure to look at the last continuation of the frame for the
5569 // {ib} case, even if that continuation is empty.
5570 //
5571 // We don't do this for the non-ib-split-frame case, since in the other
5572 // cases appending to the last nonempty continuation is fine and in fact not
5573 // doing that can confuse code that doesn't know to pull kids from
5574 // continuations other than its next one.
5575 return static_cast<nsContainerFrame*>(
5576 GetLastIBSplitSibling(aParentFrame)->LastContinuation());
5577 }
5578
5579 return nsLayoutUtils::LastContinuationWithChild(aParentFrame);
5580}
5581
5582/**
5583 * This function will get the next sibling for a frame insert operation given
5584 * the parent and previous sibling. aPrevSibling may be null.
5585 */
5586static nsIFrame* GetInsertNextSibling(nsIFrame* aParentFrame,
5587 nsIFrame* aPrevSibling) {
5588 if (aPrevSibling) {
5589 return aPrevSibling->GetNextSibling();
5590 }
5591
5592 return aParentFrame->PrincipalChildList().FirstChild();
5593}
5594
5595void nsCSSFrameConstructor::AppendFramesToParent(
5596 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
5597 nsFrameList& aFrameList, nsIFrame* aPrevSibling, bool aIsRecursiveCall) {
5598 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling
(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList
().FirstChild())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame
)->PrincipalChildList().FirstChild()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
" (" "aParentFrame has a ib-split sibling with kids?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5599 !IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling
(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList
().FirstChild())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame
)->PrincipalChildList().FirstChild()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
" (" "aParentFrame has a ib-split sibling with kids?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5600 !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling
(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList
().FirstChild())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame
)->PrincipalChildList().FirstChild()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
" (" "aParentFrame has a ib-split sibling with kids?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5601 "aParentFrame has a ib-split sibling with kids?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling
(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList
().FirstChild())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame
)->PrincipalChildList().FirstChild()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
" (" "aParentFrame has a ib-split sibling with kids?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame) || !GetIBSplitSibling(aParentFrame) || !GetIBSplitSibling(aParentFrame)->PrincipalChildList().FirstChild()"
") (" "aParentFrame has a ib-split sibling with kids?" ")");
do { *((volatile int*)__null) = 5601; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5602 MOZ_ASSERT(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
" (" "Parent and prevsibling don't match" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
") (" "Parent and prevsibling don't match" ")"); do { *((volatile
int*)__null) = 5603; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5603 "Parent and prevsibling don't match")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
" (" "Parent and prevsibling don't match" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrevSibling || aPrevSibling->GetParent() == aParentFrame"
") (" "Parent and prevsibling don't match" ")"); do { *((volatile
int*)__null) = 5603; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5604 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
) || !IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aParentFrame->HasAnyStateBits
(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit
(aParentFrame)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
" (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")"); do { *((volatile int*)__null
) = 5608; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5605 !aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
) || !IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aParentFrame->HasAnyStateBits
(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit
(aParentFrame)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
" (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")"); do { *((volatile int*)__null
) = 5608; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5606 !IsFramePartOfIBSplit(aParentFrame),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
) || !IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aParentFrame->HasAnyStateBits
(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit
(aParentFrame)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
" (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")"); do { *((volatile int*)__null
) = 5608; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5607 "We should have wiped aParentFrame in WipeContainingBlock() "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
) || !IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aParentFrame->HasAnyStateBits
(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit
(aParentFrame)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
" (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")"); do { *((volatile int*)__null
) = 5608; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
5608 "if it's part of an IB split!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR
) || !IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aParentFrame->HasAnyStateBits
(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit
(aParentFrame)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
" (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) || !IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock() "
"if it's part of an IB split!" ")"); do { *((volatile int*)__null
) = 5608; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
5609
5610 nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
5611
5612 NS_ASSERTION(nextSibling || !aParentFrame->GetNextContinuation() ||do { if (!(nextSibling || !aParentFrame->GetNextContinuation
() || !aParentFrame->GetNextContinuation() ->PrincipalChildList
() .FirstChild() || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aParentFrame has later continuations with kids?", "nextSibling || !aParentFrame->GetNextContinuation() || !aParentFrame->GetNextContinuation() ->PrincipalChildList() .FirstChild() || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5617); MOZ_PretendNoReturn(); } } while (0)
5613 !aParentFrame->GetNextContinuation()do { if (!(nextSibling || !aParentFrame->GetNextContinuation
() || !aParentFrame->GetNextContinuation() ->PrincipalChildList
() .FirstChild() || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aParentFrame has later continuations with kids?", "nextSibling || !aParentFrame->GetNextContinuation() || !aParentFrame->GetNextContinuation() ->PrincipalChildList() .FirstChild() || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5617); MOZ_PretendNoReturn(); } } while (0)
5614 ->PrincipalChildList()do { if (!(nextSibling || !aParentFrame->GetNextContinuation
() || !aParentFrame->GetNextContinuation() ->PrincipalChildList
() .FirstChild() || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aParentFrame has later continuations with kids?", "nextSibling || !aParentFrame->GetNextContinuation() || !aParentFrame->GetNextContinuation() ->PrincipalChildList() .FirstChild() || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5617); MOZ_PretendNoReturn(); } } while (0)
5615 .FirstChild() ||do { if (!(nextSibling || !aParentFrame->GetNextContinuation
() || !aParentFrame->GetNextContinuation() ->PrincipalChildList
() .FirstChild() || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aParentFrame has later continuations with kids?", "nextSibling || !aParentFrame->GetNextContinuation() || !aParentFrame->GetNextContinuation() ->PrincipalChildList() .FirstChild() || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5617); MOZ_PretendNoReturn(); } } while (0)
5616 aIsRecursiveCall,do { if (!(nextSibling || !aParentFrame->GetNextContinuation
() || !aParentFrame->GetNextContinuation() ->PrincipalChildList
() .FirstChild() || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aParentFrame has later continuations with kids?", "nextSibling || !aParentFrame->GetNextContinuation() || !aParentFrame->GetNextContinuation() ->PrincipalChildList() .FirstChild() || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5617); MOZ_PretendNoReturn(); } } while (0)
5617 "aParentFrame has later continuations with kids?")do { if (!(nextSibling || !aParentFrame->GetNextContinuation
() || !aParentFrame->GetNextContinuation() ->PrincipalChildList
() .FirstChild() || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aParentFrame has later continuations with kids?", "nextSibling || !aParentFrame->GetNextContinuation() || !aParentFrame->GetNextContinuation() ->PrincipalChildList() .FirstChild() || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5617); MOZ_PretendNoReturn(); } } while (0)
;
5618 NS_ASSERTION(do { if (!(nextSibling || !IsFramePartOfIBSplit(aParentFrame)
|| (IsInlineFrame(aParentFrame) && !GetIBSplitSibling
(aParentFrame) && !aParentFrame->GetNextContinuation
()) || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"aParentFrame is not last?", "nextSibling || !IsFramePartOfIBSplit(aParentFrame) || (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) && !aParentFrame->GetNextContinuation()) || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5623); MOZ_PretendNoReturn(); } } while (0)
5619 nextSibling || !IsFramePartOfIBSplit(aParentFrame) ||do { if (!(nextSibling || !IsFramePartOfIBSplit(aParentFrame)
|| (IsInlineFrame(aParentFrame) && !GetIBSplitSibling
(aParentFrame) && !aParentFrame->GetNextContinuation
()) || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"aParentFrame is not last?", "nextSibling || !IsFramePartOfIBSplit(aParentFrame) || (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) && !aParentFrame->GetNextContinuation()) || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5623); MOZ_PretendNoReturn(); } } while (0)
5620 (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) &&do { if (!(nextSibling || !IsFramePartOfIBSplit(aParentFrame)
|| (IsInlineFrame(aParentFrame) && !GetIBSplitSibling
(aParentFrame) && !aParentFrame->GetNextContinuation
()) || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"aParentFrame is not last?", "nextSibling || !IsFramePartOfIBSplit(aParentFrame) || (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) && !aParentFrame->GetNextContinuation()) || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5623); MOZ_PretendNoReturn(); } } while (0)
5621 !aParentFrame->GetNextContinuation()) ||do { if (!(nextSibling || !IsFramePartOfIBSplit(aParentFrame)
|| (IsInlineFrame(aParentFrame) && !GetIBSplitSibling
(aParentFrame) && !aParentFrame->GetNextContinuation
()) || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"aParentFrame is not last?", "nextSibling || !IsFramePartOfIBSplit(aParentFrame) || (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) && !aParentFrame->GetNextContinuation()) || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5623); MOZ_PretendNoReturn(); } } while (0)
5622 aIsRecursiveCall,do { if (!(nextSibling || !IsFramePartOfIBSplit(aParentFrame)
|| (IsInlineFrame(aParentFrame) && !GetIBSplitSibling
(aParentFrame) && !aParentFrame->GetNextContinuation
()) || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"aParentFrame is not last?", "nextSibling || !IsFramePartOfIBSplit(aParentFrame) || (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) && !aParentFrame->GetNextContinuation()) || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5623); MOZ_PretendNoReturn(); } } while (0)
5623 "aParentFrame is not last?")do { if (!(nextSibling || !IsFramePartOfIBSplit(aParentFrame)
|| (IsInlineFrame(aParentFrame) && !GetIBSplitSibling
(aParentFrame) && !aParentFrame->GetNextContinuation
()) || aIsRecursiveCall)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"aParentFrame is not last?", "nextSibling || !IsFramePartOfIBSplit(aParentFrame) || (IsInlineFrame(aParentFrame) && !GetIBSplitSibling(aParentFrame) && !aParentFrame->GetNextContinuation()) || aIsRecursiveCall"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5623); MOZ_PretendNoReturn(); } } while (0)
;
5624
5625 // If we're inserting a list of frames at the end of the trailing inline
5626 // of an {ib} split, we may need to create additional {ib} siblings to parent
5627 // them.
5628 if (!nextSibling && IsFramePartOfIBSplit(aParentFrame)) {
5629 // When we get here, our frame list might start with a block. If it does
5630 // so, and aParentFrame is an inline, and it and all its previous
5631 // continuations have no siblings, then put the initial blocks from the
5632 // frame list into the previous block of the {ib} split. Note that we
5633 // didn't want to stop at the block part of the split when figuring out
5634 // initial parent, because that could screw up float parenting; it's easier
5635 // to do this little fixup here instead.
5636 if (aFrameList.NotEmpty() && aFrameList.FirstChild()->IsBlockOutside()) {
5637 // See whether our trailing inline is empty
5638 nsIFrame* firstContinuation = aParentFrame->FirstContinuation();
5639 if (firstContinuation->PrincipalChildList().IsEmpty()) {
5640 // Our trailing inline is empty. Collect our starting blocks from
5641 // aFrameList, get the right parent frame for them, and put them in.
5642 nsFrameList blockKids =
5643 aFrameList.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
5644 NS_ASSERTION(blockKids.NotEmpty(), "No blocks?")do { if (!(blockKids.NotEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "No blocks?", "blockKids.NotEmpty()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5644); MOZ_PretendNoReturn(); } } while (0)
;
5645
5646 nsContainerFrame* prevBlock = GetIBSplitPrevSibling(firstContinuation);
5647 prevBlock =
5648 static_cast<nsContainerFrame*>(prevBlock->LastContinuation());
5649 NS_ASSERTION(prevBlock, "Should have previous block here")do { if (!(prevBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Should have previous block here"
, "prevBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5649); MOZ_PretendNoReturn(); } } while (0)
;
5650
5651 MoveChildrenTo(aParentFrame, prevBlock, blockKids);
5652 }
5653 }
5654
5655 // We want to put some of the frames into this inline frame.
5656 nsFrameList inlineKids =
5657 aFrameList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
5658
5659 if (!inlineKids.IsEmpty()) {
5660 AppendFrames(aParentFrame, FrameChildListID::Principal,
5661 std::move(inlineKids));
5662 }
5663
5664 if (!aFrameList.IsEmpty()) {
5665 nsFrameList ibSiblings;
5666 CreateIBSiblings(aState, aParentFrame,
5667 aParentFrame->IsAbsPosContainingBlock(), aFrameList,
5668 ibSiblings);
5669
5670 // Make sure to trigger reflow of the inline that used to be our
5671 // last one and now isn't anymore, since its GetSkipSides() has
5672 // changed.
5673 mPresShell->FrameNeedsReflow(aParentFrame,
5674 IntrinsicDirty::FrameAndAncestors,
5675 NS_FRAME_HAS_DIRTY_CHILDREN);
5676
5677 // Recurse so we create new ib siblings as needed for aParentFrame's
5678 // parent
5679 return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
5680 aParentFrame, true);
5681 }
5682 return;
5683 }
5684
5685 // If we're appending a list of frames to the last continuations of a
5686 // ::-moz-column-content, we may need to create column-span siblings for them.
5687 if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
5688 // Extract any initial non-column-span kids, and append them to
5689 // ::-moz-column-content's child list.
5690 nsFrameList initialNonColumnSpanKids =
5691 aFrameList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
5692 AppendFrames(aParentFrame, FrameChildListID::Principal,
5693 std::move(initialNonColumnSpanKids));
5694
5695 if (aFrameList.IsEmpty()) {
5696 // No more kids to process (there weren't any column-span kids).
5697 return;
5698 }
5699
5700 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
5701 aState, aParentFrame, aFrameList,
5702 // Column content should never be a absolute/fixed positioned containing
5703 // block. Pass nullptr as aPositionedFrame.
5704 nullptr);
5705
5706 nsContainerFrame* columnSetWrapper = aParentFrame->GetParent();
5707 while (!columnSetWrapper->IsColumnSetWrapperFrame()) {
5708 columnSetWrapper = columnSetWrapper->GetParent();
5709 }
5710 MOZ_ASSERT(columnSetWrapper,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(columnSetWrapper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(columnSetWrapper))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("columnSetWrapper"
" (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSetWrapper"
") (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")"); do { *((volatile int*)__null) = 5711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5711 "No ColumnSetWrapperFrame ancestor for -moz-column-content?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(columnSetWrapper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(columnSetWrapper))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("columnSetWrapper"
" (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSetWrapper"
") (" "No ColumnSetWrapperFrame ancestor for -moz-column-content?"
")"); do { *((volatile int*)__null) = 5711; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5712
5713 FinishBuildingColumns(aState, columnSetWrapper, aParentFrame,
5714 columnSpanSiblings);
5715
5716 MOZ_ASSERT(columnSpanSiblings.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(columnSpanSiblings.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(columnSpanSiblings.IsEmpty()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"columnSpanSiblings.IsEmpty()" " (" "The column-span siblings should be moved to the proper place!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 5717; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5717 "The column-span siblings should be moved to the proper place!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(columnSpanSiblings.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(columnSpanSiblings.IsEmpty()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"columnSpanSiblings.IsEmpty()" " (" "The column-span siblings should be moved to the proper place!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 5717; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5718 return;
5719 }
5720
5721 // Insert the frames after our aPrevSibling
5722 InsertFrames(aParentFrame, FrameChildListID::Principal, aPrevSibling,
5723 std::move(aFrameList));
5724}
5725
5726// This gets called to see if the frames corresponding to aSibling and aContent
5727// should be siblings in the frame tree. Although (1) rows and cols, (2) row
5728// groups and col groups, (3) row groups and captions, (4) legends and content
5729// inside fieldsets, (5) popups and other kids of the menu are siblings from a
5730// content perspective, they are not considered siblings in the frame tree.
5731bool nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
5732 nsIContent* aContent,
5733 Maybe<StyleDisplay>& aDisplay) {
5734 StyleDisplay siblingDisplay = aSibling->GetDisplay();
5735 if (StyleDisplay::TableColumnGroup == siblingDisplay ||
5736 StyleDisplay::TableColumn == siblingDisplay ||
5737 StyleDisplay::TableCaption == siblingDisplay ||
5738 StyleDisplay::TableHeaderGroup == siblingDisplay ||
5739 StyleDisplay::TableRowGroup == siblingDisplay ||
5740 StyleDisplay::TableFooterGroup == siblingDisplay) {
5741 // if we haven't already, resolve a style to find the display type of
5742 // aContent.
5743 if (aDisplay.isNothing()) {
5744 if (aContent->IsComment() || aContent->IsProcessingInstruction()) {
5745 // Comments and processing instructions never have frames, so we should
5746 // not try to generate styles for them.
5747 return false;
5748 }
5749 // FIXME(emilio): This is buggy some times, see bug 1424656.
5750 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(aContent);
5751 const nsStyleDisplay* display = computedStyle->StyleDisplay();
5752 aDisplay.emplace(display->mDisplay);
5753 }
5754
5755 StyleDisplay display = aDisplay.value();
5756 // To have decent performance we want to return false in cases in which
5757 // reordering the two siblings has no effect on display. To ensure
5758 // correctness, we MUST return false in cases where the two siblings have
5759 // the same desired parent type and live on different display lists.
5760 // Specificaly, columns and column groups should only consider columns and
5761 // column groups as valid siblings. Captions should only consider other
5762 // captions. All other things should consider each other as valid
5763 // siblings. The restriction in the |if| above on siblingDisplay is ok,
5764 // because for correctness the only part that really needs to happen is to
5765 // not consider captions, column groups, and row/header/footer groups
5766 // siblings of each other. Treating a column or colgroup as a valid
5767 // sibling of a non-table-related frame will just mean we end up reframing.
5768 if ((siblingDisplay == StyleDisplay::TableCaption) !=
5769 (display == StyleDisplay::TableCaption)) {
5770 // One's a caption and the other is not. Not valid siblings.
5771 return false;
5772 }
5773
5774 if ((siblingDisplay == StyleDisplay::TableColumnGroup ||
5775 siblingDisplay == StyleDisplay::TableColumn) !=
5776 (display == StyleDisplay::TableColumnGroup ||
5777 display == StyleDisplay::TableColumn)) {
5778 // One's a column or column group and the other is not. Not valid
5779 // siblings.
5780 return false;
5781 }
5782 // Fall through; it's possible that the display type was overridden and
5783 // a different sort of frame was constructed, so we may need to return false
5784 // below.
5785 }
5786
5787 return true;
5788}
5789
5790// FIXME(emilio): If we ever kill IsValidSibling() we can simplify this quite a
5791// bit (no need to pass aTargetContent or aTargetContentDisplay, and the
5792// adjust() calls can be responsibility of the caller).
5793template <nsCSSFrameConstructor::SiblingDirection aDirection>
5794nsIFrame* nsCSSFrameConstructor::FindSiblingInternal(
5795 FlattenedChildIterator& aIter, nsIContent* aTargetContent,
5796 Maybe<StyleDisplay>& aTargetContentDisplay) {
5797 auto adjust = [&](nsIFrame* aPotentialSiblingFrame) -> nsIFrame* {
5798 return AdjustSiblingFrame(aPotentialSiblingFrame, aTargetContent,
5799 aTargetContentDisplay, aDirection);
5800 };
5801
5802 auto nextDomSibling = [](FlattenedChildIterator& aIter) -> nsIContent* {
5803 return aDirection == SiblingDirection::Forward ? aIter.GetNextChild()
5804 : aIter.GetPreviousChild();
5805 };
5806
5807 auto getInsideMarkerFrame = [](const nsIContent* aContent) -> nsIFrame* {
5808 auto* marker = nsLayoutUtils::GetMarkerFrame(aContent);
5809 const bool isInsideMarker =
5810 marker && marker->GetInFlowParent()->StyleList()->mListStylePosition ==
5811 StyleListStylePosition::Inside;
5812 return isInsideMarker ? marker : nullptr;
5813 };
5814
5815 auto getNearPseudo = [&](const nsIContent* aContent) -> nsIFrame* {
5816 if (aDirection == SiblingDirection::Forward) {
5817 if (auto* marker = getInsideMarkerFrame(aContent)) {
5818 return marker;
5819 }
5820 return nsLayoutUtils::GetBeforeFrame(aContent);
5821 }
5822 return nsLayoutUtils::GetAfterFrame(aContent);
5823 };
5824
5825 auto getFarPseudo = [&](const nsIContent* aContent) -> nsIFrame* {
5826 if (aDirection == SiblingDirection::Forward) {
5827 return nsLayoutUtils::GetAfterFrame(aContent);
5828 }
5829 if (auto* before = nsLayoutUtils::GetBeforeFrame(aContent)) {
5830 return before;
5831 }
5832 return getInsideMarkerFrame(aContent);
5833 };
5834
5835 while (nsIContent* sibling = nextDomSibling(aIter)) {
5836 // NOTE(emilio): It's important to check GetPrimaryFrame() before
5837 // IsDisplayContents to get the correct insertion point when multiple
5838 // siblings go from display: non-none to display: contents.
5839 if (nsIFrame* primaryFrame = sibling->GetPrimaryFrame()) {
5840 // XXX the GetContent() == sibling check is needed due to bug 135040.
5841 // Remove it once that's fixed.
5842 if (primaryFrame->GetContent() == sibling) {
5843 if (nsIFrame* frame = adjust(primaryFrame)) {
5844 return frame;
5845 }
5846 }
5847 }
5848
5849 if (IsDisplayContents(sibling)) {
5850 if (nsIFrame* frame = adjust(getNearPseudo(sibling))) {
5851 return frame;
5852 }
5853
5854 const bool startFromBeginning = aDirection == SiblingDirection::Forward;
5855 FlattenedChildIterator iter(sibling, startFromBeginning);
5856 nsIFrame* sibling = FindSiblingInternal<aDirection>(
5857 iter, aTargetContent, aTargetContentDisplay);
5858 if (sibling) {
5859 return sibling;
5860 }
5861 }
5862 }
5863
5864 return adjust(getFarPseudo(aIter.Parent()));
5865}
5866
5867nsIFrame* nsCSSFrameConstructor::AdjustSiblingFrame(
5868 nsIFrame* aSibling, nsIContent* aTargetContent,
5869 Maybe<StyleDisplay>& aTargetContentDisplay, SiblingDirection aDirection) {
5870 if (!aSibling) {
5871 return nullptr;
5872 }
5873
5874 if (aSibling->IsRenderedLegend()) {
5875 return nullptr;
5876 }
5877
5878 if (aSibling->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
5879 aSibling = aSibling->GetPlaceholderFrame();
5880 MOZ_ASSERT(aSibling)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSibling)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSibling))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSibling", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSibling" ")"
); do { *((volatile int*)__null) = 5880; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5881 }
5882
5883 MOZ_ASSERT(!aSibling->GetPrevContinuation(), "How?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aSibling->GetPrevContinuation())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aSibling->GetPrevContinuation
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aSibling->GetPrevContinuation()" " (" "How?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aSibling->GetPrevContinuation()"
") (" "How?" ")"); do { *((volatile int*)__null) = 5883; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
5884 if (aDirection == SiblingDirection::Backward) {
5885 // The frame may be a ib-split frame (a split inline frame that contains a
5886 // block). Get the last part of that split.
5887 if (IsFramePartOfIBSplit(aSibling)) {
5888 aSibling = GetLastIBSplitSibling(aSibling);
5889 }
5890
5891 // The frame may have a continuation. If so, we want the last
5892 // non-overflow-container continuation as our previous sibling.
5893 aSibling = aSibling->GetTailContinuation();
5894 }
5895
5896 if (!IsValidSibling(aSibling, aTargetContent, aTargetContentDisplay)) {
5897 return nullptr;
5898 }
5899
5900 return aSibling;
5901}
5902
5903nsIFrame* nsCSSFrameConstructor::FindPreviousSibling(
5904 const FlattenedChildIterator& aIter,
5905 Maybe<StyleDisplay>& aTargetContentDisplay) {
5906 return FindSibling<SiblingDirection::Backward>(aIter, aTargetContentDisplay);
5907}
5908
5909nsIFrame* nsCSSFrameConstructor::FindNextSibling(
5910 const FlattenedChildIterator& aIter,
5911 Maybe<StyleDisplay>& aTargetContentDisplay) {
5912 return FindSibling<SiblingDirection::Forward>(aIter, aTargetContentDisplay);
5913}
5914
5915template <nsCSSFrameConstructor::SiblingDirection aDirection>
5916nsIFrame* nsCSSFrameConstructor::FindSibling(
5917 const FlattenedChildIterator& aIter,
5918 Maybe<StyleDisplay>& aTargetContentDisplay) {
5919 nsIContent* targetContent = aIter.Get();
5920 FlattenedChildIterator siblingIter = aIter;
5921 nsIFrame* sibling = FindSiblingInternal<aDirection>(
5922 siblingIter, targetContent, aTargetContentDisplay);
5923 if (sibling) {
5924 return sibling;
5925 }
5926
5927 // Our siblings (if any) do not have a frame to guide us. The frame for the
5928 // target content should be inserted whereever a frame for the container would
5929 // be inserted. This is needed when inserting into display: contents nodes.
5930 const nsIContent* current = aIter.Parent();
5931 while (IsDisplayContents(current)) {
5932 const nsIContent* parent = current->GetFlattenedTreeParent();
5933 MOZ_ASSERT(parent, "No display: contents on the root")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(parent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("parent" " (" "No display: contents on the root"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ") ("
"No display: contents on the root" ")"); do { *((volatile int
*)__null) = 5933; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5934
5935 FlattenedChildIterator iter(parent);
5936 iter.Seek(current);
5937 sibling = FindSiblingInternal<aDirection>(iter, targetContent,
5938 aTargetContentDisplay);
5939 if (sibling) {
5940 return sibling;
5941 }
5942
5943 current = parent;
5944 }
5945
5946 return nullptr;
5947}
5948
5949// For fieldsets, returns the area frame, if the child is not a legend.
5950static nsContainerFrame* GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
5951 nsIContent* aChildContent) {
5952 MOZ_ASSERT(!aParentFrame->IsTableWrapperFrame(), "Shouldn't be happening!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aParentFrame->IsTableWrapperFrame())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aParentFrame->IsTableWrapperFrame()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!aParentFrame->IsTableWrapperFrame()"
" (" "Shouldn't be happening!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aParentFrame->IsTableWrapperFrame()"
") (" "Shouldn't be happening!" ")"); do { *((volatile int*)
__null) = 5952; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5953
5954 nsContainerFrame* newParent = nullptr;
5955 if (aParentFrame->IsFieldSetFrame()) {
5956 // If the parent is a fieldSet, use the fieldSet's area frame as the
5957 // parent unless the new content is a legend.
5958 if (!aChildContent->IsHTMLElement(nsGkAtoms::legend)) {
5959 newParent = static_cast<nsFieldSetFrame*>(aParentFrame)->GetInner();
5960 if (newParent) {
5961 newParent = newParent->GetContentInsertionFrame();
5962 }
5963 }
5964 }
5965 return newParent ? newParent : aParentFrame;
5966}
5967
5968nsIFrame* nsCSSFrameConstructor::GetInsertionPrevSibling(
5969 InsertionPoint* aInsertion, nsIContent* aChild, bool* aIsAppend,
5970 bool* aIsRangeInsertSafe, nsIContent* aStartSkipChild,
5971 nsIContent* aEndSkipChild) {
5972 MOZ_ASSERT(aInsertion->mParentFrame, "Must have parent frame to start with")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInsertion->mParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInsertion->mParentFrame)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aInsertion->mParentFrame"
" (" "Must have parent frame to start with" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertion->mParentFrame"
") (" "Must have parent frame to start with" ")"); do { *((volatile
int*)__null) = 5972; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5973
5974 *aIsAppend = false;
5975
5976 // Find the frame that precedes the insertion point.
5977 FlattenedChildIterator iter(aInsertion->mContainer);
5978 if (!aChild->IsRootOfNativeAnonymousSubtree()) {
5979 // The check for IsRootOfNativeAnonymousSubtree() is because editor is
5980 // severely broken and calls us directly for native anonymous
5981 // nodes that it creates.
5982 if (aStartSkipChild) {
5983 iter.Seek(aStartSkipChild);
5984 } else {
5985 iter.Seek(aChild);
5986 }
5987 } else {
5988 // Prime the iterator for the call to FindPreviousSibling.
5989 iter.GetNextChild();
5990 MOZ_ASSERT(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
" (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5992; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5991 "Someone passed native anonymous content directly into frame "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
" (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5992; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
5992 "construction. Stop doing that!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChild->GetProperty(nsGkAtoms::restylableAnonymousNode
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
" (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 5992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetProperty(nsGkAtoms::restylableAnonymousNode)"
") (" "Someone passed native anonymous content directly into frame "
"construction. Stop doing that!" ")"); do { *((volatile int
*)__null) = 5992; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
5993 }
5994
5995 // Note that FindPreviousSibling is passed the iterator by value, so that
5996 // the later usage of the iterator starts from the same place.
5997 Maybe<StyleDisplay> childDisplay;
5998 nsIFrame* prevSibling = FindPreviousSibling(iter, childDisplay);
5999
6000 // Now, find the geometric parent so that we can handle
6001 // continuations properly. Use the prev sibling if we have it;
6002 // otherwise use the next sibling.
6003 if (prevSibling) {
6004 aInsertion->mParentFrame =
6005 prevSibling->GetParent()->GetContentInsertionFrame();
6006 } else {
6007 // If there is no previous sibling, then find the frame that follows
6008 //
6009 // FIXME(emilio): This is really complex and probably shouldn't be.
6010 if (aEndSkipChild) {
6011 iter.Seek(aEndSkipChild);
6012 iter.GetPreviousChild();
6013 }
6014 if (nsIFrame* nextSibling = FindNextSibling(iter, childDisplay)) {
6015 aInsertion->mParentFrame =
6016 nextSibling->GetParent()->GetContentInsertionFrame();
6017 } else {
6018 // No previous or next sibling, so treat this like an appended frame.
6019 *aIsAppend = true;
6020
6021 // Deal with fieldsets.
6022 aInsertion->mParentFrame =
6023 ::GetAdjustedParentFrame(aInsertion->mParentFrame, aChild);
6024
6025 aInsertion->mParentFrame =
6026 ::ContinuationToAppendTo(aInsertion->mParentFrame);
6027
6028 prevSibling = ::FindAppendPrevSibling(aInsertion->mParentFrame, nullptr);
6029 }
6030 }
6031
6032 *aIsRangeInsertSafe = childDisplay.isNothing();
6033 return prevSibling;
6034}
6035
6036nsContainerFrame* nsCSSFrameConstructor::GetContentInsertionFrameFor(
6037 nsIContent* aContent) {
6038 nsIFrame* frame;
6039 while (!(frame = aContent->GetPrimaryFrame())) {
6040 if (!IsDisplayContents(aContent)) {
6041 return nullptr;
6042 }
6043
6044 aContent = aContent->GetFlattenedTreeParent();
6045 if (!aContent) {
6046 return nullptr;
6047 }
6048 }
6049
6050 // If the content of the frame is not the desired content then this is not
6051 // really a frame for the desired content.
6052 // XXX This check is needed due to bug 135040. Remove it once that's fixed.
6053 if (frame->GetContent() != aContent) {
6054 return nullptr;
6055 }
6056
6057 nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame();
6058
6059 NS_ASSERTION(!insertionFrame || insertionFrame == frame || !frame->IsLeaf(),do { if (!(!insertionFrame || insertionFrame == frame || !frame
->IsLeaf())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "The insertion frame is the primary frame or the primary frame "
"isn't a leaf", "!insertionFrame || insertionFrame == frame || !frame->IsLeaf()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6061); MOZ_PretendNoReturn(); } } while (0)
6060 "The insertion frame is the primary frame or the primary frame "do { if (!(!insertionFrame || insertionFrame == frame || !frame
->IsLeaf())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "The insertion frame is the primary frame or the primary frame "
"isn't a leaf", "!insertionFrame || insertionFrame == frame || !frame->IsLeaf()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6061); MOZ_PretendNoReturn(); } } while (0)
6061 "isn't a leaf")do { if (!(!insertionFrame || insertionFrame == frame || !frame
->IsLeaf())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "The insertion frame is the primary frame or the primary frame "
"isn't a leaf", "!insertionFrame || insertionFrame == frame || !frame->IsLeaf()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6061); MOZ_PretendNoReturn(); } } while (0)
;
6062
6063 return insertionFrame;
6064}
6065
6066static bool IsSpecialFramesetChild(nsIContent* aContent) {
6067 // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
6068 return aContent->IsAnyOfHTMLElements(nsGkAtoms::frameset, nsGkAtoms::frame);
6069}
6070
6071static void InvalidateCanvasIfNeeded(PresShell* aPresShell, nsIContent* aNode);
6072
6073void nsCSSFrameConstructor::AddTextItemIfNeeded(
6074 nsFrameConstructorState& aState, const ComputedStyle& aParentStyle,
6075 const InsertionPoint& aInsertion, nsIContent* aPossibleTextContent,
6076 FrameConstructionItemList& aItems) {
6077 MOZ_ASSERT(aPossibleTextContent, "Must have node")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleTextContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleTextContent))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aPossibleTextContent"
" (" "Must have node" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleTextContent"
") (" "Must have node" ")"); do { *((volatile int*)__null) =
6077; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
6078 if (!aPossibleTextContent->IsText() ||
6079 !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
6080 aPossibleTextContent->HasFlag(NODE_NEEDS_FRAME)) {
6081 // Not text, or not suppressed due to being all-whitespace (if it were being
6082 // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
6083 // going to be reframed anyway.
6084 return;
6085 }
6086 MOZ_ASSERT(!aPossibleTextContent->GetPrimaryFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPossibleTextContent->GetPrimaryFrame())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aPossibleTextContent->GetPrimaryFrame()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aPossibleTextContent->GetPrimaryFrame()"
" (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6087); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPossibleTextContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6087; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6087 "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPossibleTextContent->GetPrimaryFrame())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aPossibleTextContent->GetPrimaryFrame()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aPossibleTextContent->GetPrimaryFrame()"
" (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6087); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPossibleTextContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6087; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6088 AddFrameConstructionItems(aState, aPossibleTextContent, false, aParentStyle,
6089 aInsertion, aItems);
6090}
6091
6092void nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aContent) {
6093 if (!aContent->IsText() ||
6094 !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) ||
6095 aContent->HasFlag(NODE_NEEDS_FRAME)) {
6096 // Not text, or not suppressed due to being all-whitespace (if it were being
6097 // suppressed, it would have the NS_CREATE_FRAME_IF_NON_WHITESPACE flag), or
6098 // going to be reframed anyway.
6099 return;
6100 }
6101 MOZ_ASSERT(!aContent->GetPrimaryFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aContent->GetPrimaryFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aContent->GetPrimaryFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aContent->GetPrimaryFrame()" " (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6102; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6102 "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aContent->GetPrimaryFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aContent->GetPrimaryFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aContent->GetPrimaryFrame()" " (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aContent->GetPrimaryFrame()"
") (" "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE"
")"); do { *((volatile int*)__null) = 6102; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6103 ContentInserted(aContent, InsertionKind::Async);
6104}
6105
6106#ifdef DEBUG1
6107void nsCSSFrameConstructor::CheckBitsForLazyFrameConstruction(
6108 nsIContent* aParent) {
6109 // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
6110 // we want to assert, but leaf frames that process their own children and may
6111 // ignore anonymous children (eg framesets) make this complicated. So we set
6112 // these two booleans if we encounter these situations and unset them if we
6113 // hit a node with a leaf frame.
6114 //
6115 // It's fine if one of node without primary frame is in a display:none
6116 // subtree.
6117 //
6118 // Also, it's fine if one of the nodes without primary frame is a display:
6119 // contents node.
6120 bool noPrimaryFrame = false;
6121 bool needsFrameBitSet = false;
6122 nsIContent* content = aParent;
6123 while (content && !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
6124 if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
6125 noPrimaryFrame = needsFrameBitSet = false;
6126 }
6127 if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
6128 noPrimaryFrame = !IsDisplayContents(content);
6129 }
6130 if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
6131 needsFrameBitSet = true;
6132 }
6133
6134 content = content->GetFlattenedTreeParent();
6135 }
6136 if (content && content->GetPrimaryFrame() &&
6137 content->GetPrimaryFrame()->IsLeaf()) {
6138 noPrimaryFrame = needsFrameBitSet = false;
6139 }
6140 MOZ_ASSERT(!noPrimaryFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!noPrimaryFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!noPrimaryFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!noPrimaryFrame"
" (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6141 "Ancestors of nodes with frames to be "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!noPrimaryFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!noPrimaryFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!noPrimaryFrame"
" (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6142 "constructed lazily should have frames")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!noPrimaryFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!noPrimaryFrame))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!noPrimaryFrame"
" (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!noPrimaryFrame"
") (" "Ancestors of nodes with frames to be " "constructed lazily should have frames"
")"); do { *((volatile int*)__null) = 6142; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6143 MOZ_ASSERT(!needsFrameBitSet,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsFrameBitSet)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsFrameBitSet))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!needsFrameBitSet"
" (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6145; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6144 "Ancestors of nodes with frames to be "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsFrameBitSet)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsFrameBitSet))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!needsFrameBitSet"
" (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6145; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6145 "constructed lazily should not have NEEDS_FRAME bit set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!needsFrameBitSet)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!needsFrameBitSet))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!needsFrameBitSet"
" (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!needsFrameBitSet"
") (" "Ancestors of nodes with frames to be " "constructed lazily should not have NEEDS_FRAME bit set"
")"); do { *((volatile int*)__null) = 6145; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6146}
6147#endif
6148
6149// Returns true if this operation can be lazy, false if not.
6150//
6151// FIXME(emilio, bug 1410020): This function assumes that the flattened tree
6152// parent of all the appended children is the same, which, afaict, is not
6153// necessarily true.
6154void nsCSSFrameConstructor::ConstructLazily(Operation aOperation,
6155 nsIContent* aChild) {
6156 MOZ_ASSERT(aChild->GetParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChild->GetParent()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aChild->GetParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParent()"
")"); do { *((volatile int*)__null) = 6156; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6157
6158 // We can construct lazily; just need to set suitable bits in the content
6159 // tree.
6160 Element* parent = aChild->GetFlattenedTreeParentElement();
6161 if (!parent) {
6162 // Not part of the flat tree, nothing to do.
6163 return;
6164 }
6165
6166 if (Servo_Element_IsDisplayNone(parent)) {
6167 // Nothing to do either.
6168 //
6169 // FIXME(emilio): This should be an assert, except for weird <frameset>
6170 // stuff that does its own frame construction. Such an assert would fire in
6171 // layout/style/crashtests/1411478.html, for example.
6172 return;
6173 }
6174
6175 // Set NODE_NEEDS_FRAME on the new nodes.
6176 if (aOperation == CONTENTINSERT) {
6177 NS_ASSERTION(!aChild->GetPrimaryFrame() ||do { if (!(!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame
()->GetContent() != aChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame()->GetContent() != aChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6182); MOZ_PretendNoReturn(); } } while (0)
6178 aChild->GetPrimaryFrame()->GetContent() != aChild,do { if (!(!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame
()->GetContent() != aChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame()->GetContent() != aChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6182); MOZ_PretendNoReturn(); } } while (0)
6179 // XXX the aChild->GetPrimaryFrame()->GetContent() != aChilddo { if (!(!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame
()->GetContent() != aChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame()->GetContent() != aChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6182); MOZ_PretendNoReturn(); } } while (0)
6180 // check is needed due to bug 135040. Remove it once that'sdo { if (!(!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame
()->GetContent() != aChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame()->GetContent() != aChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6182); MOZ_PretendNoReturn(); } } while (0)
6181 // fixed.do { if (!(!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame
()->GetContent() != aChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame()->GetContent() != aChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6182); MOZ_PretendNoReturn(); } } while (0)
6182 "setting NEEDS_FRAME on a node that already has a frame?")do { if (!(!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame
()->GetContent() != aChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!aChild->GetPrimaryFrame() || aChild->GetPrimaryFrame()->GetContent() != aChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6182); MOZ_PretendNoReturn(); } } while (0)
;
6183 aChild->SetFlags(NODE_NEEDS_FRAME);
6184 } else { // CONTENTAPPEND
6185 for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
6186 NS_ASSERTION(!child->GetPrimaryFrame() ||do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6191); MOZ_PretendNoReturn(); } } while (0)
6187 child->GetPrimaryFrame()->GetContent() != child,do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6191); MOZ_PretendNoReturn(); } } while (0)
6188 // XXX the child->GetPrimaryFrame()->GetContent() != childdo { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6191); MOZ_PretendNoReturn(); } } while (0)
6189 // check is needed due to bug 135040. Remove it once that'sdo { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6191); MOZ_PretendNoReturn(); } } while (0)
6190 // fixed.do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6191); MOZ_PretendNoReturn(); } } while (0)
6191 "setting NEEDS_FRAME on a node that already has a frame?")do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "setting NEEDS_FRAME on a node that already has a frame?", "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6191); MOZ_PretendNoReturn(); } } while (0)
;
6192 child->SetFlags(NODE_NEEDS_FRAME);
6193 }
6194 }
6195
6196 CheckBitsForLazyFrameConstruction(parent);
6197 parent->NoteDescendantsNeedFramesForServo();
6198}
6199
6200void nsCSSFrameConstructor::IssueSingleInsertNofications(
6201 nsIContent* aStartChild, nsIContent* aEndChild,
6202 InsertionKind aInsertionKind) {
6203 for (nsIContent* child = aStartChild; child != aEndChild;
6204 child = child->GetNextSibling()) {
6205 // XXX the GetContent() != child check is needed due to bug 135040.
6206 // Remove it once that's fixed.
6207 MOZ_ASSERT(!child->GetPrimaryFrame() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child->GetPrimaryFrame()
|| child->GetPrimaryFrame()->GetContent() != child))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
")"); do { *((volatile int*)__null) = 6208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6208 child->GetPrimaryFrame()->GetContent() != child)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child->GetPrimaryFrame()
|| child->GetPrimaryFrame()->GetContent() != child))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
")"); do { *((volatile int*)__null) = 6208; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6209
6210 // Call ContentRangeInserted with this node.
6211 ContentRangeInserted(child, child->GetNextSibling(), aInsertionKind);
6212 }
6213}
6214
6215bool nsCSSFrameConstructor::InsertionPoint::IsMultiple() const {
6216 // Fieldset frames have multiple normal flow child frame lists so handle it
6217 // the same as if it had multiple content insertion points.
6218 return mParentFrame && mParentFrame->IsFieldSetFrame();
6219}
6220
6221nsCSSFrameConstructor::InsertionPoint
6222nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aStartChild,
6223 nsIContent* aEndChild,
6224 InsertionKind aInsertionKind) {
6225 MOZ_ASSERT(aStartChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStartChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStartChild))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aStartChild", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6225); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartChild"
")"); do { *((volatile int*)__null) = 6225; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6226
6227 nsIContent* parent = aStartChild->GetParent();
6228 if (!parent) {
6229 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6230 return {};
6231 }
6232
6233 // If the children of the container may be distributed to different insertion
6234 // points, insert them separately and bail out, letting ContentInserted handle
6235 // the mess.
6236 if (parent->GetShadowRoot()) {
6237 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6238 return {};
6239 }
6240
6241#ifdef DEBUG1
6242 {
6243 nsIContent* expectedParent = aStartChild->GetFlattenedTreeParent();
6244 for (nsIContent* child = aStartChild->GetNextSibling(); child;
6245 child = child->GetNextSibling()) {
6246 MOZ_ASSERT(child->GetFlattenedTreeParent() == expectedParent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child->GetFlattenedTreeParent() == expectedParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(child->GetFlattenedTreeParent() == expectedParent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"child->GetFlattenedTreeParent() == expectedParent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child->GetFlattenedTreeParent() == expectedParent"
")"); do { *((volatile int*)__null) = 6246; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6247 }
6248 }
6249#endif
6250
6251 // Now the flattened tree parent of all the siblings is the same, just use the
6252 // same insertion point and take the fast path, unless it's a multiple
6253 // insertion point.
6254 InsertionPoint ip = GetInsertionPoint(aStartChild);
6255 if (ip.IsMultiple()) {
6256 IssueSingleInsertNofications(aStartChild, aEndChild, aInsertionKind);
6257 return {};
6258 }
6259
6260 return ip;
6261}
6262
6263bool nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
6264 nsIContent* aStartChild,
6265 nsIContent* aEndChild) {
6266 if (aParentFrame->IsFrameSetFrame()) {
6267 // Check whether we have any kids we care about.
6268 for (nsIContent* cur = aStartChild; cur != aEndChild;
6269 cur = cur->GetNextSibling()) {
6270 if (IsSpecialFramesetChild(cur)) {
6271 // Just reframe the parent, since framesets are weird like that.
6272 RecreateFramesForContent(aParentFrame->GetContent(),
6273 InsertionKind::Async);
6274 return true;
6275 }
6276 }
6277 }
6278 return false;
6279}
6280
6281void nsCSSFrameConstructor::LazilyStyleNewChildRange(nsIContent* aStartChild,
6282 nsIContent* aEndChild) {
6283 for (nsIContent* child = aStartChild; child != aEndChild;
6284 child = child->GetNextSibling()) {
6285 if (child->IsElement()) {
6286 child->AsElement()->NoteDirtyForServo();
6287 }
6288 }
6289}
6290
6291#ifdef DEBUG1
6292static bool IsFlattenedTreeChild(nsIContent* aParent, nsIContent* aChild) {
6293 FlattenedChildIterator iter(aParent);
6294 for (nsIContent* node = iter.GetNextChild(); node;
6295 node = iter.GetNextChild()) {
6296 if (node == aChild) {
6297 return true;
6298 }
6299 }
6300 return false;
6301}
6302#endif
6303
6304void nsCSSFrameConstructor::StyleNewChildRange(nsIContent* aStartChild,
6305 nsIContent* aEndChild) {
6306 ServoStyleSet* styleSet = mPresShell->StyleSet();
6307
6308 for (nsIContent* child = aStartChild; child != aEndChild;
6309 child = child->GetNextSibling()) {
6310 if (!child->IsElement()) {
6311 continue;
6312 }
6313
6314 Element* childElement = child->AsElement();
6315
6316 // We only come in here from non-lazy frame construction, so the children
6317 // should be unstyled.
6318 MOZ_ASSERT(!childElement->HasServoData())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!childElement->HasServoData())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!childElement->HasServoData
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!childElement->HasServoData()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!childElement->HasServoData()"
")"); do { *((volatile int*)__null) = 6318; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6319
6320#ifdef DEBUG1
6321 {
6322 // Furthermore, all of them should have the same flattened tree parent
6323 // (GetRangeInsertionPoint ensures it). And that parent should be styled,
6324 // otherwise we would've never found an insertion point at all.
6325 Element* parent = childElement->GetFlattenedTreeParentElement();
6326 MOZ_ASSERT(parent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(parent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("parent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6326); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent" ")"
); do { *((volatile int*)__null) = 6326; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6327 MOZ_ASSERT(parent->HasServoData())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent->HasServoData())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(parent->HasServoData())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("parent->HasServoData()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent->HasServoData()"
")"); do { *((volatile int*)__null) = 6327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6328 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFlattenedTreeChild(parent, child))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFlattenedTreeChild(parent,
child)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsFlattenedTreeChild(parent, child)" " (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6330; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6329 IsFlattenedTreeChild(parent, child),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFlattenedTreeChild(parent, child))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFlattenedTreeChild(parent,
child)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsFlattenedTreeChild(parent, child)" " (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6330; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6330 "GetFlattenedTreeParent and ChildIterator don't agree, fix this!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFlattenedTreeChild(parent, child))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFlattenedTreeChild(parent,
child)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsFlattenedTreeChild(parent, child)" " (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFlattenedTreeChild(parent, child)"
") (" "GetFlattenedTreeParent and ChildIterator don't agree, fix this!"
")"); do { *((volatile int*)__null) = 6330; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6331 }
6332#endif
6333
6334 styleSet->StyleNewSubtree(childElement);
6335 }
6336}
6337
6338nsIFrame* nsCSSFrameConstructor::FindNextSiblingForAppend(
6339 const InsertionPoint& aInsertion) {
6340 auto SlowPath = [&]() -> nsIFrame* {
6341 FlattenedChildIterator iter(aInsertion.mContainer,
6342 /* aStartAtBeginning = */ false);
6343 iter.GetPreviousChild(); // Prime the iterator.
6344 Maybe<StyleDisplay> unused;
6345 return FindNextSibling(iter, unused);
6346 };
6347
6348 if (!IsDisplayContents(aInsertion.mContainer) &&
6349 !nsLayoutUtils::GetAfterFrame(aInsertion.mContainer)) {
6350 MOZ_ASSERT(!SlowPath())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!SlowPath())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!SlowPath()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!SlowPath()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!SlowPath()"
")"); do { *((volatile int*)__null) = 6350; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6351 return nullptr;
6352 }
6353
6354 return SlowPath();
6355}
6356
6357// This is a bit slow, but sometimes we need it.
6358static bool ParentIsWrapperAnonBox(nsIFrame* aParent) {
6359 nsIFrame* maybeAnonBox = aParent;
6360 if (maybeAnonBox->Style()->GetPseudoType() == PseudoStyleType::cellContent) {
6361 // The thing that would maybe be a wrapper anon box is the cell.
6362 maybeAnonBox = maybeAnonBox->GetParent();
6363 }
6364 return maybeAnonBox->Style()->IsWrapperAnonBox();
6365}
6366
6367void nsCSSFrameConstructor::ContentAppended(nsIContent* aFirstNewContent,
6368 InsertionKind aInsertionKind) {
6369 MOZ_ASSERT(aInsertionKind == InsertionKind::Sync ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInsertionKind == InsertionKind::Sync || !RestyleManager
()->IsInStyleRefresh())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInsertionKind == InsertionKind
::Sync || !RestyleManager()->IsInStyleRefresh()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6370 !RestyleManager()->IsInStyleRefresh())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInsertionKind == InsertionKind::Sync || !RestyleManager
()->IsInStyleRefresh())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInsertionKind == InsertionKind
::Sync || !RestyleManager()->IsInStyleRefresh()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6371
6372 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentAppended",mozilla::AutoProfilerLabelHot raiiObject6373( "nsCSSFrameConstructor::ContentAppended"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
6373 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject6373( "nsCSSFrameConstructor::ContentAppended"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
6374 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
6375
6376#ifdef DEBUG1
6377 if (gNoisyContentUpdates) {
6378 printf(
6379 "nsCSSFrameConstructor::ContentAppended container=%p "
6380 "first-child=%p lazy=%d\n",
6381 aFirstNewContent->GetParent(), aFirstNewContent,
6382 aInsertionKind == InsertionKind::Async);
6383 if (gReallyNoisyContentUpdates && aFirstNewContent->GetParent()) {
6384 aFirstNewContent->GetParent()->List(stdoutstdout, 0);
6385 }
6386 }
6387
6388 for (nsIContent* child = aFirstNewContent; child;
6389 child = child->GetNextSibling()) {
6390 // XXX the GetContent() != child check is needed due to bug 135040.
6391 // Remove it once that's fixed.
6392 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child->GetPrimaryFrame()
|| child->GetPrimaryFrame()->GetContent() != child))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
" (" "asked to construct a frame for a node that already has a frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
") (" "asked to construct a frame for a node that already has a frame"
")"); do { *((volatile int*)__null) = 6395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6393 !child->GetPrimaryFrame() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child->GetPrimaryFrame()
|| child->GetPrimaryFrame()->GetContent() != child))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
" (" "asked to construct a frame for a node that already has a frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
") (" "asked to construct a frame for a node that already has a frame"
")"); do { *((volatile int*)__null) = 6395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6394 child->GetPrimaryFrame()->GetContent() != child,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child->GetPrimaryFrame()
|| child->GetPrimaryFrame()->GetContent() != child))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
" (" "asked to construct a frame for a node that already has a frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
") (" "asked to construct a frame for a node that already has a frame"
")"); do { *((volatile int*)__null) = 6395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6395 "asked to construct a frame for a node that already has a frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child->GetPrimaryFrame()
|| child->GetPrimaryFrame()->GetContent() != child))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
" (" "asked to construct a frame for a node that already has a frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
") (" "asked to construct a frame for a node that already has a frame"
")"); do { *((volatile int*)__null) = 6395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6396 }
6397#endif
6398
6399 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6400 InsertionPoint insertion =
6401 GetRangeInsertionPoint(aFirstNewContent, nullptr, aInsertionKind);
6402 nsContainerFrame*& parentFrame = insertion.mParentFrame;
6403 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6404 if (!parentFrame) {
6405 // We're punting on frame construction because there's no container frame.
6406 // The Servo-backed style system handles this case like the lazy frame
6407 // construction case, except when we're already constructing frames, in
6408 // which case we shouldn't need to do anything else.
6409 if (aInsertionKind == InsertionKind::Async) {
6410 LazilyStyleNewChildRange(aFirstNewContent, nullptr);
6411 }
6412 return;
6413 }
6414
6415 if (aInsertionKind == InsertionKind::Async) {
6416 ConstructLazily(CONTENTAPPEND, aFirstNewContent);
6417 LazilyStyleNewChildRange(aFirstNewContent, nullptr);
6418 return;
6419 }
6420
6421 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6422 if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nullptr)) {
6423 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6424 return;
6425 }
6426 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6427
6428 if (parentFrame->IsLeaf()) {
6429 // Nothing to do here; we shouldn't be constructing kids of leaves
6430 // Clear lazy bits so we don't try to construct again.
6431 ClearLazyBits(aFirstNewContent, nullptr);
6432 return;
6433 }
6434
6435 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6436 if (WipeInsertionParent(parentFrame)) {
6437 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6438 return;
6439 }
6440 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6441
6442#ifdef DEBUG1
6443 if (gNoisyContentUpdates && IsFramePartOfIBSplit(parentFrame)) {
6444 printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
6445 parentFrame->ListTag(stdoutstdout);
6446 printf(" is ib-split\n");
6447 }
6448#endif
6449
6450 // We should never get here with fieldsets, since they have
6451 // multiple insertion points.
6452 MOZ_ASSERT(!parentFrame->IsFieldSetFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parentFrame->IsFieldSetFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!parentFrame->IsFieldSetFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!parentFrame->IsFieldSetFrame()" " (" "Parent frame should not be fieldset!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6453); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentFrame->IsFieldSetFrame()"
") (" "Parent frame should not be fieldset!" ")"); do { *((volatile
int*)__null) = 6453; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6453 "Parent frame should not be fieldset!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parentFrame->IsFieldSetFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!parentFrame->IsFieldSetFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!parentFrame->IsFieldSetFrame()" " (" "Parent frame should not be fieldset!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6453); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parentFrame->IsFieldSetFrame()"
") (" "Parent frame should not be fieldset!" ")"); do { *((volatile
int*)__null) = 6453; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6454
6455 nsIFrame* nextSibling = FindNextSiblingForAppend(insertion);
6456 if (nextSibling) {
6457 parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
6458 } else {
6459 parentFrame = ::ContinuationToAppendTo(parentFrame);
6460 }
6461
6462 nsContainerFrame* containingBlock = GetFloatContainingBlock(parentFrame);
6463
6464 // See if the containing block has :first-letter style applied.
6465 const bool haveFirstLetterStyle =
6466 containingBlock && HasFirstLetterStyle(containingBlock);
6467
6468 const bool haveFirstLineStyle =
6469 containingBlock && ShouldHaveFirstLineStyle(containingBlock->GetContent(),
6470 containingBlock->Style());
6471
6472 if (haveFirstLetterStyle) {
6473 AutoWeakFrame wf(nextSibling);
6474
6475 // Before we get going, remove the current letter frames
6476 RemoveLetterFrames(mPresShell, containingBlock);
6477
6478 // Reget nextSibling, since we may have killed it.
6479 //
6480 // FIXME(emilio): This kinda sucks! :(
6481 if (nextSibling && !wf) {
6482 nextSibling = FindNextSiblingForAppend(insertion);
6483 if (nextSibling) {
6484 parentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
6485 containingBlock = GetFloatContainingBlock(parentFrame);
6486 }
6487 }
6488 }
6489
6490 // Create some new frames
6491 nsFrameConstructorState state(
6492 mPresShell, GetAbsoluteContainingBlock(parentFrame, FIXED_POS),
6493 GetAbsoluteContainingBlock(parentFrame, ABS_POS), containingBlock);
6494
6495 if (mPresShell->GetPresContext()->IsPaginated()) {
6496 // Because this function can be called outside frame construction, we need
6497 // to set state.mAutoPageNameValue based on what the parent frame's auto
6498 // value is.
6499 // Calling this from outside the frame constructor can violate many of the
6500 // expectations in AutoFrameConstructionPageName, and unlike during frame
6501 // construction we already have an auto value from parentFrame, so we do
6502 // not use AutoFrameConstructionPageName here.
6503 state.mAutoPageNameValue = parentFrame->GetAutoPageValue();
6504#ifdef DEBUG1
6505 parentFrame->mWasVisitedByAutoFrameConstructionPageName = true;
6506#endif
6507 }
6508
6509 LayoutFrameType frameType = parentFrame->Type();
6510
6511 RefPtr<ComputedStyle> parentStyle =
6512 ResolveComputedStyle(insertion.mContainer);
6513 FlattenedChildIterator iter(insertion.mContainer);
6514 const bool haveNoShadowDOM =
6515 !iter.ShadowDOMInvolved() || !iter.GetNextChild();
6516
6517 AutoFrameConstructionItemList items(this);
6518 if (aFirstNewContent->GetPreviousSibling() &&
6519 GetParentType(frameType) == eTypeBlock && haveNoShadowDOM) {
6520 // If there's a text node in the normal content list just before the new
6521 // items, and it has no frame, make a frame construction item for it. If it
6522 // doesn't need a frame, ConstructFramesFromItemList below won't give it
6523 // one. No need to do all this if our parent type is not block, though,
6524 // since WipeContainingBlock already handles that situation.
6525 //
6526 // Because we're appending, we don't need to worry about any text
6527 // after the appended content; there can only be generated content
6528 // (and bare text nodes are not generated). Native anonymous content
6529 // generated by frames never participates in inline layout.
6530 AddTextItemIfNeeded(state, *parentStyle, insertion,
6531 aFirstNewContent->GetPreviousSibling(), items);
6532 }
6533 for (nsIContent* child = aFirstNewContent; child;
6534 child = child->GetNextSibling()) {
6535 AddFrameConstructionItems(state, child, false, *parentStyle, insertion,
6536 items);
6537 }
6538
6539 nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, nextSibling);
6540
6541 // Perform special check for diddling around with the frames in
6542 // a ib-split inline frame.
6543 // If we're appending before :after content, then we're not really
6544 // appending, so let WipeContainingBlock know that.
6545 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6546 if (WipeContainingBlock(state, containingBlock, parentFrame, items, true,
6547 prevSibling)) {
6548 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6549 return;
6550 }
6551 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6552
6553 // If the parent is a block frame, and we're not in a special case
6554 // where frames can be moved around, determine if the list is for the
6555 // start or end of the block.
6556 if (parentFrame->IsBlockFrameOrSubclass() && !haveFirstLetterStyle &&
6557 !haveFirstLineStyle && !IsFramePartOfIBSplit(parentFrame)) {
6558 items.SetLineBoundaryAtStart(!prevSibling ||
6559 !prevSibling->IsInlineOutside() ||
6560 prevSibling->IsBrFrame());
6561 // :after content can't be <br> so no need to check it
6562 //
6563 // FIXME(emilio): A display: contents sibling could! Write a test-case and
6564 // fix.
6565 items.SetLineBoundaryAtEnd(!nextSibling || !nextSibling->IsInlineOutside());
6566 }
6567 // To suppress whitespace-only text frames, we have to verify that
6568 // our container's DOM child list matches its flattened tree child list.
6569 items.SetParentHasNoShadowDOM(haveNoShadowDOM);
6570
6571 nsFrameConstructorSaveState floatSaveState;
6572 state.MaybePushFloatContainingBlock(parentFrame, floatSaveState);
6573
6574 nsFrameList frameList;
6575 ConstructFramesFromItemList(state, items, parentFrame,
6576 ParentIsWrapperAnonBox(parentFrame), frameList);
6577
6578 for (nsIContent* child = aFirstNewContent; child;
6579 child = child->GetNextSibling()) {
6580 // Invalidate now instead of before the WipeContainingBlock call, just in
6581 // case we do wipe; in that case we don't need to do this walk at all.
6582 // XXXbz does that matter? Would it make more sense to save some virtual
6583 // GetChildAt_Deprecated calls instead and do this during construction of
6584 // our FrameConstructionItemList?
6585 InvalidateCanvasIfNeeded(mPresShell, child);
6586 }
6587
6588 // If the container is a table and a caption was appended, it needs to be put
6589 // in the table wrapper frame's additional child list.
6590 nsFrameList captionList;
6591 if (LayoutFrameType::Table == frameType) {
6592 // Pull out the captions. Note that we don't want to do that as we go,
6593 // because processing a single caption can add a whole bunch of things to
6594 // the frame items due to pseudoframe processing. So we'd have to pull
6595 // captions from a list anyway; might as well do that here.
6596 // XXXbz this is no longer true; we could pull captions directly out of the
6597 // FrameConstructionItemList now.
6598 PullOutCaptionFrames(frameList, captionList);
6599 }
6600
6601 if (haveFirstLineStyle && parentFrame == containingBlock) {
6602 // It's possible that some of the new frames go into a
6603 // first-line frame. Look at them and see...
6604 AppendFirstLineFrames(state, containingBlock->GetContent(), containingBlock,
6605 frameList);
6606 // That moved things into line frames as needed, reparenting their
6607 // styles. Nothing else needs to be done.
6608 } else if (parentFrame->Style()->HasPseudoElementData()) {
6609 // parentFrame might be inside a ::first-line frame. Check whether it is,
6610 // and if so fix up our styles.
6611 CheckForFirstLineInsertion(parentFrame, frameList);
6612 CheckForFirstLineInsertion(parentFrame, captionList);
6613 }
6614
6615 // Notify the parent frame passing it the list of new frames
6616 // Append the flowed frames to the principal child list; captions
6617 // need special treatment
6618 if (captionList.NotEmpty()) { // append the caption to the table wrapper
6619 NS_ASSERTION(LayoutFrameType::Table == frameType, "how did that happen?")do { if (!(LayoutFrameType::Table == frameType)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "how did that happen?", "LayoutFrameType::Table == frameType"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6619); MOZ_PretendNoReturn(); } } while (0)
;
6620 nsContainerFrame* outerTable = parentFrame->GetParent();
6621 captionList.ApplySetParent(outerTable);
6622 AppendFrames(outerTable, FrameChildListID::Caption, std::move(captionList));
6623 }
6624
6625 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6626 if (MaybeRecreateForColumnSpan(state, parentFrame, frameList, prevSibling)) {
6627 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6628 return;
6629 }
6630 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6631
6632 if (frameList.NotEmpty()) { // append the in-flow kids
6633 AppendFramesToParent(state, parentFrame, frameList, prevSibling);
6634 }
6635
6636 // Recover first-letter frames
6637 if (haveFirstLetterStyle) {
6638 RecoverLetterFrames(containingBlock);
6639 }
6640
6641#ifdef DEBUG1
6642 if (gReallyNoisyContentUpdates) {
6643 printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
6644 parentFrame->List(stdoutstdout);
6645 }
6646#endif
6647
6648#ifdef ACCESSIBILITY1
6649 if (nsAccessibilityService* accService = GetAccService()) {
6650 accService->ContentRangeInserted(mPresShell, aFirstNewContent, nullptr);
6651 }
6652#endif
6653}
6654
6655void nsCSSFrameConstructor::ContentInserted(nsIContent* aChild,
6656 InsertionKind aInsertionKind) {
6657 ContentRangeInserted(aChild, aChild->GetNextSibling(), aInsertionKind);
6658}
6659
6660// ContentRangeInserted handles creating frames for a range of nodes that
6661// aren't at the end of their childlist. ContentRangeInserted isn't a real
6662// content notification, but rather it handles regular ContentInserted calls
6663// for a single node as well as the lazy construction of frames for a range of
6664// nodes when called from CreateNeededFrames. For a range of nodes to be
6665// suitable to have its frames constructed all at once they must meet the same
6666// conditions that ContentAppended imposes (GetRangeInsertionPoint checks
6667// these), plus more. Namely when finding the insertion prevsibling we must not
6668// need to consult something specific to any one node in the range, so that the
6669// insertion prevsibling would be the same for each node in the range. So we
6670// pass the first node in the range to GetInsertionPrevSibling, and if
6671// IsValidSibling (the only place GetInsertionPrevSibling might look at the
6672// passed in node itself) needs to resolve style on the node we record this and
6673// return that this range needs to be split up and inserted separately. Table
6674// captions need extra attention as we need to determine where to insert them
6675// in the caption list, while skipping any nodes in the range being inserted
6676// (because when we treat the caption frames the other nodes have had their
6677// frames constructed but not yet inserted into the frame tree).
6678void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
6679 nsIContent* aEndChild,
6680 InsertionKind aInsertionKind) {
6681 MOZ_ASSERT(aInsertionKind == InsertionKind::Sync ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInsertionKind == InsertionKind::Sync || !RestyleManager
()->IsInStyleRefresh())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInsertionKind == InsertionKind
::Sync || !RestyleManager()->IsInStyleRefresh()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6682; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6682 !RestyleManager()->IsInStyleRefresh())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInsertionKind == InsertionKind::Sync || !RestyleManager
()->IsInStyleRefresh())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInsertionKind == InsertionKind
::Sync || !RestyleManager()->IsInStyleRefresh()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInsertionKind == InsertionKind::Sync || !RestyleManager()->IsInStyleRefresh()"
")"); do { *((volatile int*)__null) = 6682; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6683
6684 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentRangeInserted",mozilla::AutoProfilerLabelHot raiiObject6685( "nsCSSFrameConstructor::ContentRangeInserted"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
6685 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject6685( "nsCSSFrameConstructor::ContentRangeInserted"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
6686 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
6687
6688 MOZ_ASSERT(aStartChild, "must always pass a child")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStartChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStartChild))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aStartChild" " ("
"must always pass a child" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartChild"
") (" "must always pass a child" ")"); do { *((volatile int*
)__null) = 6688; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6689
6690#ifdef DEBUG1
6691 if (gNoisyContentUpdates) {
6692 printf(
6693 "nsCSSFrameConstructor::ContentRangeInserted container=%p "
6694 "start-child=%p end-child=%p lazy=%d\n",
6695 aStartChild->GetParent(), aStartChild, aEndChild,
6696 aInsertionKind == InsertionKind::Async);
6697 if (gReallyNoisyContentUpdates) {
6698 if (aStartChild->GetParent()) {
6699 aStartChild->GetParent()->List(stdoutstdout, 0);
6700 } else {
6701 aStartChild->List(stdoutstdout, 0);
6702 }
6703 }
6704 }
6705
6706 for (nsIContent* child = aStartChild; child != aEndChild;
6707 child = child->GetNextSibling()) {
6708 // XXX the GetContent() != child check is needed due to bug 135040.
6709 // Remove it once that's fixed.
6710 NS_ASSERTION(do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "asked to construct a frame for a node that already has a frame"
, "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6713); MOZ_PretendNoReturn(); } } while (0)
6711 !child->GetPrimaryFrame() ||do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "asked to construct a frame for a node that already has a frame"
, "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6713); MOZ_PretendNoReturn(); } } while (0)
6712 child->GetPrimaryFrame()->GetContent() != child,do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "asked to construct a frame for a node that already has a frame"
, "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6713); MOZ_PretendNoReturn(); } } while (0)
6713 "asked to construct a frame for a node that already has a frame")do { if (!(!child->GetPrimaryFrame() || child->GetPrimaryFrame
()->GetContent() != child)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "asked to construct a frame for a node that already has a frame"
, "!child->GetPrimaryFrame() || child->GetPrimaryFrame()->GetContent() != child"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6713); MOZ_PretendNoReturn(); } } while (0)
;
6714 }
6715#endif
6716
6717 bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
6718 NS_ASSERTION(isSingleInsert || aInsertionKind == InsertionKind::Sync,do { if (!(isSingleInsert || aInsertionKind == InsertionKind::
Sync)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "range insert shouldn't be lazy"
, "isSingleInsert || aInsertionKind == InsertionKind::Sync", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6719); MOZ_PretendNoReturn(); } } while (0)
6719 "range insert shouldn't be lazy")do { if (!(isSingleInsert || aInsertionKind == InsertionKind::
Sync)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "range insert shouldn't be lazy"
, "isSingleInsert || aInsertionKind == InsertionKind::Sync", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6719); MOZ_PretendNoReturn(); } } while (0)
;
6720 NS_ASSERTION(isSingleInsert || aEndChild,do { if (!(isSingleInsert || aEndChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "range should not include all nodes after aStartChild", "isSingleInsert || aEndChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6721); MOZ_PretendNoReturn(); } } while (0)
6721 "range should not include all nodes after aStartChild")do { if (!(isSingleInsert || aEndChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "range should not include all nodes after aStartChild", "isSingleInsert || aEndChild"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6721); MOZ_PretendNoReturn(); } } while (0)
;
6722
6723 // If we have a null parent, then this must be the document element being
6724 // inserted, or some other child of the document in the DOM (might be a PI,
6725 // say).
6726 if (!aStartChild->GetParent()) {
6727 MOZ_ASSERT(isSingleInsert,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isSingleInsert)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isSingleInsert))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isSingleInsert"
" (" "root node insertion should be a single insertion" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
") (" "root node insertion should be a single insertion" ")"
); do { *((volatile int*)__null) = 6728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6728 "root node insertion should be a single insertion")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isSingleInsert)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isSingleInsert))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isSingleInsert"
" (" "root node insertion should be a single insertion" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
") (" "root node insertion should be a single insertion" ")"
); do { *((volatile int*)__null) = 6728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6729 Element* docElement = mDocument->GetRootElement();
6730 if (aStartChild != docElement) {
6731 // Not the root element; just bail out
6732 return;
6733 }
6734
6735 MOZ_ASSERT(!mRootElementFrame, "root element frame already created")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mRootElementFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mRootElementFrame))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mRootElementFrame"
" (" "root element frame already created" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6735); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mRootElementFrame"
") (" "root element frame already created" ")"); do { *((volatile
int*)__null) = 6735; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6736 if (aInsertionKind == InsertionKind::Async) {
6737 docElement->SetFlags(NODE_NEEDS_FRAME);
6738 LazilyStyleNewChildRange(docElement, nullptr);
6739 return;
6740 }
6741
6742 // Create frames for the document element and its child elements
6743 if (ConstructDocElementFrame(docElement)) {
6744 InvalidateCanvasIfNeeded(mPresShell, aStartChild);
6745#ifdef DEBUG1
6746 if (gReallyNoisyContentUpdates) {
6747 printf(
6748 "nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
6749 "model:\n");
6750 mRootElementFrame->List(stdoutstdout);
6751 }
6752#endif
6753 }
6754
6755#ifdef ACCESSIBILITY1
6756 if (nsAccessibilityService* accService = GetAccService()) {
6757 accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
6758 }
6759#endif
6760
6761 return;
6762 }
6763
6764 InsertionPoint insertion;
6765 if (isSingleInsert) {
6766 // See if we have a Shadow DOM insertion point. If so, then that's our real
6767 // parent frame; if not, then the frame hasn't been built yet and we just
6768 // bail.
6769 insertion = GetInsertionPoint(aStartChild);
6770 } else {
6771 // Get our insertion point. If we need to issue single ContentInserteds
6772 // GetRangeInsertionPoint will take care of that for us.
6773 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6774 insertion = GetRangeInsertionPoint(aStartChild, aEndChild, aInsertionKind);
6775 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6776 }
6777
6778 if (!insertion.mParentFrame) {
6779 // We're punting on frame construction because there's no container frame.
6780 // The Servo-backed style system handles this case like the lazy frame
6781 // construction case, except when we're already constructing frames, in
6782 // which case we shouldn't need to do anything else.
6783 if (aInsertionKind == InsertionKind::Async) {
6784 LazilyStyleNewChildRange(aStartChild, aEndChild);
6785 }
6786 return;
6787 }
6788
6789 if (aInsertionKind == InsertionKind::Async) {
6790 ConstructLazily(CONTENTINSERT, aStartChild);
6791 LazilyStyleNewChildRange(aStartChild, aEndChild);
6792 return;
6793 }
6794
6795 bool isAppend, isRangeInsertSafe;
6796 nsIFrame* prevSibling = GetInsertionPrevSibling(
6797 &insertion, aStartChild, &isAppend, &isRangeInsertSafe);
6798
6799 // check if range insert is safe
6800 if (!isSingleInsert && !isRangeInsertSafe) {
6801 // must fall back to a single ContertInserted for each child in the range
6802 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6803 IssueSingleInsertNofications(aStartChild, aEndChild, InsertionKind::Sync);
6804 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6805 return;
6806 }
6807
6808 LayoutFrameType frameType = insertion.mParentFrame->Type();
6809 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6810 if (MaybeRecreateForFrameset(insertion.mParentFrame, aStartChild,
6811 aEndChild)) {
6812 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6813 return;
6814 }
6815 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6816
6817 // We should only get here with fieldsets when doing a single insert, because
6818 // fieldsets have multiple insertion points.
6819 NS_ASSERTION(isSingleInsert || frameType != LayoutFrameType::FieldSet,do { if (!(isSingleInsert || frameType != LayoutFrameType::FieldSet
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected parent", "isSingleInsert || frameType != LayoutFrameType::FieldSet"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6820); MOZ_PretendNoReturn(); } } while (0)
6820 "Unexpected parent")do { if (!(isSingleInsert || frameType != LayoutFrameType::FieldSet
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected parent", "isSingleInsert || frameType != LayoutFrameType::FieldSet"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6820); MOZ_PretendNoReturn(); } } while (0)
;
6821 // Note that this check is insufficient if aStartChild is not a legend with
6822 // display::contents that contains a legend. We'll catch that case in
6823 // WipeContainingBlock. (That code would also catch this case, but handling
6824 // this early is slightly faster.)
6825 // XXXmats we should be able to optimize this when the fieldset doesn't
6826 // currently have a rendered legend. ContentRangeInserted needs to be fixed
6827 // to use the inner frame as the content insertion frame in that case.
6828 if (GetFieldSetFrameFor(insertion.mParentFrame) &&
6829 aStartChild->NodeInfo()->NameAtom() == nsGkAtoms::legend) {
6830 // Just reframe the parent, since figuring out whether this
6831 // should be the new legend and then handling it is too complex.
6832 // We could do a little better here --- check if the fieldset already
6833 // has a legend which occurs earlier in its child list than this node,
6834 // and if so, proceed. But we'd have to extend nsFieldSetFrame
6835 // to locate this legend in the inserted frames and extract it.
6836 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6837 RecreateFramesForContent(insertion.mParentFrame->GetContent(),
6838 InsertionKind::Async);
6839 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6840 return;
6841 }
6842
6843 // Don't construct kids of leaves
6844 if (insertion.mParentFrame->IsLeaf()) {
6845 // Clear lazy bits so we don't try to construct again.
6846 ClearLazyBits(aStartChild, aEndChild);
6847 return;
6848 }
6849
6850 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6851 if (WipeInsertionParent(insertion.mParentFrame)) {
6852 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6853 return;
6854 }
6855 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6856
6857 nsFrameConstructorState state(
6858 mPresShell, GetAbsoluteContainingBlock(insertion.mParentFrame, FIXED_POS),
6859 GetAbsoluteContainingBlock(insertion.mParentFrame, ABS_POS),
6860 GetFloatContainingBlock(insertion.mParentFrame),
6861 do_AddRef(mFrameTreeState));
6862
6863 // Recover state for the containing block - we need to know if
6864 // it has :first-letter or :first-line style applied to it. The
6865 // reason we care is that the internal structure in these cases
6866 // is not the normal structure and requires custom updating
6867 // logic.
6868 nsContainerFrame* containingBlock = state.mFloatedList.mContainingBlock;
6869 bool haveFirstLetterStyle = false;
6870 bool haveFirstLineStyle = false;
6871
6872 // In order to shave off some cycles, we only dig up the
6873 // containing block haveFirst* flags if the parent frame where
6874 // the insertion/append is occurring is an inline or block
6875 // container. For other types of containers this isn't relevant.
6876 StyleDisplayInside parentDisplayInside =
6877 insertion.mParentFrame->StyleDisplay()->DisplayInside();
6878
6879 // Examine the insertion.mParentFrame where the insertion is taking
6880 // place. If it's a certain kind of container then some special
6881 // processing is done.
6882 if (StyleDisplayInside::Flow == parentDisplayInside) {
6883 // Recover the special style flags for the containing block
6884 if (containingBlock) {
6885 haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
6886 haveFirstLineStyle = ShouldHaveFirstLineStyle(
6887 containingBlock->GetContent(), containingBlock->Style());
6888 }
6889
6890 if (haveFirstLetterStyle) {
6891 // If our current insertion.mParentFrame is a Letter frame, use its parent
6892 // as our new parent hint
6893 if (insertion.mParentFrame->IsLetterFrame()) {
6894 // If insertion.mParentFrame is out of flow, then we actually want the
6895 // parent of the placeholder frame.
6896 if (insertion.mParentFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
6897 nsPlaceholderFrame* placeholderFrame =
6898 insertion.mParentFrame->GetPlaceholderFrame();
6899 NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?")do { if (!(placeholderFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "No placeholder for out-of-flow?", "placeholderFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6899); MOZ_PretendNoReturn(); } } while (0)
;
6900 insertion.mParentFrame = placeholderFrame->GetParent();
6901 } else {
6902 insertion.mParentFrame = insertion.mParentFrame->GetParent();
6903 }
6904 }
6905
6906 // Remove the old letter frames before doing the insertion
6907 RemoveLetterFrames(mPresShell, state.mFloatedList.mContainingBlock);
6908
6909 // Removing the letterframes messes around with the frame tree, removing
6910 // and creating frames. We need to reget our prevsibling, parent frame,
6911 // etc.
6912 prevSibling = GetInsertionPrevSibling(&insertion, aStartChild, &isAppend,
6913 &isRangeInsertSafe);
6914
6915 // Need check whether a range insert is still safe.
6916 if (!isSingleInsert && !isRangeInsertSafe) {
6917 // Need to recover the letter frames first.
6918 RecoverLetterFrames(state.mFloatedList.mContainingBlock);
6919
6920 // must fall back to a single ContertInserted for each child in the
6921 // range
6922 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
6923 IssueSingleInsertNofications(aStartChild, aEndChild,
6924 InsertionKind::Sync);
6925 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
6926 return;
6927 }
6928
6929 frameType = insertion.mParentFrame->Type();
6930 }
6931 }
6932
6933 // This handles fallback to 'list-style-type' when a 'list-style-image' fails
6934 // to load.
6935 if (aStartChild->IsInNativeAnonymousSubtree() &&
6936 aStartChild->IsHTMLElement(nsGkAtoms::mozgeneratedcontentimage)) {
6937 MOZ_ASSERT(isSingleInsert)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isSingleInsert)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isSingleInsert))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isSingleInsert"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isSingleInsert"
")"); do { *((volatile int*)__null) = 6937; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6938 MOZ_ASSERT(insertion.mParentFrame->Style()->GetPseudoType() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertion.mParentFrame->Style()->GetPseudoType
() == PseudoStyleType::marker)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(insertion.mParentFrame->Style
()->GetPseudoType() == PseudoStyleType::marker))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
" (" "we can only handle ::marker fallback for now" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6940; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6939 PseudoStyleType::marker,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertion.mParentFrame->Style()->GetPseudoType
() == PseudoStyleType::marker)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(insertion.mParentFrame->Style
()->GetPseudoType() == PseudoStyleType::marker))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
" (" "we can only handle ::marker fallback for now" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6940; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6940 "we can only handle ::marker fallback for now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertion.mParentFrame->Style()->GetPseudoType
() == PseudoStyleType::marker)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(insertion.mParentFrame->Style
()->GetPseudoType() == PseudoStyleType::marker))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
" (" "we can only handle ::marker fallback for now" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mParentFrame->Style()->GetPseudoType() == PseudoStyleType::marker"
") (" "we can only handle ::marker fallback for now" ")"); do
{ *((volatile int*)__null) = 6940; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6941 nsIContent* const nextSibling = aStartChild->GetNextSibling();
6942 MOZ_ASSERT(nextSibling && nextSibling->IsText(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nextSibling && nextSibling->IsText())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nextSibling && nextSibling->IsText()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("nextSibling && nextSibling->IsText()"
" (" "expected a text node after the list-style-image image"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nextSibling && nextSibling->IsText()"
") (" "expected a text node after the list-style-image image"
")"); do { *((volatile int*)__null) = 6943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6943 "expected a text node after the list-style-image image")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nextSibling && nextSibling->IsText())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nextSibling && nextSibling->IsText()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("nextSibling && nextSibling->IsText()"
" (" "expected a text node after the list-style-image image"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nextSibling && nextSibling->IsText()"
") (" "expected a text node after the list-style-image image"
")"); do { *((volatile int*)__null) = 6943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6944 DestroyContext context(mPresShell);
6945 RemoveFrame(context, FrameChildListID::Principal,
6946 nextSibling->GetPrimaryFrame());
6947 auto* const container = aStartChild->GetParent()->AsElement();
6948 nsIContent* firstNewChild = nullptr;
6949 auto InsertChild = [this, container, nextSibling,
6950 &firstNewChild](RefPtr<nsIContent>&& aChild) {
6951 // We don't strictly have to set NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE
6952 // here; it would get set under AppendChildTo. But AppendChildTo might
6953 // think that we're going from not being anonymous to being anonymous and
6954 // do some extra work; setting the flag here avoids that.
6955 aChild->SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
6956 container->InsertChildBefore(aChild, nextSibling, false, IgnoreErrors());
6957 if (auto* childElement = Element::FromNode(aChild)) {
6958 // If we created any children elements, Servo needs to traverse them,
6959 // but the root is already set up.
6960 mPresShell->StyleSet()->StyleNewSubtree(childElement);
6961 }
6962 if (!firstNewChild) {
6963 firstNewChild = aChild;
6964 }
6965 };
6966 CreateGeneratedContentFromListStyleType(
6967 state, *insertion.mContainer->AsElement(),
6968 *insertion.mParentFrame->Style(), InsertChild);
6969 if (!firstNewChild) {
6970 // No fallback content - we're done.
6971 return;
6972 }
6973 aStartChild = firstNewChild;
6974 MOZ_ASSERT(firstNewChild->GetNextSibling() == nextSibling,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(firstNewChild->GetNextSibling() == nextSibling)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(firstNewChild->GetNextSibling() == nextSibling)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("firstNewChild->GetNextSibling() == nextSibling"
" (" "list-style-type should only create one child" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6975); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstNewChild->GetNextSibling() == nextSibling"
") (" "list-style-type should only create one child" ")"); do
{ *((volatile int*)__null) = 6975; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6975 "list-style-type should only create one child")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(firstNewChild->GetNextSibling() == nextSibling)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(firstNewChild->GetNextSibling() == nextSibling)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("firstNewChild->GetNextSibling() == nextSibling"
" (" "list-style-type should only create one child" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 6975); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstNewChild->GetNextSibling() == nextSibling"
") (" "list-style-type should only create one child" ")"); do
{ *((volatile int*)__null) = 6975; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6976 }
6977
6978 AutoFrameConstructionItemList items(this);
6979 RefPtr<ComputedStyle> parentStyle =
6980 ResolveComputedStyle(insertion.mContainer);
6981 ParentType parentType = GetParentType(frameType);
6982 FlattenedChildIterator iter(insertion.mContainer);
6983 const bool haveNoShadowDOM =
6984 !iter.ShadowDOMInvolved() || !iter.GetNextChild();
6985 if (aStartChild->GetPreviousSibling() && parentType == eTypeBlock &&
6986 haveNoShadowDOM) {
6987 // If there's a text node in the normal content list just before the
6988 // new nodes, and it has no frame, make a frame construction item for
6989 // it, because it might need a frame now. No need to do this if our
6990 // parent type is not block, though, since WipeContainingBlock
6991 // already handles that situation.
6992 AddTextItemIfNeeded(state, *parentStyle, insertion,
6993 aStartChild->GetPreviousSibling(), items);
6994 }
6995
6996 if (isSingleInsert) {
6997 AddFrameConstructionItems(state, aStartChild,
6998 aStartChild->IsRootOfNativeAnonymousSubtree(),
6999 *parentStyle, insertion, items);
7000 } else {
7001 for (nsIContent* child = aStartChild; child != aEndChild;
7002 child = child->GetNextSibling()) {
7003 AddFrameConstructionItems(state, child, false, *parentStyle, insertion,
7004 items);
7005 }
7006 }
7007
7008 if (aEndChild && parentType == eTypeBlock && haveNoShadowDOM) {
7009 // If there's a text node in the normal content list just after the
7010 // new nodes, and it has no frame, make a frame construction item for
7011 // it, because it might need a frame now. No need to do this if our
7012 // parent type is not block, though, since WipeContainingBlock
7013 // already handles that situation.
7014 AddTextItemIfNeeded(state, *parentStyle, insertion, aEndChild, items);
7015 }
7016
7017 // Perform special check for diddling around with the frames in
7018 // a special inline frame.
7019 // If we're appending before :after content, then we're not really
7020 // appending, so let WipeContainingBlock know that.
7021 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7022 if (WipeContainingBlock(state, containingBlock, insertion.mParentFrame, items,
7023 isAppend, prevSibling)) {
7024 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7025 return;
7026 }
7027 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7028
7029 nsFrameConstructorSaveState floatSaveState;
7030 state.MaybePushFloatContainingBlock(insertion.mParentFrame, floatSaveState);
7031
7032 if (state.mPresContext->IsPaginated()) {
7033 // Because this function can be called outside frame construction, we need
7034 // to set state.mAutoPageNameValue based on what the parent frame's auto
7035 // value is.
7036 // Calling this from outside the frame constructor can violate many of the
7037 // expectations in AutoFrameConstructionPageName, and unlike during frame
7038 // construction we already have an auto value from parentFrame, so we do
7039 // not use AutoFrameConstructionPageName here.
7040 state.mAutoPageNameValue = insertion.mParentFrame->GetAutoPageValue();
7041#ifdef DEBUG1
7042 insertion.mParentFrame->mWasVisitedByAutoFrameConstructionPageName = true;
7043#endif
7044 }
7045
7046 // If the container is a table and a caption will be appended, it needs to be
7047 // put in the table wrapper frame's additional child list.
7048 // We make no attempt here to set flags to indicate whether the list
7049 // will be at the start or end of a block. It doesn't seem worthwhile.
7050 nsFrameList frameList, captionList;
7051 ConstructFramesFromItemList(state, items, insertion.mParentFrame,
7052 ParentIsWrapperAnonBox(insertion.mParentFrame),
7053 frameList);
7054
7055 if (frameList.NotEmpty()) {
7056 for (nsIContent* child = aStartChild; child != aEndChild;
7057 child = child->GetNextSibling()) {
7058 InvalidateCanvasIfNeeded(mPresShell, child);
7059 }
7060
7061 if (LayoutFrameType::Table == frameType ||
7062 LayoutFrameType::TableWrapper == frameType) {
7063 PullOutCaptionFrames(frameList, captionList);
7064 if (prevSibling && prevSibling->IsTableCaption()) {
7065 // This can happen, but only if the table is empty (otherwise
7066 // SafeToInsertPseudoNeedingChildren bails).
7067 prevSibling = nullptr;
7068 }
7069 }
7070 }
7071
7072 if (haveFirstLineStyle && insertion.mParentFrame == containingBlock &&
7073 isAppend) {
7074 // It's possible that the new frame goes into a first-line
7075 // frame. Look at it and see...
7076 AppendFirstLineFrames(state, containingBlock->GetContent(), containingBlock,
7077 frameList);
7078 } else if (insertion.mParentFrame->Style()->HasPseudoElementData()) {
7079 CheckForFirstLineInsertion(insertion.mParentFrame, frameList);
7080 CheckForFirstLineInsertion(insertion.mParentFrame, captionList);
7081 }
7082
7083 // We might have captions; put them into the caption list of the
7084 // table wrapper frame.
7085 if (captionList.NotEmpty()) {
7086 NS_ASSERTION(LayoutFrameType::Table == frameType ||do { if (!(LayoutFrameType::Table == frameType || LayoutFrameType
::TableWrapper == frameType)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "parent for caption is not table?", "LayoutFrameType::Table == frameType || LayoutFrameType::TableWrapper == frameType"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7088); MOZ_PretendNoReturn(); } } while (0)
7087 LayoutFrameType::TableWrapper == frameType,do { if (!(LayoutFrameType::Table == frameType || LayoutFrameType
::TableWrapper == frameType)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "parent for caption is not table?", "LayoutFrameType::Table == frameType || LayoutFrameType::TableWrapper == frameType"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7088); MOZ_PretendNoReturn(); } } while (0)
7088 "parent for caption is not table?")do { if (!(LayoutFrameType::Table == frameType || LayoutFrameType
::TableWrapper == frameType)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "parent for caption is not table?", "LayoutFrameType::Table == frameType || LayoutFrameType::TableWrapper == frameType"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7088); MOZ_PretendNoReturn(); } } while (0)
;
7089 // We need to determine where to put the caption items; start with the
7090 // the parent frame that has already been determined and get the insertion
7091 // prevsibling of the first caption item.
7092 bool captionIsAppend;
7093 nsIFrame* captionPrevSibling = nullptr;
7094
7095 // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
7096 bool ignored;
7097 InsertionPoint captionInsertion = insertion;
7098 if (isSingleInsert) {
7099 captionPrevSibling = GetInsertionPrevSibling(
7100 &captionInsertion, aStartChild, &captionIsAppend, &ignored);
7101 } else {
7102 nsIContent* firstCaption = captionList.FirstChild()->GetContent();
7103 // It is very important here that we skip the children in
7104 // [aStartChild,aEndChild) when looking for a
7105 // prevsibling.
7106 captionPrevSibling = GetInsertionPrevSibling(
7107 &captionInsertion, firstCaption, &captionIsAppend, &ignored,
7108 aStartChild, aEndChild);
7109 }
7110
7111 nsContainerFrame* outerTable =
7112 captionInsertion.mParentFrame->IsTableFrame()
7113 ? captionInsertion.mParentFrame->GetParent()
7114 : captionInsertion.mParentFrame;
7115
7116 // If the parent is not a table wrapper frame we will try to add frames
7117 // to a named child list that the parent does not honor and the frames
7118 // will get lost.
7119 MOZ_ASSERT(outerTable->IsTableWrapperFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outerTable->IsTableWrapperFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outerTable->IsTableWrapperFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("outerTable->IsTableWrapperFrame()" " (" "Pseudo frame construction failure; "
"a caption can be only a child of a table wrapper frame" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerTable->IsTableWrapperFrame()"
") (" "Pseudo frame construction failure; " "a caption can be only a child of a table wrapper frame"
")"); do { *((volatile int*)__null) = 7121; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7120 "Pseudo frame construction failure; "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outerTable->IsTableWrapperFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outerTable->IsTableWrapperFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("outerTable->IsTableWrapperFrame()" " (" "Pseudo frame construction failure; "
"a caption can be only a child of a table wrapper frame" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerTable->IsTableWrapperFrame()"
") (" "Pseudo frame construction failure; " "a caption can be only a child of a table wrapper frame"
")"); do { *((volatile int*)__null) = 7121; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7121 "a caption can be only a child of a table wrapper frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(outerTable->IsTableWrapperFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(outerTable->IsTableWrapperFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("outerTable->IsTableWrapperFrame()" " (" "Pseudo frame construction failure; "
"a caption can be only a child of a table wrapper frame" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "outerTable->IsTableWrapperFrame()"
") (" "Pseudo frame construction failure; " "a caption can be only a child of a table wrapper frame"
")"); do { *((volatile int*)__null) = 7121; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7122
7123 // If the parent of our current prevSibling is different from the frame
7124 // we'll actually use as the parent, then the calculated insertion
7125 // point is now invalid (bug 341382).
7126 if (captionPrevSibling && captionPrevSibling->GetParent() != outerTable) {
7127 captionPrevSibling = nullptr;
7128 }
7129
7130 captionList.ApplySetParent(outerTable);
7131 if (captionIsAppend) {
7132 AppendFrames(outerTable, FrameChildListID::Caption,
7133 std::move(captionList));
7134 } else {
7135 InsertFrames(outerTable, FrameChildListID::Caption, captionPrevSibling,
7136 std::move(captionList));
7137 }
7138 }
7139
7140 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7141 if (MaybeRecreateForColumnSpan(state, insertion.mParentFrame, frameList,
7142 prevSibling)) {
7143 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7144 return;
7145 }
7146 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7147
7148 if (frameList.NotEmpty()) {
7149 // Notify the parent frame
7150 if (isAppend) {
7151 AppendFramesToParent(state, insertion.mParentFrame, frameList,
7152 prevSibling);
7153 } else {
7154 InsertFrames(insertion.mParentFrame, FrameChildListID::Principal,
7155 prevSibling, std::move(frameList));
7156 }
7157 }
7158
7159 if (haveFirstLetterStyle) {
7160 // Recover the letter frames for the containing block when
7161 // it has first-letter style.
7162 RecoverLetterFrames(state.mFloatedList.mContainingBlock);
7163 }
7164
7165#ifdef DEBUG1
7166 if (gReallyNoisyContentUpdates && insertion.mParentFrame) {
7167 printf(
7168 "nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
7169 "model:\n");
7170 insertion.mParentFrame->List(stdoutstdout);
7171 }
7172#endif
7173
7174#ifdef ACCESSIBILITY1
7175 if (nsAccessibilityService* accService = GetAccService()) {
7176 accService->ContentRangeInserted(mPresShell, aStartChild, aEndChild);
7177 }
7178#endif
7179}
7180
7181static bool IsWhitespaceFrame(const nsIFrame* aFrame) {
7182 MOZ_ASSERT(aFrame, "invalid argument")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "invalid argument"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"invalid argument" ")"); do { *((volatile int*)__null) = 7182
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7183 return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
7184}
7185
7186static bool IsSyntheticColGroup(const nsIFrame* aFrame) {
7187 return aFrame->IsTableColGroupFrame() &&
7188 static_cast<const nsTableColGroupFrame*>(aFrame)->IsSynthetic();
7189}
7190
7191static bool IsOnlyNonWhitespaceFrameInList(const nsFrameList& aFrameList,
7192 const nsIFrame* aFrame) {
7193 for (const nsIFrame* f : aFrameList) {
7194 if (f == aFrame) {
7195 // If we have continuations, ignore them too.
7196 aFrame = aFrame->GetNextContinuation();
7197 } else if (!IsWhitespaceFrame(f) && !IsSyntheticColGroup(f)) {
7198 // Synthetic colgroups get created unconditionally, so let's not consider
7199 // them as giving us a non-whitespace frame.
7200 return false;
7201 }
7202 }
7203 return true;
7204}
7205
7206static bool AllChildListsAreEffectivelyEmpty(nsIFrame* aFrame) {
7207 for (auto& [list, listID] : aFrame->ChildLists()) {
7208 if (list.IsEmpty()) {
7209 continue;
7210 }
7211 // We have some existing frame, usually that would be considered as making
7212 // this list nonempty. But let's make an exception for the synthetic
7213 // colgroup that tables have, since that gets created unconditionally.
7214 if (listID == FrameChildListID::ColGroup) {
7215 if (nsIFrame* f = list.OnlyChild(); f && IsSyntheticColGroup(f)) {
7216 continue;
7217 }
7218 }
7219 return false;
7220 }
7221 return true;
7222}
7223
7224static bool SafeToInsertPseudoNeedingChildren(nsIFrame* aFrame) {
7225 return AllChildListsAreEffectivelyEmpty(aFrame);
7226}
7227
7228// Returns true if aFrame is the only meaningful child of aParent (which is
7229// known to be a wrapper-pseudo). This lets us determine whether aParent can be
7230// removed, as a result of aFrame being removed.
7231static bool IsOnlyMeaningfulChildOfWrapperPseudo(nsIFrame* aFrame,
7232 nsIFrame* aParent) {
7233 MOZ_ASSERT(IsWrapperPseudo(aParent))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsWrapperPseudo(aParent))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsWrapperPseudo(aParent)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("IsWrapperPseudo(aParent)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsWrapperPseudo(aParent)"
")"); do { *((volatile int*)__null) = 7233; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7234 // Handle a few special cases with tables and colgroups / captions.
7235 if (aParent->IsTableFrame()) {
7236 auto* wrapper = aParent->GetParent();
7237 MOZ_ASSERT(wrapper)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(wrapper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(wrapper))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("wrapper", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapper" ")"
); do { *((volatile int*)__null) = 7237; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7238 MOZ_ASSERT(wrapper->IsTableWrapperFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(wrapper->IsTableWrapperFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(wrapper->IsTableWrapperFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("wrapper->IsTableWrapperFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapper->IsTableWrapperFrame()"
")"); do { *((volatile int*)__null) = 7238; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7239 MOZ_ASSERT(!aFrame->IsTableCaption(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableCaption())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableCaption()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->IsTableCaption()" " (" "Caption parent should be the wrapper"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "Caption parent should be the wrapper" ")"); do { *((volatile
int*)__null) = 7240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7240 "Caption parent should be the wrapper")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableCaption())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableCaption()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->IsTableCaption()" " (" "Caption parent should be the wrapper"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "Caption parent should be the wrapper" ")"); do { *((volatile
int*)__null) = 7240; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7241 // We can't remove the table if there are any captions present (captions are
7242 // never anonymous themselves), because table wrapper always relies on
7243 // having a table frame.
7244 if (!wrapper->GetChildList(FrameChildListID::Caption).IsEmpty()) {
7245 return false;
7246 }
7247 // Similarly we can't remove the table if there's still a non-anonymous col
7248 // group (unless aFrame _is_ the non-anonymous colgroup).
7249 if (aFrame->IsTableColGroupFrame()) {
7250 return aParent->PrincipalChildList().IsEmpty() &&
7251 IsOnlyNonWhitespaceFrameInList(
7252 aParent->GetChildList(FrameChildListID::ColGroup), aFrame);
7253 }
7254 const auto& colGroupList =
7255 aParent->GetChildList(FrameChildListID::ColGroup);
7256 if (!colGroupList.IsEmpty()) {
7257 nsIFrame* f = colGroupList.OnlyChild();
7258 if (!f || !IsSyntheticColGroup(f)) {
7259 return false;
7260 }
7261 }
7262 }
7263 if (aFrame->IsTableCaption()) {
7264 MOZ_ASSERT(aParent->IsTableWrapperFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->IsTableWrapperFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent->IsTableWrapperFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent->IsTableWrapperFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->IsTableWrapperFrame()"
")"); do { *((volatile int*)__null) = 7264; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7265 MOZ_ASSERT(aParent->PrincipalChildList().OnlyChild())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->PrincipalChildList().OnlyChild())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aParent->PrincipalChildList().OnlyChild()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aParent->PrincipalChildList().OnlyChild()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->PrincipalChildList().OnlyChild()"
")"); do { *((volatile int*)__null) = 7265; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7266 MOZ_ASSERT(aParent->PrincipalChildList().OnlyChild()->IsTableFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->PrincipalChildList().OnlyChild()->IsTableFrame
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aParent->PrincipalChildList().OnlyChild()->IsTableFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent->PrincipalChildList().OnlyChild()->IsTableFrame()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent->PrincipalChildList().OnlyChild()->IsTableFrame()"
")"); do { *((volatile int*)__null) = 7266; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7267 return IsOnlyNonWhitespaceFrameInList(
7268 aParent->GetChildList(FrameChildListID::Caption), aFrame) &&
7269 // This checks for both colgroups and the principal list of the table
7270 // frame.
7271 AllChildListsAreEffectivelyEmpty(
7272 aParent->PrincipalChildList().OnlyChild());
7273 }
7274 MOZ_ASSERT(!aFrame->IsTableColGroupFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableColGroupFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableColGroupFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aFrame->IsTableColGroupFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7274); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableColGroupFrame()"
")"); do { *((volatile int*)__null) = 7274; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7275 return IsOnlyNonWhitespaceFrameInList(aParent->PrincipalChildList(), aFrame);
7276}
7277
7278static bool CanRemoveWrapperPseudoForChildRemoval(nsIFrame* aFrame,
7279 nsIFrame* aParent) {
7280 if (!IsOnlyMeaningfulChildOfWrapperPseudo(aFrame, aParent)) {
7281 return false;
7282 }
7283 if (aParent->IsRubyBaseContainerFrame()) {
7284 // We can't remove the first ruby base container of a ruby frame unless
7285 // it has no siblings. See CreateNeededPseudoSiblings.
7286 return aParent->GetPrevSibling() || !aParent->GetNextSibling();
7287 }
7288 return true;
7289}
7290
7291bool nsCSSFrameConstructor::ContentWillBeRemoved(nsIContent* aChild,
7292 RemoveFlags aFlags) {
7293 MOZ_ASSERT(aChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aChild", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7293); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ")"
); do { *((volatile int*)__null) = 7293; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7294 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChild->IsRootOfNativeAnonymousSubtree() || !aChild
->GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChild->IsRootOfNativeAnonymousSubtree
() || !aChild->GetNextSibling()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling()"
" (" "Anonymous roots don't have siblings" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling()"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7296; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7295 !aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChild->IsRootOfNativeAnonymousSubtree() || !aChild
->GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChild->IsRootOfNativeAnonymousSubtree
() || !aChild->GetNextSibling()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling()"
" (" "Anonymous roots don't have siblings" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling()"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7296; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7296 "Anonymous roots don't have siblings")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChild->IsRootOfNativeAnonymousSubtree() || !aChild
->GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChild->IsRootOfNativeAnonymousSubtree
() || !aChild->GetNextSibling()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling()"
" (" "Anonymous roots don't have siblings" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild->IsRootOfNativeAnonymousSubtree() || !aChild->GetNextSibling()"
") (" "Anonymous roots don't have siblings" ")"); do { *((volatile
int*)__null) = 7296; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7297 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::ContentWillBeRemoved",mozilla::AutoProfilerLabelHot raiiObject7298( "nsCSSFrameConstructor::ContentWillBeRemoved"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
7298 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject7298( "nsCSSFrameConstructor::ContentWillBeRemoved"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
7299 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
7300 nsPresContext* presContext = mPresShell->GetPresContext();
7301 MOZ_ASSERT(presContext, "Our presShell should have a valid presContext")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(presContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(presContext))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("presContext" " ("
"Our presShell should have a valid presContext" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "presContext"
") (" "Our presShell should have a valid presContext" ")"); do
{ *((volatile int*)__null) = 7301; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7302
7303 const bool wasRemovingContent = mRemovingContent;
7304 auto _ = MakeScopeExit([&] { mRemovingContent = wasRemovingContent; });
7305 mRemovingContent = true;
7306
7307 // We want to detect when the viewport override element stored in the
7308 // prescontext is in the subtree being removed. Except in fullscreen cases
7309 // (which are handled in Element::UnbindFromTree and do not get stored on the
7310 // prescontext), the override element is always either the root element or a
7311 // <body> child of the root element. So we can only be removing the stored
7312 // override element if the thing being removed is either the override element
7313 // itself or the root element (which can be a parent of the override element).
7314 //
7315 // The !wasRemovingContent check makes sure that we don't re-enter here from
7316 // other ContentWillBeRemoved calls, as that'd be useless work, and we don't
7317 // want to incorrectly pick aChild again as our viewport scroll style element
7318 // if it's getting removed from the DOM.
7319 if ((aChild == presContext->GetViewportScrollStylesOverrideElement() ||
7320 aChild->IsRootElement()) &&
7321 !wasRemovingContent) {
7322 // We might be removing the element that we propagated viewport scrollbar
7323 // styles from. Recompute those. (This clause covers two of the three
7324 // possible scrollbar-propagation sources: the <body> [as aChild or a
7325 // descendant] and the root node. The other possible scrollbar-propagation
7326 // source is a fullscreen element, and we have code elsewhere to update
7327 // scrollbars after fullscreen elements are removed -- specifically, it's
7328 // part of the fullscreen cleanup code called by Element::UnbindFromTree.
7329 // We don't handle the fullscreen case here, because it doesn't change the
7330 // scrollbar styles override element stored on the prescontext.)
7331 const Element* removingElement =
7332 aFlags == REMOVE_CONTENT ? aChild->AsElement() : nullptr;
7333 Element* newOverrideElement =
7334 presContext->UpdateViewportScrollStylesOverride(removingElement);
7335
7336 // If aChild is the root, then we don't need to do any reframing of
7337 // newOverrideElement, because we're about to tear down the whole frame tree
7338 // anyway. And we need to make sure we don't do any such reframing, because
7339 // reframing the <body> can trigger a reframe of the <html> and then reenter
7340 // here.
7341 //
7342 // But if aChild is not the root, and if newOverrideElement is not the root
7343 // and isn't aChild (which it could be if all we're doing here is reframing
7344 // the current override element), it needs reframing. In particular, it
7345 // used to have a scrollframe (because its overflow was not "visible"), but
7346 // now it will propagate its overflow to the viewport, so it should not need
7347 // a scrollframe anymore.
7348 if (aChild->GetParent() && newOverrideElement &&
7349 newOverrideElement->GetParent() && newOverrideElement != aChild) {
7350 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7351 RecreateFramesForContent(newOverrideElement, InsertionKind::Async);
7352 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7353 }
7354 }
7355
7356#ifdef DEBUG1
7357 if (gNoisyContentUpdates) {
7358 printf(
7359 "nsCSSFrameConstructor::ContentWillBeRemoved container=%p child=%p\n",
7360 aChild->GetParent(), aChild);
7361 if (gReallyNoisyContentUpdates) {
7362 aChild->GetParent()->List(stdoutstdout, 0);
7363 }
7364 }
7365#endif
7366
7367 nsIFrame* childFrame = aChild->GetPrimaryFrame();
7368 if (!childFrame || childFrame->GetContent() != aChild) {
7369 // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7370 // Remove it once that's fixed.
7371 childFrame = nullptr;
7372 }
7373
7374 // If we're removing the root, then make sure to remove things starting at
7375 // the viewport's child instead of the primary frame (which might even be
7376 // null if the root was display:none, even though the frames above it got
7377 // created). Detecting removal of a root is a little exciting; in particular,
7378 // having no parent is necessary but NOT sufficient.
7379 //
7380 // Due to how we process reframes, the content node might not even be in our
7381 // document by now. So explicitly check whether the viewport's first kid's
7382 // content node is aChild.
7383 //
7384 // FIXME(emilio): I think the "might not be in our document" bit is impossible
7385 // now.
7386 bool isRoot = false;
7387 if (!aChild->GetParent()) {
7388 if (nsIFrame* viewport = GetRootFrame()) {
7389 nsIFrame* firstChild = viewport->PrincipalChildList().FirstChild();
7390 if (firstChild && firstChild->GetContent() == aChild) {
7391 isRoot = true;
7392 childFrame = firstChild;
7393 NS_ASSERTION(!childFrame->GetNextSibling(), "How did that happen?")do { if (!(!childFrame->GetNextSibling())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "How did that happen?", "!childFrame->GetNextSibling()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7393); MOZ_PretendNoReturn(); } } while (0)
;
7394 }
7395 }
7396 }
7397
7398 // We need to be conservative about when to determine whether something has
7399 // display: contents or not because at this point our actual display may be
7400 // different.
7401 //
7402 // Consider the case of:
7403 //
7404 // <div id="A" style="display: contents"><div id="B"></div></div>
7405 //
7406 // If we reconstruct A because its display changed to "none", we still need to
7407 // cleanup the frame on B, but A's display is now "none", so we can't poke at
7408 // the style of it.
7409 //
7410 // FIXME(emilio, bug 1450366): We can make this faster without adding much
7411 // complexity for the display: none -> other case, which right now
7412 // unnecessarily walks the content tree down.
7413 auto CouldHaveBeenDisplayContents = [aFlags](nsIContent* aContent) -> bool {
7414 return aFlags == REMOVE_FOR_RECONSTRUCTION || IsDisplayContents(aContent);
7415 };
7416
7417 if (!childFrame && CouldHaveBeenDisplayContents(aChild)) {
7418 // NOTE(emilio): We may iterate through ::before and ::after here and they
7419 // may be gone after the respective ContentWillBeRemoved call. Right now
7420 // StyleChildrenIterator handles that properly, so it's not an issue.
7421 StyleChildrenIterator iter(aChild);
7422 for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
7423 if (c->GetPrimaryFrame() || CouldHaveBeenDisplayContents(c)) {
7424 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7425 bool didReconstruct = ContentWillBeRemoved(c, aFlags);
7426 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7427 if (didReconstruct) {
7428 return true;
7429 }
7430 }
7431 }
7432 return false;
7433 }
7434
7435 if (childFrame) {
7436 if (aFlags == REMOVE_FOR_RECONSTRUCTION) {
7437 // Before removing the frames associated with the content object,
7438 // ask them to save their state onto our state object.
7439 CaptureStateForFramesOf(aChild, mFrameTreeState);
7440 }
7441
7442 InvalidateCanvasIfNeeded(mPresShell, aChild);
7443
7444 // See whether we need to remove more than just childFrame
7445 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7446 if (MaybeRecreateContainerForFrameRemoval(childFrame)) {
7447 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7448 return true;
7449 }
7450 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7451
7452 // Get the childFrame's parent frame
7453 nsIFrame* parentFrame = childFrame->GetParent();
7454 LayoutFrameType parentType = parentFrame->Type();
7455
7456 if (parentType == LayoutFrameType::FrameSet &&
7457 IsSpecialFramesetChild(aChild)) {
7458 // Just reframe the parent, since framesets are weird like that.
7459 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7460 RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
7461 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7462 return true;
7463 }
7464
7465 // If we're a child of MathML, then we should reframe the MathML content.
7466 // If we're non-MathML, then we would be wrapped in a block so we need to
7467 // check our grandparent in that case.
7468 nsIFrame* possibleMathMLAncestor = parentType == LayoutFrameType::Block
7469 ? parentFrame->GetParent()
7470 : parentFrame;
7471 if (possibleMathMLAncestor->IsMathMLFrame()) {
7472 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7473 RecreateFramesForContent(parentFrame->GetContent(), InsertionKind::Async);
7474 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7475 return true;
7476 }
7477
7478#ifdef ACCESSIBILITY1
7479 if (aFlags != REMOVE_FOR_RECONSTRUCTION) {
7480 if (nsAccessibilityService* accService = GetAccService()) {
7481 accService->ContentRemoved(mPresShell, aChild);
7482 }
7483 }
7484#endif
7485
7486 // Examine the containing-block for the removed content and see if
7487 // :first-letter style applies.
7488 nsIFrame* inflowChild = childFrame;
7489 if (childFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
7490 inflowChild = childFrame->GetPlaceholderFrame();
7491 NS_ASSERTION(inflowChild, "No placeholder for out-of-flow?")do { if (!(inflowChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "No placeholder for out-of-flow?"
, "inflowChild", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7491); MOZ_PretendNoReturn(); } } while (0)
;
7492 }
7493 nsContainerFrame* containingBlock =
7494 GetFloatContainingBlock(inflowChild->GetParent());
7495 bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
7496 if (haveFLS) {
7497 // Trap out to special routine that handles adjusting a blocks
7498 // frame tree when first-letter style is present.
7499#ifdef NOISY_FIRST_LETTER
7500 printf("ContentWillBeRemoved: containingBlock=");
7501 containingBlock->ListTag(stdoutstdout);
7502 printf(" parentFrame=");
7503 parentFrame->ListTag(stdoutstdout);
7504 printf(" childFrame=");
7505 childFrame->ListTag(stdoutstdout);
7506 printf("\n");
7507#endif
7508
7509 // First update the containing blocks structure by removing the
7510 // existing letter frames. This makes the subsequent logic
7511 // simpler.
7512 RemoveLetterFrames(mPresShell, containingBlock);
7513
7514 // Recover childFrame and parentFrame
7515 childFrame = aChild->GetPrimaryFrame();
7516 if (!childFrame || childFrame->GetContent() != aChild) {
7517 // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7518 // Remove it once that's fixed.
7519 return false;
7520 }
7521 parentFrame = childFrame->GetParent();
7522 parentType = parentFrame->Type();
Value stored to 'parentType' is never read
7523
7524#ifdef NOISY_FIRST_LETTER
7525 printf(" ==> revised parentFrame=");
7526 parentFrame->ListTag(stdoutstdout);
7527 printf(" childFrame=");
7528 childFrame->ListTag(stdoutstdout);
7529 printf("\n");
7530#endif
7531 }
7532
7533#ifdef DEBUG1
7534 if (gReallyNoisyContentUpdates) {
7535 printf("nsCSSFrameConstructor::ContentWillBeRemoved: childFrame=");
7536 childFrame->ListTag(stdoutstdout);
7537 putchar('\n');
7538 parentFrame->List(stdoutstdout);
7539 }
7540#endif
7541
7542 // Notify the parent frame that it should delete the frame
7543 if (childFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
7544 childFrame = childFrame->GetPlaceholderFrame();
7545 NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.")do { if (!(childFrame)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Missing placeholder frame for out of flow."
, "childFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7545); MOZ_PretendNoReturn(); } } while (0)
;
7546 parentFrame = childFrame->GetParent();
7547 }
7548
7549 // Take care of wrapper anonymous boxes that we might need to remove while
7550 // at it. Note that MaybeRecreateContainerForFrameRemoval takes care of
7551 // harder cases (merging sibling anonymous boxes etc).
7552 while (IsWrapperPseudo(parentFrame) &&
7553 CanRemoveWrapperPseudoForChildRemoval(childFrame, parentFrame)) {
7554 childFrame = parentFrame;
7555 parentFrame = childFrame->GetParent();
7556 }
7557
7558 DestroyContext context(mPresShell);
7559 RemoveFrame(context, nsLayoutUtils::GetChildListNameFor(childFrame),
7560 childFrame);
7561
7562 // NOTE(emilio): aChild could be dead here already if it is a ::before or
7563 // ::after pseudo-element (since in that case it was owned by childFrame,
7564 // which we just destroyed).
7565
7566 if (isRoot) {
7567 mRootElementFrame = nullptr;
7568 mRootElementStyleFrame = nullptr;
7569 mDocElementContainingBlock = nullptr;
7570 mCanvasFrame = nullptr;
7571 mPageSequenceFrame = nullptr;
7572 }
7573
7574 if (haveFLS && mRootElementFrame) {
7575 RecoverLetterFrames(containingBlock);
7576 }
7577
7578 // If we're just reconstructing frames for the element, then the
7579 // following ContentInserted notification on the element will
7580 // take care of fixing up any adjacent text nodes.
7581 if (aFlags == REMOVE_CONTENT) {
7582 MOZ_ASSERT(aChild->GetParentNode(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetParentNode())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChild->GetParentNode()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChild->GetParentNode()"
" (" "How did we have a sibling without a parent?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode()"
") (" "How did we have a sibling without a parent?" ")"); do
{ *((volatile int*)__null) = 7583; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7583 "How did we have a sibling without a parent?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetParentNode())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChild->GetParentNode()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aChild->GetParentNode()"
" (" "How did we have a sibling without a parent?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetParentNode()"
") (" "How did we have a sibling without a parent?" ")"); do
{ *((volatile int*)__null) = 7583; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7584 // Adjacent whitespace-only text nodes might have been suppressed if
7585 // this node does not have inline ends. Create frames for them now
7586 // if necessary.
7587 // Reframe any text node just before the node being removed, if there is
7588 // one, and if it's not the last child or the first child. If a whitespace
7589 // textframe was being suppressed and it's now the last child or first
7590 // child then it can stay suppressed since the parent must be a block
7591 // and hence it's adjacent to a block end.
7592 // If aOldNextSibling is null, then the text node before the node being
7593 // removed is the last node, and we don't need to worry about it.
7594 nsIContent* prevSibling = aChild->GetPreviousSibling();
7595 if (prevSibling && prevSibling->GetPreviousSibling()) {
7596 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7597 ReframeTextIfNeeded(prevSibling);
7598 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7599 }
7600 // Reframe any text node just after the node being removed, if there is
7601 // one, and if it's not the last child or the first child.
7602 nsIContent* nextSibling = aChild->GetNextSibling();
7603 if (nextSibling && prevSibling && nextSibling->GetNextSibling()) {
7604 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7605 ReframeTextIfNeeded(nextSibling);
7606 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7607 }
7608 }
7609
7610#ifdef DEBUG1
7611 if (gReallyNoisyContentUpdates && parentFrame) {
7612 printf(
7613 "nsCSSFrameConstructor::ContentWillBeRemoved: resulting frame "
7614 "model:\n");
7615 parentFrame->List(stdoutstdout);
7616 }
7617#endif
7618 }
7619
7620 return false;
7621}
7622
7623/**
7624 * This method invalidates the canvas when frames are removed or added for a
7625 * node that might have its background propagated to the canvas, i.e., a
7626 * document root node or an HTML BODY which is a child of the root node.
7627 *
7628 * @param aFrame a frame for a content node about to be removed or a frame that
7629 * was just created for a content node that was inserted.
7630 */
7631static void InvalidateCanvasIfNeeded(PresShell* aPresShell, nsIContent* aNode) {
7632 MOZ_ASSERT(aPresShell->GetRootFrame(), "What happened here?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresShell->GetRootFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresShell->GetRootFrame(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPresShell->GetRootFrame()" " (" "What happened here?" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell->GetRootFrame()"
") (" "What happened here?" ")"); do { *((volatile int*)__null
) = 7632; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
7633 MOZ_ASSERT(aPresShell->GetPresContext(), "Say what?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresShell->GetPresContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresShell->GetPresContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPresShell->GetPresContext()" " (" "Say what?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell->GetPresContext()"
") (" "Say what?" ")"); do { *((volatile int*)__null) = 7633
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7634
7635 // Note that both in ContentWillBeRemoved and ContentInserted the content
7636 // node will still have the right parent pointer, so looking at that is ok.
7637
7638 nsIContent* parent = aNode->GetParent();
7639 if (parent) {
7640 // Has a parent; might not be what we want
7641 nsIContent* grandParent = parent->GetParent();
7642 if (grandParent) {
7643 // Has a grandparent, so not what we want
7644 return;
7645 }
7646
7647 // Check whether it's an HTML body
7648 if (!aNode->IsHTMLElement(nsGkAtoms::body)) {
7649 return;
7650 }
7651 }
7652
7653 // At this point the node has no parent or it's an HTML <body> child of the
7654 // root. We might not need to invalidate in this case (eg we might be in
7655 // XHTML or something), but chances are we want to. Play it safe.
7656 // Invalidate the viewport.
7657
7658 nsIFrame* rootFrame = aPresShell->GetRootFrame();
7659 rootFrame->InvalidateFrameSubtree();
7660}
7661
7662bool nsCSSFrameConstructor::EnsureFrameForTextNodeIsCreatedAfterFlush(
7663 CharacterData* aContent) {
7664 if (!aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
7665 return false;
7666 }
7667
7668 if (mAlwaysCreateFramesForIgnorableWhitespace) {
7669 return false;
7670 }
7671
7672 // Text frame may have been suppressed. Disable suppression and signal that a
7673 // flush should be performed. We do this on a document-wide basis so that
7674 // pages that repeatedly query metrics for collapsed-whitespace text nodes
7675 // don't trigger pathological behavior.
7676 mAlwaysCreateFramesForIgnorableWhitespace = true;
7677 Element* root = mDocument->GetRootElement();
7678 if (!root) {
7679 return false;
7680 }
7681
7682 RestyleManager()->PostRestyleEvent(root, RestyleHint{0},
7683 nsChangeHint_ReconstructFrame);
7684 return true;
7685}
7686
7687void nsCSSFrameConstructor::CharacterDataChanged(
7688 nsIContent* aContent, const CharacterDataChangeInfo& aInfo) {
7689 AUTO_PROFILER_LABEL_HOT("nsCSSFrameConstructor::CharacterDataChanged",mozilla::AutoProfilerLabelHot raiiObject7690( "nsCSSFrameConstructor::CharacterDataChanged"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
7690 LAYOUT_FrameConstruction)mozilla::AutoProfilerLabelHot raiiObject7690( "nsCSSFrameConstructor::CharacterDataChanged"
, nullptr, JS::ProfilingCategoryPair::LAYOUT_FrameConstruction
)
;
7691 AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC)nsAutoLayoutPhase autoLayoutPhase((mPresShell->GetPresContext
()), (nsLayoutPhase::FrameC))
;
7692
7693 if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
7694 !aContent->TextIsOnlyWhitespace()) ||
7695 (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
7696 aContent->TextIsOnlyWhitespace())) {
7697#ifdef DEBUG1
7698 nsIFrame* frame = aContent->GetPrimaryFrame();
7699 NS_ASSERTION(!frame || !frame->IsGeneratedContentFrame(),do { if (!(!frame || !frame->IsGeneratedContentFrame())) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Bit should never be set on generated content"
, "!frame || !frame->IsGeneratedContentFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7700); MOZ_PretendNoReturn(); } } while (0)
7700 "Bit should never be set on generated content")do { if (!(!frame || !frame->IsGeneratedContentFrame())) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Bit should never be set on generated content"
, "!frame || !frame->IsGeneratedContentFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7700); MOZ_PretendNoReturn(); } } while (0)
;
7701#endif
7702 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7703 RecreateFramesForContent(aContent, InsertionKind::Async);
7704 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7705 return;
7706 }
7707
7708 // It's possible the frame whose content changed isn't inserted into the
7709 // frame hierarchy yet, or that there is no frame that maps the content
7710 if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
7711#if 0
7712 NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,do { if ((int(((mozilla::LogModule*)(nsIFrame::sFrameLogModule
))->Level()) & (0x1))) { printf_stderr ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p"
, aContent, ContentTag(aContent, 0), aSubContent, frame); } }
while (0)
7713 ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p",do { if ((int(((mozilla::LogModule*)(nsIFrame::sFrameLogModule
))->Level()) & (0x1))) { printf_stderr ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p"
, aContent, ContentTag(aContent, 0), aSubContent, frame); } }
while (0)
7714 aContent, ContentTag(aContent, 0),do { if ((int(((mozilla::LogModule*)(nsIFrame::sFrameLogModule
))->Level()) & (0x1))) { printf_stderr ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p"
, aContent, ContentTag(aContent, 0), aSubContent, frame); } }
while (0)
7715 aSubContent, frame))do { if ((int(((mozilla::LogModule*)(nsIFrame::sFrameLogModule
))->Level()) & (0x1))) { printf_stderr ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p"
, aContent, ContentTag(aContent, 0), aSubContent, frame); } }
while (0)
;
7716#endif
7717
7718 if (frame->HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI)) {
7719 LAYOUT_PHASE_TEMP_EXIT()do { autoLayoutPhase.Exit(); } while (0);
7720 RecreateFramesForContent(aContent, InsertionKind::Async);
7721 LAYOUT_PHASE_TEMP_REENTER()do { autoLayoutPhase.Enter(); } while (0);
7722 return;
7723 }
7724
7725 // Special check for text content that is a child of a letter frame. If
7726 // this happens, we should remove the letter frame, do whatever we're
7727 // planning to do with this notification, then put the letter frame back.
7728 // Note that this is basically what RecreateFramesForContent ends up doing;
7729 // the reason we dont' want to call that here is that our text content
7730 // could be native anonymous, in which case RecreateFramesForContent would
7731 // completely barf on it. And recreating the non-anonymous ancestor would
7732 // just lead us to come back into this notification (e.g. if quotes or
7733 // counters are involved), leading to a loop.
7734 nsContainerFrame* block = GetFloatContainingBlock(frame);
7735 bool haveFirstLetterStyle = false;
7736 if (block) {
7737 // See if the block has first-letter style applied to it.
7738 haveFirstLetterStyle = HasFirstLetterStyle(block);
7739 if (haveFirstLetterStyle) {
7740 RemoveLetterFrames(mPresShell, block);
7741 // Reget |frame|, since we might have killed it.
7742 // Do we really need to call CharacterDataChanged in this case, though?
7743 frame = aContent->GetPrimaryFrame();
7744 NS_ASSERTION(frame, "Should have frame here!")do { if (!(frame)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Should have frame here!"
, "frame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7744); MOZ_PretendNoReturn(); } } while (0)
;
7745 }
7746 }
7747
7748 // Notify the first frame that maps the content. It will generate a reflow
7749 // command
7750 frame->CharacterDataChanged(aInfo);
7751
7752 if (haveFirstLetterStyle) {
7753 RecoverLetterFrames(block);
7754 }
7755 }
7756}
7757
7758void nsCSSFrameConstructor::RecalcQuotesAndCounters() {
7759 nsAutoScriptBlocker scriptBlocker;
7760
7761 if (mQuotesDirty) {
7762 mQuotesDirty = false;
7763 mContainStyleScopeManager.RecalcAllQuotes();
7764 }
7765
7766 if (mCountersDirty) {
7767 mCountersDirty = false;
7768 mContainStyleScopeManager.RecalcAllCounters();
7769 }
7770
7771 NS_ASSERTION(!mQuotesDirty, "Quotes updates will be lost")do { if (!(!mQuotesDirty)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Quotes updates will be lost", "!mQuotesDirty", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7771); MOZ_PretendNoReturn(); } } while (0)
;
7772 NS_ASSERTION(!mCountersDirty, "Counter updates will be lost")do { if (!(!mCountersDirty)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Counter updates will be lost", "!mCountersDirty", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7772); MOZ_PretendNoReturn(); } } while (0)
;
7773}
7774
7775void nsCSSFrameConstructor::NotifyCounterStylesAreDirty() {
7776 mContainStyleScopeManager.SetAllCountersDirty();
7777 CountersDirty();
7778}
7779
7780void nsCSSFrameConstructor::WillDestroyFrameTree() {
7781#if defined(DEBUG_dbaron_off)
7782 mContainStyleScopeManager.DumpCounters();
7783#endif
7784
7785 // Prevent frame tree destruction from being O(N^2)
7786 mContainStyleScopeManager.Clear();
7787 nsFrameManager::Destroy();
7788}
7789
7790// STATIC
7791
7792// XXXbz I'd really like this method to go away. Once we have inline-block and
7793// I can just use that for sized broken images, that can happen, maybe.
7794//
7795// NOTE(emilio): This needs to match MozAltContent handling.
7796void nsCSSFrameConstructor::GetAlternateTextFor(const Element& aElement,
7797 nsAString& aAltText) {
7798 // The "alt" attribute specifies alternate text that is rendered
7799 // when the image can not be displayed.
7800 if (aElement.GetAttr(nsGkAtoms::alt, aAltText)) {
7801 return;
7802 }
7803
7804 if (aElement.IsHTMLElement(nsGkAtoms::input)) {
7805 // If there's no "alt" attribute, and aElement is an input element, then use
7806 // the value of the "value" attribute.
7807 if (aElement.GetAttr(nsGkAtoms::value, aAltText)) {
7808 return;
7809 }
7810
7811 // If there's no "value" attribute either, then use the localized string for
7812 // "Submit" as the alternate text.
7813 nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
7814 "Submit", aElement.OwnerDoc(),
7815 aAltText);
7816 }
7817}
7818
7819nsIFrame* nsCSSFrameConstructor::CreateContinuingOuterTableFrame(
7820 nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent,
7821 ComputedStyle* aComputedStyle) {
7822 nsTableWrapperFrame* newFrame =
7823 NS_NewTableWrapperFrame(mPresShell, aComputedStyle);
7824
7825 newFrame->Init(aContent, aParentFrame, aFrame);
7826
7827 // Create a continuing inner table frame, and if there's a caption then
7828 // replicate the caption
7829 nsFrameList newChildFrames;
7830
7831 nsIFrame* childFrame = aFrame->PrincipalChildList().FirstChild();
7832 if (childFrame) {
7833 nsIFrame* continuingTableFrame =
7834 CreateContinuingFrame(childFrame, newFrame);
7835 newChildFrames.AppendFrame(nullptr, continuingTableFrame);
7836
7837 NS_ASSERTION(!childFrame->GetNextSibling(),do { if (!(!childFrame->GetNextSibling())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "there can be only one inner table frame"
, "!childFrame->GetNextSibling()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7838); MOZ_PretendNoReturn(); } } while (0)
7838 "there can be only one inner table frame")do { if (!(!childFrame->GetNextSibling())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "there can be only one inner table frame"
, "!childFrame->GetNextSibling()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7838); MOZ_PretendNoReturn(); } } while (0)
;
7839 }
7840
7841 // Set the table wrapper's initial child list
7842 newFrame->SetInitialChildList(FrameChildListID::Principal,
7843 std::move(newChildFrames));
7844
7845 return newFrame;
7846}
7847
7848nsIFrame* nsCSSFrameConstructor::CreateContinuingTableFrame(
7849 nsIFrame* aFrame, nsContainerFrame* aParentFrame, nsIContent* aContent,
7850 ComputedStyle* aComputedStyle) {
7851 nsTableFrame* newFrame = NS_NewTableFrame(mPresShell, aComputedStyle);
7852
7853 newFrame->Init(aContent, aParentFrame, aFrame);
7854
7855 // Replicate any header/footer frames
7856 nsFrameList childFrames;
7857 for (nsIFrame* childFrame : aFrame->PrincipalChildList()) {
7858 // See if it's a header/footer, possibly wrapped in a scroll frame.
7859 nsTableRowGroupFrame* rowGroupFrame =
7860 static_cast<nsTableRowGroupFrame*>(childFrame);
7861 // If the row group was continued, then don't replicate it.
7862 nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
7863 if (rgNextInFlow) {
7864 rowGroupFrame->SetRepeatable(false);
7865 } else if (rowGroupFrame->IsRepeatable()) {
7866 // Replicate the header/footer frame.
7867 nsTableRowGroupFrame* headerFooterFrame;
7868 nsFrameList childList;
7869
7870 nsFrameConstructorState state(
7871 mPresShell, GetAbsoluteContainingBlock(newFrame, FIXED_POS),
7872 GetAbsoluteContainingBlock(newFrame, ABS_POS), nullptr);
7873 state.mCreatingExtraFrames = true;
7874
7875 ComputedStyle* const headerFooterComputedStyle = rowGroupFrame->Style();
7876 headerFooterFrame = static_cast<nsTableRowGroupFrame*>(
7877 NS_NewTableRowGroupFrame(mPresShell, headerFooterComputedStyle));
7878
7879 nsIContent* headerFooter = rowGroupFrame->GetContent();
7880 headerFooterFrame->Init(headerFooter, newFrame, nullptr);
7881
7882 nsFrameConstructorSaveState absoluteSaveState;
7883 MakeTablePartAbsoluteContainingBlock(state, absoluteSaveState,
7884 headerFooterFrame);
7885
7886 nsFrameConstructorSaveState floatSaveState;
7887 state.MaybePushFloatContainingBlock(headerFooterFrame, floatSaveState);
7888
7889 ProcessChildren(state, headerFooter, rowGroupFrame->Style(),
7890 headerFooterFrame, true, childList, false, nullptr);
7891 NS_ASSERTION(state.mFloatedList.IsEmpty(), "unexpected floated element")do { if (!(state.mFloatedList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "unexpected floated element", "state.mFloatedList.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7891); MOZ_PretendNoReturn(); } } while (0)
;
7892 headerFooterFrame->SetInitialChildList(FrameChildListID::Principal,
7893 std::move(childList));
7894 headerFooterFrame->SetRepeatable(true);
7895
7896 // Table specific initialization
7897 headerFooterFrame->InitRepeatedFrame(rowGroupFrame);
7898
7899 // XXX Deal with absolute and fixed frames...
7900 childFrames.AppendFrame(nullptr, headerFooterFrame);
7901 }
7902 }
7903
7904 // Set the table frame's initial child list
7905 newFrame->SetInitialChildList(FrameChildListID::Principal,
7906 std::move(childFrames));
7907
7908 return newFrame;
7909}
7910
7911nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
7912 nsIFrame* aFrame, nsContainerFrame* aParentFrame, bool aIsFluid) {
7913 ComputedStyle* computedStyle = aFrame->Style();
7914 nsIFrame* newFrame = nullptr;
7915 nsIFrame* nextContinuation = aFrame->GetNextContinuation();
7916 nsIFrame* nextInFlow = aFrame->GetNextInFlow();
7917
7918 // Use the frame type to determine what type of frame to create
7919 LayoutFrameType frameType = aFrame->Type();
7920 nsIContent* content = aFrame->GetContent();
7921
7922 if (LayoutFrameType::Text == frameType) {
7923 newFrame = NS_NewContinuingTextFrame(mPresShell, computedStyle);
7924 newFrame->Init(content, aParentFrame, aFrame);
7925 } else if (LayoutFrameType::Inline == frameType) {
7926 newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
7927 newFrame->Init(content, aParentFrame, aFrame);
7928 } else if (LayoutFrameType::Block == frameType) {
7929 MOZ_ASSERT(!aFrame->IsTableCaption(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableCaption())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableCaption()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->IsTableCaption()" " (" "no support for fragmenting table captions yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7930; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7930 "no support for fragmenting table captions yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableCaption())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableCaption()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->IsTableCaption()" " (" "no support for fragmenting table captions yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7930; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7931 newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
7932 newFrame->Init(content, aParentFrame, aFrame);
7933 } else if (LayoutFrameType::ColumnSetWrapper == frameType) {
7934 newFrame =
7935 NS_NewColumnSetWrapperFrame(mPresShell, computedStyle, nsFrameState(0));
7936 newFrame->Init(content, aParentFrame, aFrame);
7937 } else if (LayoutFrameType::ColumnSet == frameType) {
7938 MOZ_ASSERT(!aFrame->IsTableCaption(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableCaption())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableCaption()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->IsTableCaption()" " (" "no support for fragmenting table captions yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7939; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
7939 "no support for fragmenting table captions yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aFrame->IsTableCaption())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aFrame->IsTableCaption()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aFrame->IsTableCaption()" " (" "no support for fragmenting table captions yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 7939); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aFrame->IsTableCaption()"
") (" "no support for fragmenting table captions yet" ")"); do
{ *((volatile int*)__null) = 7939; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7940 newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
7941 newFrame->Init(content, aParentFrame, aFrame);
7942 } else if (LayoutFrameType::PrintedSheet == frameType) {
7943 newFrame = ConstructPrintedSheetFrame(mPresShell, aParentFrame, aFrame);
7944 } else if (LayoutFrameType::Page == frameType) {
7945 nsCanvasFrame* canvasFrame; // (unused outparam for ConstructPageFrame)
7946 newFrame =
7947 ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
7948 } else if (LayoutFrameType::TableWrapper == frameType) {
7949 newFrame = CreateContinuingOuterTableFrame(aFrame, aParentFrame, content,
7950 computedStyle);
7951 } else if (LayoutFrameType::Table == frameType) {
7952 newFrame = CreateContinuingTableFrame(aFrame, aParentFrame, content,
7953 computedStyle);
7954 } else if (LayoutFrameType::TableRowGroup == frameType) {
7955 newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
7956 newFrame->Init(content, aParentFrame, aFrame);
7957 } else if (LayoutFrameType::TableRow == frameType) {
7958 nsTableRowFrame* rowFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
7959
7960 rowFrame->Init(content, aParentFrame, aFrame);
7961
7962 // Create a continuing frame for each table cell frame
7963 nsFrameList newChildList;
7964 nsIFrame* cellFrame = aFrame->PrincipalChildList().FirstChild();
7965 while (cellFrame) {
7966 // See if it's a table cell frame
7967 if (cellFrame->IsTableCellFrame()) {
7968 nsIFrame* continuingCellFrame =
7969 CreateContinuingFrame(cellFrame, rowFrame);
7970 newChildList.AppendFrame(nullptr, continuingCellFrame);
7971 }
7972 cellFrame = cellFrame->GetNextSibling();
7973 }
7974
7975 rowFrame->SetInitialChildList(FrameChildListID::Principal,
7976 std::move(newChildList));
7977 newFrame = rowFrame;
7978
7979 } else if (LayoutFrameType::TableCell == frameType) {
7980 // Warning: If you change this and add a wrapper frame around table cell
7981 // frames, make sure Bug 368554 doesn't regress!
7982 // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
7983 nsTableFrame* tableFrame =
7984 static_cast<nsTableRowFrame*>(aParentFrame)->GetTableFrame();
7985 nsTableCellFrame* cellFrame =
7986 NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
7987
7988 cellFrame->Init(content, aParentFrame, aFrame);
7989
7990 // Create a continuing area frame
7991 nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
7992 nsIFrame* continuingBlockFrame =
7993 CreateContinuingFrame(blockFrame, cellFrame);
7994
7995 SetInitialSingleChild(cellFrame, continuingBlockFrame);
7996 newFrame = cellFrame;
7997 } else if (LayoutFrameType::Line == frameType) {
7998 newFrame = NS_NewFirstLineFrame(mPresShell, computedStyle);
7999 newFrame->Init(content, aParentFrame, aFrame);
8000 } else if (LayoutFrameType::Letter == frameType) {
8001 newFrame = NS_NewFirstLetterFrame(mPresShell, computedStyle);
8002 newFrame->Init(content, aParentFrame, aFrame);
8003 } else if (LayoutFrameType::Image == frameType) {
8004 auto* imageFrame = static_cast<nsImageFrame*>(aFrame);
8005 newFrame = imageFrame->CreateContinuingFrame(mPresShell, computedStyle);
8006 newFrame->Init(content, aParentFrame, aFrame);
8007 } else if (LayoutFrameType::ImageControl == frameType) {
8008 newFrame = NS_NewImageControlFrame(mPresShell, computedStyle);
8009 newFrame->Init(content, aParentFrame, aFrame);
8010 } else if (LayoutFrameType::FieldSet == frameType) {
8011 newFrame = NS_NewFieldSetFrame(mPresShell, computedStyle);
8012 newFrame->Init(content, aParentFrame, aFrame);
8013 } else if (LayoutFrameType::FlexContainer == frameType) {
8014 newFrame = NS_NewFlexContainerFrame(mPresShell, computedStyle);
8015 newFrame->Init(content, aParentFrame, aFrame);
8016 } else if (LayoutFrameType::GridContainer == frameType) {
8017 newFrame = NS_NewGridContainerFrame(mPresShell, computedStyle);
8018 newFrame->Init(content, aParentFrame, aFrame);
8019 } else if (LayoutFrameType::Ruby == frameType) {
8020 newFrame = NS_NewRubyFrame(mPresShell, computedStyle);
8021 newFrame->Init(content, aParentFrame, aFrame);
8022 } else if (LayoutFrameType::RubyBaseContainer == frameType) {
8023 newFrame = NS_NewRubyBaseContainerFrame(mPresShell, computedStyle);
8024 newFrame->Init(content, aParentFrame, aFrame);
8025 } else if (LayoutFrameType::RubyTextContainer == frameType) {
8026 newFrame = NS_NewRubyTextContainerFrame(mPresShell, computedStyle);
8027 newFrame->Init(content, aParentFrame, aFrame);
8028 } else {
8029 MOZ_CRASH("unexpected frame type")do { do { } while (false); MOZ_ReportCrash("" "unexpected frame type"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8029); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected frame type"
")"); do { *((volatile int*)__null) = 8029; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
8030 }
8031
8032 // Init() set newFrame to be a fluid continuation of aFrame.
8033 // If we want a non-fluid continuation, we need to call SetPrevContinuation()
8034 // to reset NS_FRAME_IS_FLUID_CONTINUATION.
8035 if (!aIsFluid) {
8036 newFrame->SetPrevContinuation(aFrame);
8037 }
8038
8039 // If a continuing frame needs to carry frame state bits from its previous
8040 // continuation or parent, set them in nsIFrame::Init(), or in any derived
8041 // frame class's Init() if the bits are belong to specific group.
8042
8043 if (nextInFlow) {
8044 nextInFlow->SetPrevInFlow(newFrame);
8045 newFrame->SetNextInFlow(nextInFlow);
8046 } else if (nextContinuation) {
8047 nextContinuation->SetPrevContinuation(newFrame);
8048 newFrame->SetNextContinuation(nextContinuation);
8049 }
8050
8051 // aFrame cannot be a dynamic reflow root because it has a continuation now.
8052 aFrame->RemoveStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
8053
8054 MOZ_ASSERT(!newFrame->GetNextSibling(), "unexpected sibling")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newFrame->GetNextSibling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!newFrame->GetNextSibling
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!newFrame->GetNextSibling()" " (" "unexpected sibling" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8054); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newFrame->GetNextSibling()"
") (" "unexpected sibling" ")"); do { *((volatile int*)__null
) = 8054; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8055 return newFrame;
8056}
8057
8058void nsCSSFrameConstructor::MaybeSetNextPageContentFramePageName(
8059 const nsIFrame* aFrame) {
8060 MOZ_ASSERT(aFrame, "Frame should not be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "Frame should not be null"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Frame should not be null" ")"); do { *((volatile int*)__null
) = 8060; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8061 // No parent means the root frame, which isn't what this funciton is for.
8062 MOZ_ASSERT(aFrame->GetParent(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFrame->GetParent()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetParent()"
" (" "Frame should be the first child placed on a new page, not the "
"root frame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8064; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
8063 "Frame should be the first child placed on a new page, not the "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFrame->GetParent()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetParent()"
" (" "Frame should be the first child placed on a new page, not the "
"root frame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8064; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
8064 "root frame.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFrame->GetParent()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetParent()"
" (" "Frame should be the first child placed on a new page, not the "
"root frame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame should be the first child placed on a new page, not the "
"root frame." ")"); do { *((volatile int*)__null) = 8064; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8065 if (mNextPageContentFramePageName) {
8066 return;
8067 }
8068 const nsAtom* const autoValue = aFrame->GetParent()->GetAutoPageValue();
8069 mNextPageContentFramePageName = aFrame->ComputePageValue(autoValue);
8070}
8071
8072nsresult nsCSSFrameConstructor::ReplicateFixedFrames(
8073 nsPageContentFrame* aParentFrame) {
8074 // Now deal with fixed-pos things.... They should appear on all pages,
8075 // so we want to move over the placeholders when processing the child
8076 // of the pageContentFrame.
8077
8078 nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
8079 if (!prevPageContentFrame) {
8080 return NS_OK;
8081 }
8082 nsContainerFrame* canvasFrame =
8083 do_QueryFrame(aParentFrame->PrincipalChildList().FirstChild());
8084 nsIFrame* prevCanvasFrame =
8085 prevPageContentFrame->PrincipalChildList().FirstChild();
8086 if (!canvasFrame || !prevCanvasFrame) {
8087 // document's root element frame missing
8088 return NS_ERROR_UNEXPECTED;
8089 }
8090
8091 nsFrameList fixedPlaceholders;
8092 nsIFrame* firstFixed =
8093 prevPageContentFrame->GetChildList(FrameChildListID::Fixed).FirstChild();
8094 if (!firstFixed) {
8095 return NS_OK;
8096 }
8097
8098 // Don't allow abs-pos descendants of the fixed content to escape the content.
8099 // This should not normally be possible (because fixed-pos elements should
8100 // be absolute containers) but fixed-pos tables currently aren't abs-pos
8101 // containers.
8102 nsFrameConstructorState state(mPresShell, aParentFrame, nullptr,
8103 mRootElementFrame);
8104 state.mCreatingExtraFrames = true;
8105
8106 // We can't use an ancestor filter here, because we're not going to
8107 // be usefully recurring down the tree. This means that other
8108 // places in frame construction can't assume a filter is
8109 // initialized!
8110
8111 // Iterate across fixed frames and replicate each whose placeholder is a
8112 // descendant of aFrame. (We don't want to explicitly copy placeholders that
8113 // are within fixed frames, because that would cause duplicates on the new
8114 // page - bug 389619)
8115 for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
8116 nsIFrame* prevPlaceholder = fixed->GetPlaceholderFrame();
8117 if (prevPlaceholder && nsLayoutUtils::IsProperAncestorFrame(
8118 prevCanvasFrame, prevPlaceholder)) {
8119 // We want to use the same style as the primary style frame for
8120 // our content
8121 nsIContent* content = fixed->GetContent();
8122 ComputedStyle* computedStyle =
8123 nsLayoutUtils::GetStyleFrame(content)->Style();
8124 AutoFrameConstructionItemList items(this);
8125 AddFrameConstructionItemsInternal(state, content, canvasFrame, true,
8126 computedStyle,
8127 {ItemFlag::AllowPageBreak}, items);
8128 ConstructFramesFromItemList(state, items, canvasFrame,
8129 /* aParentIsWrapperAnonBox = */ false,
8130 fixedPlaceholders);
8131 }
8132 }
8133
8134 // Add the placeholders to our primary child list.
8135 // XXXbz this is a little screwed up, since the fixed frames will have
8136 // broken auto-positioning. Oh, well.
8137 NS_ASSERTION(!canvasFrame->PrincipalChildList().FirstChild(),do { if (!(!canvasFrame->PrincipalChildList().FirstChild()
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "leaking frames; doc root continuation must be empty"
, "!canvasFrame->PrincipalChildList().FirstChild()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8138); MOZ_PretendNoReturn(); } } while (0)
8138 "leaking frames; doc root continuation must be empty")do { if (!(!canvasFrame->PrincipalChildList().FirstChild()
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "leaking frames; doc root continuation must be empty"
, "!canvasFrame->PrincipalChildList().FirstChild()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8138); MOZ_PretendNoReturn(); } } while (0)
;
8139 canvasFrame->SetInitialChildList(FrameChildListID::Principal,
8140 std::move(fixedPlaceholders));
8141 return NS_OK;
8142}
8143
8144nsCSSFrameConstructor::InsertionPoint nsCSSFrameConstructor::GetInsertionPoint(
8145 nsIContent* aChild) {
8146 MOZ_ASSERT(aChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aChild", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild" ")"
); do { *((volatile int*)__null) = 8146; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8147 nsIContent* insertionElement = aChild->GetFlattenedTreeParent();
8148 if (!insertionElement) {
8149 // The element doesn't belong in the flattened tree, and thus we don't want
8150 // to render it.
8151 return {};
8152 }
8153
8154 return {GetContentInsertionFrameFor(insertionElement), insertionElement};
8155}
8156
8157// Capture state for the frame tree rooted at the frame associated with the
8158// content object, aContent
8159void nsCSSFrameConstructor::CaptureStateForFramesOf(
8160 nsIContent* aContent, nsILayoutHistoryState* aHistoryState) {
8161 if (!aHistoryState) {
8162 return;
8163 }
8164 nsIFrame* frame = aContent->GetPrimaryFrame();
8165 if (frame == mRootElementFrame) {
8166 frame = mRootElementFrame
8167 ? GetAbsoluteContainingBlock(mRootElementFrame, FIXED_POS)
8168 : GetRootFrame();
8169 }
8170 for (; frame;
8171 frame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame)) {
8172 CaptureFrameState(frame, aHistoryState);
8173 }
8174}
8175
8176static bool IsWhitespaceFrame(nsIFrame* aFrame) {
8177 MOZ_ASSERT(aFrame, "invalid argument")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "invalid argument"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"invalid argument" ")"); do { *((volatile int*)__null) = 8177
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8178 return aFrame->IsTextFrame() && aFrame->GetContent()->TextIsOnlyWhitespace();
8179}
8180
8181static nsIFrame* FindNextNonWhitespaceSibling(nsIFrame* aFrame) {
8182 nsIFrame* f = aFrame;
8183 do {
8184 f = f->GetNextSibling();
8185 } while (f && IsWhitespaceFrame(f));
8186 return f;
8187}
8188
8189static nsIFrame* FindPreviousNonWhitespaceSibling(nsIFrame* aFrame) {
8190 nsIFrame* f = aFrame;
8191 do {
8192 f = f->GetPrevSibling();
8193 } while (f && IsWhitespaceFrame(f));
8194 return f;
8195}
8196
8197bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
8198 nsIFrame* aFrame) {
8199#define TRACE(reason) \
8200 PROFILER_MARKER("MaybeRecreateContainerForFrameRemoval: " reason, LAYOUT, \do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("MaybeRecreateContainerForFrameRemoval: " reason, ::geckoprofiler
::category::LAYOUT, {}, ::geckoprofiler::markers::Tracing{}, "Layout"
); } } while (false); } while (false)
8201 {}, Tracing, "Layout")do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("MaybeRecreateContainerForFrameRemoval: " reason, ::geckoprofiler
::category::LAYOUT, {}, ::geckoprofiler::markers::Tracing{}, "Layout"
); } } while (false); } while (false)
8202 MOZ_ASSERT(aFrame, "Must have a frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "Must have a frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Must have a frame" ")"); do { *((volatile int*)__null) = 8202
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8203 MOZ_ASSERT(aFrame->GetParent(), "Frame shouldn't be root")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFrame->GetParent()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetParent()"
" (" "Frame shouldn't be root" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetParent()"
") (" "Frame shouldn't be root" ")"); do { *((volatile int*)
__null) = 8203; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8204 MOZ_ASSERT(aFrame == aFrame->FirstContinuation(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame == aFrame->FirstContinuation())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aFrame == aFrame->FirstContinuation()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aFrame == aFrame->FirstContinuation()"
" (" "aFrame not the result of GetPrimaryFrame()?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame == aFrame->FirstContinuation()"
") (" "aFrame not the result of GetPrimaryFrame()?" ")"); do
{ *((volatile int*)__null) = 8205; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8205 "aFrame not the result of GetPrimaryFrame()?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame == aFrame->FirstContinuation())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aFrame == aFrame->FirstContinuation()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aFrame == aFrame->FirstContinuation()"
" (" "aFrame not the result of GetPrimaryFrame()?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame == aFrame->FirstContinuation()"
") (" "aFrame not the result of GetPrimaryFrame()?" ")"); do
{ *((volatile int*)__null) = 8205; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8206
8207 nsIFrame* inFlowFrame = aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)
8208 ? aFrame->GetPlaceholderFrame()
8209 : aFrame;
8210 MOZ_ASSERT(inFlowFrame, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inFlowFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inFlowFrame))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("inFlowFrame" " ("
"How did that happen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 8210; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8211 MOZ_ASSERT(inFlowFrame == inFlowFrame->FirstContinuation(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inFlowFrame == inFlowFrame->FirstContinuation())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(inFlowFrame == inFlowFrame->FirstContinuation()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inFlowFrame == inFlowFrame->FirstContinuation()"
" (" "placeholder for primary frame has previous continuations?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8212); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame == inFlowFrame->FirstContinuation()"
") (" "placeholder for primary frame has previous continuations?"
")"); do { *((volatile int*)__null) = 8212; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8212 "placeholder for primary frame has previous continuations?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inFlowFrame == inFlowFrame->FirstContinuation())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(inFlowFrame == inFlowFrame->FirstContinuation()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("inFlowFrame == inFlowFrame->FirstContinuation()"
" (" "placeholder for primary frame has previous continuations?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8212); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inFlowFrame == inFlowFrame->FirstContinuation()"
") (" "placeholder for primary frame has previous continuations?"
")"); do { *((volatile int*)__null) = 8212; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8213 nsIFrame* parent = inFlowFrame->GetParent();
8214
8215 if (inFlowFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
8216 nsIFrame* grandparent = parent->GetParent();
8217 MOZ_ASSERT(grandparent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(grandparent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(grandparent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("grandparent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "grandparent"
")"); do { *((volatile int*)__null) = 8217; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8218
8219 bool needsReframe =
8220 // 1. Removing a column-span may lead to an empty
8221 // ::-moz-column-span-wrapper.
8222 inFlowFrame->IsColumnSpan() ||
8223 // 2. Removing a frame which has any column-span siblings may also
8224 // lead to an empty ::-moz-column-span-wrapper subtree. The
8225 // column-span siblings were the frame's children, but later become
8226 // the frame's siblings after CreateColumnSpanSiblings().
8227 inFlowFrame->HasColumnSpanSiblings() ||
8228 // 3. Removing the only child of a ::-moz-column-content, whose
8229 // ColumnSet grandparent has a previous column-span sibling, requires
8230 // reframing since we might connect the ColumnSet's next column-span
8231 // sibling (if there's one). Note that this isn't actually needed if
8232 // the ColumnSet is at the end of ColumnSetWrapper since we create
8233 // empty ones at the end anyway, but we're not worried about
8234 // optimizing that case.
8235 (parent->Style()->GetPseudoType() == PseudoStyleType::columnContent &&
8236 // The only child in ::-moz-column-content (might be tall enough to
8237 // split across columns)
8238 !inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
8239 // That ::-moz-column-content is the first column.
8240 !parent->GetPrevInFlow() &&
8241 // The ColumnSet grandparent has a previous sibling that is a
8242 // column-span.
8243 grandparent->GetPrevSibling());
8244
8245 if (needsReframe) {
8246 nsContainerFrame* containingBlock =
8247 GetMultiColumnContainingBlockFor(inFlowFrame);
8248
8249#ifdef DEBUG1
8250 if (IsFramePartOfIBSplit(inFlowFrame)) {
8251 nsIFrame* ibContainingBlock = GetIBContainingBlockFor(inFlowFrame);
8252 MOZ_ASSERT(containingBlock == ibContainingBlock ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
" (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
") (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")"); do { *((volatile
int*)__null) = 8256; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8253 nsLayoutUtils::IsProperAncestorFrame(containingBlock,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
" (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
") (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")"); do { *((volatile
int*)__null) = 8256; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8254 ibContainingBlock),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
" (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
") (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")"); do { *((volatile
int*)__null) = 8256; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8255 "Multi-column containing block should be equal to or be the "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
" (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
") (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")"); do { *((volatile
int*)__null) = 8256; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8256 "ancestor of the IB containing block!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(containingBlock == ibContainingBlock || nsLayoutUtils
::IsProperAncestorFrame(containingBlock, ibContainingBlock)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
" (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "containingBlock == ibContainingBlock || nsLayoutUtils::IsProperAncestorFrame(containingBlock, ibContainingBlock)"
") (" "Multi-column containing block should be equal to or be the "
"ancestor of the IB containing block!" ")"); do { *((volatile
int*)__null) = 8256; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8257 }
8258#endif
8259
8260 TRACE("Multi-column");
8261 RecreateFramesForContent(containingBlock->GetContent(),
8262 InsertionKind::Async);
8263 return true;
8264 }
8265 }
8266
8267 if (IsFramePartOfIBSplit(aFrame)) {
8268 // The removal functions can't handle removal of an {ib} split directly; we
8269 // need to rebuild the containing block.
8270 TRACE("IB split removal");
8271 ReframeContainingBlock(aFrame);
8272 return true;
8273 }
8274
8275 if (inFlowFrame->IsRenderedLegend()) {
8276 TRACE("Fieldset / Legend");
8277 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8278 return true;
8279 }
8280
8281 // Might need to reconstruct things if this frame's nextSibling is a table
8282 // or ruby pseudo, since removal of this frame might mean that this pseudo
8283 // needs to get merged with the frame's prevSibling if that's also a table
8284 // or ruby pseudo.
8285 nsIFrame* nextSibling =
8286 FindNextNonWhitespaceSibling(inFlowFrame->LastContinuation());
8287 NS_ASSERTION(!IsWrapperPseudo(inFlowFrame),do { if (!(!IsWrapperPseudo(inFlowFrame))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Shouldn't happen here (we start removals from primary frames)"
, "!IsWrapperPseudo(inFlowFrame)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8288); MOZ_PretendNoReturn(); } } while (0)
8288 "Shouldn't happen here (we start removals from primary frames)")do { if (!(!IsWrapperPseudo(inFlowFrame))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Shouldn't happen here (we start removals from primary frames)"
, "!IsWrapperPseudo(inFlowFrame)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8288); MOZ_PretendNoReturn(); } } while (0)
;
8289 // Effectively, for the ruby pseudo sibling case, only pseudo <ruby> frame
8290 // need to be checked here, since all other types of such frames will have
8291 // a ruby container parent, and be catched by "Check ruby containers" below.
8292 if (nextSibling && IsWrapperPseudo(nextSibling)) {
8293 nsIFrame* prevSibling = FindPreviousNonWhitespaceSibling(inFlowFrame);
8294 if (prevSibling && IsWrapperPseudo(prevSibling)) {
8295 TRACE("Pseudo sibling");
8296 // Good enough to recreate frames for aFrame's parent's content; even if
8297 // aFrame's parent is a pseudo, that'll be the right content node.
8298 // FIXME(emilio): Consider doing a more subtle check here like, only if
8299 // prevSibling and nextSibling share frame type. Or even consider just
8300 // moving the frames around and destroying nextSibling?
8301 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8302 return true;
8303 }
8304 }
8305
8306 // Check ruby containers
8307 LayoutFrameType parentType = parent->Type();
8308 if (parentType == LayoutFrameType::Ruby ||
8309 RubyUtils::IsRubyContainerBox(parentType)) {
8310 // In ruby containers, pseudo frames may be created from
8311 // whitespaces or even nothing. There are two cases we actually
8312 // need to handle here, but hard to check exactly:
8313 // 1. Status of spaces beside the frame may vary, and related
8314 // frames may be constructed or destroyed accordingly.
8315 // 2. The type of the first child of a ruby frame determines
8316 // whether a pseudo ruby base container should exist.
8317 TRACE("Ruby container");
8318 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8319 return true;
8320 }
8321
8322 // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
8323 // a non-fluid continuation, i.e. it was split by bidi resolution
8324 if (!inFlowFrame->GetPrevSibling() && !inFlowFrame->GetNextSibling() &&
8325 ((parent->GetPrevContinuation() && !parent->GetPrevInFlow()) ||
8326 (parent->GetNextContinuation() && !parent->GetNextInFlow()))) {
8327 TRACE("Removing last child of non-fluid split parent");
8328 RecreateFramesForContent(parent->GetContent(), InsertionKind::Async);
8329 return true;
8330 }
8331
8332 // We might still need to reconstruct things if the parent of inFlowFrame is
8333 // ib-split, since in that case the removal of aFrame might affect the
8334 // splitting of its parent.
8335 if (!IsFramePartOfIBSplit(parent)) {
8336 return false;
8337 }
8338
8339 // If inFlowFrame is not the only in-flow child of |parent|, then removing
8340 // it will change nothing about the {ib} split.
8341 if (inFlowFrame != parent->PrincipalChildList().FirstChild() ||
8342 inFlowFrame->LastContinuation()->GetNextSibling()) {
8343 return false;
8344 }
8345
8346 // If the parent is the first or last part of the {ib} split, then
8347 // removing one of its kids will have no effect on the splitting.
8348 // Get the first continuation up front so we don't have to do it twice.
8349 nsIFrame* parentFirstContinuation = parent->FirstContinuation();
8350 if (!GetIBSplitSibling(parentFirstContinuation) ||
8351 !GetIBSplitPrevSibling(parentFirstContinuation)) {
8352 return false;
8353 }
8354
8355 TRACE("IB split parent");
8356 ReframeContainingBlock(parent);
8357 return true;
8358#undef TRACE
8359}
8360
8361void nsCSSFrameConstructor::UpdateTableCellSpans(nsIContent* aContent) {
8362 nsTableCellFrame* cellFrame = do_QueryFrame(aContent->GetPrimaryFrame());
8363
8364 // It's possible that this warning could fire if some other style change
8365 // simultaneously changes the 'display' of the element and makes it no
8366 // longer be a table cell.
8367 NS_WARNING_ASSERTION(cellFrame, "Hint should only be posted on table cells!")do { if (!(cellFrame)) { NS_DebugBreak(NS_DEBUG_WARNING, "Hint should only be posted on table cells!"
, "cellFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8367); } } while (false)
;
8368
8369 if (cellFrame) {
8370 cellFrame->GetTableFrame()->RowOrColSpanChanged(cellFrame);
8371 }
8372}
8373
8374static nsIContent* GetTopmostMathMLElement(nsIContent* aMathMLContent) {
8375 MOZ_ASSERT(aMathMLContent->IsMathMLElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMathMLContent->IsMathMLElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMathMLContent->IsMathMLElement
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aMathMLContent->IsMathMLElement()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->IsMathMLElement()"
")"); do { *((volatile int*)__null) = 8375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8376 MOZ_ASSERT(aMathMLContent->GetPrimaryFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMathMLContent->GetPrimaryFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMathMLContent->GetPrimaryFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aMathMLContent->GetPrimaryFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->GetPrimaryFrame()"
")"); do { *((volatile int*)__null) = 8376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8377 MOZ_ASSERT(aMathMLContent->GetPrimaryFrame()->IsMathMLFrame())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMathMLContent->GetPrimaryFrame()->IsMathMLFrame
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aMathMLContent->GetPrimaryFrame()->IsMathMLFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aMathMLContent->GetPrimaryFrame()->IsMathMLFrame()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aMathMLContent->GetPrimaryFrame()->IsMathMLFrame()"
")"); do { *((volatile int*)__null) = 8377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8378 nsIContent* root = aMathMLContent;
8379
8380 for (nsIContent* parent = aMathMLContent->GetFlattenedTreeParent(); parent;
8381 parent = parent->GetFlattenedTreeParent()) {
8382 nsIFrame* frame = parent->GetPrimaryFrame();
8383 if (!frame || !frame->IsMathMLFrame()) {
8384 break;
8385 }
8386 root = parent;
8387 }
8388
8389 return root;
8390}
8391
8392// We don't know how to re-insert an anonymous subtree root, so recreate the
8393// closest non-generated ancestor instead, except for a few special cases...
8394static bool ShouldRecreateContainerForNativeAnonymousContentRoot(
8395 nsIContent* aContent) {
8396 if (!aContent->IsRootOfNativeAnonymousSubtree()) {
8397 return false;
8398 }
8399 if (ManualNACPtr::IsManualNAC(aContent)) {
8400 // Editor NAC, would enter an infinite loop, and we sorta get away with it
8401 // because it's all abspos.
8402 return false;
8403 }
8404 if (auto* el = Element::FromNode(aContent)) {
8405 if (auto* classes = el->GetClasses()) {
8406 if (classes->Contains(nsGkAtoms::mozCustomContentContainer,
8407 eCaseMatters)) {
8408 // Canvas anonymous content (like the custom content container) is also
8409 // fine, because its only sibling is a tooltip which is also abspos, so
8410 // relative insertion order doesn't really matter.
8411 //
8412 // This is important because the inspector uses it, and we don't want
8413 // inspecting the page to change behavior heavily (and reframing
8414 // unfortunately has side-effects sometimes, even though they're bugs).
8415 return false;
8416 }
8417 }
8418 }
8419
8420 return true;
8421}
8422
8423void nsCSSFrameConstructor::RecreateFramesForContent(
8424 nsIContent* aContent, InsertionKind aInsertionKind) {
8425 MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { *((volatile int*)__null) = 8425; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8426
8427 // If there is no document, we don't want to recreate frames for it. (You
8428 // shouldn't generally be giving this method content without a document
8429 // anyway).
8430 // Rebuilding the frame tree can have bad effects, especially if it's the
8431 // frame tree for chrome (see bug 157322).
8432 if (NS_WARN_IF(!aContent->GetComposedDoc())NS_warn_if_impl(!aContent->GetComposedDoc(), "!aContent->GetComposedDoc()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8432)
) {
8433 return;
8434 }
8435
8436 // TODO(emilio): We technically can find the right insertion point nowadays
8437 // using StyleChildrenIterator rather than FlattenedChildIterator. But we'd
8438 // need to tweak the setup to insert into replaced elements to filter which
8439 // anonymous roots can be allowed, and which can't.
8440 //
8441 // TODO(emilio, 2022): Is this true? If we have a replaced element we wouldn't
8442 // have generated e.g., a ::before/::after pseudo-element to begin with (which
8443 // is what this code is about, so maybe we can just remove this piece of code
8444 // altogether).
8445 if (ShouldRecreateContainerForNativeAnonymousContentRoot(aContent)) {
8446 do {
8447 aContent = aContent->GetParent();
8448 } while (ShouldRecreateContainerForNativeAnonymousContentRoot(aContent));
8449 return RecreateFramesForContent(aContent, InsertionKind::Async);
8450 }
8451
8452 nsIFrame* frame = aContent->GetPrimaryFrame();
8453 if (frame && frame->IsMathMLFrame()) {
8454 // Reframe the topmost MathML element to prevent exponential blowup
8455 // (see bug 397518).
8456 aContent = GetTopmostMathMLElement(aContent);
8457 frame = aContent->GetPrimaryFrame();
8458 }
8459
8460 if (frame) {
8461 nsIFrame* parent = frame->GetParent();
8462 nsIContent* parentContent = parent ? parent->GetContent() : nullptr;
8463 // If the parent frame is a leaf then the subsequent insert will fail to
8464 // create a frame, so we need to recreate the parent content. This happens
8465 // with native anonymous content from the editor.
8466 if (parent && parent->IsLeaf() && parentContent &&
8467 parentContent != aContent) {
8468 return RecreateFramesForContent(parentContent, InsertionKind::Async);
8469 }
8470 }
8471
8472 if (frame && MaybeRecreateContainerForFrameRemoval(frame)) {
8473 return;
8474 }
8475
8476 MOZ_ASSERT(aContent->GetParentNode())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->GetParentNode())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent->GetParentNode()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aContent->GetParentNode()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->GetParentNode()"
")"); do { *((volatile int*)__null) = 8476; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8477 const bool didReconstruct =
8478 ContentWillBeRemoved(aContent, REMOVE_FOR_RECONSTRUCTION);
8479
8480 if (!didReconstruct) {
8481 if (aInsertionKind == InsertionKind::Async && aContent->IsElement()) {
8482 // FIXME(emilio, bug 1397239): There's nothing removing the frame state
8483 // for elements that go away before we come back to the frame
8484 // constructor.
8485 //
8486 // Also, it'd be nice to just use the `ContentRangeInserted` path for
8487 // both elements and non-elements, but we need to make lazy frame
8488 // construction to apply to all elements first.
8489 RestyleManager()->PostRestyleEvent(aContent->AsElement(), RestyleHint{0},
8490 nsChangeHint_ReconstructFrame);
8491 } else {
8492 // Now, recreate the frames associated with this content object. If
8493 // ContentWillBeRemoved triggered reconstruction, then we don't need to do
8494 // this because the frames will already have been built.
8495 ContentRangeInserted(aContent, aContent->GetNextSibling(),
8496 aInsertionKind);
8497 }
8498 }
8499}
8500
8501bool nsCSSFrameConstructor::DestroyFramesFor(nsIContent* aContent) {
8502 MOZ_ASSERT(aContent && aContent->GetParentNode())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent && aContent->GetParentNode())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aContent && aContent->GetParentNode()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aContent && aContent->GetParentNode()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent && aContent->GetParentNode()"
")"); do { *((volatile int*)__null) = 8502; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8503 return ContentWillBeRemoved(aContent, REMOVE_FOR_RECONSTRUCTION);
8504}
8505
8506//////////////////////////////////////////////////////////////////////
8507
8508// Block frame construction code
8509
8510already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLetterStyle(
8511 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8512 if (aContent) {
8513 return mPresShell->StyleSet()->ResolvePseudoElementStyle(
8514 *aContent->AsElement(), PseudoStyleType::firstLetter, nullptr,
8515 aComputedStyle);
8516 }
8517 return nullptr;
8518}
8519
8520already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLineStyle(
8521 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8522 if (aContent) {
8523 return mPresShell->StyleSet()->ResolvePseudoElementStyle(
8524 *aContent->AsElement(), PseudoStyleType::firstLine, nullptr,
8525 aComputedStyle);
8526 }
8527 return nullptr;
8528}
8529
8530// Predicate to see if a given content (block element) has
8531// first-letter style applied to it.
8532bool nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(
8533 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8534 return nsLayoutUtils::HasPseudoStyle(aContent, aComputedStyle,
8535 PseudoStyleType::firstLetter,
8536 mPresShell->GetPresContext());
8537}
8538
8539bool nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame) {
8540 MOZ_ASSERT(aBlockFrame, "Need a frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBlockFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBlockFrame))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aBlockFrame" " ("
"Need a frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8540); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBlockFrame"
") (" "Need a frame" ")"); do { *((volatile int*)__null) = 8540
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8541 NS_ASSERTION(aBlockFrame->IsBlockFrameOrSubclass(), "Not a block frame?")do { if (!(aBlockFrame->IsBlockFrameOrSubclass())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Not a block frame?", "aBlockFrame->IsBlockFrameOrSubclass()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8541); MOZ_PretendNoReturn(); } } while (0)
;
8542
8543 return aBlockFrame->HasAnyStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
8544}
8545
8546bool nsCSSFrameConstructor::ShouldHaveFirstLineStyle(
8547 nsIContent* aContent, ComputedStyle* aComputedStyle) {
8548 bool hasFirstLine = nsLayoutUtils::HasPseudoStyle(
8549 aContent, aComputedStyle, PseudoStyleType::firstLine,
8550 mPresShell->GetPresContext());
8551 return hasFirstLine && !aContent->IsHTMLElement(nsGkAtoms::fieldset);
8552}
8553
8554void nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(
8555 nsIContent* aContent, ComputedStyle* aComputedStyle,
8556 bool* aHaveFirstLetterStyle, bool* aHaveFirstLineStyle) {
8557 *aHaveFirstLetterStyle = ShouldHaveFirstLetterStyle(aContent, aComputedStyle);
8558 *aHaveFirstLineStyle = ShouldHaveFirstLineStyle(aContent, aComputedStyle);
8559}
8560
8561/* static */
8562const nsCSSFrameConstructor::PseudoParentData
8563 nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
8564 // Cell
8565 {{&nsCSSFrameConstructor::ConstructTableCell,
8566 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8567 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8568 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow)(((uint32_t)(eTypeRow)) << 28)},
8569 PseudoStyleType::tableCell},
8570 // Row
8571 {{&nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
8572 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8573 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8574 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup)(((uint32_t)(eTypeRowGroup)) << 28)},
8575 PseudoStyleType::tableRow},
8576 // Row group
8577 {{&nsCSSFrameConstructor::ConstructTableRowOrRowGroup,
8578 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8579 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8580 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28)},
8581 PseudoStyleType::tableRowGroup},
8582 // Column group
8583 {{ToCreationFunc(NS_NewTableColGroupFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewTableColGroupFrame(aPs, aStyle); }
,
8584 FCDATA_IS_TABLE_PART0x800 | FCDATA_SKIP_FRAMESET0x1 |
8585 FCDATA_DISALLOW_OUT_OF_FLOW0x8 | FCDATA_USE_CHILD_ITEMS0x10000 |
8586 FCDATA_SKIP_ABSPOS_PUSH0x200 |
8587 // Not FCDATA_IS_WRAPPER_ANON_BOX, because we don't need to
8588 // restyle these: they have non-inheriting styles.
8589 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable)(((uint32_t)(eTypeTable)) << 28)},
8590 PseudoStyleType::tableColGroup},
8591 // Table
8592 {{&nsCSSFrameConstructor::ConstructTable,
8593 FCDATA_SKIP_FRAMESET0x1 | FCDATA_USE_CHILD_ITEMS0x10000 |
8594 FCDATA_IS_WRAPPER_ANON_BOX0x400000},
8595 PseudoStyleType::table},
8596 // Ruby
8597 {{ToCreationFunc(NS_NewRubyFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyFrame(aPs, aStyle); }
,
8598 FCDATA_IS_LINE_PARTICIPANT0x2000 | FCDATA_USE_CHILD_ITEMS0x10000 |
8599 FCDATA_IS_WRAPPER_ANON_BOX0x400000 | FCDATA_SKIP_FRAMESET0x1},
8600 PseudoStyleType::ruby},
8601 // Ruby Base
8602 {{ToCreationFunc(NS_NewRubyBaseFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseFrame(aPs, aStyle); }
,
8603 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8604 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8605 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyBaseContainer)(((uint32_t)(eTypeRubyBaseContainer)) << 28) |
8606 FCDATA_SKIP_FRAMESET0x1},
8607 PseudoStyleType::rubyBase},
8608 // Ruby Base Container
8609 {{ToCreationFunc(NS_NewRubyBaseContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyBaseContainerFrame(aPs, aStyle); }
,
8610 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8611 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8612 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28) |
8613 FCDATA_SKIP_FRAMESET0x1},
8614 PseudoStyleType::rubyBaseContainer},
8615 // Ruby Text
8616 {{ToCreationFunc(NS_NewRubyTextFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextFrame(aPs, aStyle); }
,
8617 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_LINE_PARTICIPANT0x2000 |
8618 FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8619 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRubyTextContainer)(((uint32_t)(eTypeRubyTextContainer)) << 28) |
8620 FCDATA_SKIP_FRAMESET0x1},
8621 PseudoStyleType::rubyText},
8622 // Ruby Text Container
8623 {{ToCreationFunc(NS_NewRubyTextContainerFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewRubyTextContainerFrame(aPs, aStyle); }
,
8624 FCDATA_USE_CHILD_ITEMS0x10000 | FCDATA_IS_WRAPPER_ANON_BOX0x400000 |
8625 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby)(((uint32_t)(eTypeRuby)) << 28) |
8626 FCDATA_SKIP_FRAMESET0x1},
8627 PseudoStyleType::rubyTextContainer}};
8628
8629void nsCSSFrameConstructor::CreateNeededAnonFlexOrGridItems(
8630 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8631 nsIFrame* aParentFrame) {
8632 if (aItems.IsEmpty()) {
8633 return;
8634 }
8635
8636 if (!aParentFrame->IsFlexOrGridContainer()) {
8637 return;
8638 }
8639
8640 const bool isLegacyWebKitBox =
8641 IsFlexContainerForLegacyWebKitBox(aParentFrame);
8642 FCItemIterator iter(aItems);
8643 do {
8644 // Advance iter past children that don't want to be wrapped
8645 if (iter.SkipItemsThatDontNeedAnonFlexOrGridItem(aState,
8646 isLegacyWebKitBox)) {
8647 // Hit the end of the items without finding any remaining children that
8648 // need to be wrapped. We're finished!
8649 return;
8650 }
8651
8652 // If our next potentially-wrappable child is whitespace, then see if
8653 // there's anything wrappable immediately after it. If not, we just drop
8654 // the whitespace and move on. (We're not supposed to create any anonymous
8655 // flex/grid items that _only_ contain whitespace).
8656 // (BUT if this is generated content, then we don't give whitespace nodes
8657 // any special treatment, because they're probably not really whitespace --
8658 // they're just temporarily empty, waiting for their generated text.)
8659 // XXXdholbert If this node's generated text will *actually end up being
8660 // entirely whitespace*, then we technically should still skip over it, per
8661 // the CSS grid & flexbox specs. I'm not bothering with that at this point,
8662 // since it's a pretty extreme edge case.
8663 if (!aParentFrame->IsGeneratedContentFrame() &&
8664 iter.item().IsWhitespace(aState)) {
8665 FCItemIterator afterWhitespaceIter(iter);
8666 bool hitEnd = afterWhitespaceIter.SkipWhitespace(aState);
8667 bool nextChildNeedsAnonItem =
8668 !hitEnd && afterWhitespaceIter.item().NeedsAnonFlexOrGridItem(
8669 aState, isLegacyWebKitBox);
8670
8671 if (!nextChildNeedsAnonItem) {
8672 // There's nothing after the whitespace that we need to wrap, so we
8673 // just drop this run of whitespace.
8674 iter.DeleteItemsTo(this, afterWhitespaceIter);
8675 if (hitEnd) {
8676 // Nothing left to do -- we're finished!
8677 return;
8678 }
8679 // else, we have a next child and it does not want to be wrapped. So,
8680 // we jump back to the beginning of the loop to skip over that child
8681 // (and anything else non-wrappable after it)
8682 MOZ_ASSERT(!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem
( aState, isLegacyWebKitBox))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!iter.IsDone() && !iter
.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
" (" "hitEnd and/or nextChildNeedsAnonItem lied" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8684; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8683 aState, isLegacyWebKitBox),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem
( aState, isLegacyWebKitBox))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!iter.IsDone() && !iter
.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
" (" "hitEnd and/or nextChildNeedsAnonItem lied" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8684; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8684 "hitEnd and/or nextChildNeedsAnonItem lied")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem
( aState, isLegacyWebKitBox))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!iter.IsDone() && !iter
.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
" (" "hitEnd and/or nextChildNeedsAnonItem lied" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.IsDone() && !iter.item().NeedsAnonFlexOrGridItem( aState, isLegacyWebKitBox)"
") (" "hitEnd and/or nextChildNeedsAnonItem lied" ")"); do {
*((volatile int*)__null) = 8684; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8685 continue;
8686 }
8687 }
8688
8689 // Now |iter| points to the first child that needs to be wrapped in an
8690 // anonymous flex/grid item. Now we see how many children after it also want
8691 // to be wrapped in an anonymous flex/grid item.
8692 FCItemIterator endIter(iter); // iterator to find the end of the group
8693 endIter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyWebKitBox);
8694
8695 NS_ASSERTION(iter != endIter,do { if (!(iter != endIter)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should've had at least one wrappable child to seek past", "iter != endIter"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8696); MOZ_PretendNoReturn(); } } while (0)
8696 "Should've had at least one wrappable child to seek past")do { if (!(iter != endIter)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should've had at least one wrappable child to seek past", "iter != endIter"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8696); MOZ_PretendNoReturn(); } } while (0)
;
8697
8698 // Now, we create the anonymous flex or grid item to contain the children
8699 // between |iter| and |endIter|.
8700 nsIContent* parentContent = aParentFrame->GetContent();
8701 RefPtr<ComputedStyle> wrapperStyle =
8702 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
8703 PseudoStyleType::anonymousItem, aParentFrame->Style());
8704
8705 static constexpr FrameConstructionData sBlockFCData(
8706 ToCreationFunc(NS_NewBlockFrame)[](PresShell* aPs, ComputedStyle* aStyle) -> nsIFrame* { return
NS_NewBlockFrame(aPs, aStyle); }
, FCDATA_SKIP_FRAMESET0x1 |
8707 FCDATA_USE_CHILD_ITEMS0x10000 |
8708 FCDATA_IS_WRAPPER_ANON_BOX0x400000);
8709
8710 // Use the content of our parent frame
8711 auto* newItem = new (this) FrameConstructionItem(
8712 &sBlockFCData, parentContent, wrapperStyle.forget(), true);
8713
8714 newItem->mIsAllInline =
8715 newItem->mComputedStyle->StyleDisplay()->IsInlineOutsideStyle();
8716 newItem->mIsBlock = !newItem->mIsAllInline;
8717
8718 MOZ_ASSERT(!newItem->mIsAllInline && newItem->mIsBlock,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newItem->mIsAllInline && newItem->mIsBlock
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!newItem->mIsAllInline && newItem->mIsBlock
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!newItem->mIsAllInline && newItem->mIsBlock" " ("
"expecting anonymous flex/grid items to be block-level " "(this will make a difference when we encounter "
"'align-items: baseline')" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newItem->mIsAllInline && newItem->mIsBlock"
") (" "expecting anonymous flex/grid items to be block-level "
"(this will make a difference when we encounter " "'align-items: baseline')"
")"); do { *((volatile int*)__null) = 8721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8719 "expecting anonymous flex/grid items to be block-level "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newItem->mIsAllInline && newItem->mIsBlock
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!newItem->mIsAllInline && newItem->mIsBlock
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!newItem->mIsAllInline && newItem->mIsBlock" " ("
"expecting anonymous flex/grid items to be block-level " "(this will make a difference when we encounter "
"'align-items: baseline')" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newItem->mIsAllInline && newItem->mIsBlock"
") (" "expecting anonymous flex/grid items to be block-level "
"(this will make a difference when we encounter " "'align-items: baseline')"
")"); do { *((volatile int*)__null) = 8721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8720 "(this will make a difference when we encounter "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newItem->mIsAllInline && newItem->mIsBlock
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!newItem->mIsAllInline && newItem->mIsBlock
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!newItem->mIsAllInline && newItem->mIsBlock" " ("
"expecting anonymous flex/grid items to be block-level " "(this will make a difference when we encounter "
"'align-items: baseline')" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newItem->mIsAllInline && newItem->mIsBlock"
") (" "expecting anonymous flex/grid items to be block-level "
"(this will make a difference when we encounter " "'align-items: baseline')"
")"); do { *((volatile int*)__null) = 8721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8721 "'align-items: baseline')")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newItem->mIsAllInline && newItem->mIsBlock
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!newItem->mIsAllInline && newItem->mIsBlock
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!newItem->mIsAllInline && newItem->mIsBlock" " ("
"expecting anonymous flex/grid items to be block-level " "(this will make a difference when we encounter "
"'align-items: baseline')" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newItem->mIsAllInline && newItem->mIsBlock"
") (" "expecting anonymous flex/grid items to be block-level "
"(this will make a difference when we encounter " "'align-items: baseline')"
")"); do { *((volatile int*)__null) = 8721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8722
8723 // Anonymous flex and grid items induce line boundaries around their
8724 // contents.
8725 newItem->mChildItems.SetLineBoundaryAtStart(true);
8726 newItem->mChildItems.SetLineBoundaryAtEnd(true);
8727 // The parent of the items in aItems is also the parent of the items
8728 // in mChildItems
8729 newItem->mChildItems.SetParentHasNoShadowDOM(aItems.ParentHasNoShadowDOM());
8730
8731 // Eat up all items between |iter| and |endIter| and put them in our
8732 // wrapper. This advances |iter| to point to |endIter|.
8733 iter.AppendItemsToList(this, endIter, newItem->mChildItems);
8734
8735 iter.InsertItem(newItem);
8736 } while (!iter.IsDone());
8737}
8738
8739/* static */ nsCSSFrameConstructor::RubyWhitespaceType
8740nsCSSFrameConstructor::ComputeRubyWhitespaceType(StyleDisplay aPrevDisplay,
8741 StyleDisplay aNextDisplay) {
8742 MOZ_ASSERT(aPrevDisplay.IsRuby() && aNextDisplay.IsRuby())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrevDisplay.IsRuby() && aNextDisplay.IsRuby
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aPrevDisplay.IsRuby() && aNextDisplay.IsRuby
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPrevDisplay.IsRuby() && aNextDisplay.IsRuby()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrevDisplay.IsRuby() && aNextDisplay.IsRuby()"
")"); do { *((volatile int*)__null) = 8742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8743 if (aPrevDisplay == aNextDisplay &&
8744 (aPrevDisplay == StyleDisplay::RubyBase ||
8745 aPrevDisplay == StyleDisplay::RubyText)) {
8746 return eRubyInterLeafWhitespace;
8747 }
8748 if (aNextDisplay == StyleDisplay::RubyText ||
8749 aNextDisplay == StyleDisplay::RubyTextContainer) {
8750 return eRubyInterLevelWhitespace;
8751 }
8752 return eRubyInterSegmentWhitespace;
8753}
8754
8755/**
8756 * This function checks the content from |aStartIter| to |aEndIter|,
8757 * determines whether it contains only whitespace, and if yes,
8758 * interprets the type of whitespace. This method does not change
8759 * any of the iters.
8760 */
8761/* static */ nsCSSFrameConstructor::RubyWhitespaceType
8762nsCSSFrameConstructor::InterpretRubyWhitespace(nsFrameConstructorState& aState,
8763 const FCItemIterator& aStartIter,
8764 const FCItemIterator& aEndIter) {
8765 if (!aStartIter.item().IsWhitespace(aState)) {
8766 return eRubyNotWhitespace;
8767 }
8768
8769 FCItemIterator spaceEndIter(aStartIter);
8770 spaceEndIter.SkipWhitespace(aState);
8771 if (spaceEndIter != aEndIter) {
8772 return eRubyNotWhitespace;
8773 }
8774
8775 // Any leading or trailing whitespace in non-pseudo ruby box
8776 // should have been trimmed, hence there should not be any
8777 // whitespace at the start or the end.
8778 MOZ_ASSERT(!aStartIter.AtStart() && !aEndIter.IsDone())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aStartIter.AtStart() && !aEndIter.IsDone())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aStartIter.AtStart() && !aEndIter.IsDone())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aStartIter.AtStart() && !aEndIter.IsDone()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aStartIter.AtStart() && !aEndIter.IsDone()"
")"); do { *((volatile int*)__null) = 8778; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8779 FCItemIterator prevIter(aStartIter);
8780 prevIter.Prev();
8781 return ComputeRubyWhitespaceType(
8782 prevIter.item().mComputedStyle->StyleDisplay()->mDisplay,
8783 aEndIter.item().mComputedStyle->StyleDisplay()->mDisplay);
8784}
8785
8786/**
8787 * This function eats up consecutive items which do not want the current
8788 * parent into either a ruby base box or a ruby text box. When it
8789 * returns, |aIter| points to the first item it doesn't wrap.
8790 */
8791void nsCSSFrameConstructor::WrapItemsInPseudoRubyLeafBox(
8792 FCItemIterator& aIter, ComputedStyle* aParentStyle,
8793 nsIContent* aParentContent) {
8794 StyleDisplay parentDisplay = aParentStyle->StyleDisplay()->mDisplay;
8795 ParentType parentType, wrapperType;
8796 if (parentDisplay == StyleDisplay::RubyTextContainer) {
8797 parentType = eTypeRubyTextContainer;
8798 wrapperType = eTypeRubyText;
8799 } else {
8800 MOZ_ASSERT(parentDisplay == StyleDisplay::RubyBaseContainer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parentDisplay == StyleDisplay::RubyBaseContainer)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(parentDisplay == StyleDisplay::RubyBaseContainer))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("parentDisplay == StyleDisplay::RubyBaseContainer"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8800); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parentDisplay == StyleDisplay::RubyBaseContainer"
")"); do { *((volatile int*)__null) = 8800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8801 parentType = eTypeRubyBaseContainer;
8802 wrapperType = eTypeRubyBase;
8803 }
8804
8805 MOZ_ASSERT(aIter.item().DesiredParentType() != parentType,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIter.item().DesiredParentType() != parentType)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aIter.item().DesiredParentType() != parentType))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aIter.item().DesiredParentType() != parentType"
" (" "Should point to something needs to be wrapped." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8806); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != parentType"
") (" "Should point to something needs to be wrapped." ")");
do { *((volatile int*)__null) = 8806; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8806 "Should point to something needs to be wrapped.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIter.item().DesiredParentType() != parentType)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aIter.item().DesiredParentType() != parentType))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aIter.item().DesiredParentType() != parentType"
" (" "Should point to something needs to be wrapped." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8806); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != parentType"
") (" "Should point to something needs to be wrapped." ")");
do { *((volatile int*)__null) = 8806; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8807
8808 FCItemIterator endIter(aIter);
8809 endIter.SkipItemsNotWantingParentType(parentType);
8810
8811 WrapItemsInPseudoParent(aParentContent, aParentStyle, wrapperType, aIter,
8812 endIter);
8813}
8814
8815/**
8816 * This function eats up consecutive items into a ruby level container.
8817 * It may create zero or one level container. When it returns, |aIter|
8818 * points to the first item it doesn't wrap.
8819 */
8820void nsCSSFrameConstructor::WrapItemsInPseudoRubyLevelContainer(
8821 nsFrameConstructorState& aState, FCItemIterator& aIter,
8822 ComputedStyle* aParentStyle, nsIContent* aParentContent) {
8823 MOZ_ASSERT(aIter.item().DesiredParentType() != eTypeRuby,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIter.item().DesiredParentType() != eTypeRuby)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aIter.item().DesiredParentType() != eTypeRuby))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aIter.item().DesiredParentType() != eTypeRuby"
" (" "Pointing to a level container?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != eTypeRuby"
") (" "Pointing to a level container?" ")"); do { *((volatile
int*)__null) = 8824; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8824 "Pointing to a level container?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIter.item().DesiredParentType() != eTypeRuby)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aIter.item().DesiredParentType() != eTypeRuby))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aIter.item().DesiredParentType() != eTypeRuby"
" (" "Pointing to a level container?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIter.item().DesiredParentType() != eTypeRuby"
") (" "Pointing to a level container?" ")"); do { *((volatile
int*)__null) = 8824; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8825
8826 FrameConstructionItem& firstItem = aIter.item();
8827 ParentType wrapperType = firstItem.DesiredParentType();
8828 if (wrapperType != eTypeRubyTextContainer) {
8829 // If the first item is not ruby text,
8830 // it should be in a base container.
8831 wrapperType = eTypeRubyBaseContainer;
8832 }
8833
8834 FCItemIterator endIter(aIter);
8835 do {
8836 if (endIter.SkipItemsWantingParentType(wrapperType) ||
8837 // If the skipping above stops at some item which wants a
8838 // different ruby parent, then we have finished.
8839 IsRubyParentType(endIter.item().DesiredParentType())) {
8840 // No more items need to be wrapped in this level container.
8841 break;
8842 }
8843
8844 FCItemIterator contentEndIter(endIter);
8845 contentEndIter.SkipItemsNotWantingRubyParent();
8846 // endIter must be on something doesn't want a ruby parent.
8847 MOZ_ASSERT(contentEndIter != endIter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentEndIter != endIter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(contentEndIter != endIter)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("contentEndIter != endIter"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentEndIter != endIter"
")"); do { *((volatile int*)__null) = 8847; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8848
8849 // InterpretRubyWhitespace depends on the fact that any leading or
8850 // trailing whitespace described in the spec have been trimmed at
8851 // this point. With this precondition, it is safe not to check
8852 // whether contentEndIter has been done.
8853 RubyWhitespaceType whitespaceType =
8854 InterpretRubyWhitespace(aState, endIter, contentEndIter);
8855 if (whitespaceType == eRubyInterLevelWhitespace) {
8856 // Remove inter-level whitespace.
8857 bool atStart = (aIter == endIter);
8858 endIter.DeleteItemsTo(this, contentEndIter);
8859 if (atStart) {
8860 aIter = endIter;
8861 }
8862 } else if (whitespaceType == eRubyInterSegmentWhitespace) {
8863 // If this level container starts with inter-segment whitespaces,
8864 // wrap them. Break at contentEndIter. Otherwise, leave it here.
8865 // Break at endIter. They will be wrapped when we are here again.
8866 if (aIter == endIter) {
8867 MOZ_ASSERT(wrapperType == eTypeRubyBaseContainer,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(wrapperType == eTypeRubyBaseContainer)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(wrapperType == eTypeRubyBaseContainer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("wrapperType == eTypeRubyBaseContainer"
" (" "Inter-segment whitespace should be wrapped in rbc" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapperType == eTypeRubyBaseContainer"
") (" "Inter-segment whitespace should be wrapped in rbc" ")"
); do { *((volatile int*)__null) = 8868; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8868 "Inter-segment whitespace should be wrapped in rbc")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(wrapperType == eTypeRubyBaseContainer)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(wrapperType == eTypeRubyBaseContainer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("wrapperType == eTypeRubyBaseContainer"
" (" "Inter-segment whitespace should be wrapped in rbc" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 8868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "wrapperType == eTypeRubyBaseContainer"
") (" "Inter-segment whitespace should be wrapped in rbc" ")"
); do { *((volatile int*)__null) = 8868; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8869 endIter = contentEndIter;
8870 }
8871 break;
8872 } else if (wrapperType == eTypeRubyTextContainer &&
8873 whitespaceType != eRubyInterLeafWhitespace) {
8874 // Misparented inline content that's not inter-annotation
8875 // whitespace doesn't belong in a pseudo ruby text container.
8876 // Break at endIter.
8877 break;
8878 } else {
8879 endIter = contentEndIter;
8880 }
8881 } while (!endIter.IsDone());
8882
8883 // It is possible that everything our parent wants us to wrap is
8884 // simply an inter-level whitespace, which has been trimmed, or
8885 // an inter-segment whitespace, which will be wrapped later.
8886 // In those cases, don't create anything.
8887 if (aIter != endIter) {
8888 WrapItemsInPseudoParent(aParentContent, aParentStyle, wrapperType, aIter,
8889 endIter);
8890 }
8891}
8892
8893/**
8894 * This function trims leading and trailing whitespaces
8895 * in the given item list.
8896 */
8897void nsCSSFrameConstructor::TrimLeadingAndTrailingWhitespaces(
8898 nsFrameConstructorState& aState, FrameConstructionItemList& aItems) {
8899 FCItemIterator iter(aItems);
8900 if (!iter.IsDone() && iter.item().IsWhitespace(aState)) {
8901 FCItemIterator spaceEndIter(iter);
8902 spaceEndIter.SkipWhitespace(aState);
8903 iter.DeleteItemsTo(this, spaceEndIter);
8904 }
8905
8906 iter.SetToEnd();
8907 if (!iter.AtStart()) {
8908 FCItemIterator spaceEndIter(iter);
8909 do {
8910 iter.Prev();
8911 if (iter.AtStart()) {
8912 // It's fine to not check the first item, because we
8913 // should have trimmed leading whitespaces above.
8914 break;
8915 }
8916 } while (iter.item().IsWhitespace(aState));
8917 iter.Next();
8918 if (iter != spaceEndIter) {
8919 iter.DeleteItemsTo(this, spaceEndIter);
8920 }
8921 }
8922}
8923
8924/**
8925 * This function walks through the child list (aItems) and creates
8926 * needed pseudo ruby boxes to wrap misparented children.
8927 */
8928void nsCSSFrameConstructor::CreateNeededPseudoInternalRubyBoxes(
8929 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8930 nsIFrame* aParentFrame) {
8931 const ParentType ourParentType = GetParentType(aParentFrame);
8932 if (!IsRubyParentType(ourParentType) ||
8933 aItems.AllWantParentType(ourParentType)) {
8934 return;
8935 }
8936
8937 if (!IsRubyPseudo(aParentFrame) ||
8938 ourParentType == eTypeRuby /* for 'display:block ruby' */) {
8939 // Normally, ruby pseudo frames start from and end at some elements,
8940 // which means they don't have leading and trailing whitespaces at
8941 // all. But there are two cases where they do actually have leading
8942 // or trailing whitespaces:
8943 // 1. It is an inter-segment whitespace which in an individual ruby
8944 // base container.
8945 // 2. The pseudo frame starts from or ends at consecutive inline
8946 // content, which is not pure whitespace, but includes some.
8947 // In either case, the whitespaces are not the leading or trailing
8948 // whitespaces defined in the spec, and thus should not be trimmed.
8949 TrimLeadingAndTrailingWhitespaces(aState, aItems);
8950 }
8951
8952 FCItemIterator iter(aItems);
8953 nsIContent* parentContent = aParentFrame->GetContent();
8954 ComputedStyle* parentStyle = aParentFrame->Style();
8955 while (!iter.IsDone()) {
8956 if (!iter.SkipItemsWantingParentType(ourParentType)) {
8957 if (ourParentType == eTypeRuby) {
8958 WrapItemsInPseudoRubyLevelContainer(aState, iter, parentStyle,
8959 parentContent);
8960 } else {
8961 WrapItemsInPseudoRubyLeafBox(iter, parentStyle, parentContent);
8962 }
8963 }
8964 }
8965}
8966
8967/*
8968 * This function works as follows: we walk through the child list (aItems) and
8969 * find items that cannot have aParentFrame as their parent. We wrap
8970 * continuous runs of such items into a FrameConstructionItem for a frame that
8971 * gets them closer to their desired parents. For example, a run of non-row
8972 * children of a row-group will get wrapped in a row. When we later construct
8973 * the frame for this wrapper (in this case for the row), it'll be the correct
8974 * parent for the cells in the set of items we wrapped or we'll wrap cells
8975 * around everything else. At the end of this method, aItems is guaranteed to
8976 * contain only items for frames that can be direct kids of aParentFrame.
8977 */
8978void nsCSSFrameConstructor::CreateNeededPseudoContainers(
8979 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
8980 nsIFrame* aParentFrame) {
8981 ParentType ourParentType = GetParentType(aParentFrame);
8982 if (IsRubyParentType(ourParentType) ||
8983 aItems.AllWantParentType(ourParentType)) {
8984 // Nothing to do here
8985 return;
8986 }
8987
8988 FCItemIterator iter(aItems);
8989 do {
8990 if (iter.SkipItemsWantingParentType(ourParentType)) {
8991 // Nothing else to do here; we're finished
8992 return;
8993 }
8994
8995 // Now we're pointing to the first child that wants a different parent
8996 // type.
8997
8998 // Now try to figure out what kids we can group together. We can generally
8999 // group everything that has a different desired parent type from us. Two
9000 // exceptions to this:
9001 // 1) If our parent type is table, we can't group columns with anything
9002 // else other than whitespace.
9003 // 2) Whitespace that lies between two things we can group which both want
9004 // a non-block parent should be dropped, even if we can't group them
9005 // with each other and even if the whitespace wants a parent of
9006 // ourParentType. Ends of the list count as things that don't want a
9007 // block parent (so that for example we'll drop a whitespace-only list).
9008
9009 FCItemIterator endIter(iter); /* iterator to find the end of the group */
9010 ParentType groupingParentType = endIter.item().DesiredParentType();
9011 if (aItems.AllWantParentType(groupingParentType) &&
9012 groupingParentType != eTypeBlock) {
9013 // Just group them all and be done with it. We need the check for
9014 // eTypeBlock here to catch the "all the items are whitespace" case
9015 // described above.
9016 endIter.SetToEnd();
9017 } else {
9018 // Locate the end of the group.
9019
9020 // Keep track of the type the previous item wanted, in case we have to
9021 // deal with whitespace. Start it off with ourParentType, since that's
9022 // the last thing |iter| would have skipped over.
9023 ParentType prevParentType = ourParentType;
9024 do {
9025 // Walk an iterator past any whitespace that we might be able to drop
9026 // from the list
9027 FCItemIterator spaceEndIter(endIter);
9028 if (prevParentType != eTypeBlock &&
9029 !aParentFrame->IsGeneratedContentFrame() &&
9030 spaceEndIter.item().IsWhitespace(aState)) {
9031 bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
9032
9033 // We drop the whitespace in the following cases:
9034 // 1) If these are not trailing spaces and the next item wants a table
9035 // or table-part parent
9036 // 2) If these are trailing spaces and aParentFrame is a
9037 // tabular container according to rule 1.3 of CSS 2.1 Sec 17.2.1.
9038 // (Being a tabular container pretty much means ourParentType is
9039 // not eTypeBlock besides the eTypeColGroup case, which won't
9040 // reach here.)
9041 if ((!trailingSpaces &&
9042 IsTableParentType(spaceEndIter.item().DesiredParentType())) ||
9043 (trailingSpaces && ourParentType != eTypeBlock)) {
9044 bool updateStart = (iter == endIter);
9045 endIter.DeleteItemsTo(this, spaceEndIter);
9046 NS_ASSERTION(trailingSpaces == endIter.IsDone(),do { if (!(trailingSpaces == endIter.IsDone())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "These should match", "trailingSpaces == endIter.IsDone()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9047); MOZ_PretendNoReturn(); } } while (0)
9047 "These should match")do { if (!(trailingSpaces == endIter.IsDone())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "These should match", "trailingSpaces == endIter.IsDone()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9047); MOZ_PretendNoReturn(); } } while (0)
;
9048
9049 if (updateStart) {
9050 iter = endIter;
9051 }
9052
9053 if (trailingSpaces) {
9054 break; /* Found group end */
9055 }
9056
9057 if (updateStart) {
9058 // Update groupingParentType, since it might have been eTypeBlock
9059 // just because of the whitespace.
9060 groupingParentType = iter.item().DesiredParentType();
9061 }
9062 }
9063 }
9064
9065 // Now endIter points to a non-whitespace item or a non-droppable
9066 // whitespace item. In the latter case, if this is the end of the group
9067 // we'll traverse this whitespace again. But it'll all just be quick
9068 // DesiredParentType() checks which will match ourParentType (that's
9069 // what it means that this is the group end), so it's OK.
9070 // However, when we are grouping a ruby parent, and endIter points to
9071 // a non-droppable whitespace, if the next non-whitespace item also
9072 // wants a ruby parent, the whitespace should also be included into
9073 // the current ruby container.
9074 prevParentType = endIter.item().DesiredParentType();
9075 if (prevParentType == ourParentType &&
9076 (endIter == spaceEndIter || spaceEndIter.IsDone() ||
9077 !IsRubyParentType(groupingParentType) ||
9078 !IsRubyParentType(spaceEndIter.item().DesiredParentType()))) {
9079 // End the group at endIter.
9080 break;
9081 }
9082
9083 if (ourParentType == eTypeTable &&
9084 (prevParentType == eTypeColGroup) !=
9085 (groupingParentType == eTypeColGroup)) {
9086 // Either we started with columns and now found something else, or
9087 // vice versa. In any case, end the grouping.
9088 break;
9089 }
9090
9091 // If we have some whitespace that we were not able to drop and there is
9092 // an item after the whitespace that is already properly parented, then
9093 // make sure to include the spaces in our group but stop the group after
9094 // that.
9095 if (spaceEndIter != endIter && !spaceEndIter.IsDone() &&
9096 ourParentType == spaceEndIter.item().DesiredParentType()) {
9097 endIter = spaceEndIter;
9098 break;
9099 }
9100
9101 // Include the whitespace we didn't drop (if any) in the group.
9102 endIter = spaceEndIter;
9103 prevParentType = endIter.item().DesiredParentType();
9104
9105 endIter.Next();
9106 } while (!endIter.IsDone());
9107 }
9108
9109 if (iter == endIter) {
9110 // Nothing to wrap here; just skipped some whitespace
9111 continue;
9112 }
9113
9114 // Now group together all the items between iter and endIter. The right
9115 // parent type to use depends on ourParentType.
9116 ParentType wrapperType;
9117 switch (ourParentType) {
9118 case eTypeRow:
9119 // The parent type for a cell is eTypeBlock, since that's what a cell
9120 // looks like to its kids.
9121 wrapperType = eTypeBlock;
9122 break;
9123 case eTypeRowGroup:
9124 wrapperType = eTypeRow;
9125 break;
9126 case eTypeTable:
9127 // Either colgroup or rowgroup, depending on what we're grouping.
9128 wrapperType =
9129 groupingParentType == eTypeColGroup ? eTypeColGroup : eTypeRowGroup;
9130 break;
9131 case eTypeColGroup:
9132 MOZ_CRASH("Colgroups should be suppresing non-col child items")do { do { } while (false); MOZ_ReportCrash("" "Colgroups should be suppresing non-col child items"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9132); AnnotateMozCrashReason("MOZ_CRASH(" "Colgroups should be suppresing non-col child items"
")"); do { *((volatile int*)__null) = 9132; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
9133 default:
9134 NS_ASSERTION(ourParentType == eTypeBlock, "Unrecognized parent type")do { if (!(ourParentType == eTypeBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unrecognized parent type", "ourParentType == eTypeBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9134); MOZ_PretendNoReturn(); } } while (0)
;
9135 if (IsRubyParentType(groupingParentType)) {
9136 wrapperType = eTypeRuby;
9137 } else {
9138 NS_ASSERTION(IsTableParentType(groupingParentType),do { if (!(IsTableParentType(groupingParentType))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "groupingParentType should be either Ruby or table"
, "IsTableParentType(groupingParentType)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9139); MOZ_PretendNoReturn(); } } while (0)
9139 "groupingParentType should be either Ruby or table")do { if (!(IsTableParentType(groupingParentType))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "groupingParentType should be either Ruby or table"
, "IsTableParentType(groupingParentType)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9139); MOZ_PretendNoReturn(); } } while (0)
;
9140 wrapperType = eTypeTable;
9141 }
9142 }
9143
9144 ComputedStyle* parentStyle = aParentFrame->Style();
9145 WrapItemsInPseudoParent(aParentFrame->GetContent(), parentStyle,
9146 wrapperType, iter, endIter);
9147
9148 // Now |iter| points to the item that was the first one we didn't wrap;
9149 // loop and see whether we need to skip it or wrap it in something
9150 // different.
9151 } while (!iter.IsDone());
9152}
9153
9154/**
9155 * This method wraps frame construction item from |aIter| to
9156 * |aEndIter|. After it returns, aIter points to the first item
9157 * after the wrapper.
9158 */
9159void nsCSSFrameConstructor::WrapItemsInPseudoParent(
9160 nsIContent* aParentContent, ComputedStyle* aParentStyle,
9161 ParentType aWrapperType, FCItemIterator& aIter,
9162 const FCItemIterator& aEndIter) {
9163 const PseudoParentData& pseudoData = sPseudoParentData[aWrapperType];
9164 PseudoStyleType pseudoType = pseudoData.mPseudoType;
9165 auto& parentDisplay = *aParentStyle->StyleDisplay();
9166 auto parentDisplayInside = parentDisplay.DisplayInside();
9167
9168 // XXXmats should we use IsInlineInsideStyle() here instead? seems odd to
9169 // exclude RubyBaseContainer/RubyTextContainer...
9170 if (pseudoType == PseudoStyleType::table &&
9171 (parentDisplay.IsInlineFlow() ||
9172 parentDisplayInside == StyleDisplayInside::RubyBase ||
9173 parentDisplayInside == StyleDisplayInside::RubyText)) {
9174 pseudoType = PseudoStyleType::inlineTable;
9175 }
9176
9177 RefPtr<ComputedStyle> wrapperStyle;
9178 if (pseudoData.mFCData.mBits & FCDATA_IS_WRAPPER_ANON_BOX0x400000) {
9179 wrapperStyle = mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
9180 pseudoType, aParentStyle);
9181 } else {
9182 wrapperStyle =
9183 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
9184 pseudoType);
9185 }
9186
9187 // Use the content of our parent frame
9188 auto* newItem = new (this) FrameConstructionItem(
9189 &pseudoData.mFCData, aParentContent, wrapperStyle.forget(), true);
9190
9191 const nsStyleDisplay* disp = newItem->mComputedStyle->StyleDisplay();
9192 // Here we're cheating a tad... technically, table-internal items should be
9193 // inline if aParentFrame is inline, but they'll get wrapped in an
9194 // inline-table in the end, so it'll all work out. In any case, arguably
9195 // we don't need to maintain this state at this point... but it's better
9196 // to, I guess.
9197 newItem->mIsAllInline = disp->IsInlineOutsideStyle();
9198
9199 bool isRuby = disp->IsRubyDisplayType();
9200 if (!isRuby) {
9201 // Table pseudo frames always induce line boundaries around their
9202 // contents.
9203 newItem->mChildItems.SetLineBoundaryAtStart(true);
9204 newItem->mChildItems.SetLineBoundaryAtEnd(true);
9205 }
9206 // The parent of the items in aItems is also the parent of the items
9207 // in mChildItems
9208 newItem->mChildItems.SetParentHasNoShadowDOM(
9209 aIter.List()->ParentHasNoShadowDOM());
9210
9211 // Eat up all items between |aIter| and |aEndIter| and put them in our
9212 // wrapper Advances |aIter| to point to |aEndIter|.
9213 aIter.AppendItemsToList(this, aEndIter, newItem->mChildItems);
9214
9215 aIter.InsertItem(newItem);
9216}
9217
9218void nsCSSFrameConstructor::CreateNeededPseudoSiblings(
9219 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
9220 nsIFrame* aParentFrame) {
9221 if (aItems.IsEmpty() || GetParentType(aParentFrame) != eTypeRuby) {
9222 return;
9223 }
9224
9225 FCItemIterator iter(aItems);
9226 StyleDisplay firstDisplay =
9227 iter.item().mComputedStyle->StyleDisplay()->mDisplay;
9228 if (firstDisplay == StyleDisplay::RubyBaseContainer) {
9229 return;
9230 }
9231 NS_ASSERTION(firstDisplay == StyleDisplay::RubyTextContainer,do { if (!(firstDisplay == StyleDisplay::RubyTextContainer)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Child of ruby frame should either a rbc or a rtc"
, "firstDisplay == StyleDisplay::RubyTextContainer", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9232); MOZ_PretendNoReturn(); } } while (0)
9232 "Child of ruby frame should either a rbc or a rtc")do { if (!(firstDisplay == StyleDisplay::RubyTextContainer)) {
NS_DebugBreak(NS_DEBUG_ASSERTION, "Child of ruby frame should either a rbc or a rtc"
, "firstDisplay == StyleDisplay::RubyTextContainer", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9232); MOZ_PretendNoReturn(); } } while (0)
;
9233
9234 const PseudoParentData& pseudoData =
9235 sPseudoParentData[eTypeRubyBaseContainer];
9236 RefPtr<ComputedStyle> pseudoStyle =
9237 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
9238 pseudoData.mPseudoType, aParentFrame->Style());
9239 FrameConstructionItem* newItem = new (this) FrameConstructionItem(
9240 &pseudoData.mFCData,
9241 // Use the content of the parent frame
9242 aParentFrame->GetContent(), pseudoStyle.forget(), true);
9243 newItem->mIsAllInline = true;
9244 newItem->mChildItems.SetParentHasNoShadowDOM(true);
9245 iter.InsertItem(newItem);
9246}
9247
9248#ifdef DEBUG1
9249/**
9250 * Returns true iff aFrame should be wrapped in an anonymous flex/grid item,
9251 * rather than being a direct child of aContainerFrame.
9252 *
9253 * NOTE: aContainerFrame must be a flex or grid container - this function is
9254 * purely for sanity-checking the children of these container types.
9255 * NOTE: See also NeedsAnonFlexOrGridItem(), for the non-debug version of this
9256 * logic (which operates a bit earlier, on FCData instead of frames).
9257 */
9258static bool FrameWantsToBeInAnonymousItem(const nsIFrame* aContainerFrame,
9259 const nsIFrame* aFrame) {
9260 MOZ_ASSERT(aContainerFrame->IsFlexOrGridContainer())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContainerFrame->IsFlexOrGridContainer())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aContainerFrame->IsFlexOrGridContainer()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aContainerFrame->IsFlexOrGridContainer()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContainerFrame->IsFlexOrGridContainer()"
")"); do { *((volatile int*)__null) = 9260; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9261
9262 // Any line-participant frames (e.g. text) definitely want to be wrapped in
9263 // an anonymous flex/grid item.
9264 if (aFrame->IsLineParticipant()) {
9265 return true;
9266 }
9267
9268 // If the container is a -webkit-{inline-}box container, then placeholders
9269 // also need to be wrapped, for compatibility.
9270 if (IsFlexContainerForLegacyWebKitBox(aContainerFrame) &&
9271 aFrame->IsPlaceholderFrame()) {
9272 return true;
9273 }
9274
9275 return false;
9276}
9277#endif
9278
9279static void VerifyGridFlexContainerChildren(nsIFrame* aParentFrame,
9280 const nsFrameList& aChildren) {
9281#ifdef DEBUG1
9282 if (!aParentFrame->IsFlexOrGridContainer()) {
9283 return;
9284 }
9285
9286 bool prevChildWasAnonItem = false;
9287 for (const nsIFrame* child : aChildren) {
9288 MOZ_ASSERT(!FrameWantsToBeInAnonymousItem(aParentFrame, child),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!FrameWantsToBeInAnonymousItem(aParentFrame, child))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!FrameWantsToBeInAnonymousItem(aParentFrame, child))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
" (" "frame wants to be inside an anonymous item, but it isn't"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
") (" "frame wants to be inside an anonymous item, but it isn't"
")"); do { *((volatile int*)__null) = 9289; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9289 "frame wants to be inside an anonymous item, but it isn't")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!FrameWantsToBeInAnonymousItem(aParentFrame, child))
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!FrameWantsToBeInAnonymousItem(aParentFrame, child))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
" (" "frame wants to be inside an anonymous item, but it isn't"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!FrameWantsToBeInAnonymousItem(aParentFrame, child)"
") (" "frame wants to be inside an anonymous item, but it isn't"
")"); do { *((volatile int*)__null) = 9289; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9290 if (IsAnonymousItem(child)) {
9291 AssertAnonymousFlexOrGridItemParent(child, aParentFrame);
9292 MOZ_ASSERT(!prevChildWasAnonItem, "two anon items in a row")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!prevChildWasAnonItem)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!prevChildWasAnonItem))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!prevChildWasAnonItem"
" (" "two anon items in a row" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!prevChildWasAnonItem"
") (" "two anon items in a row" ")"); do { *((volatile int*)
__null) = 9292; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9293 nsIFrame* firstWrappedChild = child->PrincipalChildList().FirstChild();
9294 MOZ_ASSERT(firstWrappedChild, "anonymous item shouldn't be empty")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(firstWrappedChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(firstWrappedChild))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("firstWrappedChild"
" (" "anonymous item shouldn't be empty" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstWrappedChild"
") (" "anonymous item shouldn't be empty" ")"); do { *((volatile
int*)__null) = 9294; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9295 prevChildWasAnonItem = true;
9296 } else {
9297 prevChildWasAnonItem = false;
9298 }
9299 }
9300#endif
9301}
9302
9303static bool FrameHasOnlyPlaceholderPrevSiblings(const nsIFrame* aFrame) {
9304 // Check for prev siblings, ignoring placeholder frames.
9305 MOZ_ASSERT(aFrame, "frame must not be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "frame must not be null"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"frame must not be null" ")"); do { *((volatile int*)__null)
= 9305; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9306 const nsIFrame* prevSibling = aFrame;
9307 do {
9308 prevSibling = prevSibling->GetPrevSibling();
9309 } while (prevSibling && prevSibling->IsPlaceholderFrame());
9310 return !prevSibling;
9311}
9312
9313static bool FrameHasOnlyPlaceholderNextSiblings(const nsIFrame* aFrame) {
9314 // Check for next siblings, ignoring placeholder frames.
9315 MOZ_ASSERT(aFrame, "frame must not be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "frame must not be null"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"frame must not be null" ")"); do { *((volatile int*)__null)
= 9315; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9316 const nsIFrame* nextSibling = aFrame;
9317 do {
9318 nextSibling = nextSibling->GetNextSibling();
9319 } while (nextSibling && nextSibling->IsPlaceholderFrame());
9320 return !nextSibling;
9321}
9322
9323static void SetPageValues(nsIFrame* const aFrame,
9324 const nsAtom* const aAutoValue,
9325 const nsAtom* const aStartValue,
9326 const nsAtom* const aEndValue) {
9327 MOZ_ASSERT(aAutoValue, "Auto page value should never be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aAutoValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aAutoValue))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aAutoValue" " (" "Auto page value should never be null"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aAutoValue"
") (" "Auto page value should never be null" ")"); do { *((volatile
int*)__null) = 9327; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9328 MOZ_ASSERT(aStartValue || aEndValue, "Should not have called with no values")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStartValue || aEndValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStartValue || aEndValue))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aStartValue || aEndValue"
" (" "Should not have called with no values" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartValue || aEndValue"
") (" "Should not have called with no values" ")"); do { *((
volatile int*)__null) = 9328; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9329 nsIFrame::PageValues* pageValues =
9330 aFrame->GetProperty(nsIFrame::PageValuesProperty());
9331
9332 if (aStartValue) {
9333 if (aStartValue == aAutoValue) {
9334 // If the page value struct already exists, set the start value to null
9335 // to indicate the auto value.
9336 if (pageValues) {
9337 pageValues->mStartPageValue = nullptr;
9338 }
9339 } else {
9340 // The start value is not auto, so we need to store it, creating the
9341 // page values struct if it does not already exist.
9342 if (!pageValues) {
9343 pageValues = new nsIFrame::PageValues();
9344 aFrame->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9345 }
9346 pageValues->mStartPageValue = aStartValue;
9347 }
9348 }
9349 if (aEndValue) {
9350 if (aEndValue == aAutoValue) {
9351 // If the page value struct already exists, set the end value to null
9352 // to indicate the auto value.
9353 if (pageValues) {
9354 pageValues->mEndPageValue = nullptr;
9355 }
9356 } else {
9357 // The end value is not auto, so we need to store it, creating the
9358 // page values struct if it does not already exist.
9359 if (!pageValues) {
9360 pageValues = new nsIFrame::PageValues();
9361 aFrame->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9362 }
9363 pageValues->mEndPageValue = aEndValue;
9364 }
9365 }
9366}
9367
9368inline void nsCSSFrameConstructor::ConstructFramesFromItemList(
9369 nsFrameConstructorState& aState, FrameConstructionItemList& aItems,
9370 nsContainerFrame* aParentFrame, bool aParentIsWrapperAnonBox,
9371 nsFrameList& aFrameList) {
9372#ifdef DEBUG1
9373 if (aParentFrame->StyleContent()->mContent.IsNone() &&
9374 StaticPrefs::layout_css_element_content_none_enabled()) {
9375 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9376 MOZ_ASSERT(iter.item().mContent->IsInNativeAnonymousSubtree() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(iter.item().mContent->IsInNativeAnonymousSubtree(
) || iter.item().mComputedStyle->IsPseudoOrAnonBox())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(iter.item().mContent->IsInNativeAnonymousSubtree(
) || iter.item().mComputedStyle->IsPseudoOrAnonBox()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
")"); do { *((volatile int*)__null) = 9377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9377 iter.item().mComputedStyle->IsPseudoOrAnonBox())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(iter.item().mContent->IsInNativeAnonymousSubtree(
) || iter.item().mComputedStyle->IsPseudoOrAnonBox())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(iter.item().mContent->IsInNativeAnonymousSubtree(
) || iter.item().mComputedStyle->IsPseudoOrAnonBox()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "iter.item().mContent->IsInNativeAnonymousSubtree() || iter.item().mComputedStyle->IsPseudoOrAnonBox()"
")"); do { *((volatile int*)__null) = 9377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9378 }
9379 }
9380
9381 // The assertion condition should match the logic in
9382 // MaybePushFloatContainingBlock().
9383 MOZ_ASSERT(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||
aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate
== aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(ShouldSuppressFloatingOfDescendants
(aParentFrame) || aParentFrame->IsFloatContainingBlock()) ||
aState.mFloatCBCandidate == aParentFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
" (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
") (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")"); do { *((volatile int*)__null) = 9388
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9384 aParentFrame->IsFloatContainingBlock()) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||
aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate
== aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(ShouldSuppressFloatingOfDescendants
(aParentFrame) || aParentFrame->IsFloatContainingBlock()) ||
aState.mFloatCBCandidate == aParentFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
" (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
") (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")"); do { *((volatile int*)__null) = 9388
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9385 aState.mFloatCBCandidate == aParentFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||
aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate
== aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(ShouldSuppressFloatingOfDescendants
(aParentFrame) || aParentFrame->IsFloatContainingBlock()) ||
aState.mFloatCBCandidate == aParentFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
" (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
") (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")"); do { *((volatile int*)__null) = 9388
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9386 "Our caller or ProcessChildren()'s caller should call "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||
aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate
== aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(ShouldSuppressFloatingOfDescendants
(aParentFrame) || aParentFrame->IsFloatContainingBlock()) ||
aState.mFloatCBCandidate == aParentFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
" (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
") (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")"); do { *((volatile int*)__null) = 9388
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9387 "MaybePushFloatContainingBlock() to handle the float containing "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||
aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate
== aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(ShouldSuppressFloatingOfDescendants
(aParentFrame) || aParentFrame->IsFloatContainingBlock()) ||
aState.mFloatCBCandidate == aParentFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
" (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
") (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")"); do { *((volatile int*)__null) = 9388
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
9388 "block candidate!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(ShouldSuppressFloatingOfDescendants(aParentFrame) ||
aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate
== aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(ShouldSuppressFloatingOfDescendants
(aParentFrame) || aParentFrame->IsFloatContainingBlock()) ||
aState.mFloatCBCandidate == aParentFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
" (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(ShouldSuppressFloatingOfDescendants(aParentFrame) || aParentFrame->IsFloatContainingBlock()) || aState.mFloatCBCandidate == aParentFrame"
") (" "Our caller or ProcessChildren()'s caller should call "
"MaybePushFloatContainingBlock() to handle the float containing "
"block candidate!" ")"); do { *((volatile int*)__null) = 9388
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9389 aState.mFloatCBCandidate = nullptr;
9390#endif
9391
9392 // Ensure aParentIsWrapperAnonBox is correct. We _could_ compute it directly,
9393 // but it would be a bit slow, which is why we pass it from callers, who have
9394 // that information offhand in many cases.
9395 MOZ_ASSERT(ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ParentIsWrapperAnonBox(aParentFrame) == aParentIsWrapperAnonBox"
")"); do { *((volatile int*)__null) = 9395; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9396
9397 // Note: we explicitly exclude TableColGroupFrame because it doesn't
9398 // have the FCDATA_IS_WRAPPER_ANON_BOX on pseudos so aParentIsWrapperAnonBox
9399 // is false for such pseudos (see sPseudoParentData below).
9400 if (!aParentIsWrapperAnonBox && aState.mHasRenderedLegend &&
9401 aParentFrame->GetContent()->IsHTMLElement(nsGkAtoms::fieldset) &&
9402 !aParentFrame->IsTableColGroupFrame()) {
9403 DebugOnly<bool> found = false;
9404 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9405 if (iter.item().mIsRenderedLegend) {
9406 // This makes the rendered legend the first frame in the fieldset child
9407 // list which makes keyboard traversal follow the visual order.
9408 nsFieldSetFrame* fieldSetFrame = GetFieldSetFrameFor(aParentFrame);
9409 nsFrameList renderedLegend;
9410 ConstructFramesFromItem(aState, iter, fieldSetFrame, renderedLegend);
9411 MOZ_ASSERT(renderedLegend.OnlyChild(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(renderedLegend.OnlyChild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(renderedLegend.OnlyChild()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("renderedLegend.OnlyChild()"
" (" "a rendered legend should have exactly one frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "renderedLegend.OnlyChild()"
") (" "a rendered legend should have exactly one frame" ")")
; do { *((volatile int*)__null) = 9412; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9412 "a rendered legend should have exactly one frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(renderedLegend.OnlyChild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(renderedLegend.OnlyChild()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("renderedLegend.OnlyChild()"
" (" "a rendered legend should have exactly one frame" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "renderedLegend.OnlyChild()"
") (" "a rendered legend should have exactly one frame" ")")
; do { *((volatile int*)__null) = 9412; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9413 fieldSetFrame->InsertFrames(FrameChildListID::Principal, nullptr,
9414 nullptr, std::move(renderedLegend));
9415 FCItemIterator next = iter;
9416 next.Next();
9417 iter.DeleteItemsTo(this, next);
9418 found = true;
9419 break;
9420 }
9421 }
9422 MOZ_ASSERT(found, "should have found our rendered legend")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(found)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(found))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("found" " (" "should have found our rendered legend"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9422); AnnotateMozCrashReason("MOZ_ASSERT" "(" "found" ") ("
"should have found our rendered legend" ")"); do { *((volatile
int*)__null) = 9422; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9423 }
9424
9425 CreateNeededPseudoContainers(aState, aItems, aParentFrame);
9426 CreateNeededAnonFlexOrGridItems(aState, aItems, aParentFrame);
9427 CreateNeededPseudoInternalRubyBoxes(aState, aItems, aParentFrame);
9428 CreateNeededPseudoSiblings(aState, aItems, aParentFrame);
9429
9430 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
9431 MOZ_ASSERT(!iter.item().mIsRenderedLegend,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!iter.item().mIsRenderedLegend)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!iter.item().mIsRenderedLegend
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!iter.item().mIsRenderedLegend" " (" "Only one item can be the rendered legend, "
"and it should've been handled above" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.item().mIsRenderedLegend"
") (" "Only one item can be the rendered legend, " "and it should've been handled above"
")"); do { *((volatile int*)__null) = 9433; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9432 "Only one item can be the rendered legend, "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!iter.item().mIsRenderedLegend)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!iter.item().mIsRenderedLegend
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!iter.item().mIsRenderedLegend" " (" "Only one item can be the rendered legend, "
"and it should've been handled above" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.item().mIsRenderedLegend"
") (" "Only one item can be the rendered legend, " "and it should've been handled above"
")"); do { *((volatile int*)__null) = 9433; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9433 "and it should've been handled above")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!iter.item().mIsRenderedLegend)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!iter.item().mIsRenderedLegend
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!iter.item().mIsRenderedLegend" " (" "Only one item can be the rendered legend, "
"and it should've been handled above" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!iter.item().mIsRenderedLegend"
") (" "Only one item can be the rendered legend, " "and it should've been handled above"
")"); do { *((volatile int*)__null) = 9433; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9434 NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),do { if (!(iter.item().DesiredParentType() == GetParentType(aParentFrame
))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Needed pseudos didn't get created; expect bad things"
, "iter.item().DesiredParentType() == GetParentType(aParentFrame)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9435); MOZ_PretendNoReturn(); } } while (0)
9435 "Needed pseudos didn't get created; expect bad things")do { if (!(iter.item().DesiredParentType() == GetParentType(aParentFrame
))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Needed pseudos didn't get created; expect bad things"
, "iter.item().DesiredParentType() == GetParentType(aParentFrame)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9435); MOZ_PretendNoReturn(); } } while (0)
;
9436 ConstructFramesFromItem(aState, iter, aParentFrame, aFrameList);
9437 }
9438
9439 VerifyGridFlexContainerChildren(aParentFrame, aFrameList);
9440
9441 // Calculate and propagate page-name values for each frame in the frame list.
9442 // We do not want to compute and propagate page-name values from frames that
9443 // are children of any subclasses of block frames, but not actually a block
9444 // frame. The page-name property does not apply to frames which cannot create
9445 // class A breakpoints (currently no subclass of BlockFrame can). Because the
9446 // property does not apply, those children also cannot propagate page-name
9447 // values.
9448 // This assumption helps avoid unnecessarily handling page-names for frames
9449 // such as form controls, which also avoids bug 1819468.
9450 if (aState.mPresContext->IsPaginated() && aParentFrame->IsBlockFrame()) {
9451 // Set the start/end page values while iterating the frame list, to walk
9452 // up the frame tree only once after iterating the frame list.
9453 // This also avoids extra property lookups on these frames.
9454 MOZ_ASSERT(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue()"
" (" "aState.mAutoPageNameValue should have been equivalent to "
"the auto value stored on our parent frame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue()"
") (" "aState.mAutoPageNameValue should have been equivalent to "
"the auto value stored on our parent frame." ")"); do { *((volatile
int*)__null) = 9456; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9455 "aState.mAutoPageNameValue should have been equivalent to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue()"
" (" "aState.mAutoPageNameValue should have been equivalent to "
"the auto value stored on our parent frame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue()"
") (" "aState.mAutoPageNameValue should have been equivalent to "
"the auto value stored on our parent frame." ")"); do { *((volatile
int*)__null) = 9456; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9456 "the auto value stored on our parent frame.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue()"
" (" "aState.mAutoPageNameValue should have been equivalent to "
"the auto value stored on our parent frame." ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mAutoPageNameValue == aParentFrame->GetAutoPageValue()"
") (" "aState.mAutoPageNameValue should have been equivalent to "
"the auto value stored on our parent frame." ")"); do { *((volatile
int*)__null) = 9456; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9457 // Even though we store null for page values that equal the "auto" resolved
9458 // value on frames, we always want startPageValue/endPageValue to be the
9459 // actual atoms reflecting the start/end values. This is because when we
9460 // propagate the values up the frame tree, we will need to compare them to
9461 // the auto value for each ancestor. This value might be different than the
9462 // auto value for this frame.
9463 const nsAtom* startPageValue = nullptr;
9464 const nsAtom* endPageValue = nullptr;
9465 for (nsIFrame* f : aFrameList) {
9466 if (f->IsPlaceholderFrame()) {
9467 continue;
9468 }
9469 // Resolve auto against the parent frame's used page name, which has been
9470 // determined and set on aState.mAutoPageNameValue. If this item is not
9471 // block-level then we use the value that auto resolves to.
9472 //
9473 // This is to achieve the propagation behavior described in the spec:
9474 //
9475 // "A start page value and end page value is determined for each box as
9476 // the value (if any) propagated from its first or last child box
9477 // (respectively), else the used value on the box itself."
9478 //
9479 // "A child propagates its own start or end page value if and only if the
9480 // page property applies to it."
9481 //
9482 // The page property only applies to "boxes that create class A break
9483 // points". When taken together, this means that non block-level children
9484 // do not propagate start/end page values, and instead we use "the used
9485 // value on the box itself", the "box itself" being aParentFrame. This
9486 // value has been determined and saved as aState.mAutoPageNameValue
9487 //
9488 // https://www.w3.org/TR/css-page-3/#using-named-pages
9489 // https://www.w3.org/TR/css-break-3/#btw-blocks
9490 const StylePageName& pageName = f->StylePage()->mPage;
9491 const nsAtom* const pageNameAtom =
9492 (pageName.IsPageName() && f->IsBlockOutside())
9493 ? pageName.AsPageName().AsAtom()
9494 : aState.mAutoPageNameValue;
9495 nsIFrame::PageValues* pageValues =
9496 f->GetProperty(nsIFrame::PageValuesProperty());
9497 // If this frame has any children, it will already have had its page
9498 // values set at this point. However, if no page values have been set,
9499 // we must ensure that the appropriate PageValuesProperty value has been
9500 // set.
9501 // If the page name is equal to the auto value, then PageValuesProperty
9502 // should remain null to indicate that the start/end values are both
9503 // equal to the auto value.
9504 if (pageNameAtom != aState.mAutoPageNameValue && !pageValues) {
9505 pageValues = new nsIFrame::PageValues{pageNameAtom, pageNameAtom};
9506 f->SetProperty(nsIFrame::PageValuesProperty(), pageValues);
9507 }
9508 // We don't want to use GetStartPageValue() or GetEndPageValue(), as each
9509 // requires a property lookup which we can avoid here.
9510 if (!startPageValue) {
9511 startPageValue = (pageValues && pageValues->mStartPageValue)
9512 ? pageValues->mStartPageValue.get()
9513 : aState.mAutoPageNameValue;
9514 }
9515 endPageValue = (pageValues && pageValues->mEndPageValue)
9516 ? pageValues->mEndPageValue.get()
9517 : aState.mAutoPageNameValue;
9518 MOZ_ASSERT(startPageValue && endPageValue,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(startPageValue && endPageValue)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(startPageValue && endPageValue))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("startPageValue && endPageValue"
" (" "Should have found start/end page value" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startPageValue && endPageValue"
") (" "Should have found start/end page value" ")"); do { *(
(volatile int*)__null) = 9519; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9519 "Should have found start/end page value")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(startPageValue && endPageValue)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(startPageValue && endPageValue))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("startPageValue && endPageValue"
" (" "Should have found start/end page value" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "startPageValue && endPageValue"
") (" "Should have found start/end page value" ")"); do { *(
(volatile int*)__null) = 9519; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9520 }
9521 MOZ_ASSERT(!startPageValue == !endPageValue,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!startPageValue == !endPageValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!startPageValue == !endPageValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!startPageValue == !endPageValue" " (" "Should have set both or neither page values"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!startPageValue == !endPageValue"
") (" "Should have set both or neither page values" ")"); do
{ *((volatile int*)__null) = 9522; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9522 "Should have set both or neither page values")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!startPageValue == !endPageValue)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!startPageValue == !endPageValue
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!startPageValue == !endPageValue" " (" "Should have set both or neither page values"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!startPageValue == !endPageValue"
") (" "Should have set both or neither page values" ")"); do
{ *((volatile int*)__null) = 9522; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9523 if (startPageValue) {
9524 // Walk up the frame tree from our parent frame, propagating start and
9525 // end page values.
9526 // As we go, if we find that, for a frame, we are not contributing one of
9527 // the start/end page values, then our subtree will not contribute this
9528 // value from that frame onward. startPageValue/endPageValue are set to
9529 // null to indicate this.
9530 // Stop iterating when we are not contributing either start or end
9531 // values, when we hit the root frame (no parent), or when we find a
9532 // frame that is not a block frame.
9533 for (nsContainerFrame* ancestorFrame = aParentFrame;
9534 (startPageValue || endPageValue) && ancestorFrame &&
9535 ancestorFrame->IsBlockFrame();
9536 ancestorFrame = ancestorFrame->GetParent()) {
9537 MOZ_ASSERT(!ancestorFrame->GetPrevInFlow(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!ancestorFrame->GetPrevInFlow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!ancestorFrame->GetPrevInFlow
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!ancestorFrame->GetPrevInFlow()" " (" "Should not have fragmentation yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ancestorFrame->GetPrevInFlow()"
") (" "Should not have fragmentation yet" ")"); do { *((volatile
int*)__null) = 9538; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9538 "Should not have fragmentation yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!ancestorFrame->GetPrevInFlow())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!ancestorFrame->GetPrevInFlow
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!ancestorFrame->GetPrevInFlow()" " (" "Should not have fragmentation yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9538); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ancestorFrame->GetPrevInFlow()"
") (" "Should not have fragmentation yet" ")"); do { *((volatile
int*)__null) = 9538; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9539 MOZ_ASSERT(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
" (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9541; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9540 "Frame should have been visited by "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
" (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9541; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9541 "AutoFrameConstructionPageName")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(ancestorFrame->mWasVisitedByAutoFrameConstructionPageName
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
" (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ancestorFrame->mWasVisitedByAutoFrameConstructionPageName"
") (" "Frame should have been visited by " "AutoFrameConstructionPageName"
")"); do { *((volatile int*)__null) = 9541; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9542 {
9543 // Get what the auto value is, based on this frame's parent.
9544 // For the root frame, `auto` resolves to the empty atom.
9545 const nsContainerFrame* const parent = ancestorFrame->GetParent();
9546 const nsAtom* const parentAuto = MOZ_LIKELY(parent)(__builtin_expect(!!(parent), 1))
9547 ? parent->GetAutoPageValue()
9548 : nsGkAtoms::_empty;
9549 SetPageValues(ancestorFrame, parentAuto, startPageValue,
9550 endPageValue);
9551 }
9552 // Once we stop contributing start/end values, we know there is a
9553 // sibling subtree that contributed that value to our shared parent
9554 // instead of our starting frame's subtree. This means once
9555 // startPageValue/endPageValue becomes null, indicating that we are no
9556 // longer contributing that page value, it should stay null and we no
9557 // longer need to check for siblings in that direction.
9558 if (startPageValue &&
9559 !FrameHasOnlyPlaceholderPrevSiblings(ancestorFrame)) {
9560 startPageValue = nullptr;
9561 }
9562 if (endPageValue &&
9563 !FrameHasOnlyPlaceholderNextSiblings(ancestorFrame)) {
9564 endPageValue = nullptr;
9565 }
9566 }
9567 }
9568 }
9569
9570 if (aParentIsWrapperAnonBox) {
9571 for (nsIFrame* f : aFrameList) {
9572 f->SetParentIsWrapperAnonBox();
9573 }
9574 }
9575}
9576
9577void nsCSSFrameConstructor::AddFCItemsForAnonymousContent(
9578 nsFrameConstructorState& aState, nsContainerFrame* aFrame,
9579 const nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
9580 FrameConstructionItemList& aItemsToConstruct,
9581 const AutoFrameConstructionPageName&) {
9582 for (const auto& info : aAnonymousItems) {
9583 nsIContent* content = info.mContent;
9584 // Gecko-styled nodes should have no pending restyle flags.
9585 // Assert some things about this content
9586 MOZ_ASSERT(!(content->GetFlags() &do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES
| NODE_NEEDS_FRAME)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(content->GetFlags() &
(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
" (" "Should not be marked as needing frames" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9588; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9587 (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME)),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES
| NODE_NEEDS_FRAME)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(content->GetFlags() &
(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
" (" "Should not be marked as needing frames" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9588; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9588 "Should not be marked as needing frames")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES
| NODE_NEEDS_FRAME)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(content->GetFlags() &
(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
" (" "Should not be marked as needing frames" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(content->GetFlags() & (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME))"
") (" "Should not be marked as needing frames" ")"); do { *(
(volatile int*)__null) = 9588; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9589 MOZ_ASSERT(!content->GetPrimaryFrame(), "Should have no existing frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!content->GetPrimaryFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!content->GetPrimaryFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!content->GetPrimaryFrame()" " (" "Should have no existing frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->GetPrimaryFrame()"
") (" "Should have no existing frame" ")"); do { *((volatile
int*)__null) = 9589; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9590 MOZ_ASSERT(!content->IsComment() && !content->IsProcessingInstruction(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!content->IsComment() && !content->IsProcessingInstruction
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!content->IsComment() && !content->IsProcessingInstruction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!content->IsComment() && !content->IsProcessingInstruction()"
" (" "Why is someone creating garbage anonymous content" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsComment() && !content->IsProcessingInstruction()"
") (" "Why is someone creating garbage anonymous content" ")"
); do { *((volatile int*)__null) = 9591; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9591 "Why is someone creating garbage anonymous content")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!content->IsComment() && !content->IsProcessingInstruction
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!content->IsComment() && !content->IsProcessingInstruction
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!content->IsComment() && !content->IsProcessingInstruction()"
" (" "Why is someone creating garbage anonymous content" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsComment() && !content->IsProcessingInstruction()"
") (" "Why is someone creating garbage anonymous content" ")"
); do { *((volatile int*)__null) = 9591; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9592
9593 // Make sure we eagerly performed the servo cascade when the anonymous
9594 // nodes were created.
9595 MOZ_ASSERT(!content->IsElement() || content->AsElement()->HasServoData())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!content->IsElement() || content->AsElement()->
HasServoData())>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(!content->IsElement() || content
->AsElement()->HasServoData()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!content->IsElement() || content->AsElement()->HasServoData()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!content->IsElement() || content->AsElement()->HasServoData()"
")"); do { *((volatile int*)__null) = 9595; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9596
9597 RefPtr<ComputedStyle> computedStyle = ResolveComputedStyle(content);
9598
9599 AddFrameConstructionItemsInternal(aState, content, aFrame, true,
9600 computedStyle, {ItemFlag::AllowPageBreak},
9601 aItemsToConstruct);
9602 }
9603}
9604
9605void nsCSSFrameConstructor::ProcessChildren(
9606 nsFrameConstructorState& aState, nsIContent* aContent,
9607 ComputedStyle* aComputedStyle, nsContainerFrame* aFrame,
9608 const bool aCanHaveGeneratedContent, nsFrameList& aFrameList,
9609 const bool aAllowBlockStyles, nsIFrame* aPossiblyLeafFrame) {
9610 MOZ_ASSERT(aFrame, "Must have parent frame here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aFrame))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aFrame" " (" "Must have parent frame here"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame" ") ("
"Must have parent frame here" ")"); do { *((volatile int*)__null
) = 9610; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9611 MOZ_ASSERT(aFrame->GetContentInsertionFrame() == aFrame,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetContentInsertionFrame() == aFrame)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->GetContentInsertionFrame() == aFrame))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetContentInsertionFrame() == aFrame"
" (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9613; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9612 "Parent frame in ProcessChildren should be its own "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetContentInsertionFrame() == aFrame)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->GetContentInsertionFrame() == aFrame))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetContentInsertionFrame() == aFrame"
" (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9613; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9613 "content insertion frame")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFrame->GetContentInsertionFrame() == aFrame)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFrame->GetContentInsertionFrame() == aFrame))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aFrame->GetContentInsertionFrame() == aFrame"
" (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aFrame->GetContentInsertionFrame() == aFrame"
") (" "Parent frame in ProcessChildren should be its own " "content insertion frame"
")"); do { *((volatile int*)__null) = 9613; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9614
9615 const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH1026;
9616 static_assert(kMaxDepth <= UINT16_MAX(65535), "mCurrentDepth type is too narrow");
9617 AutoRestore<uint16_t> savedDepth(mCurrentDepth);
9618 if (mCurrentDepth != UINT16_MAX(65535)) {
9619 ++mCurrentDepth;
9620 }
9621
9622 if (!aPossiblyLeafFrame) {
9623 aPossiblyLeafFrame = aFrame;
9624 }
9625
9626 // XXXbz ideally, this would do all the pushing of various
9627 // containing blocks as needed, so callers don't have to do it...
9628
9629 // Check that our parent frame is a block before allowing ::first-letter/line.
9630 // E.g. <button style="display:grid"> should not allow it.
9631 const bool allowFirstPseudos =
9632 aAllowBlockStyles && aFrame->IsBlockFrameOrSubclass();
9633 bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
9634 if (allowFirstPseudos) {
9635 ShouldHaveSpecialBlockStyle(aContent, aComputedStyle, &haveFirstLetterStyle,
9636 &haveFirstLineStyle);
9637 }
9638
9639 AutoFrameConstructionItemList itemsToConstruct(this);
9640 AutoFrameConstructionPageName pageNameTracker(aState, aFrame);
9641
9642 // If we have first-letter or first-line style then frames can get
9643 // moved around so don't set these flags.
9644 if (allowFirstPseudos && !haveFirstLetterStyle && !haveFirstLineStyle) {
9645 itemsToConstruct.SetLineBoundaryAtStart(true);
9646 itemsToConstruct.SetLineBoundaryAtEnd(true);
9647 }
9648
9649 // Create any anonymous frames we need here.
9650 AutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
9651 GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
9652#ifdef DEBUG1
9653 for (uint32_t i = 0; i < anonymousItems.Length(); ++i) {
9654 MOZ_ASSERT(anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
" (" "Content should know it's an anonymous subtree" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
") (" "Content should know it's an anonymous subtree" ")"); do
{ *((volatile int*)__null) = 9655; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9655 "Content should know it's an anonymous subtree")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
" (" "Content should know it's an anonymous subtree" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9655); AnnotateMozCrashReason("MOZ_ASSERT" "(" "anonymousItems[i].mContent->IsRootOfNativeAnonymousSubtree()"
") (" "Content should know it's an anonymous subtree" ")"); do
{ *((volatile int*)__null) = 9655; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9656 }
9657#endif
9658 AddFCItemsForAnonymousContent(aState, aFrame, anonymousItems,
9659 itemsToConstruct, pageNameTracker);
9660
9661 nsBlockFrame* listItem = nullptr;
9662 bool isOutsideMarker = false;
9663 if (!aPossiblyLeafFrame->IsLeaf()) {
9664 // :before/:after content should have the same style parent as normal kids.
9665 //
9666 // Note that we don't use this style for looking up things like special
9667 // block styles because in some cases involving table pseudo-frames it has
9668 // nothing to do with the parent frame's desired behavior.
9669 auto* styleParentFrame =
9670 nsIFrame::CorrectStyleParentFrame(aFrame, PseudoStyleType::NotPseudo);
9671 ComputedStyle* computedStyle = styleParentFrame->Style();
9672
9673 if (aCanHaveGeneratedContent) {
9674 if (computedStyle->StyleDisplay()->IsListItem() &&
9675 (listItem = do_QueryFrame(aFrame)) &&
9676 !styleParentFrame->IsFieldSetFrame()) {
9677 isOutsideMarker = computedStyle->StyleList()->mListStylePosition ==
9678 StyleListStylePosition::Outside;
9679 ItemFlags extraFlags;
9680 if (isOutsideMarker) {
9681 extraFlags += ItemFlag::IsForOutsideMarker;
9682 }
9683 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9684 *computedStyle, PseudoStyleType::marker,
9685 itemsToConstruct, extraFlags);
9686 }
9687 // Probe for generated content before
9688 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9689 *computedStyle, PseudoStyleType::before,
9690 itemsToConstruct);
9691 }
9692
9693 const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth)(__builtin_expect(!!(mCurrentDepth < kMaxDepth), 1));
9694 if (!addChildItems) {
9695 NS_WARNING("ProcessChildren max depth exceeded")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessChildren max depth exceeded"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9695)
;
9696 }
9697
9698 FlattenedChildIterator iter(aContent);
9699 const InsertionPoint insertion(aFrame, aContent);
9700 for (nsIContent* child = iter.GetNextChild(); child;
9701 child = iter.GetNextChild()) {
9702 MOZ_ASSERT(insertion.mContainer == GetInsertionPoint(child).mContainer,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertion.mContainer == GetInsertionPoint(child).mContainer
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(insertion.mContainer == GetInsertionPoint(child).mContainer
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"insertion.mContainer == GetInsertionPoint(child).mContainer"
" (" "GetInsertionPoint should agree with us" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9703); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mContainer == GetInsertionPoint(child).mContainer"
") (" "GetInsertionPoint should agree with us" ")"); do { *(
(volatile int*)__null) = 9703; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9703 "GetInsertionPoint should agree with us")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(insertion.mContainer == GetInsertionPoint(child).mContainer
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(insertion.mContainer == GetInsertionPoint(child).mContainer
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"insertion.mContainer == GetInsertionPoint(child).mContainer"
" (" "GetInsertionPoint should agree with us" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9703); AnnotateMozCrashReason("MOZ_ASSERT" "(" "insertion.mContainer == GetInsertionPoint(child).mContainer"
") (" "GetInsertionPoint should agree with us" ")"); do { *(
(volatile int*)__null) = 9703; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9704 if (addChildItems) {
9705 AddFrameConstructionItems(aState, child, iter.ShadowDOMInvolved(),
9706 *computedStyle, insertion, itemsToConstruct);
9707 } else {
9708 ClearLazyBits(child, child->GetNextSibling());
9709 }
9710 }
9711 itemsToConstruct.SetParentHasNoShadowDOM(!iter.ShadowDOMInvolved());
9712
9713 if (aCanHaveGeneratedContent) {
9714 // Probe for generated content after
9715 CreateGeneratedContentItem(aState, aFrame, *aContent->AsElement(),
9716 *computedStyle, PseudoStyleType::after,
9717 itemsToConstruct);
9718 }
9719 } else {
9720 ClearLazyBits(aContent->GetFirstChild(), nullptr);
9721 }
9722
9723 ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
9724 /* aParentIsWrapperAnonBox = */ false,
9725 aFrameList);
9726
9727 if (listItem) {
9728 if (auto* markerFrame = nsLayoutUtils::GetMarkerFrame(aContent)) {
9729 for (auto* childFrame : aFrameList) {
9730 if (markerFrame == childFrame) {
9731 if (isOutsideMarker) {
9732 // SetMarkerFrameForListItem will add childFrame to the
9733 // FrameChildListID::Bullet
9734 aFrameList.RemoveFrame(childFrame);
9735 auto* grandParent = listItem->GetParent()->GetParent();
9736 if (listItem->Style()->GetPseudoType() ==
9737 PseudoStyleType::columnContent &&
9738 grandParent && grandParent->IsColumnSetWrapperFrame()) {
9739 listItem = do_QueryFrame(grandParent);
9740 MOZ_ASSERT(listItem,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(listItem)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(listItem))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("listItem" " (" "ColumnSetWrapperFrame is expected to be "
"a nsBlockFrame subclass" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9741 "ColumnSetWrapperFrame is expected to be "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(listItem)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(listItem))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("listItem" " (" "ColumnSetWrapperFrame is expected to be "
"a nsBlockFrame subclass" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9742 "a nsBlockFrame subclass")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(listItem)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(listItem))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("listItem" " (" "ColumnSetWrapperFrame is expected to be "
"a nsBlockFrame subclass" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem" ") ("
"ColumnSetWrapperFrame is expected to be " "a nsBlockFrame subclass"
")"); do { *((volatile int*)__null) = 9742; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9743 childFrame->SetParent(listItem);
9744 }
9745 }
9746 listItem->SetMarkerFrameForListItem(childFrame);
9747 MOZ_ASSERT(listItem->HasOutsideMarker() == isOutsideMarker)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(listItem->HasOutsideMarker() == isOutsideMarker)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(listItem->HasOutsideMarker() == isOutsideMarker))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("listItem->HasOutsideMarker() == isOutsideMarker"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listItem->HasOutsideMarker() == isOutsideMarker"
")"); do { *((volatile int*)__null) = 9747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9748#ifdef ACCESSIBILITY1
9749 if (nsAccessibilityService* accService = GetAccService()) {
9750 auto* marker = markerFrame->GetContent();
9751 accService->ContentRangeInserted(mPresShell, marker, nullptr);
9752 }
9753#endif
9754 break;
9755 }
9756 }
9757 }
9758 }
9759
9760 if (haveFirstLetterStyle) {
9761 WrapFramesInFirstLetterFrame(aFrame, aFrameList);
9762 }
9763 if (haveFirstLineStyle) {
9764 WrapFramesInFirstLineFrame(aState, aContent, aFrame, nullptr, aFrameList);
9765 }
9766}
9767
9768//----------------------------------------------------------------------
9769
9770// Support for :first-line style
9771
9772// Special routine to handle placing a list of frames into a block
9773// frame that has first-line style. The routine ensures that the first
9774// collection of inline frames end up in a first-line frame.
9775// NOTE: aState may have containing block information related to a
9776// different part of the frame tree than where the first line occurs.
9777// In particular aState may be set up for where ContentInserted or
9778// ContentAppended is inserting content, which may be some
9779// non-first-in-flow continuation of the block to which the first-line
9780// belongs. So this function needs to be careful about how it uses
9781// aState.
9782void nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
9783 nsFrameConstructorState& aState, nsIContent* aBlockContent,
9784 nsContainerFrame* aBlockFrame, nsFirstLineFrame* aLineFrame,
9785 nsFrameList& aFrameList) {
9786 // Extract any initial inline frames from aFrameList so we can put them
9787 // in the first-line.
9788 nsFrameList firstLineChildren =
9789 aFrameList.Split([](nsIFrame* f) { return !f->IsInlineOutside(); });
9790
9791 if (firstLineChildren.IsEmpty()) {
9792 // Nothing is supposed to go into the first-line; nothing to do
9793 return;
9794 }
9795
9796 if (!aLineFrame) {
9797 // Create line frame
9798 ComputedStyle* parentStyle = nsIFrame::CorrectStyleParentFrame(
9799 aBlockFrame, PseudoStyleType::firstLine)
9800 ->Style();
9801 RefPtr<ComputedStyle> firstLineStyle =
9802 GetFirstLineStyle(aBlockContent, parentStyle);
9803
9804 aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
9805
9806 // Initialize the line frame
9807 InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, aLineFrame);
9808
9809 // The lineFrame will be the block's first child; the rest of the
9810 // frame list (after lastInlineFrame) will be the second and
9811 // subsequent children; insert lineFrame into aFrameList.
9812 aFrameList.InsertFrame(nullptr, nullptr, aLineFrame);
9813
9814 NS_ASSERTION(aLineFrame->Style() == firstLineStyle,do { if (!(aLineFrame->Style() == firstLineStyle)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Bogus style on line frame", "aLineFrame->Style() == firstLineStyle"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9815); MOZ_PretendNoReturn(); } } while (0)
9815 "Bogus style on line frame")do { if (!(aLineFrame->Style() == firstLineStyle)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Bogus style on line frame", "aLineFrame->Style() == firstLineStyle"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9815); MOZ_PretendNoReturn(); } } while (0)
;
9816 }
9817
9818 // Give the inline frames to the lineFrame <b>after</b> reparenting them
9819 ReparentFrames(this, aLineFrame, firstLineChildren, true);
9820 if (aLineFrame->PrincipalChildList().IsEmpty() &&
9821 aLineFrame->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
9822 aLineFrame->SetInitialChildList(FrameChildListID::Principal,
9823 std::move(firstLineChildren));
9824 } else {
9825 AppendFrames(aLineFrame, FrameChildListID::Principal,
9826 std::move(firstLineChildren));
9827 }
9828}
9829
9830// Special routine to handle appending a new frame to a block frame's
9831// child list. Takes care of placing the new frame into the right
9832// place when first-line style is present.
9833void nsCSSFrameConstructor::AppendFirstLineFrames(
9834 nsFrameConstructorState& aState, nsIContent* aBlockContent,
9835 nsContainerFrame* aBlockFrame, nsFrameList& aFrameList) {
9836 // It's possible that aBlockFrame needs to have a first-line frame
9837 // created because it doesn't currently have any children.
9838 const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
9839 if (blockKids.IsEmpty()) {
9840 WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame, nullptr,
9841 aFrameList);
9842 return;
9843 }
9844
9845 // Examine the last block child - if it's a first-line frame then
9846 // appended frames need special treatment.
9847 nsIFrame* lastBlockKid = blockKids.LastChild();
9848 if (!lastBlockKid->IsLineFrame()) {
9849 // No first-line frame at the end of the list, therefore there is
9850 // an intervening block between any first-line frame the frames
9851 // we are appending. Therefore, we don't need any special
9852 // treatment of the appended frames.
9853 return;
9854 }
9855
9856 nsFirstLineFrame* lineFrame = static_cast<nsFirstLineFrame*>(lastBlockKid);
9857 WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame, lineFrame,
9858 aFrameList);
9859}
9860
9861void nsCSSFrameConstructor::CheckForFirstLineInsertion(
9862 nsIFrame* aParentFrame, nsFrameList& aFrameList) {
9863 MOZ_ASSERT(aParentFrame->Style()->HasPseudoElementData(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParentFrame->Style()->HasPseudoElementData())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aParentFrame->Style()->HasPseudoElementData())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParentFrame->Style()->HasPseudoElementData()"
" (" "Why were we called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame->Style()->HasPseudoElementData()"
") (" "Why were we called?" ")"); do { *((volatile int*)__null
) = 9864; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
9864 "Why were we called?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParentFrame->Style()->HasPseudoElementData())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aParentFrame->Style()->HasPseudoElementData())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aParentFrame->Style()->HasPseudoElementData()"
" (" "Why were we called?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame->Style()->HasPseudoElementData()"
") (" "Why were we called?" ")"); do { *((volatile int*)__null
) = 9864; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9865
9866 if (aFrameList.IsEmpty()) {
9867 // Happens often enough, with the caption stuff. No need to do the ancestor
9868 // walk here.
9869 return;
9870 }
9871
9872 class RestyleManager* restyleManager = RestyleManager();
9873
9874 // Check whether there's a ::first-line on the path up from aParentFrame.
9875 // Note that we can't stop until we've run out of ancestors with
9876 // pseudo-element data, because the first-letter might be somewhere way up the
9877 // tree; in particular it might be past our containing block.
9878 nsIFrame* ancestor = aParentFrame;
9879 while (ancestor) {
9880 if (!ancestor->Style()->HasPseudoElementData()) {
9881 // We know we won't find a ::first-line now.
9882 return;
9883 }
9884
9885 if (!ancestor->IsLineFrame()) {
9886 ancestor = ancestor->GetParent();
9887 continue;
9888 }
9889
9890 if (!ancestor->Style()->IsPseudoElement()) {
9891 // This is a continuation lineframe, not the first line; no need to do
9892 // anything to the styles.
9893 return;
9894 }
9895
9896 // Fix up the styles of aFrameList for ::first-line.
9897 for (nsIFrame* f : aFrameList) {
9898 restyleManager->ReparentComputedStyleForFirstLine(f);
9899 }
9900 return;
9901 }
9902}
9903
9904//----------------------------------------------------------------------
9905
9906// First-letter support
9907
9908// Determine how many characters in the text fragment apply to the
9909// first letter
9910static int32_t FirstLetterCount(const nsTextFragment* aFragment) {
9911 int32_t count = 0;
9912 int32_t firstLetterLength = 0;
9913
9914 const uint32_t n = aFragment->GetLength();
9915 for (uint32_t i = 0; i < n; i++) {
9916 const char16_t ch = aFragment->CharAt(i);
9917 // FIXME: take content language into account when deciding whitespace.
9918 if (dom::IsSpaceCharacter(ch)) {
9919 if (firstLetterLength) {
9920 break;
9921 }
9922 count++;
9923 continue;
9924 }
9925 // XXX I18n
9926 if ((ch == '\'') || (ch == '\"')) {
9927 if (firstLetterLength) {
9928 break;
9929 }
9930 // keep looping
9931 firstLetterLength = 1;
9932 } else {
9933 count++;
9934 break;
9935 }
9936 }
9937
9938 return count;
9939}
9940
9941static bool NeedFirstLetterContinuation(Text* aText) {
9942 MOZ_ASSERT(aText, "null ptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aText)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aText))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aText" " (" "null ptr" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9942); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aText" ") ("
"null ptr" ")"); do { *((volatile int*)__null) = 9942; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
9943 int32_t flc = FirstLetterCount(&aText->TextFragment());
9944 int32_t tl = aText->TextDataLength();
9945 return flc < tl;
9946}
9947
9948static bool IsFirstLetterContent(Text* aText) {
9949 return aText->TextDataLength() && !aText->TextIsOnlyWhitespace();
9950}
9951
9952/**
9953 * Create a letter frame, only make it a floating frame.
9954 */
9955nsFirstLetterFrame* nsCSSFrameConstructor::CreateFloatingLetterFrame(
9956 nsFrameConstructorState& aState, Text* aTextContent, nsIFrame* aTextFrame,
9957 nsContainerFrame* aParentFrame, ComputedStyle* aParentStyle,
9958 ComputedStyle* aComputedStyle, nsFrameList& aResult) {
9959 MOZ_ASSERT(aParentStyle)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParentStyle)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParentStyle))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aParentStyle", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentStyle"
")"); do { *((volatile int*)__null) = 9959; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9960
9961 nsFirstLetterFrame* letterFrame =
9962 NS_NewFloatingFirstLetterFrame(mPresShell, aComputedStyle);
9963 // We don't want to use a text content for a non-text frame (because we want
9964 // its primary frame to be a text frame).
9965 nsIContent* letterContent = aParentFrame->GetContent();
9966 nsContainerFrame* containingBlock =
9967 aState.GetGeometricParent(*aComputedStyle->StyleDisplay(), aParentFrame);
9968 InitAndRestoreFrame(aState, letterContent, containingBlock, letterFrame);
9969
9970 // Init the text frame to refer to the letter frame.
9971 //
9972 // Make sure we get a proper style for it (the one passed in is for the letter
9973 // frame and will have the float property set on it; the text frame shouldn't
9974 // have that set).
9975 ServoStyleSet* styleSet = mPresShell->StyleSet();
9976 RefPtr<ComputedStyle> textSC =
9977 styleSet->ResolveStyleForText(aTextContent, aComputedStyle);
9978 aTextFrame->SetComputedStyleWithoutNotification(textSC);
9979 InitAndRestoreFrame(aState, aTextContent, letterFrame, aTextFrame);
9980
9981 // And then give the text frame to the letter frame
9982 SetInitialSingleChild(letterFrame, aTextFrame);
9983
9984 // See if we will need to continue the text frame (does it contain
9985 // more than just the first-letter text or not?) If it does, then we
9986 // create (in advance) a continuation frame for it.
9987 nsIFrame* nextTextFrame = nullptr;
9988 if (NeedFirstLetterContinuation(aTextContent)) {
9989 // Create continuation
9990 nextTextFrame = CreateContinuingFrame(aTextFrame, aParentFrame);
9991 RefPtr<ComputedStyle> newSC =
9992 styleSet->ResolveStyleForText(aTextContent, aParentStyle);
9993 nextTextFrame->SetComputedStyle(newSC);
9994 }
9995
9996 NS_ASSERTION(aResult.IsEmpty(), "aResult should be an empty nsFrameList!")do { if (!(aResult.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aResult should be an empty nsFrameList!", "aResult.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 9996); MOZ_PretendNoReturn(); } } while (0)
;
9997 // Put the new float before any of the floats in the block we're doing
9998 // first-letter for, that is, before any floats whose parent is
9999 // containingBlock.
10000 nsIFrame* prevSibling = nullptr;
10001 for (nsIFrame* f : aState.mFloatedList) {
10002 if (f->GetParent() == containingBlock) {
10003 break;
10004 }
10005 prevSibling = f;
10006 }
10007
10008 aState.AddChild(letterFrame, aResult, letterContent, aParentFrame, false,
10009 true, true, prevSibling);
10010
10011 if (nextTextFrame) {
10012 aResult.AppendFrame(nullptr, nextTextFrame);
10013 }
10014
10015 return letterFrame;
10016}
10017
10018/**
10019 * Create a new letter frame for aTextFrame. The letter frame will be
10020 * a child of aParentFrame.
10021 */
10022void nsCSSFrameConstructor::CreateLetterFrame(
10023 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
10024 Text* aTextContent, nsContainerFrame* aParentFrame, nsFrameList& aResult) {
10025 NS_ASSERTION(aBlockFrame->IsBlockFrameOrSubclass(), "Not a block frame?")do { if (!(aBlockFrame->IsBlockFrameOrSubclass())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Not a block frame?", "aBlockFrame->IsBlockFrameOrSubclass()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10025); MOZ_PretendNoReturn(); } } while (0)
;
10026
10027 // Get a ComputedStyle for the first-letter-frame.
10028 //
10029 // Keep this in sync with nsBlockFrame::UpdatePseudoElementStyles.
10030 nsIFrame* parentFrame = nsIFrame::CorrectStyleParentFrame(
10031 aParentFrame, PseudoStyleType::firstLetter);
10032
10033 ComputedStyle* parentComputedStyle = parentFrame->Style();
10034 ComputedStyle* parentComputedStyleIgnoringFirstLine = parentComputedStyle;
10035 if (parentFrame->IsLineFrame()) {
10036 parentComputedStyleIgnoringFirstLine =
10037 nsIFrame::CorrectStyleParentFrame(aBlockFrame,
10038 PseudoStyleType::firstLetter)
10039 ->Style();
10040 }
10041
10042 // Use content from containing block so that we can actually
10043 // find a matching style rule.
10044 nsIContent* blockContent = aBlockFrame->GetContent();
10045
10046 // Create first-letter style rule, ignoring first line. If we already have a
10047 // first-line we'll reparent the style below.
10048 RefPtr<ComputedStyle> sc =
10049 GetFirstLetterStyle(blockContent, parentComputedStyleIgnoringFirstLine);
10050
10051 if (sc) {
10052 if (parentComputedStyleIgnoringFirstLine != parentComputedStyle) {
10053 sc = mPresShell->StyleSet()->ReparentComputedStyle(
10054 sc, parentComputedStyle, parentComputedStyle,
10055 blockContent->AsElement());
10056 }
10057
10058 RefPtr<ComputedStyle> textSC =
10059 mPresShell->StyleSet()->ResolveStyleForText(aTextContent, sc);
10060
10061 // Create a new text frame (the original one will be discarded)
10062 // pass a temporary stylecontext, the correct one will be set
10063 // later. Start off by unsetting the primary frame for
10064 // aTextContent, so it's no longer pointing to the to-be-destroyed
10065 // frame.
10066 // XXXbz it would be really nice to destroy the old frame _first_,
10067 // then create the new one, so we could avoid this hack.
10068 aTextContent->SetPrimaryFrame(nullptr);
10069 nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
10070
10071 NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame),do { if (!(aBlockContinuation == GetFloatContainingBlock(aParentFrame
))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Containing block is confused"
, "aBlockContinuation == GetFloatContainingBlock(aParentFrame)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10072); MOZ_PretendNoReturn(); } } while (0)
10072 "Containing block is confused")do { if (!(aBlockContinuation == GetFloatContainingBlock(aParentFrame
))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Containing block is confused"
, "aBlockContinuation == GetFloatContainingBlock(aParentFrame)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10072); MOZ_PretendNoReturn(); } } while (0)
;
10073 nsFrameConstructorState state(
10074 mPresShell, GetAbsoluteContainingBlock(aParentFrame, FIXED_POS),
10075 GetAbsoluteContainingBlock(aParentFrame, ABS_POS), aBlockContinuation);
10076
10077 // Create the right type of first-letter frame
10078 const nsStyleDisplay* display = sc->StyleDisplay();
10079 nsFirstLetterFrame* letterFrame;
10080 if (display->IsFloatingStyle() && !aParentFrame->IsInSVGTextSubtree()) {
10081 // Make a floating first-letter frame
10082 letterFrame = CreateFloatingLetterFrame(state, aTextContent, textFrame,
10083 aParentFrame, parentComputedStyle,
10084 sc, aResult);
10085 } else {
10086 // Make an inflow first-letter frame
10087 letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
10088
10089 // Initialize the first-letter-frame. We don't want to use a text
10090 // content for a non-text frame (because we want its primary frame to
10091 // be a text frame).
10092 nsIContent* letterContent = aParentFrame->GetContent();
10093 letterFrame->Init(letterContent, aParentFrame, nullptr);
10094
10095 InitAndRestoreFrame(state, aTextContent, letterFrame, textFrame);
10096
10097 SetInitialSingleChild(letterFrame, textFrame);
10098 aResult.Clear();
10099 aResult.AppendFrame(nullptr, letterFrame);
10100 NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),do { if (!(!aBlockFrame->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should have the first continuation here"
, "!aBlockFrame->GetPrevContinuation()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10101); MOZ_PretendNoReturn(); } } while (0)
10101 "should have the first continuation here")do { if (!(!aBlockFrame->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should have the first continuation here"
, "!aBlockFrame->GetPrevContinuation()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10101); MOZ_PretendNoReturn(); } } while (0)
;
10102 aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
10103 }
10104 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aBlockFrame->GetPrevContinuation())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aBlockFrame->GetPrevContinuation()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!aBlockFrame->GetPrevContinuation()"
" (" "Setting up a first-letter frame on a non-first block continuation?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10106; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10105 !aBlockFrame->GetPrevContinuation(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aBlockFrame->GetPrevContinuation())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aBlockFrame->GetPrevContinuation()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!aBlockFrame->GetPrevContinuation()"
" (" "Setting up a first-letter frame on a non-first block continuation?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10106; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10106 "Setting up a first-letter frame on a non-first block continuation?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aBlockFrame->GetPrevContinuation())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aBlockFrame->GetPrevContinuation()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!aBlockFrame->GetPrevContinuation()"
" (" "Setting up a first-letter frame on a non-first block continuation?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aBlockFrame->GetPrevContinuation()"
") (" "Setting up a first-letter frame on a non-first block continuation?"
")"); do { *((volatile int*)__null) = 10106; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10107 auto parent =
10108 static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
10109 if (MOZ_UNLIKELY(parent->IsLineFrame())(__builtin_expect(!!(parent->IsLineFrame()), 0))) {
10110 parent = static_cast<nsContainerFrame*>(
10111 parent->GetParent()->FirstContinuation());
10112 }
10113 parent->SetHasFirstLetterChild();
10114 aBlockFrame->SetProperty(nsContainerFrame::FirstLetterProperty(),
10115 letterFrame);
10116 aTextContent->SetPrimaryFrame(textFrame);
10117 }
10118}
10119
10120void nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
10121 nsContainerFrame* aBlockFrame, nsFrameList& aBlockFrames) {
10122 aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
10123
10124 nsContainerFrame* parentFrame = nullptr;
10125 nsIFrame* textFrame = nullptr;
10126 nsIFrame* prevFrame = nullptr;
10127 nsFrameList letterFrames;
10128 bool stopLooking = false;
10129 WrapFramesInFirstLetterFrame(
10130 aBlockFrame, aBlockFrame, aBlockFrame, aBlockFrames.FirstChild(),
10131 &parentFrame, &textFrame, &prevFrame, letterFrames, &stopLooking);
10132 if (!parentFrame) {
10133 return;
10134 }
10135 DestroyContext context(mPresShell);
10136 if (parentFrame == aBlockFrame) {
10137 // Take textFrame out of the block's frame list and substitute the
10138 // letter frame(s) instead.
10139 aBlockFrames.DestroyFrame(context, textFrame);
10140 aBlockFrames.InsertFrames(nullptr, prevFrame, std::move(letterFrames));
10141 } else {
10142 // Take the old textFrame out of the inline parent's child list
10143 RemoveFrame(context, FrameChildListID::Principal, textFrame);
10144
10145 // Insert in the letter frame(s)
10146 parentFrame->InsertFrames(FrameChildListID::Principal, prevFrame, nullptr,
10147 std::move(letterFrames));
10148 }
10149}
10150
10151void nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
10152 nsContainerFrame* aBlockFrame, nsContainerFrame* aBlockContinuation,
10153 nsContainerFrame* aParentFrame, nsIFrame* aParentFrameList,
10154 nsContainerFrame** aModifiedParent, nsIFrame** aTextFrame,
10155 nsIFrame** aPrevFrame, nsFrameList& aLetterFrames, bool* aStopLooking) {
10156 nsIFrame* prevFrame = nullptr;
10157 nsIFrame* frame = aParentFrameList;
10158
10159 // This loop attempts to implement "Finding the First Letter":
10160 // https://drafts.csswg.org/css-pseudo-4/#application-in-css
10161 // FIXME: we don't handle nested blocks correctly yet though (bug 214004)
10162 while (frame) {
10163 nsIFrame* nextFrame = frame->GetNextSibling();
10164
10165 // Skip all ::markers and placeholders.
10166 if (frame->Style()->GetPseudoType() == PseudoStyleType::marker ||
10167 frame->IsPlaceholderFrame()) {
10168 prevFrame = frame;
10169 frame = nextFrame;
10170 continue;
10171 }
10172 LayoutFrameType frameType = frame->Type();
10173 if (LayoutFrameType::Text == frameType) {
10174 // Wrap up first-letter content in a letter frame
10175 Text* textContent = frame->GetContent()->AsText();
10176 if (IsFirstLetterContent(textContent)) {
10177 // Create letter frame to wrap up the text
10178 CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
10179 aParentFrame, aLetterFrames);
10180
10181 // Provide adjustment information for parent
10182 *aModifiedParent = aParentFrame;
10183 *aTextFrame = frame;
10184 *aPrevFrame = prevFrame;
10185 *aStopLooking = true;
10186 return;
10187 }
10188 } else if (IsInlineFrame(frame) && frameType != LayoutFrameType::Br) {
10189 nsIFrame* kids = frame->PrincipalChildList().FirstChild();
10190 WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation,
10191 static_cast<nsContainerFrame*>(frame), kids,
10192 aModifiedParent, aTextFrame, aPrevFrame,
10193 aLetterFrames, aStopLooking);
10194 if (*aStopLooking) {
10195 return;
10196 }
10197 } else {
10198 // This will stop us looking to create more letter frames. For
10199 // example, maybe the frame-type is "letterFrame" or
10200 // "placeholderFrame". This keeps us from creating extra letter
10201 // frames, and also prevents us from creating letter frames when
10202 // the first real content child of a block is not text (e.g. an
10203 // image, hr, etc.)
10204 *aStopLooking = true;
10205 break;
10206 }
10207
10208 prevFrame = frame;
10209 frame = nextFrame;
10210 }
10211}
10212
10213static nsIFrame* FindFirstLetterFrame(nsIFrame* aFrame,
10214 FrameChildListID aListID) {
10215 for (nsIFrame* f : aFrame->GetChildList(aListID)) {
10216 if (f->IsLetterFrame()) {
10217 return f;
10218 }
10219 }
10220 return nullptr;
10221}
10222
10223static void ClearHasFirstLetterChildFrom(nsContainerFrame* aParentFrame) {
10224 MOZ_ASSERT(aParentFrame)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParentFrame)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParentFrame))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aParentFrame", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParentFrame"
")"); do { *((volatile int*)__null) = 10224; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10225 auto* parent =
10226 static_cast<nsContainerFrame*>(aParentFrame->FirstContinuation());
10227 if (MOZ_UNLIKELY(parent->IsLineFrame())(__builtin_expect(!!(parent->IsLineFrame()), 0))) {
10228 MOZ_ASSERT(!parent->HasFirstLetterChild())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!parent->HasFirstLetterChild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!parent->HasFirstLetterChild
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!parent->HasFirstLetterChild()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!parent->HasFirstLetterChild()"
")"); do { *((volatile int*)__null) = 10228; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10229 parent = static_cast<nsContainerFrame*>(
10230 parent->GetParent()->FirstContinuation());
10231 }
10232 MOZ_ASSERT(parent->HasFirstLetterChild())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent->HasFirstLetterChild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(parent->HasFirstLetterChild
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("parent->HasFirstLetterChild()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "parent->HasFirstLetterChild()"
")"); do { *((volatile int*)__null) = 10232; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10233 parent->ClearHasFirstLetterChild();
10234}
10235
10236void nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
10237 PresShell* aPresShell, nsIFrame* aBlockFrame) {
10238 // Look for the first letter frame on the FrameChildListID::Float, then
10239 // FrameChildListID::PushedFloats.
10240 nsIFrame* floatFrame =
10241 ::FindFirstLetterFrame(aBlockFrame, FrameChildListID::Float);
10242 if (!floatFrame) {
10243 floatFrame =
10244 ::FindFirstLetterFrame(aBlockFrame, FrameChildListID::PushedFloats);
10245 if (!floatFrame) {
10246 return;
10247 }
10248 }
10249
10250 // Take the text frame away from the letter frame (so it isn't
10251 // destroyed when we destroy the letter frame).
10252 nsIFrame* textFrame = floatFrame->PrincipalChildList().FirstChild();
10253 if (!textFrame) {
10254 return;
10255 }
10256
10257 // Discover the placeholder frame for the letter frame
10258 nsPlaceholderFrame* placeholderFrame = floatFrame->GetPlaceholderFrame();
10259 if (!placeholderFrame) {
10260 // Somethings really wrong
10261 return;
10262 }
10263 nsContainerFrame* parentFrame = placeholderFrame->GetParent();
10264 if (!parentFrame) {
10265 // Somethings really wrong
10266 return;
10267 }
10268
10269 ClearHasFirstLetterChildFrom(parentFrame);
10270
10271 // Create a new text frame with the right style that maps all of the content
10272 // that was previously part of the letter frame (and probably continued
10273 // elsewhere).
10274 ComputedStyle* parentSC = parentFrame->Style();
10275 nsIContent* textContent = textFrame->GetContent();
10276 if (!textContent) {
10277 return;
10278 }
10279 RefPtr<ComputedStyle> newSC =
10280 aPresShell->StyleSet()->ResolveStyleForText(textContent, parentSC);
10281 nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
10282 newTextFrame->Init(textContent, parentFrame, nullptr);
10283
10284 // Destroy the old text frame's continuations (the old text frame
10285 // will be destroyed when its letter frame is destroyed).
10286 nsIFrame* frameToDelete = textFrame->LastContinuation();
10287 DestroyContext context(mPresShell);
10288 while (frameToDelete != textFrame) {
10289 nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
10290 RemoveFrame(context, FrameChildListID::Principal, frameToDelete);
10291 frameToDelete = nextFrameToDelete;
10292 }
10293
10294 nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
10295
10296 // Now that everything is set...
10297#ifdef NOISY_FIRST_LETTER
10298 printf(
10299 "RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p "
10300 "newTextFrame=%p\n",
10301 textContent.get(), textFrame, newTextFrame);
10302#endif
10303
10304 // Remove placeholder frame and the float
10305 RemoveFrame(context, FrameChildListID::Principal, placeholderFrame);
10306
10307 // Now that the old frames are gone, we can start pointing to our
10308 // new primary frame.
10309 textContent->SetPrimaryFrame(newTextFrame);
10310
10311 // Wallpaper bug 822910.
10312 bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
10313 if (offsetsNeedFixing) {
10314 prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
10315 }
10316
10317 // Insert text frame in its place
10318 InsertFrames(parentFrame, FrameChildListID::Principal, prevSibling,
10319 nsFrameList(newTextFrame, newTextFrame));
10320
10321 if (offsetsNeedFixing) {
10322 prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
10323 }
10324}
10325
10326void nsCSSFrameConstructor::RemoveFirstLetterFrames(
10327 PresShell* aPresShell, nsContainerFrame* aFrame,
10328 nsContainerFrame* aBlockFrame, bool* aStopLooking) {
10329 nsIFrame* prevSibling = nullptr;
10330 nsIFrame* kid = aFrame->PrincipalChildList().FirstChild();
10331
10332 while (kid) {
10333 if (kid->IsLetterFrame()) {
10334 ClearHasFirstLetterChildFrom(aFrame);
10335 nsIFrame* textFrame = kid->PrincipalChildList().FirstChild();
10336 if (!textFrame) {
10337 break;
10338 }
10339
10340 // Create a new textframe
10341 ComputedStyle* parentSC = aFrame->Style();
10342 if (!parentSC) {
10343 break;
10344 }
10345 nsIContent* textContent = textFrame->GetContent();
10346 if (!textContent) {
10347 break;
10348 }
10349 RefPtr<ComputedStyle> newSC =
10350 aPresShell->StyleSet()->ResolveStyleForText(textContent, parentSC);
10351 textFrame = NS_NewTextFrame(aPresShell, newSC);
10352 textFrame->Init(textContent, aFrame, nullptr);
10353
10354 DestroyContext context(mPresShell);
10355
10356 // Next rip out the kid and replace it with the text frame
10357 RemoveFrame(context, FrameChildListID::Principal, kid);
10358
10359 // Now that the old frames are gone, we can start pointing to our
10360 // new primary frame.
10361 textContent->SetPrimaryFrame(textFrame);
10362
10363 // Wallpaper bug 822910.
10364 bool offsetsNeedFixing = prevSibling && prevSibling->IsTextFrame();
10365 if (offsetsNeedFixing) {
10366 prevSibling->AddStateBits(TEXT_OFFSETS_NEED_FIXING);
10367 }
10368
10369 // Insert text frame in its place
10370 InsertFrames(aFrame, FrameChildListID::Principal, prevSibling,
10371 nsFrameList(textFrame, textFrame));
10372
10373 if (offsetsNeedFixing) {
10374 prevSibling->RemoveStateBits(TEXT_OFFSETS_NEED_FIXING);
10375 }
10376
10377 *aStopLooking = true;
10378 NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),do { if (!(!aBlockFrame->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should have the first continuation here"
, "!aBlockFrame->GetPrevContinuation()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10379); MOZ_PretendNoReturn(); } } while (0)
10379 "should have the first continuation here")do { if (!(!aBlockFrame->GetPrevContinuation())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should have the first continuation here"
, "!aBlockFrame->GetPrevContinuation()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10379); MOZ_PretendNoReturn(); } } while (0)
;
10380 aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
10381 break;
10382 }
10383 if (IsInlineFrame(kid)) {
10384 nsContainerFrame* kidAsContainerFrame = do_QueryFrame(kid);
10385 if (kidAsContainerFrame) {
10386 // Look inside child inline frame for the letter frame.
10387 RemoveFirstLetterFrames(aPresShell, kidAsContainerFrame, aBlockFrame,
10388 aStopLooking);
10389 if (*aStopLooking) {
10390 break;
10391 }
10392 }
10393 }
10394 prevSibling = kid;
10395 kid = kid->GetNextSibling();
10396 }
10397}
10398
10399void nsCSSFrameConstructor::RemoveLetterFrames(PresShell* aPresShell,
10400 nsContainerFrame* aBlockFrame) {
10401 aBlockFrame =
10402 static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
10403 aBlockFrame->RemoveProperty(nsContainerFrame::FirstLetterProperty());
10404 nsContainerFrame* continuation = aBlockFrame;
10405
10406 bool stopLooking = false;
10407 do {
10408 RemoveFloatingFirstLetterFrames(aPresShell, continuation);
10409 RemoveFirstLetterFrames(aPresShell, continuation, aBlockFrame,
10410 &stopLooking);
10411 if (stopLooking) {
10412 break;
10413 }
10414 continuation =
10415 static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
10416 } while (continuation);
10417}
10418
10419// Fixup the letter frame situation for the given block
10420void nsCSSFrameConstructor::RecoverLetterFrames(nsContainerFrame* aBlockFrame) {
10421 aBlockFrame =
10422 static_cast<nsContainerFrame*>(aBlockFrame->FirstContinuation());
10423 nsContainerFrame* continuation = aBlockFrame;
10424
10425 nsContainerFrame* parentFrame = nullptr;
10426 nsIFrame* textFrame = nullptr;
10427 nsIFrame* prevFrame = nullptr;
10428 nsFrameList letterFrames;
10429 bool stopLooking = false;
10430 do {
10431 // XXX shouldn't this bit be set already (bug 408493), assert instead?
10432 continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
10433 WrapFramesInFirstLetterFrame(
10434 aBlockFrame, continuation, continuation,
10435 continuation->PrincipalChildList().FirstChild(), &parentFrame,
10436 &textFrame, &prevFrame, letterFrames, &stopLooking);
10437 if (stopLooking) {
10438 break;
10439 }
10440 continuation =
10441 static_cast<nsContainerFrame*>(continuation->GetNextContinuation());
10442 } while (continuation);
10443
10444 if (!parentFrame) {
10445 return;
10446 }
10447 // Take the old textFrame out of the parent's child list
10448 DestroyContext context(mPresShell);
10449 RemoveFrame(context, FrameChildListID::Principal, textFrame);
10450
10451 // Insert in the letter frame(s)
10452 parentFrame->InsertFrames(FrameChildListID::Principal, prevFrame, nullptr,
10453 std::move(letterFrames));
10454}
10455
10456//----------------------------------------------------------------------
10457
10458void nsCSSFrameConstructor::ConstructBlock(
10459 nsFrameConstructorState& aState, nsIContent* aContent,
10460 nsContainerFrame* aParentFrame, nsContainerFrame* aContentParentFrame,
10461 ComputedStyle* aComputedStyle, nsContainerFrame** aNewFrame,
10462 nsFrameList& aFrameList, nsIFrame* aPositionedFrameForAbsPosContainer) {
10463 // clang-format off
10464 //
10465 // If a block frame is in a multi-column subtree, its children may need to
10466 // be chopped into runs of blocks containing column-spans and runs of
10467 // blocks containing no column-spans. Each run containing column-spans
10468 // will be wrapped by an anonymous block. See CreateColumnSpanSiblings() for
10469 // the implementation.
10470 //
10471 // If a block frame is a multi-column container, its children will need to
10472 // be processed as above. Moreover, it creates a ColumnSetWrapperFrame as
10473 // its outermost frame, and its children which have no
10474 // -moz-column-span-wrapper pseudo will be wrapped in ColumnSetFrames. See
10475 // FinishBuildingColumns() for the implementation.
10476 //
10477 // The multi-column subtree maintains the following invariants:
10478 //
10479 // 1) All the frames have the frame state bit
10480 // NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR set, except for top-level
10481 // ColumnSetWrapperFrame and those children in the column-span subtrees.
10482 //
10483 // 2) The first and last frame under ColumnSetWrapperFrame are always
10484 // ColumnSetFrame.
10485 //
10486 // 3) ColumnSetFrames are linked together as continuations.
10487 //
10488 // 4) Those column-span wrappers are *not* linked together with themselves nor
10489 // with the original block frame. The continuation chain consists of the
10490 // original block frame and the original block's continuations wrapping
10491 // non-column-spans.
10492 //
10493 // For example, this HTML
10494 // <div id="x" style="column-count: 2;">
10495 // <div style="column-span: all">a</div>
10496 // <div id="y">
10497 // b
10498 // <div style="column-span: all">c</div>
10499 // <div style="column-span: all">d</div>
10500 // e
10501 // </div>
10502 // </div>
10503 // <div style="column-span: all">f</div>
10504 //
10505 // yields the following frame tree.
10506 //
10507 // A) ColumnSetWrapper (original style)
10508 // B) ColumnSet (-moz-column-set) <-- always created by BeginBuildingColumns
10509 // C) Block (-moz-column-content)
10510 // D) Block (-moz-column-span-wrapper, created by x)
10511 // E) Block (div)
10512 // F) Text ("a")
10513 // G) ColumnSet (-moz-column-set)
10514 // H) Block (-moz-column-content, created by x)
10515 // I) Block (div, y)
10516 // J) Text ("b")
10517 // K) Block (-moz-column-span-wrapper, created by x)
10518 // L) Block (-moz-column-span-wrapper, created by y)
10519 // M) Block (div, new BFC)
10520 // N) Text ("c")
10521 // O) Block (div, new BFC)
10522 // P) Text ("d")
10523 // Q) ColumnSet (-moz-column-set)
10524 // R) Block (-moz-column-content, created by x)
10525 // S) Block (div, y)
10526 // T) Text ("e")
10527 // U) Block (div, new BFC) <-- not in multi-column hierarchy
10528 // V) Text ("f")
10529 //
10530 // ColumnSet linkage described in 3): B -> G -> Q
10531 //
10532 // Block linkage described in 4): C -> H -> R and I -> S
10533 //
10534 // clang-format on
10535
10536 nsBlockFrame* blockFrame = do_QueryFrame(*aNewFrame);
10537 MOZ_ASSERT(blockFrame && blockFrame->IsBlockFrame(), "not a block frame?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(blockFrame && blockFrame->IsBlockFrame())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(blockFrame && blockFrame->IsBlockFrame())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("blockFrame && blockFrame->IsBlockFrame()"
" (" "not a block frame?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "blockFrame && blockFrame->IsBlockFrame()"
") (" "not a block frame?" ")"); do { *((volatile int*)__null
) = 10537; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
10538
10539 // Create column hierarchy if necessary.
10540 const bool needsColumn =
10541 aComputedStyle->StyleColumn()->IsColumnContainerStyle();
10542 if (needsColumn) {
10543 *aNewFrame = BeginBuildingColumns(aState, aContent, aParentFrame,
10544 blockFrame, aComputedStyle);
10545
10546 if (aPositionedFrameForAbsPosContainer == blockFrame) {
10547 aPositionedFrameForAbsPosContainer = *aNewFrame;
10548 }
10549 } else {
10550 // No need to create column hierarchy. Initialize block frame.
10551 blockFrame->SetComputedStyleWithoutNotification(aComputedStyle);
10552 InitAndRestoreFrame(aState, aContent, aParentFrame, blockFrame);
10553 }
10554
10555 aState.AddChild(*aNewFrame, aFrameList, aContent,
10556 aContentParentFrame ? aContentParentFrame : aParentFrame);
10557 if (!mRootElementFrame) {
10558 mRootElementFrame = *aNewFrame;
10559 }
10560
10561 // We should make the outer frame be the absolute containing block,
10562 // if one is required. We have to do this because absolute
10563 // positioning must be computed with respect to the CSS dimensions
10564 // of the element, which are the dimensions of the outer block. But
10565 // we can't really do that because only blocks can have absolute
10566 // children. So use the block and try to compensate with hacks
10567 // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
10568 nsFrameConstructorSaveState absoluteSaveState;
10569 (*aNewFrame)->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10570 if (aPositionedFrameForAbsPosContainer) {
10571 aState.PushAbsoluteContainingBlock(
10572 *aNewFrame, aPositionedFrameForAbsPosContainer, absoluteSaveState);
10573 }
10574
10575 nsFrameConstructorSaveState floatSaveState;
10576 aState.MaybePushFloatContainingBlock(blockFrame, floatSaveState);
10577
10578 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10579 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10580 blockFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10581 }
10582
10583 // Process the child content
10584 nsFrameList childList;
10585 ProcessChildren(aState, aContent, aComputedStyle, blockFrame, true, childList,
10586 true);
10587
10588 if (!MayNeedToCreateColumnSpanSiblings(blockFrame, childList)) {
10589 // No need to create column-span siblings.
10590 blockFrame->SetInitialChildList(FrameChildListID::Principal,
10591 std::move(childList));
10592 return;
10593 }
10594
10595 // Extract any initial non-column-span kids, and put them in block frame's
10596 // child list.
10597 nsFrameList initialNonColumnSpanKids =
10598 childList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
10599 blockFrame->SetInitialChildList(FrameChildListID::Principal,
10600 std::move(initialNonColumnSpanKids));
10601
10602 if (childList.IsEmpty()) {
10603 // No more kids to process (there weren't any column-span kids).
10604 return;
10605 }
10606
10607 nsFrameList columnSpanSiblings = CreateColumnSpanSiblings(
10608 aState, blockFrame, childList,
10609 // If we're constructing a column container, pass nullptr as
10610 // aPositionedFrame to forbid reparenting absolute/fixed positioned frames
10611 // to column contents or column-span wrappers.
10612 needsColumn ? nullptr : aPositionedFrameForAbsPosContainer);
10613
10614 if (needsColumn) {
10615 // We're constructing a column container; need to finish building it.
10616 FinishBuildingColumns(aState, *aNewFrame, blockFrame, columnSpanSiblings);
10617 } else {
10618 // We're constructing a normal block which has column-span children in a
10619 // column hierarchy such as "x" in the following example.
10620 //
10621 // <div style="column-count: 2">
10622 // <div id="x">
10623 // <div>normal child</div>
10624 // <div style="column-span">spanner</div>
10625 // </div>
10626 // </div>
10627 aFrameList.AppendFrames(nullptr, std::move(columnSpanSiblings));
10628 }
10629
10630 MOZ_ASSERT(columnSpanSiblings.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(columnSpanSiblings.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(columnSpanSiblings.IsEmpty()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"columnSpanSiblings.IsEmpty()" " (" "The column-span siblings should be moved to the proper place!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 10631; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10631 "The column-span siblings should be moved to the proper place!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(columnSpanSiblings.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(columnSpanSiblings.IsEmpty()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"columnSpanSiblings.IsEmpty()" " (" "The column-span siblings should be moved to the proper place!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "columnSpanSiblings.IsEmpty()"
") (" "The column-span siblings should be moved to the proper place!"
")"); do { *((volatile int*)__null) = 10631; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10632}
10633
10634nsBlockFrame* nsCSSFrameConstructor::BeginBuildingColumns(
10635 nsFrameConstructorState& aState, nsIContent* aContent,
10636 nsContainerFrame* aParentFrame, nsContainerFrame* aColumnContent,
10637 ComputedStyle* aComputedStyle) {
10638 MOZ_ASSERT(aColumnContent->IsBlockFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aColumnContent->IsBlockFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aColumnContent->IsBlockFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aColumnContent->IsBlockFrame()" " (" "aColumnContent should be a block frame."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnContent->IsBlockFrame()"
") (" "aColumnContent should be a block frame." ")"); do { *
((volatile int*)__null) = 10639; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
10639 "aColumnContent should be a block frame.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aColumnContent->IsBlockFrame())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aColumnContent->IsBlockFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aColumnContent->IsBlockFrame()" " (" "aColumnContent should be a block frame."
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnContent->IsBlockFrame()"
") (" "aColumnContent should be a block frame." ")"); do { *
((volatile int*)__null) = 10639; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10640 MOZ_ASSERT(aComputedStyle->StyleColumn()->IsColumnContainerStyle(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aComputedStyle->StyleColumn()->IsColumnContainerStyle
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aComputedStyle->StyleColumn()->IsColumnContainerStyle
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
" (" "No need to build a column hierarchy!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10641); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
") (" "No need to build a column hierarchy!" ")"); do { *((volatile
int*)__null) = 10641; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
10641 "No need to build a column hierarchy!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aComputedStyle->StyleColumn()->IsColumnContainerStyle
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aComputedStyle->StyleColumn()->IsColumnContainerStyle
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
" (" "No need to build a column hierarchy!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10641); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aComputedStyle->StyleColumn()->IsColumnContainerStyle()"
") (" "No need to build a column hierarchy!" ")"); do { *((volatile
int*)__null) = 10641; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10642
10643 // The initial column hierarchy looks like this:
10644 //
10645 // ColumnSetWrapper (original style)
10646 // ColumnSet (-moz-column-set)
10647 // Block (-moz-column-content)
10648 //
10649 nsBlockFrame* columnSetWrapper = NS_NewColumnSetWrapperFrame(
10650 mPresShell, aComputedStyle, nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
10651 InitAndRestoreFrame(aState, aContent, aParentFrame, columnSetWrapper);
10652 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10653 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10654 columnSetWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10655 }
10656
10657 AutoFrameConstructionPageName pageNameTracker(aState, columnSetWrapper);
10658 RefPtr<ComputedStyle> columnSetStyle =
10659 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
10660 PseudoStyleType::columnSet, aComputedStyle);
10661 nsContainerFrame* columnSet = NS_NewColumnSetFrame(
10662 mPresShell, columnSetStyle, nsFrameState(NS_FRAME_OWNS_ANON_BOXES));
10663 InitAndRestoreFrame(aState, aContent, columnSetWrapper, columnSet);
10664 columnSet->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10665
10666 RefPtr<ComputedStyle> blockStyle =
10667 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
10668 PseudoStyleType::columnContent, columnSetStyle);
10669 aColumnContent->SetComputedStyleWithoutNotification(blockStyle);
10670 InitAndRestoreFrame(aState, aContent, columnSet, aColumnContent);
10671 aColumnContent->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10672
10673 // Set up the parent-child chain.
10674 SetInitialSingleChild(columnSetWrapper, columnSet);
10675 SetInitialSingleChild(columnSet, aColumnContent);
10676
10677 return columnSetWrapper;
10678}
10679
10680void nsCSSFrameConstructor::FinishBuildingColumns(
10681 nsFrameConstructorState& aState, nsContainerFrame* aColumnSetWrapper,
10682 nsContainerFrame* aColumnContent, nsFrameList& aColumnContentSiblings) {
10683 nsContainerFrame* prevColumnSet = aColumnContent->GetParent();
10684
10685 MOZ_ASSERT(prevColumnSet->IsColumnSetFrame() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevColumnSet->IsColumnSetFrame() && prevColumnSet
->GetParent() == aColumnSetWrapper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(prevColumnSet->IsColumnSetFrame
() && prevColumnSet->GetParent() == aColumnSetWrapper
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
" (" "Should have established column hierarchy!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10687; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
10686 prevColumnSet->GetParent() == aColumnSetWrapper,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevColumnSet->IsColumnSetFrame() && prevColumnSet
->GetParent() == aColumnSetWrapper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(prevColumnSet->IsColumnSetFrame
() && prevColumnSet->GetParent() == aColumnSetWrapper
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
" (" "Should have established column hierarchy!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10687; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
10687 "Should have established column hierarchy!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(prevColumnSet->IsColumnSetFrame() && prevColumnSet
->GetParent() == aColumnSetWrapper)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(prevColumnSet->IsColumnSetFrame
() && prevColumnSet->GetParent() == aColumnSetWrapper
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
" (" "Should have established column hierarchy!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "prevColumnSet->IsColumnSetFrame() && prevColumnSet->GetParent() == aColumnSetWrapper"
") (" "Should have established column hierarchy!" ")"); do {
*((volatile int*)__null) = 10687; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
10688
10689 // Tag the first ColumnSet to have column-span siblings so that the bit can
10690 // propagate to all the continuations. We don't want the last ColumnSet to
10691 // have this bit, so we will unset the bit for it at the end of this function.
10692 prevColumnSet->SetHasColumnSpanSiblings(true);
10693
10694 nsFrameList finalList;
10695 while (aColumnContentSiblings.NotEmpty()) {
10696 nsIFrame* f = aColumnContentSiblings.RemoveFirstChild();
10697 if (f->IsColumnSpan()) {
10698 // Do nothing for column-span wrappers. Just move it to the final
10699 // items.
10700 finalList.AppendFrame(aColumnSetWrapper, f);
10701 } else {
10702 auto* continuingColumnSet = static_cast<nsContainerFrame*>(
10703 CreateContinuingFrame(prevColumnSet, aColumnSetWrapper, false));
10704 MOZ_ASSERT(continuingColumnSet->HasColumnSpanSiblings(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(continuingColumnSet->HasColumnSpanSiblings())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(continuingColumnSet->HasColumnSpanSiblings()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("continuingColumnSet->HasColumnSpanSiblings()"
" (" "The bit should propagate to the next continuation!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "continuingColumnSet->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10705; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10705 "The bit should propagate to the next continuation!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(continuingColumnSet->HasColumnSpanSiblings())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(continuingColumnSet->HasColumnSpanSiblings()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("continuingColumnSet->HasColumnSpanSiblings()"
" (" "The bit should propagate to the next continuation!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "continuingColumnSet->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10705; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10706
10707 f->SetParent(continuingColumnSet);
10708 SetInitialSingleChild(continuingColumnSet, f);
10709 finalList.AppendFrame(aColumnSetWrapper, continuingColumnSet);
10710 prevColumnSet = continuingColumnSet;
10711 }
10712 }
10713
10714 // Unset the bit because the last ColumnSet has no column-span siblings.
10715 prevColumnSet->SetHasColumnSpanSiblings(false);
10716
10717 aColumnSetWrapper->AppendFrames(FrameChildListID::Principal,
10718 std::move(finalList));
10719}
10720
10721bool nsCSSFrameConstructor::MayNeedToCreateColumnSpanSiblings(
10722 nsContainerFrame* aBlockFrame, const nsFrameList& aChildList) {
10723 if (!aBlockFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
10724 // The block frame isn't in a multi-column block formatting context.
10725 return false;
10726 }
10727
10728 if (ShouldSuppressColumnSpanDescendants(aBlockFrame)) {
10729 // No need to create column-span siblings for a frame that suppresses them.
10730 return false;
10731 }
10732
10733 if (aChildList.IsEmpty()) {
10734 // No child needs to be processed.
10735 return false;
10736 }
10737
10738 // Need to actually look into the child list.
10739 return true;
10740}
10741
10742nsFrameList nsCSSFrameConstructor::CreateColumnSpanSiblings(
10743 nsFrameConstructorState& aState, nsContainerFrame* aInitialBlock,
10744 nsFrameList& aChildList, nsIFrame* aPositionedFrame) {
10745 MOZ_ASSERT(aInitialBlock->IsBlockFrameOrSubclass())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aInitialBlock->IsBlockFrameOrSubclass())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aInitialBlock->IsBlockFrameOrSubclass()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aInitialBlock->IsBlockFrameOrSubclass()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aInitialBlock->IsBlockFrameOrSubclass()"
")"); do { *((volatile int*)__null) = 10745; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10746 MOZ_ASSERT(!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPositionedFrame || aPositionedFrame->IsAbsPosContainingBlock()"
")"); do { *((volatile int*)__null) = 10746; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10747
10748 nsIContent* const content = aInitialBlock->GetContent();
10749 nsContainerFrame* const parentFrame = aInitialBlock->GetParent();
10750 const bool isInitialBlockFloatCB = aInitialBlock->IsFloatContainingBlock();
10751
10752 nsFrameList siblings;
10753 nsContainerFrame* lastNonColumnSpanWrapper = aInitialBlock;
10754
10755 // Tag the first non-column-span wrapper to have column-span siblings so that
10756 // the bit can propagate to all the continuations. We don't want the last
10757 // wrapper to have this bit, so we will unset the bit for it at the end of
10758 // this function.
10759 lastNonColumnSpanWrapper->SetHasColumnSpanSiblings(true);
10760 do {
10761 MOZ_ASSERT(aChildList.NotEmpty(), "Why call this if child list is empty?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChildList.NotEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildList.NotEmpty()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aChildList.NotEmpty()"
" (" "Why call this if child list is empty?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.NotEmpty()"
") (" "Why call this if child list is empty?" ")"); do { *((
volatile int*)__null) = 10761; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10762 MOZ_ASSERT(aChildList.FirstChild()->IsColumnSpan(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChildList.FirstChild()->IsColumnSpan())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aChildList.FirstChild()->IsColumnSpan()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aChildList.FirstChild()->IsColumnSpan()"
" (" "Must have the child starting with column-span!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsColumnSpan()"
") (" "Must have the child starting with column-span!" ")");
do { *((volatile int*)__null) = 10763; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10763 "Must have the child starting with column-span!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChildList.FirstChild()->IsColumnSpan())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aChildList.FirstChild()->IsColumnSpan()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aChildList.FirstChild()->IsColumnSpan()"
" (" "Must have the child starting with column-span!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsColumnSpan()"
") (" "Must have the child starting with column-span!" ")");
do { *((volatile int*)__null) = 10763; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10764
10765 // Grab the consecutive column-span kids, and reparent them into a
10766 // block frame.
10767 RefPtr<ComputedStyle> columnSpanWrapperStyle =
10768 mPresShell->StyleSet()->ResolveNonInheritingAnonymousBoxStyle(
10769 PseudoStyleType::columnSpanWrapper);
10770 nsBlockFrame* columnSpanWrapper =
10771 NS_NewBlockFrame(mPresShell, columnSpanWrapperStyle);
10772 InitAndRestoreFrame(aState, content, parentFrame, columnSpanWrapper, false);
10773 columnSpanWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR |
10774 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10775
10776 nsFrameList columnSpanKids =
10777 aChildList.Split([](nsIFrame* f) { return !f->IsColumnSpan(); });
10778 columnSpanKids.ApplySetParent(columnSpanWrapper);
10779 columnSpanWrapper->SetInitialChildList(FrameChildListID::Principal,
10780 std::move(columnSpanKids));
10781 if (aPositionedFrame) {
10782 aState.ReparentAbsoluteItems(columnSpanWrapper);
10783 }
10784
10785 siblings.AppendFrame(nullptr, columnSpanWrapper);
10786
10787 // Grab the consecutive non-column-span kids, and reparent them into a new
10788 // continuation of the last non-column-span wrapper frame.
10789 auto* nonColumnSpanWrapper = static_cast<nsContainerFrame*>(
10790 CreateContinuingFrame(lastNonColumnSpanWrapper, parentFrame, false));
10791 nonColumnSpanWrapper->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR |
10792 NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10793 MOZ_ASSERT(nonColumnSpanWrapper->HasColumnSpanSiblings(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nonColumnSpanWrapper->HasColumnSpanSiblings())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nonColumnSpanWrapper->HasColumnSpanSiblings()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("nonColumnSpanWrapper->HasColumnSpanSiblings()"
" (" "The bit should propagate to the next continuation!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nonColumnSpanWrapper->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10794; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10794 "The bit should propagate to the next continuation!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nonColumnSpanWrapper->HasColumnSpanSiblings())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nonColumnSpanWrapper->HasColumnSpanSiblings()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("nonColumnSpanWrapper->HasColumnSpanSiblings()"
" (" "The bit should propagate to the next continuation!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nonColumnSpanWrapper->HasColumnSpanSiblings()"
") (" "The bit should propagate to the next continuation!" ")"
); do { *((volatile int*)__null) = 10794; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10795
10796 if (aChildList.NotEmpty()) {
10797 nsFrameList nonColumnSpanKids =
10798 aChildList.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
10799
10800 nonColumnSpanKids.ApplySetParent(nonColumnSpanWrapper);
10801 nonColumnSpanWrapper->SetInitialChildList(FrameChildListID::Principal,
10802 std::move(nonColumnSpanKids));
10803 if (aPositionedFrame) {
10804 aState.ReparentAbsoluteItems(nonColumnSpanWrapper);
10805 }
10806 if (isInitialBlockFloatCB) {
10807 aState.ReparentFloats(nonColumnSpanWrapper);
10808 }
10809 }
10810
10811 siblings.AppendFrame(nullptr, nonColumnSpanWrapper);
10812
10813 lastNonColumnSpanWrapper = nonColumnSpanWrapper;
10814 } while (aChildList.NotEmpty());
10815
10816 // Unset the bit because the last non-column-span wrapper has no column-span
10817 // siblings.
10818 lastNonColumnSpanWrapper->SetHasColumnSpanSiblings(false);
10819
10820 return siblings;
10821}
10822
10823bool nsCSSFrameConstructor::MaybeRecreateForColumnSpan(
10824 nsFrameConstructorState& aState, nsContainerFrame* aParentFrame,
10825 nsFrameList& aFrameList, nsIFrame* aPrevSibling) {
10826 if (!aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
10827 return false;
10828 }
10829
10830 if (aFrameList.IsEmpty()) {
10831 return false;
10832 }
10833
10834 MOZ_ASSERT(!IsFramePartOfIBSplit(aParentFrame),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsFramePartOfIBSplit(aParentFrame)" " (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10836
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
10835 "We should have wiped aParentFrame in WipeContainingBlock if it's "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsFramePartOfIBSplit(aParentFrame)" " (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10836
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
10836 "part of IB split!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsFramePartOfIBSplit(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsFramePartOfIBSplit(aParentFrame
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsFramePartOfIBSplit(aParentFrame)" " (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 10836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsFramePartOfIBSplit(aParentFrame)"
") (" "We should have wiped aParentFrame in WipeContainingBlock if it's "
"part of IB split!" ")"); do { *((volatile int*)__null) = 10836
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
10837
10838 nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
10839 if (!nextSibling && IsLastContinuationForColumnContent(aParentFrame)) {
10840 // We are appending a list of frames to the last continuation of a
10841 // ::-moz-column-content. This is the case where we can fix the frame tree
10842 // instead of reframing the containing block. Return false and let
10843 // AppendFramesToParent() deal with this.
10844 return false;
10845 }
10846
10847 auto HasColumnSpan = [](const nsFrameList& aList) {
10848 for (nsIFrame* f : aList) {
10849 if (f->IsColumnSpan()) {
10850 return true;
10851 }
10852 }
10853 return false;
10854 };
10855
10856 if (HasColumnSpan(aFrameList)) {
10857 // If any frame in the frame list has "column-span:all" style, i.e. a
10858 // -moz-column-span-wrapper frame, we need to reframe the multi-column
10859 // containing block.
10860 //
10861 // We can only be here if none of the new inserted nsIContent* nodes (via
10862 // ContentAppended or ContentRangeInserted) have column-span:all style, yet
10863 // some of them have column-span:all descendants. Sadly, there's no way to
10864 // detect this by checking FrameConstructionItems in WipeContainingBlock().
10865 // Otherwise, we would have already wiped the multi-column containing block.
10866 PROFILER_MARKER("Reframe multi-column after constructing frame list",do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Reframe multi-column after constructing frame list", ::geckoprofiler
::category::LAYOUT, {}, ::geckoprofiler::markers::Tracing{}, "Layout"
); } } while (false); } while (false)
10867 LAYOUT, {}, Tracing, "Layout")do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Reframe multi-column after constructing frame list", ::geckoprofiler
::category::LAYOUT, {}, ::geckoprofiler::markers::Tracing{}, "Layout"
); } } while (false); } while (false)
;
10868
10869 // aFrameList can contain placeholder frames. In order to destroy their
10870 // associated out-of-flow frames properly, we need to manually flush all the
10871 // out-of-flow frames in aState to their container frames.
10872 aState.ProcessFrameInsertionsForAllLists();
10873 DestroyContext context(mPresShell);
10874 aFrameList.DestroyFrames(context);
10875 RecreateFramesForContent(
10876 GetMultiColumnContainingBlockFor(aParentFrame)->GetContent(),
10877 InsertionKind::Async);
10878 return true;
10879 }
10880
10881 return false;
10882}
10883
10884nsIFrame* nsCSSFrameConstructor::ConstructInline(
10885 nsFrameConstructorState& aState, FrameConstructionItem& aItem,
10886 nsContainerFrame* aParentFrame, const nsStyleDisplay* aDisplay,
10887 nsFrameList& aFrameList) {
10888 // If an inline frame has non-inline kids, then we chop up the child list
10889 // into runs of blocks and runs of inlines, create anonymous block frames to
10890 // contain the runs of blocks, inline frames with our style for the runs of
10891 // inlines, and put all these frames, in order, into aFrameList.
10892 //
10893 // When there are column-span blocks in a run of blocks, instead of creating
10894 // an anonymous block to wrap them, we create multiple anonymous blocks,
10895 // wrapping runs of non-column-spans and runs of column-spans.
10896 //
10897 // We return the the first one. The whole setup is called an {ib}
10898 // split; in what follows "frames in the split" refers to the anonymous blocks
10899 // and inlines that contain our children.
10900 //
10901 // {ib} splits maintain the following invariants:
10902 // 1) All frames in the split have the NS_FRAME_PART_OF_IBSPLIT bit
10903 // set.
10904 //
10905 // 2) Each frame in the split has the nsIFrame::IBSplitSibling
10906 // property pointing to the next frame in the split, except for the last
10907 // one, which does not have it set.
10908 //
10909 // 3) Each frame in the split has the nsIFrame::IBSplitPrevSibling
10910 // property pointing to the previous frame in the split, except for the
10911 // first one, which does not have it set.
10912 //
10913 // 4) The first and last frame in the split are always inlines.
10914 //
10915 // 5) The frames wrapping runs of non-column-spans are linked together as
10916 // continuations. The frames wrapping runs of column-spans are *not*
10917 // linked with each other nor with other non-column-span wrappers.
10918 //
10919 // 6) The first and last frame in the chains of blocks are always wrapping
10920 // non-column-spans. Both of them are created even if they're empty.
10921 //
10922 // An invariant that is NOT maintained is that the wrappers are actually
10923 // linked via GetNextSibling linkage. A simple example is an inline
10924 // containing an inline that contains a block. The three parts of the inner
10925 // inline end up with three different parents.
10926 //
10927 // For example, this HTML:
10928 // <span>
10929 // <div>a</div>
10930 // <span>
10931 // b
10932 // <div>c</div>
10933 // </span>
10934 // d
10935 // <div>e</div>
10936 // f
10937 // </span>
10938 // Gives the following frame tree:
10939 //
10940 // Inline (outer span)
10941 // Block (anonymous, outer span)
10942 // Block (div)
10943 // Text("a")
10944 // Inline (outer span)
10945 // Inline (inner span)
10946 // Text("b")
10947 // Block (anonymous, outer span)
10948 // Block (anonymous, inner span)
10949 // Block (div)
10950 // Text("c")
10951 // Inline (outer span)
10952 // Inline (inner span)
10953 // Text("d")
10954 // Block (anonymous, outer span)
10955 // Block (div)
10956 // Text("e")
10957 // Inline (outer span)
10958 // Text("f")
10959
10960 nsIContent* const content = aItem.mContent;
10961 ComputedStyle* const computedStyle = aItem.mComputedStyle;
10962
10963 nsInlineFrame* newFrame = NS_NewInlineFrame(mPresShell, computedStyle);
10964
10965 // Initialize the frame
10966 InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
10967
10968 // definition cannot be inside next block because the object's destructor is
10969 // significant. this is part of the fix for bug 42372
10970 nsFrameConstructorSaveState absoluteSaveState;
10971
10972 bool isAbsPosCB = newFrame->IsAbsPosContainingBlock();
10973 newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
10974 if (isAbsPosCB) {
10975 // Relatively positioned frames becomes a container for child
10976 // frames that are positioned
10977 aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
10978 }
10979
10980 if (aParentFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR) &&
10981 !ShouldSuppressColumnSpanDescendants(aParentFrame)) {
10982 newFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
10983 }
10984
10985 // Process the child content
10986 nsFrameList childList;
10987 ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
10988 /* aParentIsWrapperAnonBox = */ false, childList);
10989
10990 nsIFrame* firstBlock = nullptr;
10991 if (!aItem.mIsAllInline) {
10992 for (nsIFrame* f : childList) {
10993 if (f->IsBlockOutside()) {
10994 firstBlock = f;
10995 break;
10996 }
10997 }
10998 }
10999
11000 if (aItem.mIsAllInline || !firstBlock) {
11001 // This part is easy. We either already know we have no non-inline kids,
11002 // or haven't found any when constructing actual frames (the latter can
11003 // happen only if out-of-flows that we thought had no containing block
11004 // acquired one when ancestor inline frames and {ib} splits got
11005 // constructed). Just put all the kids into the single inline frame and
11006 // bail.
11007 newFrame->SetInitialChildList(FrameChildListID::Principal,
11008 std::move(childList));
11009 aState.AddChild(newFrame, aFrameList, content, aParentFrame);
11010 return newFrame;
11011 }
11012
11013 // This inline frame contains several types of children. Therefore this frame
11014 // has to be chopped into several pieces, as described above.
11015
11016 // Grab the first inline's kids
11017 nsFrameList firstInlineKids = childList.TakeFramesBefore(firstBlock);
11018 newFrame->SetInitialChildList(FrameChildListID::Principal,
11019 std::move(firstInlineKids));
11020
11021 aFrameList.AppendFrame(nullptr, newFrame);
11022
11023 newFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
11024 CreateIBSiblings(aState, newFrame, isAbsPosCB, childList, aFrameList);
11025
11026 return newFrame;
11027}
11028
11029void nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
11030 nsContainerFrame* aInitialInline,
11031 bool aIsAbsPosCB,
11032 nsFrameList& aChildList,
11033 nsFrameList& aSiblings) {
11034 MOZ_ASSERT(aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock()"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11034); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aIsAbsPosCB == aInitialInline->IsAbsPosContainingBlock()"
")"); do { *((volatile int*)__null) = 11034; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11035
11036 nsIContent* content = aInitialInline->GetContent();
11037 ComputedStyle* computedStyle = aInitialInline->Style();
11038 nsContainerFrame* parentFrame = aInitialInline->GetParent();
11039
11040 // Resolve the right style for our anonymous blocks.
11041 //
11042 // The distinction in styles is needed because of CSS 2.1, section
11043 // 9.2.1.1, which says:
11044 //
11045 // When such an inline box is affected by relative positioning, any
11046 // resulting translation also affects the block-level box contained
11047 // in the inline box.
11048 RefPtr<ComputedStyle> blockSC =
11049 mPresShell->StyleSet()->ResolveInheritingAnonymousBoxStyle(
11050 PseudoStyleType::mozBlockInsideInlineWrapper, computedStyle);
11051
11052 nsContainerFrame* lastNewInline =
11053 static_cast<nsContainerFrame*>(aInitialInline->FirstContinuation());
11054 do {
11055 // On entry to this loop aChildList is not empty and the first frame in it
11056 // is block-level.
11057 MOZ_ASSERT(aChildList.NotEmpty(), "Should have child items")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChildList.NotEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChildList.NotEmpty()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aChildList.NotEmpty()"
" (" "Should have child items" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11057); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.NotEmpty()"
") (" "Should have child items" ")"); do { *((volatile int*)
__null) = 11057; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11058 MOZ_ASSERT(aChildList.FirstChild()->IsBlockOutside(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChildList.FirstChild()->IsBlockOutside())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aChildList.FirstChild()->IsBlockOutside()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aChildList.FirstChild()->IsBlockOutside()"
" (" "Must have list starting with block" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsBlockOutside()"
") (" "Must have list starting with block" ")"); do { *((volatile
int*)__null) = 11059; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11059 "Must have list starting with block")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChildList.FirstChild()->IsBlockOutside())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aChildList.FirstChild()->IsBlockOutside()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aChildList.FirstChild()->IsBlockOutside()"
" (" "Must have list starting with block" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChildList.FirstChild()->IsBlockOutside()"
") (" "Must have list starting with block" ")"); do { *((volatile
int*)__null) = 11059; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11060
11061 // The initial run of blocks belongs to an anonymous block that we create
11062 // right now. The anonymous block will be the parent of these block
11063 // children of the inline.
11064 nsBlockFrame* blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
11065 InitAndRestoreFrame(aState, content, parentFrame, blockFrame, false);
11066 if (aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11067 blockFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
11068 }
11069
11070 // Find the first non-block child which defines the end of our block kids
11071 // and the start of our next inline's kids
11072 nsFrameList blockKids =
11073 aChildList.Split([](nsIFrame* f) { return !f->IsBlockOutside(); });
11074
11075 if (!aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11076 MoveChildrenTo(aInitialInline, blockFrame, blockKids);
11077
11078 SetFrameIsIBSplit(lastNewInline, blockFrame);
11079 aSiblings.AppendFrame(nullptr, blockFrame);
11080 } else {
11081 // Extract any initial non-column-span frames, and put them in
11082 // blockFrame's child list.
11083 nsFrameList initialNonColumnSpanKids =
11084 blockKids.Split([](nsIFrame* f) { return f->IsColumnSpan(); });
11085 MoveChildrenTo(aInitialInline, blockFrame, initialNonColumnSpanKids);
11086
11087 SetFrameIsIBSplit(lastNewInline, blockFrame);
11088 aSiblings.AppendFrame(nullptr, blockFrame);
11089
11090 if (blockKids.NotEmpty()) {
11091 // Although SetFrameIsIBSplit() will add NS_FRAME_PART_OF_IBSPLIT for
11092 // blockFrame later, we manually add the bit earlier here to make all
11093 // the continuations of blockFrame created in
11094 // CreateColumnSpanSiblings(), i.e. non-column-span wrappers, have the
11095 // bit via nsIFrame::Init().
11096 blockFrame->AddStateBits(NS_FRAME_PART_OF_IBSPLIT);
11097
11098 nsFrameList columnSpanSiblings =
11099 CreateColumnSpanSiblings(aState, blockFrame, blockKids,
11100 aIsAbsPosCB ? aInitialInline : nullptr);
11101 aSiblings.AppendFrames(nullptr, std::move(columnSpanSiblings));
11102 }
11103 }
11104
11105 // Now grab the initial inlines in aChildList and put them into an inline
11106 // frame.
11107 nsInlineFrame* inlineFrame = NS_NewInlineFrame(mPresShell, computedStyle);
11108 InitAndRestoreFrame(aState, content, parentFrame, inlineFrame, false);
11109 inlineFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
11110 if (aInitialInline->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11111 inlineFrame->AddStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
11112 }
11113
11114 if (aIsAbsPosCB) {
11115 inlineFrame->MarkAsAbsoluteContainingBlock();
11116 }
11117
11118 if (aChildList.NotEmpty()) {
11119 nsFrameList inlineKids =
11120 aChildList.Split([](nsIFrame* f) { return f->IsBlockOutside(); });
11121 MoveChildrenTo(aInitialInline, inlineFrame, inlineKids);
11122 }
11123
11124 SetFrameIsIBSplit(blockFrame, inlineFrame);
11125 aSiblings.AppendFrame(nullptr, inlineFrame);
11126 lastNewInline = inlineFrame;
11127 } while (aChildList.NotEmpty());
11128
11129 SetFrameIsIBSplit(lastNewInline, nullptr);
11130}
11131
11132void nsCSSFrameConstructor::BuildInlineChildItems(
11133 nsFrameConstructorState& aState, FrameConstructionItem& aParentItem,
11134 bool aItemIsWithinSVGText, bool aItemAllowsTextPathChild) {
11135 ComputedStyle* const parentComputedStyle = aParentItem.mComputedStyle;
11136 nsIContent* const parentContent = aParentItem.mContent;
11137
11138 if (!aItemIsWithinSVGText) {
11139 if (parentComputedStyle->StyleDisplay()->IsListItem()) {
11140 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11141 *parentComputedStyle, PseudoStyleType::marker,
11142 aParentItem.mChildItems);
11143 }
11144 // Probe for generated content before
11145 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11146 *parentComputedStyle, PseudoStyleType::before,
11147 aParentItem.mChildItems);
11148 }
11149
11150 ItemFlags flags;
11151 if (aItemIsWithinSVGText) {
11152 flags += ItemFlag::IsWithinSVGText;
11153 }
11154 if (aItemAllowsTextPathChild &&
11155 aParentItem.mContent->IsSVGElement(nsGkAtoms::a)) {
11156 flags += ItemFlag::AllowTextPathChild;
11157 }
11158
11159 FlattenedChildIterator iter(parentContent);
11160 for (nsIContent* content = iter.GetNextChild(); content;
11161 content = iter.GetNextChild()) {
11162 AddFrameConstructionItems(aState, content, iter.ShadowDOMInvolved(),
11163 *parentComputedStyle, InsertionPoint(),
11164 aParentItem.mChildItems, flags);
11165 }
11166
11167 if (!aItemIsWithinSVGText) {
11168 // Probe for generated content after
11169 CreateGeneratedContentItem(aState, nullptr, *parentContent->AsElement(),
11170 *parentComputedStyle, PseudoStyleType::after,
11171 aParentItem.mChildItems);
11172 }
11173
11174 aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
11175}
11176
11177// return whether it's ok to append (in the AppendFrames sense) to
11178// aParentFrame if our nextSibling is aNextSibling. aParentFrame must
11179// be an ib-split inline.
11180static bool IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame,
11181 nsIFrame* aNextSibling) {
11182 MOZ_ASSERT(IsInlineFrame(aParentFrame), "Must have an inline parent here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsInlineFrame(aParentFrame))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInlineFrame(aParentFrame))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsInlineFrame(aParentFrame)"
" (" "Must have an inline parent here" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsInlineFrame(aParentFrame)"
") (" "Must have an inline parent here" ")"); do { *((volatile
int*)__null) = 11182; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11183
11184 do {
11185 NS_ASSERTION(IsFramePartOfIBSplit(aParentFrame),do { if (!(IsFramePartOfIBSplit(aParentFrame))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "How is this not part of an ib-split?", "IsFramePartOfIBSplit(aParentFrame)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11186); MOZ_PretendNoReturn(); } } while (0)
11186 "How is this not part of an ib-split?")do { if (!(IsFramePartOfIBSplit(aParentFrame))) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "How is this not part of an ib-split?", "IsFramePartOfIBSplit(aParentFrame)"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11186); MOZ_PretendNoReturn(); } } while (0)
;
11187 if (aNextSibling || aParentFrame->GetNextContinuation() ||
11188 GetIBSplitSibling(aParentFrame)) {
11189 return false;
11190 }
11191
11192 aNextSibling = aParentFrame->GetNextSibling();
11193 aParentFrame = aParentFrame->GetParent();
11194 } while (IsInlineFrame(aParentFrame));
11195
11196 return true;
11197}
11198
11199bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
11200#define TRACE(reason) \
11201 PROFILER_MARKER("WipeInsertionParent: " reason, LAYOUT, {}, Tracing, \do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("WipeInsertionParent: " reason, ::geckoprofiler::category::LAYOUT
, {}, ::geckoprofiler::markers::Tracing{}, "Layout"); } } while
(false); } while (false)
11202 "Layout")do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("WipeInsertionParent: " reason, ::geckoprofiler::category::LAYOUT
, {}, ::geckoprofiler::markers::Tracing{}, "Layout"); } } while
(false); } while (false)
;
11203
11204 const LayoutFrameType frameType = aFrame->Type();
11205
11206 // FIXME(emilio): This looks terribly inefficient if you insert elements deep
11207 // in a MathML subtree.
11208 if (aFrame->IsMathMLFrame()) {
11209 TRACE("MathML");
11210 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11211 return true;
11212 }
11213
11214 // A ruby-related frame that's getting new children.
11215 // The situation for ruby is complex, especially when interacting with
11216 // spaces. It contains these two special cases apart from tables:
11217 // 1) There are effectively three types of white spaces in ruby frames
11218 // we handle differently: leading/tailing/inter-level space,
11219 // inter-base/inter-annotation space, and inter-segment space.
11220 // These three types of spaces can be converted to each other when
11221 // their sibling changes.
11222 // 2) The first effective child of a ruby frame must always be a ruby
11223 // base container. It should be created or destroyed accordingly.
11224 if (IsRubyPseudo(aFrame) || frameType == LayoutFrameType::Ruby ||
11225 RubyUtils::IsRubyContainerBox(frameType)) {
11226 // We want to optimize it better, and avoid reframing as much as
11227 // possible. But given the cases above, and the fact that a ruby
11228 // usually won't be very large, it should be fine to reframe it.
11229 TRACE("Ruby");
11230 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11231 return true;
11232 }
11233
11234 // Reframe the multi-column container whenever elements insert/append
11235 // into it because we need to reconstruct column-span split.
11236 if (aFrame->IsColumnSetWrapperFrame()) {
11237 TRACE("Multi-column");
11238 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11239 return true;
11240 }
11241
11242 return false;
11243
11244#undef TRACE
11245}
11246
11247bool nsCSSFrameConstructor::WipeContainingBlock(
11248 nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
11249 nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
11250 nsIFrame* aPrevSibling) {
11251#define TRACE(reason) \
11252 PROFILER_MARKER("WipeContainingBlock: " reason, LAYOUT, {}, Tracing, \do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("WipeContainingBlock: " reason, ::geckoprofiler::category::LAYOUT
, {}, ::geckoprofiler::markers::Tracing{}, "Layout"); } } while
(false); } while (false)
11253 "Layout")do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("WipeContainingBlock: " reason, ::geckoprofiler::category::LAYOUT
, {}, ::geckoprofiler::markers::Tracing{}, "Layout"); } } while
(false); } while (false)
;
11254
11255 if (aItems.IsEmpty()) {
11256 return false;
11257 }
11258
11259 // Before we go and append the frames, we must check for several
11260 // special situations.
11261
11262 if (aFrame->GetContent() == mDocument->GetRootElement()) {
11263 // Situation #1 is when we insert content that becomes the canonical body
11264 // element, and its used WritingMode is different from the root element's
11265 // used WritingMode.
11266 // We need to reframe the root element so that the root element's frames has
11267 // the correct writing-mode propagated from body element. (See
11268 // nsCSSFrameConstructor::ConstructDocElementFrame.)
11269 //
11270 // Bug 1594297: When inserting a new <body>, we may need to reframe the old
11271 // <body> which has a "overflow" value other than simple "visible". But it's
11272 // tricky, see bug 1593752.
11273 nsIContent* bodyElement = mDocument->GetBodyElement();
11274 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11275 const WritingMode bodyWM(iter.item().mComputedStyle);
11276 if (iter.item().mContent == bodyElement &&
11277 bodyWM != aFrame->GetWritingMode()) {
11278 TRACE("Root");
11279 RecreateFramesForContent(mDocument->GetRootElement(),
11280 InsertionKind::Async);
11281 return true;
11282 }
11283 }
11284 }
11285
11286 nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
11287
11288 // Situation #2 is a flex / grid container frame into which we're inserting
11289 // new inline non-replaced children, adjacent to an existing anonymous flex or
11290 // grid item.
11291 if (aFrame->IsFlexOrGridContainer()) {
11292 FCItemIterator iter(aItems);
11293
11294 // Check if we're adding to-be-wrapped content right *after* an existing
11295 // anonymous flex or grid item (which would need to absorb this content).
11296 const bool isLegacyWebKitBox = IsFlexContainerForLegacyWebKitBox(aFrame);
11297 if (aPrevSibling && IsAnonymousItem(aPrevSibling) &&
11298 iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11299 TRACE("Inserting inline after anon flex or grid item");
11300 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11301 return true;
11302 }
11303
11304 // Check if we're adding to-be-wrapped content right *before* an existing
11305 // anonymous flex or grid item (which would need to absorb this content).
11306 if (nextSibling && IsAnonymousItem(nextSibling)) {
11307 // Jump to the last entry in the list
11308 iter.SetToEnd();
11309 iter.Prev();
11310 if (iter.item().NeedsAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11311 TRACE("Inserting inline before anon flex or grid item");
11312 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11313 return true;
11314 }
11315 }
11316 }
11317
11318 // Situation #3 is an anonymous flex or grid item that's getting new children
11319 // who don't want to be wrapped.
11320 if (IsAnonymousItem(aFrame)) {
11321 AssertAnonymousFlexOrGridItemParent(aFrame, aFrame->GetParent());
11322
11323 // We need to push a null float containing block to be sure that
11324 // "NeedsAnonFlexOrGridItem" will know we're not honoring floats for this
11325 // inserted content. (In particular, this is necessary in order for
11326 // its "GetGeometricParent" call to return the correct result.)
11327 // We're not honoring floats on this content because it has the
11328 // _flex/grid container_ as its parent in the content tree.
11329 nsFrameConstructorSaveState floatSaveState;
11330 aState.PushFloatContainingBlock(nullptr, floatSaveState);
11331
11332 FCItemIterator iter(aItems);
11333 // Skip over things that _do_ need an anonymous flex item, because
11334 // they're perfectly happy to go here -- they won't cause a reframe.
11335 nsIFrame* containerFrame = aFrame->GetParent();
11336 const bool isLegacyWebKitBox =
11337 IsFlexContainerForLegacyWebKitBox(containerFrame);
11338 if (!iter.SkipItemsThatNeedAnonFlexOrGridItem(aState, isLegacyWebKitBox)) {
11339 // We hit something that _doesn't_ need an anonymous flex item!
11340 // Rebuild the flex container to bust it out.
11341 TRACE("Inserting non-inlines inside anon flex or grid item");
11342 RecreateFramesForContent(containerFrame->GetContent(),
11343 InsertionKind::Async);
11344 return true;
11345 }
11346
11347 // If we get here, then everything in |aItems| needs to be wrapped in
11348 // an anonymous flex or grid item. That's where it's already going - good!
11349 }
11350
11351 // Situation #4 is a case when table pseudo-frames don't work out right
11352 ParentType parentType = GetParentType(aFrame);
11353 // If all the kids want a parent of the type that aFrame is, then we're all
11354 // set to go. Indeed, there won't be any table pseudo-frames created between
11355 // aFrame and the kids, so those won't need to be merged with any table
11356 // pseudo-frames that might already be kids of aFrame. If aFrame itself is a
11357 // table pseudo-frame, then all the kids in this list would have wanted a
11358 // frame of that type wrapping them anyway, so putting them inside it is ok.
11359 if (!aItems.AllWantParentType(parentType)) {
11360 // Don't give up yet. If parentType is not eTypeBlock and the parent is
11361 // not a generated content frame, then try filtering whitespace out of the
11362 // list.
11363 if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
11364 // For leading whitespace followed by a kid that wants our parent type,
11365 // there are four cases:
11366 // 1) We have a previous sibling which is not a table pseudo. That means
11367 // that previous sibling wanted a (non-block) parent of the type we're
11368 // looking at. Then the whitespace comes between two table-internal
11369 // elements, so should be collapsed out.
11370 // 2) We have a previous sibling which is a table pseudo. It might have
11371 // kids who want this whitespace, so we need to reframe.
11372 // 3) We have no previous sibling and our parent frame is not a table
11373 // pseudo. That means that we'll be at the beginning of our actual
11374 // non-block-type parent, and the whitespace is OK to collapse out.
11375 // If something is ever inserted before us, it'll find our own parent
11376 // as its parent and if it's something that would care about the
11377 // whitespace it'll want a block parent, so it'll trigger a reframe at
11378 // that point.
11379 // 4) We have no previous sibling and our parent frame is a table pseudo.
11380 // Need to reframe.
11381 // All that is predicated on finding the correct previous sibling. We
11382 // might have to walk backwards along continuations from aFrame to do so.
11383 //
11384 // It's always OK to drop whitespace between any two items that want a
11385 // parent of type parentType.
11386 //
11387 // For trailing whitespace preceded by a kid that wants our parent type,
11388 // there are four cases:
11389 // 1) We have a next sibling which is not a table pseudo. That means
11390 // that next sibling wanted a (non-block) parent of the type we're
11391 // looking at. Then the whitespace comes between two table-internal
11392 // elements, so should be collapsed out.
11393 // 2) We have a next sibling which is a table pseudo. It might have
11394 // kids who want this whitespace, so we need to reframe.
11395 // 3) We have no next sibling and our parent frame is not a table
11396 // pseudo. That means that we'll be at the end of our actual
11397 // non-block-type parent, and the whitespace is OK to collapse out.
11398 // If something is ever inserted after us, it'll find our own parent
11399 // as its parent and if it's something that would care about the
11400 // whitespace it'll want a block parent, so it'll trigger a reframe at
11401 // that point.
11402 // 4) We have no next sibling and our parent frame is a table pseudo.
11403 // Need to reframe.
11404 // All that is predicated on finding the correct next sibling. We might
11405 // have to walk forward along continuations from aFrame to do so. That
11406 // said, in the case when nextSibling is null at this point and aIsAppend
11407 // is true, we know we're in case 3. Furthermore, in that case we don't
11408 // even have to worry about the table pseudo situation; we know our
11409 // parent is not a table pseudo there.
11410 FCItemIterator iter(aItems);
11411 FCItemIterator start(iter);
11412 do {
11413 if (iter.SkipItemsWantingParentType(parentType)) {
11414 break;
11415 }
11416
11417 // iter points to an item that wants a different parent. If it's not
11418 // whitespace, we're done; no more point scanning the list.
11419 if (!iter.item().IsWhitespace(aState)) {
11420 break;
11421 }
11422
11423 if (iter == start) {
11424 // Leading whitespace. How to handle this depends on our
11425 // previous sibling and aFrame. See the long comment above.
11426 nsIFrame* prevSibling = aPrevSibling;
11427 if (!prevSibling) {
11428 // Try to find one after all
11429 nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
11430 while (parentPrevCont) {
11431 prevSibling = parentPrevCont->PrincipalChildList().LastChild();
11432 if (prevSibling) {
11433 break;
11434 }
11435 parentPrevCont = parentPrevCont->GetPrevContinuation();
11436 }
11437 };
11438 if (prevSibling) {
11439 if (IsTablePseudo(prevSibling)) {
11440 // need to reframe
11441 break;
11442 }
11443 } else if (IsTablePseudo(aFrame)) {
11444 // need to reframe
11445 break;
11446 }
11447 }
11448
11449 FCItemIterator spaceEndIter(iter);
11450 // Advance spaceEndIter past any whitespace
11451 bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
11452
11453 bool okToDrop;
11454 if (trailingSpaces) {
11455 // Trailing whitespace. How to handle this depeds on aIsAppend, our
11456 // next sibling and aFrame. See the long comment above.
11457 okToDrop = aIsAppend && !nextSibling;
11458 if (!okToDrop) {
11459 if (!nextSibling) {
11460 // Try to find one after all
11461 nsIFrame* parentNextCont = aFrame->GetNextContinuation();
11462 while (parentNextCont) {
11463 nextSibling = parentNextCont->PrincipalChildList().FirstChild();
11464 if (nextSibling) {
11465 break;
11466 }
11467 parentNextCont = parentNextCont->GetNextContinuation();
11468 }
11469 }
11470
11471 okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
11472 (!nextSibling && !IsTablePseudo(aFrame));
11473 }
11474#ifdef DEBUG1
11475 else {
11476 NS_ASSERTION(!IsTablePseudo(aFrame), "How did that happen?")do { if (!(!IsTablePseudo(aFrame))) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "How did that happen?", "!IsTablePseudo(aFrame)", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11476); MOZ_PretendNoReturn(); } } while (0)
;
11477 }
11478#endif
11479 } else {
11480 okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
11481 }
11482
11483 if (okToDrop) {
11484 iter.DeleteItemsTo(this, spaceEndIter);
11485 } else {
11486 // We're done: we don't want to drop the whitespace, and it has the
11487 // wrong parent type.
11488 break;
11489 }
11490
11491 // Now loop, since |iter| points to item right after the whitespace we
11492 // removed.
11493 } while (!iter.IsDone());
11494 }
11495
11496 // We might be able to figure out some sort of optimizations here, but they
11497 // would have to depend on having a correct aPrevSibling and a correct next
11498 // sibling. For example, we can probably avoid reframing if none of
11499 // aFrame, aPrevSibling, and next sibling are table pseudo-frames. But it
11500 // doesn't seem worth it to worry about that for now, especially since we
11501 // in fact do not have a reliable aPrevSibling, nor any next sibling, in
11502 // this method.
11503
11504 // aItems might have changed, so recheck the parent type thing. In fact,
11505 // it might be empty, so recheck that too.
11506 if (aItems.IsEmpty()) {
11507 return false;
11508 }
11509
11510 // If aFrame is empty, the insertion process will be able to take care of
11511 // creating any needed pseudo-parents.
11512 if (!aItems.AllWantParentType(parentType) &&
11513 !SafeToInsertPseudoNeedingChildren(aFrame)) {
11514 // Reframing aFrame->GetContent() is good enough, since the content of
11515 // table pseudo-frames is the ancestor content.
11516 TRACE("Pseudo-frames going wrong");
11517 RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
11518 return true;
11519 }
11520 }
11521
11522 // Situation #5 is a frame in multicol subtree that's getting new children.
11523 if (aFrame->HasAnyStateBits(NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR)) {
11524 bool anyColumnSpanItems = false;
11525 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11526 if (iter.item().mComputedStyle->StyleColumn()->IsColumnSpanStyle()) {
11527 anyColumnSpanItems = true;
11528 break;
11529 }
11530 }
11531
11532 bool needsReframe =
11533 // 1. Insert / append any column-span children.
11534 anyColumnSpanItems ||
11535 // 2. GetInsertionPrevSibling() modifies insertion parent. If the prev
11536 // sibling is a column-span, aFrame ends up being the
11537 // column-span-wrapper.
11538 aFrame->Style()->GetPseudoType() ==
11539 PseudoStyleType::columnSpanWrapper ||
11540 // 3. Append into {ib} split container. There might be room for
11541 // optimization, but let's reframe for correctness...
11542 IsFramePartOfIBSplit(aFrame);
11543
11544 if (needsReframe) {
11545 TRACE("Multi-column");
11546 RecreateFramesForContent(
11547 GetMultiColumnContainingBlockFor(aFrame)->GetContent(),
11548 InsertionKind::Async);
11549 return true;
11550 }
11551
11552 // If we get here, then we need further check for {ib} split to decide
11553 // whether to reframe. For example, appending a block into an empty inline
11554 // that is not part of an {ib} split, but should become an {ib} split.
11555 }
11556
11557 // A <fieldset> may need to pick up a new rendered legend from aItems.
11558 // We currently can't handle this case without recreating frames for
11559 // the fieldset.
11560 // XXXmats we should be able to optimize this when the fieldset doesn't
11561 // currently have a rendered legend. ContentRangeInserted needs to be fixed
11562 // to use the inner frame as the content insertion frame in that case.
11563 if (const auto* fieldset = GetFieldSetFrameFor(aFrame)) {
11564 // Check if any item is eligible to be a rendered legend.
11565 for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
11566 const auto& item = iter.item();
11567 if (!item.mContent->IsHTMLElement(nsGkAtoms::legend)) {
11568 continue;
11569 }
11570 const auto* display = item.mComputedStyle->StyleDisplay();
11571 if (display->IsFloatingStyle() ||
11572 display->IsAbsolutelyPositionedStyle()) {
11573 continue;
11574 }
11575 TRACE("Fieldset with rendered legend");
11576 RecreateFramesForContent(fieldset->GetContent(), InsertionKind::Async);
11577 return true;
11578 }
11579 }
11580
11581 // Now we have several cases involving {ib} splits. Put them all in a
11582 // do/while with breaks to take us to the "go and reconstruct" code.
11583 do {
11584 if (IsInlineFrame(aFrame)) {
11585 if (aItems.AreAllItemsInline()) {
11586 // We can just put the kids in.
11587 return false;
11588 }
11589
11590 if (!IsFramePartOfIBSplit(aFrame)) {
11591 // Need to go ahead and reconstruct.
11592 break;
11593 }
11594
11595 // Now we're adding kids including some blocks to an inline part of an
11596 // {ib} split. If we plan to call AppendFrames, and don't have a next
11597 // sibling for the new frames, and our parent is the last continuation of
11598 // the last part of the {ib} split, and the same is true of all our
11599 // ancestor inlines (they have no following continuations and they're the
11600 // last part of their {ib} splits and we'd be adding to the end for all
11601 // of them), then AppendFrames will handle things for us. Bail out in
11602 // that case.
11603 if (aIsAppend && IsSafeToAppendToIBSplitInline(aFrame, nextSibling)) {
11604 return false;
11605 }
11606
11607 // Need to reconstruct.
11608 break;
11609 }
11610
11611 // Now we know we have a block parent. If it's not part of an
11612 // ib-split, we're all set.
11613 if (!IsFramePartOfIBSplit(aFrame)) {
11614 return false;
11615 }
11616
11617 // We're adding some kids to a block part of an {ib} split. If all the
11618 // kids are blocks, we don't need to reconstruct.
11619 if (aItems.AreAllItemsBlock()) {
11620 return false;
11621 }
11622
11623 // We might have some inline kids for this block. Just fall out of the
11624 // loop and reconstruct.
11625 } while (false);
11626
11627 // If we don't have a containing block, start with aFrame and look for one.
11628 if (!aContainingBlock) {
11629 aContainingBlock = aFrame;
11630 }
11631
11632 // To find the right block to reframe, just walk up the tree until we find a
11633 // frame that is:
11634 // 1) Not part of an IB split
11635 // 2) Not a pseudo-frame
11636 // 3) Not an inline frame
11637 // We're guaranteed to find one, since ComputedStyle::ApplyStyleFixups
11638 // enforces that the root is display:none, display:table, or display:block.
11639 // Note that walking up "too far" is OK in terms of correctness, even if it
11640 // might be a little inefficient. This is why we walk out of all
11641 // pseudo-frames -- telling which ones are or are not OK to walk out of is
11642 // too hard (and I suspect that we do in fact need to walk out of all of
11643 // them).
11644 while (IsFramePartOfIBSplit(aContainingBlock) ||
11645 aContainingBlock->IsInlineOutside() ||
11646 aContainingBlock->Style()->IsPseudoOrAnonBox()) {
11647 aContainingBlock = aContainingBlock->GetParent();
11648 NS_ASSERTION(aContainingBlock,do { if (!(aContainingBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Must have non-inline, non-ib-split, non-pseudo frame as " "root (or child of root, for a table root)!"
, "aContainingBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11650); MOZ_PretendNoReturn(); } } while (0)
11649 "Must have non-inline, non-ib-split, non-pseudo frame as "do { if (!(aContainingBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Must have non-inline, non-ib-split, non-pseudo frame as " "root (or child of root, for a table root)!"
, "aContainingBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11650); MOZ_PretendNoReturn(); } } while (0)
11650 "root (or child of root, for a table root)!")do { if (!(aContainingBlock)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Must have non-inline, non-ib-split, non-pseudo frame as " "root (or child of root, for a table root)!"
, "aContainingBlock", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11650); MOZ_PretendNoReturn(); } } while (0)
;
11651 }
11652
11653 // Tell parent of the containing block to reformulate the
11654 // entire block. This is painful and definitely not optimal
11655 // but it will *always* get the right answer.
11656
11657 nsIContent* blockContent = aContainingBlock->GetContent();
11658 TRACE("IB splits");
11659 RecreateFramesForContent(blockContent, InsertionKind::Async);
11660 return true;
11661#undef TRACE
11662}
11663
11664void nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame) {
11665 // XXXbz how exactly would we get here while isReflowing anyway? Should this
11666 // whole test be ifdef DEBUG?
11667 if (mPresShell->IsReflowLocked()) {
11668 // don't ReframeContainingBlock, this will result in a crash
11669 // if we remove a tree that's in reflow - see bug 121368 for testcase
11670 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a "
"Reflow!!!", "Error", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11672); MOZ_PretendNoReturn(); } while (0)
11671 "Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a "do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a "
"Reflow!!!", "Error", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11672); MOZ_PretendNoReturn(); } while (0)
11672 "Reflow!!!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a "
"Reflow!!!", "Error", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11672); MOZ_PretendNoReturn(); } while (0)
;
11673 return;
11674 }
11675
11676 // Get the first "normal" ancestor of the target frame.
11677 nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
11678 if (containingBlock) {
11679 // From here we look for the containing block in case the target
11680 // frame is already a block (which can happen when an inline frame
11681 // wraps some of its content in an anonymous block; see
11682 // ConstructInline)
11683
11684 // NOTE: We used to get the FloatContainingBlock here, but it was often
11685 // wrong. GetIBContainingBlock works much better and provides the correct
11686 // container in all cases so GetFloatContainingBlock(aFrame) has been
11687 // removed
11688
11689 // And get the containingBlock's content
11690 if (nsIContent* blockContent = containingBlock->GetContent()) {
11691#ifdef DEBUG1
11692 if (gNoisyContentUpdates) {
11693 printf(" ==> blockContent=%p\n", blockContent);
11694 }
11695#endif
11696 RecreateFramesForContent(blockContent, InsertionKind::Async);
11697 return;
11698 }
11699 }
11700
11701 // If we get here, we're screwed!
11702 RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
11703 InsertionKind::Async);
11704}
11705
11706//////////////////////////////////////////////////////////
11707// nsCSSFrameConstructor::FrameConstructionItem methods //
11708//////////////////////////////////////////////////////////
11709bool nsCSSFrameConstructor::FrameConstructionItem::IsWhitespace(
11710 nsFrameConstructorState& aState) const {
11711 MOZ_ASSERT(aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
" (" "How did that happen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11712; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
11712 "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
" (" "How did that happen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aState.mCreatingExtraFrames || !mContent->GetPrimaryFrame()"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11712; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11713 if (!mIsText) {
11714 return false;
11715 }
11716 mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
11717 NS_REFRAME_IF_WHITESPACE);
11718 return mContent->TextIsOnlyWhitespace();
11719}
11720
11721//////////////////////////////////////////////////////////////
11722// nsCSSFrameConstructor::FrameConstructionItemList methods //
11723//////////////////////////////////////////////////////////////
11724void nsCSSFrameConstructor::FrameConstructionItemList::AdjustCountsForItem(
11725 FrameConstructionItem* aItem, int32_t aDelta) {
11726 MOZ_ASSERT(aDelta == 1 || aDelta == -1, "Unexpected delta")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDelta == 1 || aDelta == -1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDelta == 1 || aDelta == -1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aDelta == 1 || aDelta == -1"
" (" "Unexpected delta" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDelta == 1 || aDelta == -1"
") (" "Unexpected delta" ")"); do { *((volatile int*)__null)
= 11726; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
11727 mItemCount += aDelta;
11728 if (aItem->mIsAllInline) {
11729 mInlineCount += aDelta;
11730 }
11731 if (aItem->mIsBlock) {
11732 mBlockCount += aDelta;
11733 }
11734 mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
11735}
11736
11737////////////////////////////////////////////////////////////////////////
11738// nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
11739////////////////////////////////////////////////////////////////////////
11740inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11741 SkipItemsWantingParentType(ParentType aParentType) {
11742 MOZ_ASSERT(!IsDone(), "Shouldn't be done yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "Shouldn't be done yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11742); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11742; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11743 while (item().DesiredParentType() == aParentType) {
11744 Next();
11745 if (IsDone()) {
11746 return true;
11747 }
11748 }
11749 return false;
11750}
11751
11752inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11753 SkipItemsNotWantingParentType(ParentType aParentType) {
11754 MOZ_ASSERT(!IsDone(), "Shouldn't be done yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "Shouldn't be done yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11754); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11754; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11755 while (item().DesiredParentType() != aParentType) {
11756 Next();
11757 if (IsDone()) {
11758 return true;
11759 }
11760 }
11761 return false;
11762}
11763
11764// Note: we implement -webkit-{inline-}box using nsFlexContainerFrame, but we
11765// use different rules for what gets wrapped in an anonymous flex item.
11766bool nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem(
11767 const nsFrameConstructorState& aState, bool aIsLegacyWebKitBox) {
11768 if (mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT0x2000) {
11769 // This will be an inline non-replaced box.
11770 return true;
11771 }
11772
11773 if (aIsLegacyWebKitBox) {
11774 if (mComputedStyle->StyleDisplay()->IsInlineOutsideStyle()) {
11775 // In an emulated legacy box, all inline-level content gets wrapped in an
11776 // anonymous flex item.
11777 return true;
11778 }
11779 if (mIsPopup ||
11780 (!(mFCData->mBits & FCDATA_DISALLOW_OUT_OF_FLOW0x8) &&
11781 aState.GetGeometricParent(*mComputedStyle->StyleDisplay(), nullptr))) {
11782 // We're abspos or fixedpos (or a XUL popup), which means we'll spawn a
11783 // placeholder which (because our container is an emulated legacy box)
11784 // we'll need to wrap in an anonymous flex item. So, we just treat
11785 // _this_ frame as if _it_ needs to be wrapped in an anonymous flex item,
11786 // and then when we spawn the placeholder, it'll end up in the right
11787 // spot.
11788 return true;
11789 }
11790 }
11791
11792 return false;
11793}
11794
11795inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11796 SkipItemsThatNeedAnonFlexOrGridItem(const nsFrameConstructorState& aState,
11797 bool aIsLegacyWebKitBox) {
11798 MOZ_ASSERT(!IsDone(), "Shouldn't be done yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "Shouldn't be done yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11798); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11798; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11799 while (item().NeedsAnonFlexOrGridItem(aState, aIsLegacyWebKitBox)) {
11800 Next();
11801 if (IsDone()) {
11802 return true;
11803 }
11804 }
11805 return false;
11806}
11807
11808inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11809 SkipItemsThatDontNeedAnonFlexOrGridItem(
11810 const nsFrameConstructorState& aState, bool aIsLegacyWebKitBox) {
11811 MOZ_ASSERT(!IsDone(), "Shouldn't be done yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "Shouldn't be done yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11811; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11812 while (!(item().NeedsAnonFlexOrGridItem(aState, aIsLegacyWebKitBox))) {
11813 Next();
11814 if (IsDone()) {
11815 return true;
11816 }
11817 }
11818 return false;
11819}
11820
11821inline bool nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11822 SkipItemsNotWantingRubyParent() {
11823 MOZ_ASSERT(!IsDone(), "Shouldn't be done yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "Shouldn't be done yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11823; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11824 while (!IsRubyParentType(item().DesiredParentType())) {
11825 Next();
11826 if (IsDone()) {
11827 return true;
11828 }
11829 }
11830 return false;
11831}
11832
11833inline bool
11834nsCSSFrameConstructor::FrameConstructionItemList::Iterator::SkipWhitespace(
11835 nsFrameConstructorState& aState) {
11836 MOZ_ASSERT(!IsDone(), "Shouldn't be done yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "Shouldn't be done yet"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11836); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "Shouldn't be done yet" ")"); do { *((volatile int*)__null
) = 11836; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11837 MOZ_ASSERT(item().IsWhitespace(aState), "Not pointing to whitespace?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(item().IsWhitespace(aState))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(item().IsWhitespace(aState))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("item().IsWhitespace(aState)"
" (" "Not pointing to whitespace?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "item().IsWhitespace(aState)"
") (" "Not pointing to whitespace?" ")"); do { *((volatile int
*)__null) = 11837; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11838 do {
11839 Next();
11840 if (IsDone()) {
11841 return true;
11842 }
11843 } while (item().IsWhitespace(aState));
11844
11845 return false;
11846}
11847
11848void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11849 AppendItemToList(FrameConstructionItemList& aTargetList) {
11850 NS_ASSERTION(&aTargetList != &mList, "Unexpected call")do { if (!(&aTargetList != &mList)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected call", "&aTargetList != &mList", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11850); MOZ_PretendNoReturn(); } } while (0)
;
11851 MOZ_ASSERT(!IsDone(), "should not be done")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsDone())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsDone()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!IsDone()" " (" "should not be done"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsDone()"
") (" "should not be done" ")"); do { *((volatile int*)__null
) = 11851; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11852
11853 FrameConstructionItem* item = mCurrent;
11854 Next();
11855 item->remove();
11856 aTargetList.mItems.insertBack(item);
11857
11858 mList.AdjustCountsForItem(item, -1);
11859 aTargetList.AdjustCountsForItem(item, 1);
11860}
11861
11862void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::
11863 AppendItemsToList(nsCSSFrameConstructor* aFCtor, const Iterator& aEnd,
11864 FrameConstructionItemList& aTargetList) {
11865 NS_ASSERTION(&aTargetList != &mList, "Unexpected call")do { if (!(&aTargetList != &mList)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected call", "&aTargetList != &mList", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11865); MOZ_PretendNoReturn(); } } while (0)
;
11866 MOZ_ASSERT(&mList == &aEnd.mList, "End iterator for some other list?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&mList == &aEnd.mList)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(&mList == &aEnd.mList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"&mList == &aEnd.mList" " (" "End iterator for some other list?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&mList == &aEnd.mList"
") (" "End iterator for some other list?" ")"); do { *((volatile
int*)__null) = 11866; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11867
11868 // We can't just move our guts to the other list if it already has
11869 // some information or if we're not moving our entire list.
11870 if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
11871 do {
11872 AppendItemToList(aTargetList);
11873 } while (*this != aEnd);
11874 return;
11875 }
11876
11877 // Move our entire list of items into the empty target list.
11878 aTargetList.mItems = std::move(mList.mItems);
11879
11880 // Copy over the various counters
11881 aTargetList.mInlineCount = mList.mInlineCount;
11882 aTargetList.mBlockCount = mList.mBlockCount;
11883 aTargetList.mItemCount = mList.mItemCount;
11884 memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
11885 sizeof(aTargetList.mDesiredParentCounts));
11886
11887 // reset mList
11888 mList.Reset(aFCtor);
11889
11890 // Point ourselves to aEnd, as advertised
11891 SetToEnd();
11892 MOZ_ASSERT(*this == aEnd, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*this == aEnd)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*this == aEnd))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("*this == aEnd" " ("
"How did that happen?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*this == aEnd"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11892; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11893}
11894
11895void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::InsertItem(
11896 FrameConstructionItem* aItem) {
11897 if (IsDone()) {
11898 mList.mItems.insertBack(aItem);
11899 } else {
11900 // Just insert the item before us. There's no magic here.
11901 mCurrent->setPrevious(aItem);
11902 }
11903 mList.AdjustCountsForItem(aItem, 1);
11904
11905 MOZ_ASSERT(aItem->getNext() == mCurrent, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aItem->getNext() == mCurrent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aItem->getNext() == mCurrent
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aItem->getNext() == mCurrent" " (" "How did that happen?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11905); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aItem->getNext() == mCurrent"
") (" "How did that happen?" ")"); do { *((volatile int*)__null
) = 11905; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
11906}
11907
11908void nsCSSFrameConstructor::FrameConstructionItemList::Iterator::DeleteItemsTo(
11909 nsCSSFrameConstructor* aFCtor, const Iterator& aEnd) {
11910 MOZ_ASSERT(&mList == &aEnd.mList, "End iterator for some other list?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&mList == &aEnd.mList)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(&mList == &aEnd.mList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"&mList == &aEnd.mList" " (" "End iterator for some other list?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&mList == &aEnd.mList"
") (" "End iterator for some other list?" ")"); do { *((volatile
int*)__null) = 11910; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11911 MOZ_ASSERT(*this != aEnd, "Shouldn't be at aEnd yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*this != aEnd)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*this != aEnd))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("*this != aEnd" " ("
"Shouldn't be at aEnd yet" ")", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*this != aEnd"
") (" "Shouldn't be at aEnd yet" ")"); do { *((volatile int*
)__null) = 11911; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11912
11913 do {
11914 NS_ASSERTION(!IsDone(), "Ran off end of list?")do { if (!(!IsDone())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Ran off end of list?"
, "!IsDone()", "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11914); MOZ_PretendNoReturn(); } } while (0)
;
11915 FrameConstructionItem* item = mCurrent;
11916 Next();
11917 item->remove();
11918 mList.AdjustCountsForItem(item, -1);
11919 item->Delete(aFCtor);
11920 } while (*this != aEnd);
11921}
11922
11923void nsCSSFrameConstructor::QuotesDirty() {
11924 mQuotesDirty = true;
11925 mPresShell->SetNeedLayoutFlush();
11926}
11927
11928void nsCSSFrameConstructor::CountersDirty() {
11929 mCountersDirty = true;
11930 mPresShell->SetNeedLayoutFlush();
11931}
11932
11933void* nsCSSFrameConstructor::AllocateFCItem() {
11934 void* item;
11935 if (mFirstFreeFCItem) {
11936 item = mFirstFreeFCItem;
11937 mFirstFreeFCItem = mFirstFreeFCItem->mNext;
11938 } else {
11939 item = mFCItemPool.Allocate(sizeof(FrameConstructionItem));
11940 }
11941 ++mFCItemsInUse;
11942 return item;
11943}
11944
11945void nsCSSFrameConstructor::FreeFCItem(FrameConstructionItem* aItem) {
11946 MOZ_ASSERT(mFCItemsInUse != 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mFCItemsInUse != 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mFCItemsInUse != 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mFCItemsInUse != 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/layout/base/nsCSSFrameConstructor.cpp"
, 11946); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFCItemsInUse != 0"
")"); do { *((volatile int*)__null) = 11946; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11947 if (--mFCItemsInUse == 0) {
11948 // The arena is now unused - clear it but retain one chunk.
11949 mFirstFreeFCItem = nullptr;
11950 mFCItemPool.Clear();
11951 } else {
11952 // Prepend it to the list of free items.
11953 FreeFCItemLink* item = reinterpret_cast<FreeFCItemLink*>(aItem);
11954 item->mNext = mFirstFreeFCItem;
11955 mFirstFreeFCItem = item;
11956 }
11957}
11958
11959void nsCSSFrameConstructor::AddSizeOfIncludingThis(
11960 nsWindowSizes& aSizes) const {
11961 if (nsIFrame* rootFrame = GetRootFrame()) {
11962 rootFrame->AddSizeOfExcludingThisForTree(aSizes);
11963 if (RetainedDisplayListBuilder* builder =
11964 rootFrame->GetProperty(RetainedDisplayListBuilder::Cached())) {
11965 builder->AddSizeOfIncludingThis(aSizes);
11966 }
11967 }
11968
11969 // This must be done after measuring from the frame tree, since frame
11970 // manager will measure sizes of staled computed values and style
11971 // structs, which only make sense after we know what are being used.
11972 nsFrameManager::AddSizeOfIncludingThis(aSizes);
11973
11974 // Measurement of the following members may be added later if DMD finds it
11975 // is worthwhile:
11976 // - mFCItemPool
11977 // - mContainStyleScopeManager
11978}